我目前正试图用这样的东西结束一个while循环:
#include <stdio.h>
int main()
{
while(getchar() != EOF)
{
if( getchar() == EOF )
break;
}
return 0;
}
当我在我的Ubuntu上按CTRL+D
时,它会立即结束循环。但在Windows上,我必须按CTRL+Z
,然后按ENTER
关闭循环。我可以摆脱Windows上的ENTER
吗?
答案 0 :(得分:7)
对于linux,EOF字符用 ctrl + d 编写,而在Windows上,当你按输入后由控制台写入通过 ctrl + z 更改CRT库的内部状态(保留此行为是为了与非常旧的系统进行后向兼容)。如果我没错,那就称为文件的软端。我不认为你可以绕过它,因为当你按输入时,你的getchar
实际上消耗了EOF字符,而不是按 ctrl + < KBD>ž
据报道here:
在Microsoft的DOS和Windows(以及CP / M和许多DEC操作系统)中,从终端读取将永远不会产生EOF 。相反,程序认识到源是终端(或其他“字符设备”)并且将给定的保留字符或序列解释为文件结束指示符;最常见的是这是一个ASCII Control-Z ,代码26.一些MS-DOS程序,包括Microsoft MS-DOS shell(COMMAND.COM)和操作系统实用程序(如EDLIN)的一部分,对待文本文件中的Control-Z标记有意义数据的结尾,和/或在写入文本文件时将Control-Z附加到末尾。这样做有两个原因:
与CP / M的向后兼容性。 CP / M文件系统仅以128字节“记录”的倍数记录文件长度,因此按照惯例,如果有意义数据在记录中间结束,则使用Control-Z字符标记有意义数据的结尾。 MS-DOS文件系统始终记录文件的确切字节长度,因此在MS-DOS上永远不需要这样做。
它允许程序使用相同的代码从终端和文本文件中读取输入。
其他信息也会报告here:
某些现代文本文件格式(例如CSV-1203 [6])仍建议将尾随EOF字符作为文件中的最后一个字符追加。但是,键入Control + Z不会将EOF字符嵌入到MS-DOS或Microsoft Windows中的文件中,这些系统的API也不会使用该字符来表示文件的实际结尾。
当使用内置文本文件读取基元(INPUT,LINE INPUT等)时,某些编程语言(例如Visual Basic)将不会读取“软”EOF,并且必须采用替代方法,例如,以二进制模式打开文件或使用文件系统对象超越它。
字符26用于标记“文件结束”,即使ASCII称之为替换,并且还有其他字符。
如果您修改代码:
#include <stdio.h>
int main() {
while(1) {
char c = getchar();
printf("%d\n", c);
if (c == EOF) // tried with also -1 and 26
break;
}
return 0;
}
并且你测试它,在Windows上你会看到EOF
( - 1)它没有写入控制台,直到你按 enter 。 Beore of a ^Z
由终端模拟器打印(我怀疑)。从我的测试中,如果出现以下情况,则会重复此行为:
根据@eryksun的建议,我成功地为Windows编写了一个(可笑的复杂功能)代码,它改变了conhost的行为,实际上在按下 ctrl + <时出现了“退出” KBD> d ”。它不处理所有事情,这只是一个例子。 恕我直言,这是尽可能避免的,因为可移植性小于0.此外,要实际正确处理其他输入案例,应编写更多代码,因为这个东西将stdin从控制台中分离出来,你必须自己处理它。
这些方法或多或少地起作用如下:
这是代码:
#include <windows.h>
#include <stdio.h>
#define Kev input_buffer[i].Event.KeyEvent // a shortcut
int main(void) {
HANDLE h_std_in; // Handler for the stdin
DWORD read_count, // number of events intercepted by ReadConsoleInput
i; // iterator
INPUT_RECORD input_buffer[128]; // Vector of events
h_std_in = GetStdHandle( // Get the stdin handler
STD_INPUT_HANDLE // enumerator for stdin. Others exist for stdout and stderr
);
while(1) {
ReadConsoleInput( // Read the input from the handler
h_std_in, // our handler
input_buffer, // the vector in which events will be saved
128, // the dimension of the vector
&read_count); // the number of events captured and saved (always < 128 in this case)
for (i = 0; i < read_count; i++) { // and here we iterate from 0 to read_count
switch(input_buffer[i].EventType) { // let's check the type of event
case KEY_EVENT: // to intercept the keyboard ones
if (Kev.bKeyDown) { // and refine only on key pressed (avoid a second event for key released)
// Intercepts CTRL + D
if (Kev.uChar.AsciiChar != 4)
printf("%c", Kev.uChar.AsciiChar);
else
return 0;
}
break;
default:
break;
}
}
}
return 0;
}
答案 1 :(得分:0)
while(getchar() != EOF)
{
if( getchar() == EOF )
break;
}
return 0;
这里不一致。
如果getchar() != EOF
它将进入循环,否则(如果getchar() == EOF
)它将不会进入循环。因此,没有理由在循环中检查getchar() == EOF
。
另一方面,您拨打getchar()
2次,等待输入2个字符而不是1个。
你尝试做什么?