输入输出与测试方法
对于刚开始接触OJ(Online Judge)的同学估计对于OJ的输入输出存在疑惑,OJ的输入输出基本都是使用标准输入输出(也称标准I/O,即直接读键盘、写屏幕)。
OJ的判题方式则是使用输入输出重定向到文件
./test < data_in > data_out
可执行文件test
中使用标准输入输出,data_in
是输入文件,data_out
是输出文件,最后将test
的输出data_out
与答案文件比对判断程序是否运行正确。
我们在测试自己的程序时,可以在代码里加入重定向语句来方便测试,但是必须注意:自我测试完毕之后删除重定向语句,再提交代码。
代码里重定向方法:
#define LOCAL //在提交代码时注释掉
#include<stdio.h>
int main(){
#ifdef LOCAL
freopen("data.in", "r", stdin);//将data.in改为输入文件路径
freopen("data.out", "w", stdout);//将data.out改为输出文件路径
#endif
return 0;
}
随后,正常使用C/C++的标准输入,都会定向到上述两个文件中,以便于自测代码。
字符串
C语言中的字符串就是字符数组,处处受限。例如,如何编写一个函数,把两个字符串拼接成一个长字符串?
这个任务看上去简单,实际上却暗藏陷阱:新字符串的存储空间从哪里来?
不能在函数中定义一个数组然后返回它的地址,因为函数返回后其中局部变量的地址便失效了。因此“字符串拼接”函数必须申请新的内存空间以存放结果,用完之后还要将申请的空间“退回去”,这会很麻烦。另外,字符串数组本身并不保存字符串长度,每次需要时都要用strlen函数重算一次。如果字符串很长,则strlen函数的开销将不容忽视。
为了避免不必要的strlen调用,可以在某个变量中保存字符串的长度,但这样一来,程序会变得更加复杂,难以调试。总而言之,C语言处理字符串并不方便。
C++提供了一个新的string类型,用来替代C语言中的字符数组。用户仍然可以继续用字符数组当字符串用,但是如果希望程序更加简单、自然,string类型往往是更好的选择。例如,C++的cin/cout可以直接读写string类型,却不能读写字符数组;string类型还可以像整数那样“相加”,而在C语言里只能使用strcat函数。
C++在string头文件里定义了string类型,直接支持流式读写。
string有很多方便的函数和运算符,但速度有些慢。考虑这样一个题目:输入数据的每行包含若干个(至少一个)以空格隔开的整数,输出每行中所有整数之和。如果只能使用字符与字符数组,一般有两种方案:一是使用getchar( )边读边算,代码较短,但容易写错,并且相对较难理解;二是每次读取一行,然后再扫描该行的字符,同时计算结果。如果使用C++,代码可以很简单。
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main() {
string line;
while(getline(cin, line)) {
int sum = 0, x;
stringstream ss(line);
while(ss >> x) sum += x;
cout << sum << "\n";
}
return 0;
}
string类在string头文件中,而stringstream在sstream头文件中。首先用getline函数读一行数据(相当于C语言中的fgets,但由于使用string类,无须指定字符串的最大长度),然后用这一行创建一个“字符串流”——ss。接下来只需像读取cin那样读取ss即可。
可以把string作为流进行读写,定义在sstream头文件中。
对于字符串的操作请尽量使用C++提供的string方法!
思考:如果输入数据不是以空格进行分隔的,是特殊字符如*、|等怎么处理?
只需扫描整个字符串,将特殊字符全部替换成空格即可