根据标题,我试图理解带有gets的while循环中Ctrl+ D/ Ctrl+ 的确切行为Z(我需要使用它).我正在测试的代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[80];
while(printf("Insert string: ") && gets(str) != NULL) {
puts(str);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我的输入只是一个Ctrl+ D(或Windows上的Ctrl+ Z),则gets返回NULL并且程序正确退出.不清楚的情况是我插入类似house^D^D(Unix)或house^Z^Z\n(Windows)的东西.
getchar(或gets函数内部类似的东西)等待read()获取输入,第一个Ctrl+ D刷新非空的缓冲区(因此不是EOF)然后第二次调用read() EOF被触发.house^Z并丢弃其他返回5(读取的字符数)的其他内容.(我说5,因为否则我认为一个简单的Ctrl+ Z应该返回1而不触发EOF).然后程序等待来自用户的更多输入,因此进行第二次read()调用.我想知道我的工作方式是对是错,哪一部分只是依赖于实现,如果有的话.
此外我注意到在Unix和Windows中,即使在触发EOF之后,它似乎在下面的gets()调用中重置为false ,我不明白为什么会发生这种情况以及代码的哪一行.
我真的很感激任何帮助.
(12/20/2016)我对我的问题进行了大量编辑,以避免混淆
CTRL-D 和 CTRL-Z “文件结束”指示符分别在 Unix 和 Windows 系统上起到类似的作用,但实现方式却大不相同。
在 Unix 系统(包括像 Linux 这样的 Unix 克隆)上,CTRL-D 虽然官方描述为文件结束符,但实际上是一个分隔符。它的作用与用于分隔行的行尾字符(通常是回车或 CTRL-M)几乎相同。这两个字符都告诉操作系统输入行已完成并使程序可用。唯一的区别是,对于行尾字符,在输入缓冲区的末尾插入换行 (CTRL-J) 字符以标记行尾,而对于文件结束字符,则不插入任何内容.
这意味着当您house^D^D在 Unix 上输入时,read系统调用将首先返回一个长度为 5 的缓冲区,其中包含 5 个字符house。当read再次调用以获取更多输入时,它将返回长度为 0 且其中没有字符的缓冲区。由于对普通文件的零长度读取表明已到达文件末尾,这将返回用户键入的任何后续字符。gets库函数也将其解释为文件末尾并停止读取输入。但是,由于它用 5 个字符填充了缓冲区,因此它不会返回 NULL 以指示它已到达文件末尾。并且由于它实际上并没有真正到达文件末尾,因为终端设备实际上不是文件,gets在此之后的进一步调用将进一步调用read
在 Windows 上,CTRL-Z 的处理方式大不相同。最大的区别是它根本没有被操作系统特别对待。当您house^Z^Z^M在 Windows 上键入时,仅对回车符进行特殊处理。就像在 Unix 上一样,回车使键入的行可供程序使用,但在这种情况下,回车和换行会添加到缓冲区以标记行的结尾。所以结果是该ReadFile函数返回一个 9 字节长的缓冲区,其中包含 9 个字符house^Z^Z^M^J。
它实际上是程序本身,特别是 C 运行时库,它特别对待 CTRL-Z。对于 Microsoft C 运行时库,当它在返回的缓冲区中看到 CTRL-Z 字符时ReadFile,会将其视为文件结束标记并忽略其后的所有其他内容。使用上一段中的示例,gets最终调用ReadFile以获取更多输入,因为在从控制台(或其他设备)读取时不会记住它看到 CTRL-Z 字符的事实,并且它还没有看到结尾-line(被忽略)。如果再按回车,gets将返回填充了 7 个字节的缓冲区house^Z\0(添加一个 0 字节以指示字符串的结尾)。默认情况下,它在读取普通文件时会做同样的事情,如果一个 CTRL-Z 字符出现在文件中,它和它之后的所有内容都会被忽略。这是为了与 CP/M 向后兼容,CP/M 只支持长度为 128 倍数的文件,并使用 CTRL-Z 来标记文本文件真正应该结束的位置。
请注意,上述 Unix 和 Windows 行为都只是用户输入的正常默认处理。CTRL-D 的 Unix 处理仅在以规范模式从终端设备读取时发生,并且可以将“文件结束”字符更改为其他字符。在 Windows 上,操作系统从不特别对待 CTRL-Z,但 C 运行时库是否这样做取决于正在读取的 FILE 流是文本模式还是二进制模式。这就是为什么在可移植程序b中,当打开二进制文件(例如fopen("foo.gif", "rb"))时,您应该始终在模式字符串中包含该字符。
| 归档时间: |
|
| 查看次数: |
2004 次 |
| 最近记录: |