istringstream忽略第一个字母

时间:2016-05-29 18:37:42

标签: c++ istringstream

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

任何人都可以建议我做什么以及为什么会出现这种错误?

3 个答案:

答案 0 :(得分:4)

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

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

  1. std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');跳过所有前导空格。这可能包括行开头的多个换行符和空格。跳过那些可能不一定是可取的。
  2. {{1}}忽略所有字符,包括第一个换行符。这将允许空行跟进以及从前导空格开始的行。

答案 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阻止并等待用户输入

考虑到这一点,让我们分解您的代码所做的事情:

  1. 第一次在循环中调用此函数时,它会发生 忽略仍在缓冲区中的新行字符 以前的cin>>t操作。然后getline语句将等待并从用户读取一行。
  2. 下一次,因为缓冲区中没有任何内容 忽略(因为std::getline不会将新行字符留在 缓冲区),它将阻止并等待输入忽略。所以 下次程序阻塞并等待输入时,这是因为 ignore()函数,而不是getline函数 希望,以及你提供输入的那一刻(即你第二次测试 case),输入中的一个字符将被忽略。
  3. 下一个getline函数不会阻止,因为有东西 在之后的ignore函数留下的缓冲区中 忽略输入的第一个字符,以便getline读取 剩余的字符串恰好是一个字符短。
  4. 该过程从步骤2继续,直到您的循环终止。
  5. 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