提问人:abhinavk 提问时间:8/12/2018 最后编辑:Studentabhinavk 更新时间:8/13/2018 访问量:331
实际结束从终端读取所需的两个 EOF
Two EOF required to actually end reading from terminal
问:
我一直在试图了解工作原理。在我的代码中(在 Windows 上),第一次调用 (+ 和 ) 不起作用,我必须提供两个才能真正停止读取输入。此外,第一个被读取为一些垃圾字符,当我打印输入时会显示。(我们可以在提供的输出中看到末尾显示的垃圾字符)。EOF
EOF
CtrlZEnterEOF
EOF
这是我的代码:-
#include<stdio.h>
#define Max 1000
int main()
{
char c, text[Max];
int i = 0;
while((c = getchar()) != EOF)
{
text[i] = c;
i++;
}
printf("\nEntered Text: \n");
puts(text);
return 0;
}
我的输出:
我有这个疑问:-
为什么需要两个 s?我如何防止第一个被读取(作为一些垃圾)并存储为我的输入的一部分?EOF
答:
尝试将 的类型更改为 as 可以是负数,通常将其定义为 。 可能存储也可能无法存储 。另外,在将字符串传递给 之前,不要忘记以 结束字符串。c
int
EOF
-1
char
-1
\0
puts
评论
getchar()
int
getchar()
char
text
i < Max
Control-Z 仅被识别为在新行的开头。因此,如果您想在一行中间检测它,则需要自己进行检测。EOF
所以改变这一行:
while((c = getchar()) != EOF)
对此:
while((c = getchar()) != EOF && c != CTRL_Z)
然后添加:
#define CTRL_Z ('Z' & 0x1f)
在程序的顶部。
您可能仍然需要在 - 之后键入 a 来获取程序要读取的缓冲输入,但它应该丢弃 ^Z 之后的所有内容。returnCtrlz
评论
以下解决方案修复了 Ctrl+Z 问题和垃圾输出,并阻止了缓冲区溢出。我已经评论了这些更改:
#include <stdio.h>
#define Max 1000
#define CTRL_Z 26 // Ctrl+Z is ASCII/ANSI 26
int main()
{
int c ; // getchar() returns int
char text[Max + 1] ; // +1 to acommodate terminating nul
int i = 0;
while( i < Max && // Bounds check
(c = getchar()) != EOF &&
c != CTRL_Z ) // Check for ^Z when not start of input buffer
{
text[i] = c;
i++;
}
text[i] = 0 ; // Terminate string after last added character
printf( "\nEntered Text:\n" );
puts( text );
return 0;
}
这种行为的原因有些晦涩难懂,但文件末尾与 Ctrl-Z 不同。当且仅当控制台输入缓冲区为空时,控制台会生成文件末尾,导致返回 EOF (-1),否则它会将 ASCII SUB (26) 字符插入到流中。SUB的使用最初是为了MS-DOS与更早的CP / M操作系统的兼容性。特别是,CP/M 文件由固定长度的记录组成,因此记录中间的 ^Z 用于指示不是记录长度精确倍数的文件的有效数据的结尾。在控制台中,如果 SUB 不在输入缓冲区的开头,并且 SUB 之后的所有字符都被丢弃,则 SUB 是可读的,而不是生成 EOF。这都是从路上开始的混乱宿醉。getchar()
Windows 终端在键盘输入中遵循的逻辑(至少在其默认配置中)如下:^Z
这种组合本身不会导致输入线路缓冲器被推送到等待的应用。此组合键只是在输入缓冲区中生成字符。您必须按下以完成该行缓冲区并将其发送到应用程序。Ctrl-Z
^Z
Enter实际上,您可以在按 之后和之前继续输入其他字符。
^Z
Enter如果输入行不以 开头,而是包含 inside,则应用程序将接收该行,直到并包含第一个字符(读取为字符)。其余的输入将被丢弃。
^Z
^Z
^Z
\x1A
例如,如果您输入
Hello^Z World^Z123
并按你的C程序将实际读取序列。不会出现EOF条件。Enter
Hello\x1A
如果输入线以 开头,则丢弃整条线并设置 EOF 条件。
^Z
例如,如果您输入
^ZHello World
并按下您的程序将不读取任何内容并立即检测到 EOF。Enter
这是您在实验中观察到的行为。请记住,的结果应该被接收到一个变量中,而不是一个变量。getchar()
int
char
评论
puts
text[i] = 0;
c
Hello World
Hello World <enter>