C++程序无法进入for循环

4

好的,下面是给您翻译的代码部分,它给我带来了一个问题。我想让它接受一个成绩,判断它是否为有效的成绩,如果不是则继续要求输入有效数字。然而,它甚至不会进入循环,所以... 有什么建议吗?我已经编程了一段时间,但我还是很新,所以额外的解释非常好!此外,这是我第一次在for循环中使用布尔值。

for (bool b_valid=false; b_valid=false ; )
{
cin >> n_grade;
b_valid = true;
    if (n_grade>100 || n_grade<0)
        {
            cout << "Invalid grade: Re-enter a number between 0-100 : " << endl;
            cin >> n_grade;
            b_valid = false;
        }
}

你是说你的程序告诉你它甚至没有进入这个for循环吗?因为这就是问题标题所说的,但我并不真正理解你的问题。 - ihtkwot
1
如果你正在使用gcc编译器,建议加上-Wall参数进行编译。 - Karoly Horvath
1
如果我输入900、90、900、90、900、90、900、90(无限循环),代码将永远不会终止。你正在丢弃一半的输入。 - Ben Voigt
真的,你很敏锐!我在将等号改为双等号后运行了几次程序后就能够解决这个问题了!谢谢你!此外,我还注意到,如果重新输入的数字不在0-100之间,那么我还需要进行另一个无意义的输入,所以我也修复了这个问题! - samuraiseoul
如果你读了编译器生成的警告,它会告诉你这是错误的。确保编译时没有任何警告(警告是编译器告诉你代码中存在逻辑错误的方式)。同时将警告级别设置高于默认值。 - Martin York
我的编译器没有发出任何警告。 - samuraiseoul
7个回答

15
你的条件语句是一个赋值语句:b_valid=false。它会被解析为false,循环将永远不会执行。你的意思应该是:

```python if b_valid == False: # do something ```

for(bool b_valid = false; b_valid == false; )
                                 ^^^^ 

有一种编码风格规定,在比较操作中常量应该是第一个参数,例如 if(false == b_valid)。在这种情况下,如果您意外地键入了 = ,您将得到一个编译错误。无论如何,许多编译器都会在您写下赋值而期望布尔表达式的情况下给出警告。要么您使用的编译器不够复杂,要么您忽略了警告。


1
发牢骚:我鄙视那种编程标准。真的很鄙视它。在我有影响力制定标准的项目中,那个规则被取消了。在我没有影响力的项目中,我会忽略那个规则(并告诉我的团队成员也这样做),让审核者见鬼去吧。最终,这个规则会被废除。 - David Hammen
1
@Ben:“这里的条件已经是布尔类型了”:变量已经是布尔类型了。不要将布尔类型与true或false进行比较。 - David Hammen
编码风格在十年前就已经被弃用了(真的很糟糕),它使代码更难阅读。所有编译器都会为此生成警告。只需将编译器设置为将警告视为错误进行编译(因为它们确实是逻辑错误,需要修复),现在当你忽略这个问题时,你的代码将无法编译。 - Martin York
@Ben:认为条件 必须 包括比较是一个常见的错误。在我能够影响标准的项目中,我确保将Konrad的规则作为一条规则添加--然后解释程序员应该做什么。由于某种原因,工程师和科学家很难理解这个概念--但之后他们会明白。 - David Hammen
我在大学学到的一件事就是所谓的Yoda逻辑。养成这样的习惯,写语句时像这样写false = b_valid而不是b_valid = false,编译器肯定会在false = b_valid这行抛出编译时错误,因为你试图给false赋值。 - Scott Chamberlain
显示剩余4条评论

11

我不同意其他(被过分点赞的)答案。

不要将布尔值与truefalse进行比较。

这是毫无意义、冗余且会导致错误(就像在你的情况中一样)。

只需测试值本身。也就是说,写 ! b_valid

此外,在这里使用for循环实际上是误导性的。改用while

while (! b_valid) {
    …
}

1
在这里使用while循环是非常误导人的(直到你测试第一组数据之前,它既不是有效的也不是无效的)。改用do/while循环。 - Ben Voigt
@Ben 你可以认为(我确实…)在有效输入之前,它是无效的。因此,通过推断,默认状态是无效的。我真的看不出do...while在这里的优势。 - Konrad Rudolph
+1(如果可以的话,还有+Inf)对于“不要将布尔值与true或false进行比较”。 - David Hammen

8
你在循环条件中使用了赋值运算符('='),应该使用相等运算符('=='):
for (bool b_valid=false; false==b_valid; )

3
for( a; b; c ) { body; }

除了范围不同外,它与原来的相同。

a;
while (b) {
   body;
   c;
}

让我们为你的代码做这件事:
bool b_valid=false;
while (b_valid = false) { // uh-oh

我们不必深入探讨。这是一项任务,而不是比较。它将 b_valid 设置为 false,然后检查它是否为 true。由于它永远不会是 true,因此循环永远不会执行。

但您真正想要的是一个 do/while 循环:

bool b_valid;
do {
    cin >> n_grade;
    if ( n_grade>100 || n_grade<0 ) {
        cout << "Invalid grade: Re-enter a number between 0-100 : " << endl;
        // let the next pass through the loop re-read n_grade
        b_valid = false;
    }
    else {
        b_valid = true;
    }
} while (!b_valid);

do-while循环总是至少运行一次。


但是在for循环中,它总是会运行一次,对吧?至少在以下情况下: for (bool b_value: b_value == false ; ) 是这样的吗? - samuraiseoul
1
@Samurai:没错。控制变量也可以命名为rainbow,同样可以工作。由于这三个循环在技术上是等效的,所以选择具有表达性组件,可以记录未来开发人员的意图。在这种情况下,do-while是正确的,因为意图是“做这个;并在输入无效时重复”。 - Ben Voigt

2
等值比较运算符是==。现在你的条件是b_valid=false,这只会返回false

1

= 是赋值运算符
== 是比较运算符

所以你的 for 循环约束条件没有检查任何东西...

或者使用 while 循环:

bool b_valid = false;
cin >> n_grade;
while(!b_valid){
   if(n_grade>100 || n_grade<0) {
      b_valid = true;
   } else {
      cout << "Invalid grade: Re-enter a number between 0-100 : " << endl;
      cin >> n_grade;   
   }
}

似乎有很多建议使用while循环。是否有while循环更好的原因? - samuraiseoul
1
由于它被设计为循环直到一个值变为真,所以使用它比使用for循环更合适... 即使你大声说出来,使用while比for更有意义 :) - Hoof

1
你可以将代码重构为 while 循环。例如:
bool b_valid = false;
while( !b_valid )
{
    cin >> n_grade;
    b_valid = true;
    if (n_grade>100 || n_grade<0)
    {
        cout << "Invalid grade: Re-enter a number between 0-100 : " << endl;
        cin >> n_grade;
        b_valid = false;
    }
}

使用while循环相比for循环有额外的好处吗? - samuraiseoul
1
条件判断写反了,循环应该在数据无效时重复执行,但这个却在无效时退出了。 - Ben Voigt
谢谢Voigt,愚蠢的错误。@Samurai,while循环对于你的特定情况似乎更加清晰。for和while循环总是可以互换(几乎总是,因为我想不出为什么不能互换),正如@Ben Voigt所指出的,您还可以使用do...while循环来确保它至少执行一次。 - ihtkwot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接