6

来自C 编程语言

int c;
while ((c = getchar()) != EOF)
    putchar(c);

“......解决方案是getchar在没有更多输入时返回一个独特的值,这个值不能与任何真实字符混淆。这个值称为EOF, 用于“文件结束”。我们必须声明c为大类型足以容纳任何getchar返回的值。我们不能使用char,因为c必须大到足以容纳EOF任何可能的值char

我签入stdio.h并在我的系统上打印了 EOF 的值,它设置为-1. 在我的系统上,chars已签名,尽管我知道这取决于系统。所以,EOF可以适合char我的系统。我通过定义c为 a重写了上面的小例程,char并且程序按预期工作。这里的 ASCII 字符表中还有一个字符,它似乎有一个对应于 255 的空白字符,看起来像EOF.

那么,为什么 ASCII 似乎有一个为 EOF 指定的字符(255)?这似乎与The C Programming Language书中所说的相矛盾。

4

5 回答 5

5

getchar()读取字节 255 时,返回 255。当getchar()发现没有更多输入时,返回 -1。

如果将结果存储在 achar中,则无法区分两者。但是,当您将它们存储在 中时int,您可以。(此声明独立于 的签名char)。

只有当您知道结果有效时,您才能将其转换为char并获得通常的 C 样式字符类型。

于 2013-10-31T20:25:56.783 回答
3

根据 getchar() 手册,它总是返回 int 值:

#include <stdio.h>
...
int getchar(void);
...
RETURN VALUE
fgetc(), getc() and getchar() return the character read as 
an unsigned char cast to an int or EOF on end of file or error.

因此使用 char 而不是 int 会导致截断(int -1 (0xffffffff) 变为 char -1 (0xff))并可能导致错误。

于 2013-10-31T20:37:11.407 回答
3

那么,为什么 ASCII 似乎有一个为 EOF 指定的字符(255)?

它没有。更准确地说,这不是 EOF “字符”。

诀窍是,getchar()如果有要读取的内容,它将始终返回非负值。如果遇到文件结尾,它只会返回-1(这EOF似乎是在您的实现中定义的)。

事实char是:

  1. 8位宽,
  2. 签署和
  3. 使用 2 的补码表示,

只是您实现的一个怪癖(尽管现在非常普遍)。因此,如果您使用 achar来存储 的返回值getchar(),那么读取输入可能会提前终止:代码为 255 的字符将被误认为 -1 aka EOF这是一个错误。这就是发生在你身上的事。它没有用- 相反,你的第二种方法完全被打破了。

于 2013-10-31T20:23:39.973 回答
2

要了解这是如何工作的,请想象一下编写 getchar 的人的想法。你需要读取一个文件。首先创建一个例程 - 例如:

unsigned char get_me_a_byte(file)... // 0..255

现在您想从文件中读取所有字节:

unsigned char c;

while( c = get_me_a_byte(file) ) // while( (c = get_me_a_byte(file)) != 0 )
{
  ... do sth
}

问题是它会在遇到 z 零时停止,但是一旦一切都是红色的,您就想停止。现在你变得更聪明了——你知道文件可以被认为是字节序列。如果您的get_me_a_byte可以返回 16 位或 32 位类型怎么办?然后你可以使用一些字节不能保存的值作为文件结束标记。

答对了

由于决定权在您手中,您可能有:

int get_me_a byte_U(file) ... // returning bytes as 0..255
int get_me_a byte_S(file) ... // returning bytes as -128..127

现在你可以这样做:

int c;
while( (c = get_me_a_byte_U(file) != UUU ) ....

其中UUU可以是您平台上从 256 到 MAXINT 的任何值

相似地:

int c;
while( (c = get_me_a_byte_S(file) != SSS ) ....

其中SSS可以是 MININT..-129 和 128..MAXINT 中的任何内容

现在,如果您选择第一种方法,则会出现一个问题:UUU(您的 EOF)的值应该是多少?

(-1) 对 EOF 有好处,因为无论您分配给它的变量的位宽是多少,它都将保持 (-1)。'保持-1'我的意思是它永远都是一个模式。

char c = -1; // c = 11111111b / 0xFF / 255 (assuming your char is signed 8bit)
short s = -1; // s = 1111111111111111b / 0xFFFF / 65535
int i = -1; // s = 11111111111111111111111111111111b / 0xFFFFFFFF / 4294967295

现在应该很明显了。

于 2013-10-31T22:00:16.423 回答
1

没有矛盾。

  • EOF 不是字符,只是读取文件时发现的条件。
  • ASCII 255 有时对应于不间断空格,也就是 HTML 实体&nbsp;

如评论中所述,ASCII 仅编码 128 个字符,因此除此之外您会发现不同的编码。

从您链接到的表中,我只想说:

255 是不可打印的字符

于 2013-10-31T20:24:43.977 回答