istringstream忽略第一个字母

istringstream ignores first letter

本文关键字:第一个 istringstream      更新时间:2023-10-16

我正在尝试使用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

女孩吃香蕉

我得到了:

输出:


嘿,嘿

i嗨嗨

y名称是xyz

irl吃香蕉

有人能告诉我该怎么做吗?为什么会出现这种错误?

您的问题是格式化的输入,即像in >> value这样的输入,在尝试读取之前通常会跳过前导空格。另一方面,未格式化的输入不会跳过前导空格。使用循环中的std::cin.ignore();,您可以假设std::getline(std::cin, arr)会像t的输入一样在输入中保留换行符。事实并非如此。std::getline()提取并存储所有字符,直到它停止的第一个换行符,仍然提取换行符。因此,您应该从循环中删除cin.ignore();

关键问题是如何在格式化输入和非格式化输入之间切换。由于输入数值时的换行符前面可能有任意空格,您可能也想忽略这些空格,因此基本上有以下几种方法:

  1. std::cin >> std::ws;跳过所有前导空格。这可能包括多个换行符和行开头的空格。跳过这些可能并不一定是可取的
  2. std::cin.ignore(std::numeric_limits<std::streamsize>::max(), 'n');忽略第一个换行符之前(包括该换行符)的所有字符。这将允许空行跟在后面,也允许以前导空格开头的行

这一行是罪魁祸首:cin.ignore();

当在没有任何参数的情况下调用std::basic_istream::ignore时,它只忽略1个字符。

在您的情况下,std::cin.ignore()将忽略第一个字母,但对于第一个测试用例则不会,因为此时std::cin为空,因此没有什么可忽略的。但是,std::cin中有其他单词,因此它忽略了第一个单词中的1个字符。

根据std::basic_istream::ignore:的文档

从输入流中提取并丢弃字符,直到和包括熟食ignore表现为UnformattedInputFunction

值得一提的是,如果流中没有可忽略的东西std::basic_istream::ignore阻塞并等待用户输入

考虑到这一点,让我们分解一下你的代码的作用:

  1. 第一次在循环中调用此函数时忽略仍在缓冲区中的换行符先前的CCD_ 17操作。然后getline语句将等待并读取来自用户的一行
  2. 下一次,由于缓冲区中没有任何内容忽略(因为std::getline没有在缓冲区),它将进入块并等待输入被忽略。所以下一次程序阻塞并等待输入时,是因为ignore()函数,而不是像您希望的那样使用getline函数希望,并且在你提供输入的那一刻(即你的第二次测试case),则将忽略输入中的一个字符
  3. 下一个getline函数将不会阻塞,因为存在某些内容在前一个ignore函数之后留下的缓冲区中忽略输入的第一个字符,因此getline将读取刚好短一个字符的剩余字符串
  4. 该过程从步骤2开始继续,直到循环终止

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');。您可能还想阅读这个答案,了解何时以及如何使用ignore