我在 25 保研高校夏令营机试中,被输入输出处理毒害不浅。不是不会做,而是花了大力气从提供的输入中解析出需要的数据,以及将得到的答案按照题目要求输出出来。
这次,真要把部分输入输出处理的方法整理出来。
1 stringstream
算法题输入输出主要有两种方式。第一种是
ACM
竞赛中提交完整的程序代码,输入输出分别在stdin
和stdout
中;第二种如力扣的提交部分代码,输入输出分别在函数的参数和返回值中。
那么下述这种方式真的很难遇到:提交部分代码,输入以 string
字符串传入函数,输出以 string
字符串返回。代码框架如下:
string solve(string s) {
}
如果输入是一个长度为 $n$ 的数组,那么 s
组成方式为 n a1 a2 a3 ... an
。如果不会 stringstream
,只有将这个当一个 char
逐个字符解析了。如果输出是多个数字,你还需要想办法构造这样一个字符串。
stringstream
是一种流,可以操作输入输出,使用方法如下:
string solve(string s) {
stringstream in(s); // use string s as input stream.
int n;
in >> n;
vecotr<int> a(n);
for (int &x: a) {
in >> x;
}
stringstream out; // output stream.
for (int x: a) {
out << x << '\n';
}
return out.str(); // get string object from stringstream
}
2 输入处理
题目描述:我们的输入可能包含多个空格……
2.1 getline
问题来源,
gets
是一个非安全函数,已经被弃用了。
getline
需要传入两个参数。第一个参数 is
,为输入流;第二个参数为 str
,为 string
类型变量。示例如下:
void solve() {
string input_line;
getline(cin, input_line); // the end character is '\0', not '\n'.
}
2.2 split
这种输入含多个空格的一般会提供分隔符。我们需要使用 string
类相关方法来实现:
find
方法:传递两个参数。第一个参数为需要查找的字符串str
,第二个参数为查找的起始位置pos
(默认为 0 )。如果没有找到,返回string::npos
。substr
方法:传递两个参数。第一参数子串起始位置下表,第二个参数为子串结束位置的下标的下一位。erease
方法:传递两个参数。第一参数需要删除子串起始位置迭代器,第二个参数为需要删除子串结束位置迭代器。
我们假设分隔符为 :
。首先需要找到 :
的位置,代码为 s.find(delimiter)
,在此位置之前就是我们需要的数据,可以使用 substr
方法获取,代码为 s.substr(0, s.find(delimiter))
。如果有多个数据以该分隔符分离,代码实现如下:
std::string s = "scott>=tiger>=mushroom";
std::string delimiter = ">=";
size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
std::cout << token << std::endl;
s.erase(0, pos + delimiter.length());
}
std::cout << s << std::endl;
2.3 trim
按照 2.2 节的方法获得数据之后,需要过滤首尾多余的空格。C++
并不像 Java
等语言提供了该函数,我们需要自己使用 string
的 find
方法以及 erase
方法实现。实现的代码如下:
inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
参考资料
Parse (split) a string in C++ using string delimiter (standard C++)