提问人:drain_ 提问时间:9/14/2022 最后编辑:Rachid K.drain_ 更新时间:9/19/2022 访问量:525
在 C 语言中将 EOF 读取为字符
Reading EOF as a char in C
问:
我知道这听起来可能很愚蠢,但我怎样才能退出这个循环?
#include <stdio.h>
#include <stdlib.h>
int main(){
char c;
do {
c = getchar();
printf("%c", c);
}while(c != EOF);
return 0;
}
我正在读一本书,并尝试做以下练习: “验证表达式 getchar() != EOF 是否为 0 或 1” 如果我读取存储在整数值中的EOF值,它将等于-1,但是如果我试图将-1捕获为char,那就太他妈的了。据我了解,EOF 是一个未分配给任何其他字符的值。
有人可以帮忙吗?
编辑1: 我知道 c 应该是一个整数......我故意把它读成一个字符。
编辑2:
int main(){
int c;
while((c = getchar()) != EOF)
{
printf("%d\n", c);
}
return 0;
}
----->
int main(){
int c;
int i = 0;
char str[2];
while((c = getchar()) != EOF)
{
str[i] = c;
++i;
if(i > 1) i = 0;
if(str[0]=='-'&&str[1]=='1')
{
c = EOF; // doens't exit loop
}
else printf("%d\n", c);
}
return 0;
}
为什么我不明白这一点。
答:
c
一定不是.这在未签名的实现中尤为重要。 由 0xffffffff(32 位整数,二进制补码)表示,并作为0xff分配给 char。相比之下0xff总是不相等的。这就是为什么你应该使用 not .int
char
char
-1
-1
int
char
- 打印前测试EOF。更适合的是循环
while(...) {}
int main(){
int c;
while((c = getchar()) != EOF)
{
printf("%c", c);
}
}
https://godbolt.org/z/6sqa98bnq
这里有一个示例,如果 is 和 is unsigns,会发生什么:https://godbolt.org/z/bjfGv56z3c
char
char
评论
如果您像这样更改程序,它可能会帮助您了解发生了什么:
#include <stdio.h>
int main(){
int c;
do {
c = getchar();
printf("%d\n", c);
} while(c != EOF);
}
你会注意到我有:
- 声明为
c
int
- 打印它
%d
如果我运行这个程序并键入“abc”,然后点击然后,这就是我看到的:EnterCTRL-D
97
98
99
10
-1
97、98 和 99 是 、 和 的 ASCII 代码。10 是换行符的代码,又名 .然后 -1 是我键入时生成的 EOF。(如果您使用的是 Windows,则会改用 And Another 代替。a
b
c
\n
CTRL-DCTRL-ZEnter
在这个程序中,虽然是一个变量,但这并不意味着它不包含字符!在 C 中,字符由小整数表示,这些整数是它们在机器字符集中的代码。下面是演示这一点的修改:c
int
int c;
int nch = 0;
char string[100];
do {
c = getchar();
printf("%d", c)
if(c >= 32 && c < 127) {
printf(" = '%c'", c);
string[nch++] = c;
}
printf("\n");
} while(c != EOF);
string[nch] = '\0';
printf("You typed \"%s\"\n", string);
现在它打印
97 = 'a'
98 = 'b'
99 = 'c'
10
-1
You typed "abc"
打电话没有问题
printf(" = '%c'", c);
即使是一个 int 并且用于打印字符。
分配没有问题c
%c
string[nch++] = c;
即使是一个 int 并且是字符数组。c
string
评论
EOF
getchar
getchar()
返回 [ ... ] 范围内的 an 或 。int
0
UCHAR_MAX
EOF
要很好地区分这些典型的 257 个不同值,请保存在 .int
如果保存在有符号的 a 中,则保存典型值为 -1 的字符,但某些字符也会保存,可能值为 255。然后,循环在以下 2 种条件之一下结束。char
EOF
如果保存在无符号中,则典型值为 -1 的 将保存为 255,并且永远不会等同于导致无限循环。char
EOF
EOF
做正确的事。保存在 .int
打印前进行比较,否则返回时,打印结果可能与读取带有 255 的字符相同。EOF
// char c;
int c;
while ((c = getchar()) != EOF)) {
printf("%c", c);
}
据我了解,EOF 是一个未分配给任何其他字符的值
这并不完全正确。 为负数,字符(不是字符)与值一起读取。EOF
unsigned char
EOF
可以是 -1,a 在有符号时也可以具有 -1 的值。关键是最好将章程最初视为无符号值,即使出人意料地保存在有符号的 .char
char
更深层次:这是一个旧的 C 历史妥协,有签名或未签名。不过,字符处理最好按条件进行,字符被视为 。这会影响 、 和其他函数。char
unsigned char
getchar()
is...()
strcmp()
根据 C 标准(7.21 输入/输出 <stdio.h>)
EOF
它扩展为一个整数常量表达式,类型为 int 和 负值,由多个函数返回以指示 文件末尾,即不再有来自流的输入;
正如你所看到的,没有说常量表达式有什么负值。
但是,通常它等于 -1。
do-while 语句的条件
}while(c != EOF);
将正确计算为 以及类型是否表现为类型 。在这种情况下,由于整数升级,类型的对象将隐式转换为条件中的类型。也就是说,存储在该类型的对象中的整数值将提升为该类型并保留其值。1
0
char
signed char
c
char
int
-1
c
char
int
-1
但是,根据编译器选项,该类型可以表现为类型 。在这种情况下,在此分配之后char
unsigned char
c = getchar()
该变量将具有一个无符号值。例如,如果它被赋值为 that is equalto,则该变量将具有在整数提升后将保留的正值。
因此,条件c
EOF
-1
c
255
}while(c != EOF);
将始终计算为 因为不等于 。1
-1
255
因此,您应该始终将变量声明为具有 .在这种情况下,您的代码将不依赖于类型的行为方式:as 或 as 。c
int
char
signed char
unsigned char
在您问题的附录中,您试图在用户键入“-1”时退出循环,您想知道为什么这不起作用。你犯了一两个错误。这是一个更正后的版本,您可以尝试:
int c;
int i = 0;
char str[20];
while((c = getchar()) != EOF)
{
str[i] = c;
++i;
if(str[0]=='-' && str[1]=='1')
{
break; /* fix here: was "c = EOF" */
}
else printf("%d\n", c);
}
您的代码实际上确实识别了“-1”,但在响应中它设置为 ,但这什么也没做,因为接下来发生的事情是对循环顶部标头的另一次调用。c
EOF
c = getchar()
while
在修改后的版本中,我在看到“-1”时调用,这有效。break
请注意,若要退出循环,必须键入两个字符“-”和“1”,并且必须在行的开头键入它们。
请注意,您在此处阅读的是字符。两个字符“-”和“1”不被视为整数 -1 或 C 值。他们只是两个角色。如果将语句更改为EOF
if
if(str[0]=='x' && str[1]=='y')
你最终会得到一个循环,当用户在一行的开头输入“xy”时,这个循环就停止了。
评论
read
来填充它。如果返回 <= 0,则表示文件结束或错误,因此返回非字符值 EOF。getchar
stdin
read
getchar
read
read
read
read
read
read
上一个:在端子线上读/写问题
下一个:C开关,如何修复多个默认打印?
评论
getchar()
返回 因此,您应该更改为 。在打印之前检查它是否不是也是一个好主意。 -或int
char c
int c
EOF
int c; while((c = getchar()) != EOF) { printf("%c", c); }
for(int c; (c = getchar()) != EOF;) { printf("%c", c); }
EOF
char
char
char c;
char
int
%c
printf
char*
scanf
char
int
EOF
char
EOF
sizeof (int) == sizeof (char)
EOF
确实有一个char
值。回想一下,以 或 字符值的形式返回 ,而不是 .getchar
EOF
unsigned char
char