C语言 在 while 循环中使用 scanf

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2970880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:35:05  来源:igfitidea点击:

Using scanf in a while loop

cwhile-loopequalityscanf

提问by Tyler Brock

Probably an extremely simple answer to this extremely simple question:

对于这个极其简单的问题,可能是一个极其简单的答案:

I'm reading "C Primer Plus" by Pratta and he keeps using the example

我正在阅读 Pratta 的“C Primer Plus”,他一直在使用这个例子

while (scanf("%d", &num) == 1)...

Is the == 1 really necessary? It seems like one could just write:

== 1 真的有必要吗?似乎可以只写:

while (scanf("%d", &num))

It seems like the equality test is unnecessary since scanf returns the number of objects read and 1 would make the while loop true. Is the reason to make sure that the number of elements read is exactly 1 or is this totally superfluous?

似乎相等测试是不必要的,因为 scanf 返回读取的对象数,而 1 将使 while 循环为真。是确保读取的元素数量恰好为 1 的原因还是完全多余?

回答by JRL

In C, 0 is evaluated to false and everything else to true. Thus, if scanf returned EOF, which is a negative value, the loop would evaluate to true, which is not what you'd want.

在 C 中,0 被评估为假,其他一切都为真。因此,如果 scanf 返回 EOF,这是一个负值,循环将评估为真,这不是您想要的。

回答by RBerteig

Since scanfreturns the value EOF (which is -1) on end of file, the loop as written is correct. It runs as long as the input contains text that matches %d, and stops either at the first non-match or end of file.

由于scanf在文件末尾返回值 EOF(即 -1),因此写入的循环是正确的。只要输入包含匹配的文本,它就会运行%d,并在第一个不匹配或文件末尾停止。

It would have been clearer at a glance if scanfwere expecting more than one input....

如果scanf期待多个输入,一目了然会更清楚......

while (scanf("%d %d", &x, &y)==2) { ... }

would exit the loop when the first time it was unable to match two values, either due to end of file end of file (scanfreturns EOF (which is -1)) or on input matching error (e.g. the input xyzzy 42does not match %d %dso scanfstops on the first failure and returns 0 without writing to either xor y) when it returns some value less than 2.

当第一次无法匹配两个值时会退出循环,要么是由于文件结尾的文件结尾(scanf返回 EOF(即 -1)),要么是输入匹配错误(例如输入xyzzy 42不匹配%d %d所以scanf停止第一次失败并在返回小于 2 的某个值时返回 0而不写入任何一个xy)。

Of course, scanfis notyour friend when parsing real input from normal humans. There are many pitfalls in its handling of error cases.

当然,在解析来自正常人类的真实输入时,scanf不是你的朋友。它在处理错误情况时存在许多陷阱。

Edit:Corrected an error: scanfreturns EOFon end of file, or a non-negative integer counting the number of variables it successfully set.

编辑:更正了一个错误:在文件末尾scanf返回EOF,或者一个非负整数,计算它成功设置的变量数。

The key point is that since any non-zero value is TRUEin C, failing to test the return value correctly in a loop like this can easily lead to unexpected behavior. In particular, while(scanf(...))is an infinite loop unless it encounters input text that cannot be converted according to its format.

关键在于,由于任何非零值都TRUE在 C 中,因此未能在这样的循环中正确测试返回值很容易导致意外行为。特别是,while(scanf(...))除非遇到无法根据其格式转换的输入文本,否则是无限循环。

And I cannot emphasize strongly enough that scanfis notyour friend. A combination of fgetsand sscanfmight be enough for some simple parsing, but even then it is easily overwhelmed by edge cases and errors.

我不能强调足够强烈认为scanf不是你的朋友。的组合fgets以及sscanf可能足以为一些简单的解析,但即使如此,它很容易被边缘情况和错误不堪重负。

回答by Windows programmer

You understood the C code correctly.

您正确理解了 C 代码。

Sometimes the reason for testing the number of items read is that someone wants to make sure that all items were read instead of scanf quitting early when it the input didn't match the expected type. In this particular case it didn't matter.

有时测试读取的项目数的原因是有人想确保所有项目都被读取,而不是当输入与预期类型不匹配时 scanf 提前退出。在这种特殊情况下,这无关紧要。

Usually scanf is a poor choice of functions because it doesn't meet the needs of interactive input from a human user. Usually a combination of fgets and sscanf yield better results. In this particular case it didn't matter.

通常 scanf 是一个糟糕的函数选择,因为它不能满足人类用户交互输入的需求。通常 fgets 和 sscanf 的组合会产生更好的结果。在这种特殊情况下,这无关紧要。

If later chapters explain why some kinds of coding practices are better than this trivial example, good. But if not, you should dump the book you're reading.

如果后面的章节解释了为什么某些类型的编码实践比这个简单的例子更好,那很好。但如果没有,你应该放弃你正在阅读的书。

On the other hand, your substitute code isn't exactly a substitute. If scanf returns -1 then your while loop will execute.

另一方面,您的替代代码并不完全是替代品。如果 scanf 返回 -1,则您的 while 循环将执行。

回答by abelenky

While you are correct it is not strictly necessary, some people prefer it for several reasons.

虽然您是对的,但并非绝对必要,但有些人出于多种原因更喜欢它。

First, by comparing to 1 it becomes an explicit boolean value (true or false). Without the comparison, you are testing on an integer, which is valid in C, but not in later languages (like C#).

首先,通过与 1 进行比较,它变成了一个明确的布尔值(真或假)。如果没有比较,您将测试一个整数,该整数在 C 中有效,但在更高版本的语言(如 C#)中无效。

Secondly, some people would read the second version in terms of while([function]), instead of while([return value]), and be momentarily confused by testing a function, when what is clearly meant is testing the return value.

其次,有些人会根据 while([function]) 而不是 while([return value]) 来阅读第二个版本,并且对测试函数一时感到困惑,而这显然意味着测试返回值。

This can be completely a matter of personal preference, and as far as I'm concerned, both are valid.

这完全是个人喜好的问题,就我而言,两者都是有效的。

回答by AnT

One probably could write it without an explicit comparison (see the JRL's answer though), but why would one? I'd say that comparison-less conditions should only be used with values that have explicitly boolean semantics (like an isdigit()call, for example). Everything else should use an explicit comparison. In this case (the result of scanf) the semantics is pronouncedly non-boolean, so the explicit comparison is in order.

人们可能可以在没有明确比较的情况下编写它(尽管请参阅 JRL 的答案),但为什么会这样呢?我会说无比较条件应该只用于具有明确布尔语义的值(例如isdigit()调用)。其他一切都应该使用显式比较。在这种情况下( 的结果scanf)语义明显是非布尔值,因此显式比较是有序的。

Also, the comparison one can usually omit is normally a comparison with zero. When you feel the urge to omit the comparison with something else (like 1in this case) it is better to think twice and make sure you know what your are doing (see the JRL's answer again).

此外,通常可以省略的比较通常是与的比较。当您想要忽略与其他事物的比较时(例如1在这种情况下),最好三思而后行并确保您知道自己在做什么(再次参见 JRL 的回答)。

In any case, when the comparison can be safely omitted and you actually omit it, the actual semantical meaning of the condition remains the same. It has absolutely no impact on the efficiency of the resultant code, if that's something you are worrying about.

在任何情况下,当比较可以安全地省略而您实际上省略它时,条件的实际语义含义保持不变。如果您担心的话,它对结果代码的效率绝对没有影响。