简体   繁体   English

在while循环中使用scanf

[英]Using scanf in a while loop

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? == 1真的有必要吗? 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. 似乎相等测试是不必要的,因为scanf返回读取的对象数,1将使while循环为真。 Is the reason to make sure that the number of elements read is exactly 1 or is this totally superfluous? 是确保读取的元素数量正好为1还是完全多余的原因?

In C, 0 is evaluated to false and everything else to true. 在C中,0被评估为false,其他一切被评估为true。 Thus, if scanf returned EOF, which is a negative value, the loop would evaluate to true, which is not what you'd want. 因此,如果scanf返回EOF,这是一个负值,则循环将评估为true,这不是您想要的。

Since scanf returns the value EOF (which is -1) on end of file, the loop as written is correct. 由于scanf在文件末尾返回值EOF(-1),因此写入的循环是正确的。 It runs as long as the input contains text that matches %d , and stops either at the first non-match or end of file. 只要输入包含与%d匹配的文本,它就会运行,并在文件的第一个不匹配或结尾处停止。

It would have been clearer at a glance if scanf were 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 ( scanf returns EOF (which is -1)) or on input matching error (eg 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. 当第一次无法匹配两个值时,将退出循环,这可能是由于文件结束( scanf返回EOF(-1))或输入匹配错误(例如输入xyzzy 42不匹配) %d %d因此scanf在第一次失败时停止,并在返回某个小于2的值时返回0 而不写入xy )。

Of course, scanf is not your friend when parsing real input from normal humans. 当然,在解析来自普通人的真实输入时, scanf 不是你的朋友。 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. 编辑:更正了错误: scanf在文件末尾返回EOF ,或者计算其成功设置的变量数的非负整数。

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. 关键点在于,由于C中的任何非零值都为TRUE ,因此无法在循环中正确测试返回值,这很容易导致意外行为。 In particular, while(scanf(...)) is an infinite loop unless it encounters input text that cannot be converted according to its format. 特别是, while(scanf(...))是一个无限循环,除非它遇到无法根据其格式转换的输入文本。

And I cannot emphasize strongly enough that scanf is not your friend. 而且我不能强烈强调scanf 不是你的朋友。 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. fgetssscanf组合可能足以进行一些简单的解析,但即使这样,它也很容易被边缘情况和错误所淹没。

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. 有时,测试读取的项目数量的原因是,当输入与预期类型不匹配时,有人希望确保所有项目都被读取而不是提前退出scanf。 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. 通常,scanf是功能较差的选择,因为它不能满足人类用户的交互输入需求。 Usually a combination of fgets and sscanf yield better results. 通常fgets和sscanf的组合会产生更好的结果。 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. 如果scanf返回-1,则执行while循环。

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). 首先,通过比较1,它成为一个显式的布尔值(true或false)。 Without the comparison, you are testing on an integer, which is valid in C, but not in later languages (like C#). 如果没有比较,您将测试一个整数,该整数在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([返回值]),并且通过测试函数暂时会混淆,当显然意味着测试返回值时。

This can be completely a matter of personal preference, and as far as I'm concerned, both are valid. 这完全取决于个人偏好,就我而言,两者都是有效的。

One probably could write it without an explicit comparison (see the JRL's answer though), but why would one? 有人可能会在没有明确比较的情况下编写它(虽然参见JRL的答案),但为什么会这样呢? I'd say that comparison-less conditions should only be used with values that have explicitly boolean semantics (like an isdigit() call, for example). 我会说无比较条件只应该用于具有显式布尔语义的值(例如,像isdigit()调用)。 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. 在这种情况下( 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 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). 如果你觉得省略与其他东西比较的冲动(比如在这种情况下为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. 如果您担心的话,它对结果代码的效率绝对没有影响。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM