【问题标题】:C++ reading input from cin until the whole line has been readC++ 从 cin 读取输入,直到整行都被读取
【发布时间】:2014-05-30 05:43:23
【问题描述】:

我在一个字符'c'中读取了一个while循环,我检查了这个字符是否是一个运算符; “+”、“-”、“/”或“*”。 while 循环逐个字符地读取,但它不会停止……例如,如果输入的最后一个字符是“+”。它将永远留在循环中,将 char 'c' 设置为 '+'。

stack<int> num;
char c;
int n,count=0,a,b;
while (cin>>c)
{
    if (c != '+' && c != '-' && c != '/' && c != '*')
     {
         cout << c << endl;
         n = (c - 48);
         num.push(n);
         cin >> c;
         count++;
     }
     else if (c == '+' || c == '-' || c == '/' || c == '*')
     {
         cout << "count is " << count << endl;
         if (count>1)
         {
            b =  num.top();
            a = num.top();
            num.pop();
            num.pop();

            if (c == '+')
            {
                num.push(a+b);
                count--;
            }
            else if (c == '-')
            {
                num.push(a+b);
                count--;
            }
            else if (c == '/')
            {
                if (b != 0)
                {
                    num.push(a/b);
                    count--;
                }
                else
                {
                    cout << "division by zero" << endl;
                    return(0);
                }
            }
            else if (c == '*')
            {
                num.push(a*b);
                count--;
            }
            else
            {
                cout << "invalid input" << endl;
                return(0);          
            }
         }
         else
         {
             cout << "stack underflow" << c << endl;
             return(0);
         }
     }
     cout << c << endl;
 }
}

【问题讨论】:

  • 你的问题不够清楚。
  • 您的问题不清楚,该循环应该可以正常工作。 @TeoZec 他在那里不需要 break 语句,条件应该可以正常工作。
  • 为什么不使用getline? getline(cin, string) 然后做点什么?
  • 当没有更多输入时它不会停止,如果输入行中的最后一个字符是“+”,那么它会一直停留在 while 循环中使用“+”进行计算,而不是读完所有内容后退出。
  • @user3678093 你能发布更多代码吗?

标签: c++ input eof cin


【解决方案1】:

既然您已经澄清了您的问题,那就更清楚了。 @TeoZec 的答案应该是正确的。我只想注意您上面的代码中看起来有问题的两件事:

else if (c == '-')
{
    num.push(a+b);
    count--;
}

这里你可能想要a-b

if (count>1)
{
    b =  num.top();
    a = num.top();
    num.pop();
    num.pop();

ba 在这里将是相同的号码,您应该在获得第二个号码之前拨打pop(),例如:

if (count>1)
{
    b =  num.top();
    num.pop();
    a = num.top();
    num.pop();

【讨论】:

    【解决方案2】:

    因为您没有条件终止您的 while 循环,您需要向您的 while 添加更多条件,如下所示:

    while(cin>>c && c != '+' && c != '-' && c != '*' && c != '/')
    {
        //do stuff here
    }
    

    或者在执行检查以查看输入的字符之后,将 break 添加到 while 循环的内部。

    【讨论】:

    • 他的循环中有一个条件。 cin&gt;&gt;c 到达 eof 后将返回 false 并且循环将结束。
    • 这就是我的想法,但它没有检测到 eof
    • 是的,但它只会在到达行尾时退出循环,而不是在找到他正在寻找的字符之一时。
    • @user3678093 cin &gt;&gt; c 在 eof 处停止。也许你在 eof 和 eol 之间混淆了。
    • 在控制台输入一行时不会创建EOF字符。您需要通过按 CTRL-D 手动输入它,或者另一种方法是在循环中添加一个中断。
    【解决方案3】:

    您的代码存在几个问题。对于初学者, 我不明白ifcin &gt;&gt; c 的用途 分支;您输入了一个字符,但您似乎从未使用过它; 它只是丢失了。当然,不需要if 加入else if,因为它是 if 的条件。当然,switch 远不止这些 自然你if/else if链比较单的时候 字符对许多不同的常数。和的 当然,'0' 并不总是 48(即使是,'0' 也是 比48更具可读性)。

    至于将字符 c 设置为 + 时保持循环,我不知道 看见。我看到的唯一循环是while( std::cin &gt;&gt; c ),并且 这将读取一个新字符,或者终止。

    如果您的目标是只阅读一行,那可能会更好 使用std::getline,然后遍历您输入的字符串:

    std::string line;
    while ( std::getline( std::cin, line ) ) {
        //  Set up your stack here...
        for ( std::string::const_iterator it = line.begin(); it != line.end(); ++ it ) {
            if ( isdigit( static_cast<unsigned char>( *it ) ) ) {
                //  process digit...
            } else if ( ispunct( static_cast<unsigned char>( *it ) ) ) {
                //  process punctuation, with eventually
                switch ( *it ) {
                case '+':
                    //  addition...
                    break;
                case '-':
                    //  substraction...
                    break;
                //  ...
                default:
                    //  illegal operator...
                    break;
                }
            } else {
                //  process anything else...
            }
    
        }
    }
    

    或者,您可以定义一个isOperator 函数,以及 行:

    bool
    isOperator( char ch )
    {
        static std::string const legalOps( "+-*/" );
        return std::find( legalOps.begin(), legalOps.end(), ch) != legalOps.end();
    }
    

    【讨论】:

      【解决方案4】:

      这应该可行:

      #include <cstdio>
      ...
      
      int c; // As pointed out by James Kanze in his comment, c should be an int to detect EOF
      do {
          c = getchar();
          // Do stuff
      } while ((c != '\n') && c != EOF))
      

      您不仅需要检查 EOF,还需要检查行终止符。

      【讨论】:

      • cin &gt;&gt; c 永远不会将c 设置为'\n'(除非您取消设置skipws),因此第二个测试将始终评估为真。
      • @james 这样他就可以使用 getchar(),就像在 C 中一样。感谢您的注意,我会更正它。但是为什么 cin 不将 c 设置为'\n'?我不是 C++ 方面的专家,我想要一些解释。谢谢!
      • 您的修订版也不起作用;它将在文件末尾进入无限循环。至于看不到'\n'&gt;&gt; 用于格式化输入(有一个非常特殊的例外),并从跳过空格开始。而'\n'是一个空格字符。
      • @james 好的,感谢您的解释。但我认为只要我们从键盘获得输入,带有 getchar() 的版本就可以工作。但是,我将对其进行修复,以便它也可以工作 stdin 是一个文件。再次感谢您的解释。
      • getchar() 的结果(与std::cin::get() 相同)在测试前必须分配给int,而不是char;否则,您将无法检测到文件结尾。他可以做到:for ( int c = getchar(); c != EOF &amp;&amp; c != '\n'; c = getchar() )。如果他想保留cchar,他可以做到while ( std::cin.get( c ) &amp;&amp; c != '\n' )。当然,在这两种情况下,他都必须自己处理行中的空白,因为它不会被剥离。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-17
      • 2013-07-31
      • 1970-01-01
      • 1970-01-01
      • 2017-10-18
      • 2011-08-18
      • 2023-03-06
      相关资源
      最近更新 更多