C 编程语言中的 EOF 是什么?

What is EOF in the C programming language?

提问人:Chris_45 提问时间:11/23/2009 最后编辑:UndoChris_45 更新时间:6/19/2019 访问量:207499

问:

你怎么能看到最后的印刷品?换句话说,EOF要放什么?我检查了定义,它说EOF是-1。

如果你输入Ctrl-D,你不会看到任何东西。

#include <stdio.h>

int main() {
 int c;
 while((c = getchar() != EOF)) {
  printf("%d\n", c);
 }
 printf("%d - at EOF\n", c);
}
C 输入 EOF

评论

0赞 qrdl 11/23/2009
你介意澄清一下吗?你的问题是什么?
0赞 Chris_45 11/23/2009
我想输入 EOF 并查看 printf(“%d - at EOF\n”, c);
0赞 Chris_45 11/23/2009
EOF 据说是 -1,但它将其解释为三个字符并输出三个 1
3赞 Lucas 11/23/2009
@reinierpost:C 语言中的 EOF 是 stdio.h 中定义的宏。
6赞 Koray Tugay 1/14/2015
我发现这非常有用:latedev.wordpress.com/2012/12/04/all-about-eof

答:

3赞 Ikke 11/23/2009 #1

EOF 表示文件结束。这表明已到达文件末尾,并且将不再有数据。

编辑:

我纠正了。在这种情况下,它不是文件的结束。如前所述,当 CTRL+d (linux) 或 CTRL+z (windows) 被传递时,它会被传递。

评论

0赞 William Pursell 1/10/2013
编辑不正确。短语“当 CTRL+d...是[按下]“是无稽之谈。当用户键入 ctrl-D 时,输入文件将关闭并返回 EOF 以指示已到达文件末尾。没有发送到进程的 EOF 字符。getchar
0赞 Koray Tugay 1/11/2015
你说这是一个标志吗?它是特定的位模式吗?
0赞 Stephen C 4/16/2020
他的意思是正常(非 IT、非数学)意义上的符号;即指示。狗摇尾巴表示它很开心。
11赞 Stephen C 11/23/2009 #2

EOF 的值是一个负整数,以区别于 0 到 255 范围内的“char”值。它通常是 -1,但它可能是任何其他负数......根据 POSIX 规范,因此您不应假设它是 -1。

^D 字符是在 UNIX/Linux 上的控制台流中键入的字符,用于告诉它在逻辑上结束输入流。但在其他上下文中(例如,当您从文件中读取时),它只是另一个数据字符。无论哪种方式,^D 字符(表示输入的结尾)都不会出现在应用程序代码中。

正如 @Bastien 所说,如果失败,也会返回 EOF。严格来说,您应该调用 或 查看 EOF 是否表示错误或流结束。但在大多数情况下,无论哪种情况,您的应用程序都会执行相同的操作。getchar()ferrorfeof

评论

0赞 Chris_45 11/23/2009
所以你永远不能让 win32 上的 EOF 进入应用代码并看到最后的打印?
0赞 Stephen C 11/24/2009
@Chris_45 - 我说的是EOF的含义。你的“appcode”中错误的根本原因是完全不同的东西——看@Lucas的回答,
56赞 Carl Smotricz 11/23/2009 #3

在 Linux 系统和 OS X 上,要输入以导致 EOF 的字符为 -。对于 Windows,它是 -。CtrlDCtrlZ

