【问题标题】:istringstream ignores first letteristringstream 忽略第一个字母
【发布时间】:2016-09-27 13:37:21
【问题描述】:

我正在尝试使用 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 名字是 xyz

我吃香蕉

谁能建议我该怎么做?为什么会出现这个错误?

【问题讨论】:

  • 请提供minimal reproducible examplearr到底是什么?
  • 是的,非常感谢您指出这一点。
  • 在循环之前移动cin.ignore()。也试着弄清楚它实际上做了什么,

标签: c++ istringstream


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    std::basic_istream::ignore 不带任何参数调用时,它会忽略 1 个字符。

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

    【讨论】:

    • 我认为在第一种情况下有一些东西可以忽略,即换行符,但是下一次用户输入到getline时已经跳过了一个字符声明。
    【解决方案3】:

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

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

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

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

    1. 第一次在循环中调用此函数时,它将 忽略仍在缓冲区中的换行符 以前的cin&gt;&gt;t 操作。然后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&gt;&gt;t 语句旁边。在这种情况下,最好写ignore(INT_MAX,'\n');。您可能还想阅读this answer 以了解何时以及如何使用ignore

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-24
      • 2014-06-05
      • 1970-01-01
      • 2012-06-11
      • 1970-01-01
      相关资源
      最近更新 更多