在C代码中,换行符由"\n"
表示。是否存在与文件结尾(EOF)字符相当的等效字符?
在C代码中,换行符由"\n"
表示。是否存在与文件结尾(EOF)字符相当的等效字符?
在大多数现代操作系统中,EOF不是一个字符。它只是适用于文件流的一种条件,当流的结尾被达到时就会发生。混淆之处在于用户可能通过输入特殊字符(例如Unix、Linux和其他操作系统中的Control-D)来"信号化"控制台输入的EOF,但是该字符并不会被正在运行的程序看到,而是被操作系统捕获,进而向进程发出EOF信号。
注意:在一些非常旧的操作系统中,EOF确实是一个字符,例如CP/M中的Control-Z,但这是一种粗糙的hack,以避免在文件系统目录中维护实际文件长度的开销。
getchar()
等函数的返回值要么是一个有效的字符,要么是一种不同于有效字符代码的特殊代码EOF。EOF是一个整型常量表达式,类型为int且具有负值,由多个函数返回以指示文件末尾,即没有更多的输入流。fgetc
函数将[下一个]字符作为无符号字符转换为int获取。因此,在任何sizeof(char) != sizeof(int)
的系统上,EOF都不同于任何字符。 - Jonathan LefflerEOF
不是一个字符。因为(二进制)文件可以包含任何字符。假设你有一个文件,其中的字节逐渐增加,变成 0 1 2 3 ... 255 然后再次变成 0 1 ... 255,总共 512 个字节。无论你认为哪一个那 256 个可能的字节是 EOF
,该文件将被截断。
这就是为什么 getchar()
等返回一个 int
。可能的返回值范围是一个 char
可以拥有的,再加上一个真正的 int
值 EOF
(在 stdio.h
中定义)。这也是为什么在检查 EOF
之前将返回值转换为 char
将不起作用。
注意,一些协议有 "EOF" "字符"。ASCII 有 "End of Text"、"End of Transmission"、"End of Transmission Block" 和 "End of Medium"。其他答案已经提到了旧操作系统。我自己在 Linux 上输入 ^D,在 Windows 控制台上输入 ^Z 来停止给程序输入。(但通过管道读取的文件可以在任何地方拥有 ^D 和 ^Z 字符,并且仅在它们耗尽字节时才信号 EOF。)C 字符串以字符 '\0'
结尾,但这也意味着它们不能包含字符 '\0'
。这就是为什么所有 C 非字符串数据函数都使用一个 char
数组(用于包含数据)和一个 size_t
(用于知道数据在哪里结束)。
编辑:C99 标准 §7.19.1.3 规定:
宏是 [...]
EOF
它扩展为一个整数常量表达式,带有类型int
和负值,由多个函数返回,以表示文件结束,即来自流的没有更多输入;
((charVar = getchar()) == EOF)
的人将会看到错误的行为。你所说的是,当他们读取那个被提升为 int
类型的 char
值等于 EOF
时,他们可能会得到一个过早的、虚假的 EOF
,而不是因为没有任何 char
等于 EOF
而永远循环下去。解决方案仍然是相同的:((intVar = getchar()) == EOF)
。 - aibEOF
不等于char
值。”实际上,即使一个实现使用相同类型的char
和int
,它们对于标准和符合标准的实现仍然是不同的类型。 - aibfgetc
之类的函数的返回值来检测EOF
,该函数返回一个字符作为unsigned char
转换为int
或EOF
。这将适用于除我提供的链接中讨论的奇特假设C实现之外的所有情况。(要编写即使对于那些实现也能工作的代码,请使用feof
函数。)但是,不应假定char
值不等于EOF
。 - Eric Postpischil不,EOF不是一个字符,而是文件句柄的一种状态。
虽然ASCII字符集中有表示数据结束的控制字符,但这些字符通常不用来标识文件的结尾。例如EOT(^D),在某些情况下几乎具有相同的信号意义。
当标准C库使用带符号整数返回字符,并将-1用于文件结束时,实际上只是表示发生了错误的信号。我没有可用的C标准,但引用SUSv3:
如果流的文件结束指示器被设置或者流处于文件末尾,则流的文件结束指示器应该被设置,并且fgetc()应该返回EOF。如果读取错误发生,则流的错误指示器应该被设置,fgetc()应该返回EOF,并设置errno以指示错误。
我已经阅读了所有评论。有趣的是,当您打印出以下内容时会发生什么:
printf("\nInteger = %d\n", EOF); //OUTPUT = -1
printf("Decimal = %d\n", EOF); //OUTPUT = -1
printf("Octal = %o\n", EOF); //OUTPUT = 37777777777
printf("Hexadecimal = %x\n", EOF); //OUTPUT = ffffffff
printf("Double and float = %f\n", EOF); //OUTPUT = 0.000000
printf("Long double = %Lf\n", EOF); //OUTPUT = 0.000000
printf("Character = %c\n", EOF); //OUTPUT = nothing
正如我们在这里看到的,EOF并不是一个字符(无论如何)。
EOF
既不是浮点型、双精度浮点型也不是长双精度浮点型,因此以浮点类型打印它显然行不通。 - phuclvdouble
值时,库函数从堆栈读取8个字节,其中最后4个字节是您可以从%x
看到的0xFFFFFFFF
,并将这8个字节解释为double
。它很可能看到一个非常小的非零非规格化值,打印为0.0000000,因为只有6位小数。其他4个字节可能是0x00
,但它们可能是任何东西;因此是"未定义行为",您可能会看到其他随机无意义的内容。 - szmoore"Some description\x1a"
开头,则用户可以使用TYPE
命令将文件内容转储到控制台,并且在EOF字符处停止转储,即打印 Some description 并停止,而不是继续打印后面的垃圾。我认为这可能因系统而异,但一种检查方法是只需使用printf
#include <stdio.h>
int main(void)
{
printf("%d", EOF);
return 0;
}
我在Windows上执行了这个操作,控制台输出了-1
。希望这可以帮到你。
fgets()
的行为感到困惑。EOF的值不能与任何实际字符混淆。
如果 a= getchar()
,那么我们必须声明 a
足够大,以容纳 getchar()
返回的任何值。我们不能使用 char
,因为 a
必须足够大,能够除了字符外还能容纳EOF。
a
大小的第二部分很难理解。我编辑了你的帖子以增加一些清晰度。 - Luke Taylor#include <stdio.h>
int main()
{
char c;
int i = 0;
printf("INPUT:\t");
c = getchar();
while (c != EOF)
{
++i;
c = getchar();
};
printf("NUMBER OF CHARACTERS %d.", i);
return 0;}
#include <stdio.h>
int main()
{
char c;
int i = 0;
printf("INPUT:\t");
c = getchar();
while (c != EOF)
{
if (c != '\n')
{
++i;
}
c = getchar();
};
printf("NUMBER OF CHARACTERS %d.", i);
return 0;}.
现在的主要问题是如何输入内容。很简单: 先写下你想要的所有故事,然后换行并输入^Z,再按一次回车。