C++多测试用例字符串输入首用例读空的原因及解决方法
为什么第一个测试用例会读入空字符串?
这是因为cin >> t读取整数后,输入缓冲区里会残留一个换行符——就是你输入t后按下的回车键。接下来的getline(cin, s)会直接读取这个换行符,把它当作一个空字符串,所以第一个测试用例就变成空的了。
举个实际输入的例子:
2 hello world
cin >> t会读取2,此时输入缓冲区里剩下\nhello\nworld。第一个getline直接把\n读入,导致s是空字符串,第二个getline才会读到hello。
怎么解决这个问题?
这里有几种实用的解决方案,你可以根据场景选择:
方法一:读取整数后用
cin.ignore()跳过换行符
这是最通用的处理方式,在cin >> t之后,添加一行代码清除缓冲区里的换行符(以及可能存在的其他多余字符)。记得要包含<limits>头文件来调用numeric_limits。修改后的完整代码:
#include <iostream> #include <string> #include <limits> // 必须包含这个头文件 using namespace std; int main() { int t; cin >> t; // 清除缓冲区直到遇到换行符,把残留的回车吃掉 cin.ignore(numeric_limits<streamsize>::max(), '\n'); while(t--) { string s; getline(cin, s); cout << s << endl; } return 0; }方法二:全程用
getline读取,再转换整数
如果你不想处理缓冲区的残留问题,可以先读取第一行作为字符串,再把它转换成整数t,之后循环读取剩下的行即可。这种方式完全避开了混合输入的问题。示例代码:
#include <iostream> #include <string> #include <sstream> using namespace std; int main() { string t_str; getline(cin, t_str); int t = stoi(t_str); // 将字符串转换为整数 while(t--) { string s; getline(cin, s); cout << s << endl; } return 0; }方法三:用
cin >> s代替getline(仅适用于无空格的字符串)
如果你要读取的字符串本身不包含空格,直接用cin >> s就可以——因为cin >> s会自动跳过所有空白字符(包括换行、空格、制表符),不会被残留的回车影响。但如果字符串有空格,这个方法就失效了。示例代码:
#include <iostream> #include <string> using namespace std; int main() { int t; cin >> t; while(t--) { string s; cin >> s; // 自动跳过空白,包括之前的换行 cout << s << endl; } return 0; }
总结
如果需要读取带空格的字符串,优先选第一种方法;如果字符串不含空格,第三种方法最简洁;第二种方法适合完全不想处理缓冲区细节的场景。
内容的提问来源于stack exchange,提问作者Nishikant Singh

