需要一步一步地解释“while((ch = getchar())!='\ n'&& c!= EOF;”

时间:2017-09-17 08:58:42

标签: c stdin getchar

我知道这个问题已被提出;但它没有一步一步地解释,或者彻底解释它是如何被执行的;所以,假设我有这部分代码:

char ch;
while((ch = getchar()) != '\n' && ch != EOF);

getchar()是否将单个字符读入ch变量1st,然后进行比较,即ch != '\n' && ch != EOF,保留新行转义序列缓冲,但实际上不在ch变量中?如果是这样,这是不是意味着它会无限循环直到它遇到换行转义序列/ EOF?如果遇到换行转义序列,它是否存储在ch变量中?如果没有,怎么回事?

1 个答案:

答案 0 :(得分:7)

char ch;

首先,我们定义ch类型的char变量。

while((ch = getchar()) != '\n' && ch != EOF);

这是一个while循环。循环条件为(ch = getchar()) != '\n' && ch != EOF,循环体为;(空语句)。

循环条件包括&&(逻辑"和")和两个操作数(ch = getchar()) != '\n'ch != EOF&&运算符始终首先计算其左操作数。

(ch = getchar()) != '\n'是一种不平等比较。右侧是'\n'(表示换行符)。左侧是赋值表达式ch = getchar()

getchar()调用getchar函数,该函数从stdin(标准输入)读取字符。如果成功,则以unsigned char的形式返回此字符(通常在0 ... 255范围内);否则(如果getchar失败)它返回EOF(这是一个(特定于实现的)负值)。这就是getchar的返回类型为int的原因:它需要将所有有效字符值表示为错误指示符。

此值存储在ch中。此时,有两种可能性:

  1. char是您的实施中的无符号类型。在这种情况下,每个成功读取的字符都按原样存储,但EOF将映射到某个正常字符。如果(通常情况下)EOF的值为-1,则最终会变为UCHAR_MAX(通常为255)。

  2. char是您实施中的签名类型。在这种情况下,所有可能的字符值中有一半超出范围(通常签名char的范围为-128 .. 127,并且无法存储128 ... 255的值。这里的事情有点模糊:超出范围的字符将导致(实现定义的)信号或将转换为其他(实现定义的)字符。另一方面,EOF可能会保留原样(除非它的值小于CHAR_MIN,在这种情况下,您获得实现定义的信号或转换,如前所述)。

  3. 赋值表达式具有赋值后左操作数的值。因此(ch = getchar())返回ch的新值(如上所述,它是输入字符的修改)。我们将此字符与'\n'(换行符)进行比较。如果是换行符,!=会产生错误,&&会立即产生错误,并且循环停止。 (请注意,根据您的实现,其他字符甚至EOF可能会被错误检测为'\n',因为上面描述了错误。)

    如果输入字符不是换行符,!=将返回true,&&继续评估其右侧操作数。在这里,我们比较ch != EOF。如果我们遇到#1(即char是无符号类型),则此比较始终为真,因为EOF是负值(除非我们处于更奇特的情况并且{{1} } / char具有相同大小/范围的可能值,我不打算这样做。如果我们遇到#2(即int是签名类型),如果char返回getchar(即输入的结束已达到或者是{1}},则此比较将返回false发生错误),循环停止。它也会将某些字符(通常为EOF,255)误识别为UCHAR_MAX

    否则(即EOF不是ch'\n')循环重复,读取并检查下一个字符。

    此代码的目的是使用和丢弃输入,直到达到换行符或输入结束。

    但由于编写代码的方式,实际上它不会识别EOF(因此在到达输入结尾时永远循环)或将有效输入视为EOF(和因此早点结束。)

    修复方法是将EOF声明为ch

    int