【问题标题】:Problem of using cin twice两次使用cin的问题
【发布时间】:2010-03-26 17:30:11
【问题描述】:

代码如下:

string str;
cin>>str;
cout<<"first input:"<<str<<endl;
getline(cin, str);
cout<<"line input:"<<str<<endl;

结果是 getline 永远不会因用户输入而暂停,因此第二个输出始终为空。

花了一些时间之后,我意识到在第一次调用“cin>>str”之后,似乎'\n'仍然存储在cin中(使用cin.peek()检查),它立即结束了getline。解决方案将在第一个用法和第二个用法之间再添加一行: cin.ignore(numeric_limits::max(), '\n');

但是,我还是不明白,为什么在第一次调用后还剩下'\n'? istream& operator>> 到底是做什么的?

【问题讨论】:

  • 更多挖掘揭示了描述的微妙之处:“当 next 字符是有效的空格或空字符,或者 End-Of-文件已到达。”

标签: c++ cin


【解决方案1】:

按照为std::string 定义operator&gt;&gt; 的方式,\n 留在输入流中。 std::string 被输入流中的字符填充,直到找到空白字符(在本例中为 \n),此时填充停止,空白现在是输入流中的下一个字符。

您也可以通过在cin&gt;&gt;str 之后立即调用cin.get() 来删除\n。然而,有很多很多不同的方法可以给这个特定的 I/O 猫蒙皮。 (也许这本身就是一个好问题?)

【讨论】:

  • 摆脱尾随空白字符的更好方法可能是std::cin &gt;&gt; str &gt;&gt; std::ws;
  • 运行一些测试,意识到这不是如何为 std::string 定义的问题。事实上, operator>> 将换行符留在流中,无论它后面的变量是什么。但是感谢您开始讨论摆脱空白!
【解决方案2】:

默认情况下,流插入运算符会一直读取,直到看到空白为止。在看到空格、制表符、换行符等之前,您的第一个调用不会返回。然后需要消耗下一个字符,以便您可以进入下一个。

【讨论】:

    【解决方案3】:

    我通常建议只从 std::cin 进行面向行的输入。因此,您的代码可能如下所示:

    string str;
    int val;
    // Read an entire line and parse an integer from it
    {
        string line;
        getline(cin, line);
        istringstream iss(line);
        iss >> val;
    }
    cout<<"first input:"<<val<<endl;
    getline(cin, str);
    cout<<"line input:"<<str<<endl;
    

    一定要添加错误检查。

    getline-only 方法避免了必须考虑输入的行缓冲、清除输入等。如果您直接使用 >> 读取某些内容,如果用户按 Enter 键而不是输入内容,则输入不会终止需要,而是一直持续到输入令牌为止(通常不需要这种行为)。

    【讨论】:

      【解决方案4】:

      正如其他人所说,问题在于第一次提取时留下了换行符。我做的一种解决方案是丢弃流中的所有左侧字符:

      std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
      

      【讨论】:

        【解决方案5】:

        Good writeup that explains some of the reasons why您遇到了这个问题,主要是由于输入类型的行为以及您正在混合它们

        【讨论】:

          【解决方案6】:

          也在寻找最合适的解决方案。此运算符的实施可能会产生问题。读取整行并不总是可以接受的,或者不在一个输入行中混合不同类型。

          为了解决问题,当你想从cin读取一些数据,并且不知道上次输入操作后是否正确提取了空格,你可以这样做:

          std::string str;
          std::cin >> std::ws >> str;
          

          但是您不能使用它在最后一次输入操作后从 cin 清除尾随换行符以不影响新输入,因为 std::ws 将消耗所有空格并且在第一个非 ws 字符或 @987654324 之前不会返回控制@ 将被找到,因此按 Enter 不会完成输入过程。 在这种情况下应该使用

           std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
          

          更灵活。

          附:如果max() 函数出现错误,例如“预期标识符”,则可能是由某些标头中定义的max 宏(例如,Microsoft)引起的;这可以通过使用

          来解决
           #undef max
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-03-05
            • 1970-01-01
            • 1970-01-01
            • 2016-05-11
            • 1970-01-01
            • 2013-07-31
            • 1970-01-01
            相关资源
            最近更新 更多