【问题标题】:Why this code cause an infinity loop when '|' is entered in C++?为什么此代码在“|”时会导致无限循环在 C++ 中输入?
【发布时间】:2018-03-15 03:49:00
【问题描述】:

我正在阅读编程:使用 C++ 的原理和实践(第 2 版)
我发现了这个问题:

  • 编写一个包含 while 循环的程序,该循环(每次围绕循环)读取两个 整数,然后打印它们。终止时退出程序'|'已输入。

这是我尝试过的:

#include <iostream>
using namespace std;
int main () {
int x, y;
while (x != '|' || y != '|'){
    cin >> x;
    cin >> y;
    cout << x << endl;
    cout << y << endl;
}

return 0;
}

当'|'输入时,它会打印类似无限循环、意外输出的内容。

  • 那里发生了什么?
  • 我做错了什么?

【问题讨论】:

  • 您的代码显示“虽然 x 不等于 '|' or y 不等于 '|'..." 这意味着两个变量都必须是 '|'为了让循环中断。
  • 另外,xy 是整数,而不是字符。它们不能是“|”。使用cin.peek() 检查“|”在输入之前。
  • 您的代码有未定义的行为:您正在尝试使用 xy 而不将它们初始化为任何内容。
  • @FeiXiang 它说读取两个整数,使用while循环。不是字符串先生。
  • 使用&amp;&amp; 而不是||。并考虑改用do..while 循环。

标签: c++ loops cin


【解决方案1】:

首先,在将while 循环中的'|''|' 进行比较之前,您尚未将xy 设置为任何值。这意味着它们可能具有 任意 值,并且您的循环甚至可能不会开始。


至于为什么你会看到一个无限循环,因为变量的类型是intcin &gt;&gt; something 会尝试将你输入的字符翻译成 em> 一个整数并将其放入变量中。

如果这些字符的初始序列不是形成一个有效的整数(例如,它是| 字符),cin &gt;&gt; 将失败,变量将保持不变,并且输入流将保持原样。

因此,当您再次获取下一个整数时,| 在输入流中仍然,并且将再次发生完全相同的事情,无穷无尽 - 请注意拉丁语之间的相似性短语和你的问题标题:-)


您可以做的解决方法是尝试逐个字符地向前看,看看您是否在流中具有|。如果是这样,只需退出。如果没有,请尝试使用普通的if (stream &gt;&gt; variable) 方法获取两个整数。

这可以通过cin.peek() 来检查下一个字符,cin.get() 来删除一个字符。您还必须考虑到peekget 都不会像operator&gt;&gt; 那样跳过空白。

这样的事情应该是一个好的开始:

#include <iostream>
#include <cctype>

int main() {
    int x, y;

    while (true) {
        // Skip all white space to (hopefully) get to number or '|'.

        while (std::isspace(std::cin.peek())) std::cin.get();

        // If it's '|', just exit, your input is done.

        if (std::cin.peek() == '|') break;

        // Otherwise, try to get two integers, fail and stop if no good.

        if (! (std::cin >> x >> y)) {
            std::cout << "Invalid input, not two integers\n";
            break;
        }

        // Print the integers and carry on.

        std::cout << "You entered " << x << " and " << y << "\n";
    }

    return 0;
}

使用各种测试数据表明它涵盖了所有情况(我能想到的):

pax$ ./myprog </dev/null
Invalid input, not two integers

pax$ echo hello | ./myprog
Invalid input, not two integers

pax$ echo 1 | ./myprog
Invalid input, not two integers

pax$ echo 1 2 | ./myprog
You entered 1 and 2
Invalid input, not two integers

pax$ printf '1 2|' | ./myprog
You entered 1 and 2

pax$ printf '1 2\n3 4\n5     6 7   8   \n|' | ./myprog
You entered 1 and 2
You entered 3 and 4
You entered 5 and 6
You entered 7 and 8

pax$ printf '1 10     11   12   13    14    |   ' | ./myprog
You entered 1 and 10
You entered 11 and 12
You entered 13 and 14

【讨论】:

  • 对不起,我不明白什么是测试数据。我是初学者先生。
  • @DarinBenas,测试数据是您用来测试程序的数据 :-) 最后的部分显示了各种测试用例(echoprintf 声明)。您可以只运行程序并自己输入值,但前提是自动化测试通常更有用。
【解决方案2】:

正如人们在 cmets 和 paxdiablo 的回答中指出的那样,您是两个未初始化的变量,您正在尝试输入 int,然后将其与 char 进行比较。

我们可以使用cin.peek() 来查看下一个字符并检查它是否是'|',而不是尝试将输入的 int 与 char 进行比较在阅读之前。

#include <iostream>
int main()
{
    int x, y;
    while(std::cin.peek() != '|') //cin.peek() will return the next character to be read
    {
        std::cin >> x >> y;
        std::cout << x << ' ' << y << '\n';
        std::cin.ignore(); //ignore whitespace/linebreak character left by extraction (>> operator)
    }
}

【讨论】:

  • cin 状态应该被检查。对于非整数输入,这是一个无限循环。顺便说一句,不是反对者....
  • 为了完整起见,您可能需要查看空白处理。问题是peek 不会跳过空白行cin &gt;&gt; someInt 会,所以输入&lt;space&gt;| 会导致问题。您的答案(包括单字符 ignore)似乎假设 no 有多余的空白。此外,检查cin &gt;&gt; 的结果以确保其正常运行也不是一个好主意(与在C 中检查scanf 的返回值相同)。
  • @paxdiablo 我通常假设输入在我的示例程序中格式正确,否则,您最终会得到一些不相关的代码,使人们感到困惑。例如,OP 可能不明白为什么if(!(cin &gt;&gt; x)) 检查输入是否失败。对于其他程序,这可能是检查输入是否在范围内的代码。不过,这只是我的看法。
【解决方案3】:

因为您将 x , y 定义为整数,但您将输入输入为 char。 试试这段代码

#include <iostream>
using namespace std;
int main ()
{
    char x=NULL, y=NULL;
    while (x != '|' || y != '|')
    {
        cin >> x;
        cin >> y;
        cout << x << endl;
        cout << y << endl;
    }

    return 0;
}

但它也有局限性。您只能将输入作为单个数字。如果您想输入大数字,请尝试这个

#include <iostream>
using namespace std;
int main ()
{
    string  x="", y="";
    while (x != "|" || y != "|")
    {
        cin >> x;
        cin >> y;
        cout << x << endl;
        cout << y << endl;
    }

    return 0;
}

【讨论】:

    猜你喜欢
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多