【发布时间】:2017-05-04 12:10:46
【问题描述】:
根据标题,我试图了解 Ctrl+D / Ctrl+Z 的确切行为在一个带有gets的while循环中(我需要使用它)。我正在测试的代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[80];
while(printf("Insert string: ") && gets(str) != NULL) {
puts(str);
}
return 0;
}
如果我的输入只是 Ctrl+D(或 Windows 上的 Ctrl+Z)@987654322 @ 返回 NULL,程序正确退出。不清楚的情况是当我插入类似house^D^D(Unix)或house^Z^Z\n(Windows)的东西时。
- 在第一种情况下,我的解释是
getchar(或gets函数中的类似内容)等待 read() 获取输入,第一个 Ctrl+D 刷新非空缓冲区(因此不是 EOF),然后触发第二次 read() 调用 EOF。 - 在第二种情况下,我注意到第一个 Ctrl+Z 被插入到缓冲区中,而后面的所有内容都被忽略了。因此,我的理解是插入
house^Z的第一个 read() 调用并丢弃返回 5(读取的字符数)的所有其他内容。 (我说 5 是因为否则我认为一个简单的 Ctrl+Z 应该返回 1 而不会触发 EOF)。然后程序等待来自用户的更多输入,因此第二次 read() 调用。
我想知道我对它的工作方式的正确和错误以及它的哪一部分只是依赖于实现(如果有的话)。
此外,我注意到在 Unix 和 Windows 中,即使在触发 EOF 之后,它似乎在以下 gets() 调用中重置为 false,我不明白为什么会发生这种情况以及代码的哪一行。
我非常感谢任何形式的帮助。
(2016 年 12 月 20 日)为了避免混淆,我大量编辑了我的问题
【问题讨论】:
-
这个表达式:
|| !feof(stdin))没有任何用处。主要是因为函数:feof()检查代码是否试图读取 EOF,并且这个表达式只有在遇到 EOF 时才会检查,所以总是错误的。由于该功能不符合(通常)预期,强烈建议不要使用它。 -
这个表达式:
*curr++可以/将是一个问题。问题是因为C中运算符的优先级。建议:*curr = (char)c; curr++; -
我使用 !feof(stdin) 检查是否遇到了读取错误而不是 eof。我只是试图模拟 get(...) 函数,以便更好地隔离我怀疑的根源(即 getchar())
-
如果出现 I/O 错误,函数:
feof()不会告诉您该错误。而是:#include <errno.h>然后在调用getchar()errno = 0;之后紧接着调用getchar()if( 0 != errno ) // handle error -
在大多数面向 Windows 的现代编译器上,
_WIN32宏是预定义的。您可以使用它在*curr++ = c;行之前有条件地包含if (c != 0x1a)。这将避免将^Z存储在输入缓冲区中并等待更多输入,类似于Unix 终端驱动程序不会将^D传递给house^D中的stdin。除此之外,您的功能看起来是正确的。