在 while 循环中使用 scanf

发布于 2024-09-04 00:10:13 字数 313 浏览 3 评论 0原文

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

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

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

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

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

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

Probably an extremely simple answer to this extremely simple question:

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

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

滥情稳全场 2024-09-11 00:10:13

在 C 中,0 被评估为 false,其他所有值都被评估为 true。因此,如果 scanf 返回 EOF(负值),则循环将计算为 true,这不是您想要的。

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.

勿忘初心 2024-09-11 00:10:13

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

如果 scanf 期望多个输入,那么一目了然......

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

将在第一次无法匹配两个值时退出循环,或者由于文件结束文件(scanf 返回 EOF(即 -1))或输入匹配错误(例如,输入 xyzzy 42%d %d 不匹配code> ,因此 scanf 在第一次失败时停止并返回 0 ,而不写入 xy)返回一些小于 2 的值。

当然,在解析普通人的真实输入时,scanf 不是你的朋友。它在处理错误情况时存在很多陷阱。

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

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

我再怎么强调也不为过,scanf 不是你的朋友。 fgetssscanf 的组合可能足以进行一些简单的解析,但即使如此,它也很容易被边缘情况和错误所淹没。

Since scanf returns 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.

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

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 (scanf returns EOF (which is -1)) or on input matching error (e.g. the input xyzzy 42 does not match %d %d so scanf stops on the first failure and returns 0 without writing to either x or y) when it returns some value less than 2.

Of course, scanf is not your friend when parsing real input from normal humans. There are many pitfalls in its handling of error cases.

Edit: Corrected an error: scanf returns EOF on end of file, or a non-negative integer counting the number of variables it successfully set.

The key point is that since any non-zero value is TRUE in 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.

And I cannot emphasize strongly enough that scanf is not your friend. A combination of fgets and sscanf might be enough for some simple parsing, but even then it is easily overwhelmed by edge cases and errors.

讽刺将军 2024-09-11 00:10:13

您正确理解了 C 代码。

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

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

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

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

You understood the C code correctly.

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.

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.

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.

貪欢 2024-09-11 00:10:13

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

首先,通过与 1 进行比较,它变成一个显式的布尔值(true 或 false)。如果没有比较,您将测试一个整数,这在 C 中有效,但在后来的语言(如 C#)中无效。

其次,有些人会用 while([function]) 而不是 while([return value]) 来阅读第二个版本,并且当明确的意思是测试返回值时,会因为测试函数而暂时感到困惑。

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

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#).

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.

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

够运 2024-09-11 00:10:13

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

另外,通常可以省略的比较通常是与的比较。当您想要省略与其他内容的比较时(例如本例中的 1),最好三思而后行并确保您知道自己在做什么(再次参见 JRL 的答案)。

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

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.

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 1 in this case) it is better to think twice and make sure you know what your are doing (see the JRL's answer again).

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文