【问题标题】:infinite loop in c++ [duplicate]C ++中的无限循环[重复]
【发布时间】:2010-09-20 23:13:19
【问题描述】:

我正在学习 C++ 并编写一些小程序。下面是一个这样的程序:

// This program is intended to take any integer and convert to the
// corresponding signed char.

#include <iostream>

int main()
{
  signed char sch = 0;
  int n = 0;
  while(true){
    std::cin >> n;
    sch = n;
    std::cout << n << " --> " << sch << std::endl;
  }
}

当我运行这个程序并将输入保持在相当小的绝对值时,它的行为与预期一样。但是当我输入更大的输入时,例如 10000000000,程序会重复输出相同的输出。某些输入组合会导致行为不稳定。例如:

#: ./int2ch
10
10 --> 

10000000000
10 -->

10 -->

10 -->

10 -->

程序吐出“10 -->”直到它被杀死。 (在这种特殊的输入序列下,程序的输出速度会发生不规律的变化。)我还注意到,大值的输出取决于先前的合法输入以及当前非法输入的值。

发生了什么事? (我不关心修复程序,这很容易。我想了解它。)

【问题讨论】:

    标签: c++ stream infinite-loop biginteger largenumber


    【解决方案1】:

    假设您使用的是 32 位机器,10000000000 是一个太大的数字,无法用 int 表示。此外,将 int 转换为 char 只会给你 0..255 或 -128..127 ,具体取决于编译器。

    【讨论】:

    • 实际上是 0..255 或 -128..127。 :)
    【解决方案2】:

    基本上,您的cin 流处于失败状态,因此当您尝试读取它时会立即返回。像这样重写你的例子:

    #include <iostream>
    
    int main()
    {
      signed char sch = 0;
      int n = 0;
      while(std::cin >> n){
        sch = n;
        std::cout << n << " --> " << sch << std::endl;
      }
    }
    

    cin &gt;&gt; n 将返回对cin 的引用,您可以在条件中测试它是否“良好”。所以基本上“while(std::cin &gt;&gt; n)”是在说“虽然我仍然可以成功地从标准输入中读取,但请执行以下操作”

    编辑:它重复输出最后输入的好值的原因是因为那是最后一个成功读取 n 的值,失败的读取不会改变 n 的值

    编辑:如评论中所述,您可以清除错误状态并重试,这样可能会起作用,而忽略错误的数字:

    #include <iostream>
    #include <climits>
    
    int main() {
        signed char sch = 0;
        int n = 0;
        while(true) {
            if(std::cin >> n) {
                sch = n;
                std::cout << n << " --> " << sch << std::endl;
            } else {
                std::cin.clear(); // clear error state
                std::cin.ignore(INT_MAX, '\n'); // ignore this line we couldn't read it
            }
        }
    }
    

    【讨论】:

    • 或者,在下一次循环之前调用 std::cin.clear() 以消除错误状态。
    【解决方案3】:

    这里的一个问题是char 的大小为一个字节,因此只能容纳 -127 到 128 之间的数字。另一方面,int 通常为 4 个字节,并且可以占用更大的值。第二个问题是您输入的值对于int 来说太大了。

    【讨论】:

    • 首先打印“一些奇怪的字符”不是原因,其次一个字符默认没有签名,这取决于编译器。它经常签名,但不需要。
    【解决方案4】:

    是的,Evan Teran 已经指出了大部分内容。我想补充的一件事(因为我还不能评论他的评论:))是您必须在调用 istream::ignore 之前调用 istream::clear 。原因是如果流仍处于失败状态,istream::ignore 同样会拒绝执行任何操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-06
      • 2020-12-25
      • 1970-01-01
      • 2012-03-06
      • 2014-03-09
      • 1970-01-01
      • 2013-05-21
      相关资源
      最近更新 更多