根据操作系统的不同,此字符仅在它是一行上的第一个字符(即 .由于控制台输入通常是面向行的,因此系统也可能无法识别 EOF 字符,直到您使用 .EnterEnter

是的,如果该字符被识别为 EOF,那么您的程序将永远不会看到实际字符。相反,C 程序将从 .-1getchar()

评论

0赞 Chris_45 11/23/2009
好的,但是 Windows 上的 Ctrl-z 和 Ctrl-D 有什么区别?Ctrl-z = EFO Ctrl-D = 杀死?
0赞 Carl Smotricz 11/23/2009
@Chris_45:在 Windows 上,Ctrl-Z 标记 EOF,Ctrl-D 只是 Ctrl-D(或字符 04)。@gotch4:它是标准的(但很少使用)HTML:< kbd >。
1赞 Clifford 11/23/2009
@Chris_45:Ctrl-D 对应于 ASCII EOT(传输结束),但 MS-DOS 使用 Ctrl-Z (ASCII SUB) 与 CP/M 兼容,Windows 继承了这一点。在 CP/M 中,EOF 字符实际上是文件中的一个字符,因为所有文件都必须是 128 个字符的倍数。用于发出 EOF 信号的字符特定于操作系统,而不是编程语言。en.wikipedia.org/wiki/End-of-file
0赞 Chris_45 11/23/2009
好吧,我的意思是 Ctrl-Z 和 Ctrl-C 之间的区别?不是 Ctrl-d
4赞 Carl Smotricz 11/24/2009
那就这么说吧!:)Ctrl-C 通常会终止接受来自控制台的输入的程序。Ctrl-D 将标记输入的结束,但程序可以在此之后继续运行。
32赞 Lucas 11/23/2009 #4

您应该将括号改为

while((c = getchar()) != EOF)

因为“=”运算符的优先级低于“!=”运算符。然后你会得到预期的结果。您的表达式等于

while (c = (getchar()!= EOF))

你得到两个 1 作为输出,因为你正在进行比较“c!=EOF”。对于您输入的字符,这将始终成为 1,然后是按回车键后面的“\n”。除了最后一个比较,其中 c 确实是 EOF,它会给你一个 0。

关于EOF的编辑:EOF通常为-1,但标准不保证这一点。该标准仅在第 7.19.1 节中定义了 EOF:

EOF 扩展为整数 常量表达式,类型为 int 和 负值,由 几个功能来指示 文件末尾,即不再输入 从溪流;

假设 EOF 等于 -1 是合理的,但在使用 EOF 时,不应针对特定值进行测试,而应使用宏。

评论

0赞 Laurie Stearn 1/23/2016
“EOF which expands to an integer constant expression, with type int and a negative value”是 32 位,EOF 通常在wchar_t值 -1(或 65535)或字符值 -1 上表示成功,并带有无关的 ÿInt
0赞 Lucas 1/23/2016
@LaurieStearn:在 C 中,EOF 实际上只是一个宏,它扩展为常量整数表达式(通常在某些标头中定义为:),因此通常为 4 个字节宽。EOF 宏不表示任何信号,因为它只是一个值。 - 如标准库中所定义 - 始终返回一个整数值,当它返回与 EOF 等效的值(通常为 -1)时,表示它已到达文件末尾。底层机制显然取决于你的 C 运行时,你不能真正做出任何概括性陈述。#define EOF (-1)getchar
0赞 Laurie Stearn 1/23/2016
@Lucas:原谅我的死灵咆哮,同意。在 VS10 中,65535 并不是严格意义上的 int,但 2 的补语和符号位发生了一些事情,使它看起来如此。
0赞 Laurie Stearn 1/24/2016
嘎,不知道有一个宽版本的 EOF,正如这里所解释的。
4赞 sud03r 11/23/2009 #5

几个错别字:

while((c = getchar())!= EOF)

代替:

while((c = getchar() != EOF))

此外,getchar() 将返回键视为有效输入,因此您也需要对其进行缓冲。EOF 是指示输入结束的标记。通常,它是设置了所有位的 int。


#include <stdio.h>
int main()
{
 int c;
 while((c = getchar())!= EOF)
 {
  if( getchar() == EOF )
    break;
  printf(" %d\n", c);
 }
  printf("%d %u %x- at EOF\n", c , c, c);
}

指纹:

49
50
-1 4294967295 ffffffff- at EOF

对于输入:

1
2
<ctrl-d>

评论

