我正在尝试使用std::istringstream
访问字符串中的不同单词,并且我也在使用多个测试用例。
int t;
cin>>t;
while(t--)
{
string arr;
cin.ignore();
getline(cin,arr);
istringstream iss(arr);
string word;
while(iss>>word)
{
cout<<word;
}
}
对于第一个测试用例,一切都很完美(即输出正确的单词)。但是对于每个后续的测试用例,第一个单词的第一个字母都被省略了。
示例:
输入:
<小时/> 4
嘿,嘿嘿
嗨嗨
我的名字是xyz
女孩吃香蕉
我得到了:
输出:
嘿,嘿嘿我喜欢
y name是xyz
irl吃香蕉
任何人都可以建议我做什么以及为什么会出现这种错误?
答案 0 :(得分:4)
你的问题是格式化的输入,即类似std::cin.ignore();
之类的东西,在尝试阅读之前通常会跳过前导空格。另一方面,未格式化的输入不会跳过前导空格。使用循环中的std::getline(std::cin, arr)
,您可以假设t
会像输入std::getline()
那样将换行符留在输入中。事实并非如此。 cin.ignore();
提取并存储所有字符,直到它停止的第一个换行符,仍然提取换行符。所以,你要从循环中删除std::cin >> std::ws;
。
关键问题是如何在格式化输入和未格式化输入之间切换。由于输入数字值时的换行符可能前面有您可能也想忽略的任意空格,因此主要有以下几种方法:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
跳过所有前导空格。这可能包括行开头的多个换行符和空格。跳过那些可能不一定是可取的。答案 1 :(得分:2)
这一行是罪魁祸首:cin.ignore();
。
当没有任何参数调用std::basic_istream::ignore
时,它会忽略1个字符。
在您的情况下,std::cin.ignore()
将忽略第一个字母,但不会忽略第一个测试用例,因为此时std::cin
为空,因此没有什么可以忽略的。但是,std::cin
中包含其他单词,因此忽略了第一个单词中的1个字符。
答案 2 :(得分:2)
根据std::basic_istream::ignore
的文件:
从输入流中提取并丢弃字符,直到和 包括delim。 忽略表现为UnformattedInputFunction
值得一提的是,如果在流中忽略无,则std::basic_istream::ignore
将阻止并等待用户输入。
考虑到这一点,让我们分解您的代码所做的事情:
cin>>t
操作。然后getline
语句将等待并从用户读取一行。std::getline
不会将新行字符留在
缓冲区),它将阻止并等待输入忽略。所以
下次程序阻塞并等待输入时,这是因为
ignore()
函数,而不是getline
函数
希望,以及你提供输入的那一刻(即你第二次测试
case),输入中的一个字符将被忽略。getline
函数不会阻止,因为有东西
在之后的ignore
函数留下的缓冲区中
忽略输入的第一个字符,以便getline
读取
剩余的字符串恰好是一个字符短。int t;
cin>>t;//this leaves new line character in the buffer
while(t--)
{
string arr;
cin.ignore();//this will ignore one character from the buffer,so the first time
//it will ignore the new line character from the previous cin input
//but next time it will block and wait for input to ignore
getline(cin,arr);//this will not block if there is something in the buffer
//to read
...
}
解决方案是将ignore
语句移出循环并移到cin>>t
语句旁边。在这种情况下,最好写ignore(INT_MAX,'\n');
。您可能还想阅读this answer,了解何时以及如何使用ignore
。