刷OJ时输入输出与字符串

输入输出与测试方法

对于刚开始接触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方法!
思考:如果输入数据不是以空格进行分隔的,是特殊字符如*、|等怎么处理?

只需扫描整个字符串,将特殊字符全部替换成空格即可
posted @ 2018-04-04 12:04  migoo  阅读(2406)  评论(0编辑  收藏  举报