2赞 Heinzi 11/23/2009
你的代码中不是也有错误吗?您调用了两次(一次在 while 循环中,一次在 if 中),因此第二个输入将丢失......getchar()
0赞 Lucas 11/23/2009
它之所以有效,是因为第二个 getchar() 从按回车键中获取“\n”。
0赞 sud03r 11/23/2009
@Heinzi第二个 getchar() 用于从 return 中捕获 “\n”。这样做是为了解释 OP 在 hi 代码中的行为。
1赞 srikanth rongali 11/23/2009 #6
#include <stdio.h>

int main() {
    int c;
    while((c = getchar()) != EOF) { //precedence of != is greater than =, so use braces
        printf("%d\n", c);
    }
    printf("%d - at EOF\n", c);
}

我认为这是检查EOF值的正确方法。 我检查了输出。

对于 INPUT: abc 和 Enter,我得到了 OUTPUT: 97 98 99 10。( ASCII 值)

对于 INPUT Ctrl-D,我在 EOF 处得到了 OUTPUT: -1 -。 所以我认为 -1 是 EOF 的值。

尝试使用其他输入而不是 Ctrl-D,例如 Ctrl-Z。 我认为它因编译器而异。

评论

1赞 Carl Smotricz 11/23/2009
当然,定义为 .但这不应该引起你的兴趣,你也不需要看它或打印出来。只需检查代码中的 EOF,让编译器担心细节。stdio.hEOF-1
3赞 redtone 4/26/2015 #7

来自终端的 nput 永远不会真正“结束”(除非设备已断开连接),但在终端中输入多个“文件”很有用,因此保留一个键序列来指示输入结束。在 UNIX 中,击键到 EOF 的转换由终端驱动程序执行,因此程序不需要将终端与其他输入文件区分开来。默认情况下,驱动程序将行首的 Control-D 字符转换为文件结束指示符。若要将实际的 Control-D (ASCII 04) 字符插入到输入流中,用户需要在其前面加上一个“引号”命令字符(通常为 Control-V)。AmigaDOS 与此类似,但使用 Control-\ 而不是 Control-D。

在 Microsoft 的 DOS 和 Windows(以及 CP/M 和许多 DEC 操作系统)中,从终端读取永远不会产生 EOF。取而代之的是,程序识别源是终端(或其他“字符设备”),并将给定的保留字符或序列解释为文件结束指示符;最常见的是 ASCII Control-Z,代码 26。某些 MS-DOS 程序(包括Microsoft MS-DOS shell (COMMAND.COM) 和操作系统实用程序(如 EDLIN)的一部分)将文本文件中的 Control-Z 视为标记有意义数据的末尾,和/或在写入文本文件时将 Control-Z 追加到末尾。这样做有两个原因:

  1. 向后兼容 CP/M。CP/M 文件系统仅以 128 字节“记录”的倍数记录文件的长度,因此按照惯例,如果有意义数据在记录中间结束,则使用 Control-Z 字符来标记该数据的结尾。MS-DOS 文件系统始终记录文件的确切字节长度,因此在 MS-DOS 上从不需要这样做。

  2. 它允许程序使用相同的代码从终端和文本文件读取输入。

-1赞 mateen maldar 6/7/2016 #8
#include <stdio.h>

int main() {
    int c;
    while((c = getchar()) != EOF) { 
        putchar(c);
    }    
    printf("%d  at EOF\n", c);
}

修改了上面的代码以更清楚地了解 EOF,按 Ctrl+d 和 putchar 用于打印字符,避免在 while 循环中使用 printf。

评论

0赞 mateen maldar 6/7/2016
在 Ubuntu 14.04 上测试
-3赞 Fernando Rodrigues 5/26/2017 #9
int c;

while((c = getchar())!= 10)
{
    if( getchar() == EOF )
        break;

     printf(" %d\n", c);
}

评论

1赞 Username Obfuscation 9/8/2020
不确定这个答案的目的是什么(或者为什么有些人在没有解释的情况下将代码块转储到 SO 上),但请注意这里的错误:由于错误的 EOF 检查逻辑,每两个字符都会被丢弃。
0赞 Jency 6/19/2019 #10

简单起见:EOF 是值为 -1 的整数类型。因此,我们必须使用整数变量来测试 EOF。