C中的文件结尾(EOF)


68

我目前正在阅读Ritchie&Kernighan撰写的《 C编程语言》一书。对于getchar()函数中EOF的使用,我感到很困惑。

首先,我想知道为什么EOF的值为-1,为什么EOF的值为getchar()!=EOF0。请原谅我的问题,但我真的不明白。我确实尝试过,但不能。

然后,我尝试在书上运行可以使用以下代码计数字符数的示例,但即使按回车键,我也似乎永远不会循环,所以我想知道何时到达EOF?

然后,我在C中的EOF问题中阅读了相同的问题。大多数人建议不要使用EOF,而应使用终止符\ n或空终止符'\ 0',这很有意义。

这是否意味着书中的示例还有其他目的?


6
您知道您提到的书是C语言的原始作者编写的,对吗?
David Gelhar 2010年

Answers:


93

EOF表示“文件结束”。换行符(也就是当你按回车键会发生什么)不是结束文件,这是一个结束,因此换行符不会终止这个循环。

代码没有错[*],只是没有按照您的期望做。它读到输入的末尾,但是您似乎只想读到一行的末尾。

EOF的值是-1,因为它必须与任何返回值都不同,因为返回值getchar是实际字符。因此,getchar将任何字符值作为无符号char返回,转换为int,因此将为非负数。

如果要在终端上键入文件并希望引起文件结尾,请使用CTRL-D(unix风格的系统)或CTRL-Z(Windows)。然后,在读取完所有输入之后,getchar()将返回EOF,因此getchar() != EOF将为false,并且循环将终止。

[*]好吧,如果由于整数溢出而导致输入的字符数超过LONG_MAX个,则它具有未定义的行为,但是在一个简单的示例中我们可以原谅。


我现在知道问题了..这就是为什么我看不到结果的原因..那是因为我使用的是Dev-C ++并且它没有system(“ pause”),所以我需要在代码末尾键入。
新手

4
实际上,CTRL + D不会引发EOF。它只是终止您的终端,这又使内核知道无法再读取任何字节,因此标准输入文件描述符中没有可用数据。
Koray Tugay 2015年

@newbiesystem函数创建一个新的shell并运行传递给它的命令。该命令由系统外壳执行,与编译器
无关-phuclv

如果您按下返回键“ enter”,“ getchar()”,则只能看到一个字符,并且您的“ nc”变量增加了。
EsmaeelE

18

EOF为-1,因为这是它的定义方式。该名称由您提供的标准库头提供#include。它们使它等于-1,因为它必须是不能被读取的实际字节错误的东西getchar()getchar()使用正数(0到255,包括上限)报告实际字节的值,因此-1可以正常工作。

!=运营商表示“不等于”。0代表假,其他代表真。所以发生了什么,我们调用getchar()函数,并将结果与​​-1(EOF)比较。如果结果不等于EOF,则结果为true,因为不相等的事物不相等。如果结果等于EOF,则结果为false,因为相等的事物不相等(不相等)。

getchar()到达“文件结尾”时,对EOF的调用将返回EOF。就C而言,“标准输入”(通过在命令窗口中键入来提供给程序的数据)就像一个文件。当然,您总是可以键入更多内容,因此您需要一种明确的方式来说“我完成了”。在Windows系统上,这是control-Z。在Unix系统上,这是control-D。

书中的例子不是“错误的”。这取决于您实际想要做什么。阅读直到EOF意味着您阅读了所有内容,直到用户说“我完成了”,然后您再也无法阅读了。读到'\ n'表示您读了一行输入。如果希望用户键入输入内容,请读到'\ 0'是个坏主意,因为在命令提示符下用键盘产生此字节很困难或不可能:)


9

有很多问题。

  1. 为什么EOF为-1:通常在错误时返回POSIX系统调用中的-1,所以我想这个想法是“ EOF是一种错误”

  2. 如果为TRUE,则任何布尔运算(包括!=)都将返回1,如果为FALSE,getchar() != EOF则返回0;如果为FALSE,则返回0 0,这意味着getchar()返回EOF

  3. 为了模仿新闻EOF阅读stdinCtrl+D


布尔运算返回true的非零值和false的非零值。有区别。
我的正确意见,2010年

7
否,运算符被定义为返回1。在布尔上下文中(例如,if()orwhile()条件)任何非零值均为“ true” 。
David Gelhar 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.