C中的EOF问题

我正在编写一个程序,它应该读取两个可以包含换行符和其他各种字符的字符串。 因此,我使用EOF(Ctrl-Z或Ctrl-D)结束字符串。

这适用于第一个变量,但是使用第二个变量,然而,这似乎是有问题的,因为显然某些东西卡在输入缓冲区中而用户无法输入任何内容。

我试着用while (getchar() != '\n');清理缓冲区while (getchar() != '\n'); 和几个类似的变化,但似乎没有任何帮助。 所有清洁尝试都导致无限循环,如果没有清洁,添加第二个变量是不可能的。

这两个变量的字符都是在这样的循环中读取的: while((c = getchar()) != EOF) ,这表明它是我在缓冲区中停留的EOF。 或者它是否以其他方式影响程序的行为? 我正在使用的逻辑有什么问题吗?

经过几个小时的挣扎,我开始有点绝望了。

[编辑:下面添加代码]

[编辑2:clearerr()似乎使这个EOF解决方案毕竟有效。

它似乎以我在Linux下的原始forms运行,我昨天在Windows上试用它。

码:

 #include  #include  int main(void) { int x = 0; int c; char a[100]; char b[100]; printf("Enter a: "); while((c = getchar()) != EOF) { a[x] = c; x++; } a[x] = '\0'; x = 0; /*while (getchar() != '\n'); - the non-working loop*/ printf("\nEnter b: "); while((c = getchar()) != EOF) { b[x] = c; x++; } b[x] = '\0'; printf("\n\nResults:\na: %s\n", a); printf("b: %s\n", b); return(0); } 

[编辑3:]

动态内存问题:

我的程序也应该处理超过100个字符的字符串。 最初我打算通过动态内存分配解决这个问题,但是当我遇到上述无限循环和内存相关崩溃的问题时,我把它留了出来并切换到char [100]。

我想我尝试过的通常是这样的:

 while((c = getchar()) != EOF) { a = malloc(sizeof(char)); a[x] = c; x++; } 

这是一种可能的(或明智的)方法吗? 我正在尝试为那里处理的每个角色分配更多内存。 独立。 使用这样的代码(这个例子可能包含语法错误)我经历过崩溃,所以在我看来malloc可能不是正确的function,或者我试错了。 假设它甚至可能。

从终端收到EOF后, 您将不会收到任何其他数据 。 没有办法取消输入 – 文件的结尾就是结束。

因此,您应该定义每个变量在单独的行上输入,并让用户按Enter键而不是EOF。 您仍然需要检查是否已收到eof,因为这意味着用户实际输入了EOF,而您将看不到任何其他内容 – 在这种情况下,您需要突破循环并打印错误消息。

EOF不是一个字符 – 它是一个特殊值,输入函数返回以指示一个条件 ,即已达到该输入流上的“文件结尾”。 正如Martinv.Löwis所说,一旦出现“文件结束”条件,就意味着该流上不再有可用的输入。

出现混乱的原因是:

  • 当“文件”是交互式终端时(例如,Ctrl-Z或Ctrl-D),许多终端类型识别出用于发出“文件结束”信号的特殊按键; 和
  • EOF值是getchar()函数系列可以返回的值之一。

您将需要使用实际字符值来分隔输入 – 如果ASCII nul字符'\0'在输入本身中不能显示为有效值,则它可能是一个不错的选择。

我在我的linux机器上运行代码,结果如下:

 Enter a: qwer asdf Enter b: 123 456 Results: a: qwer asdf b: 123 456 

需要两个Ctrl-D,因为终端输入缓冲区不为空。

您可以使用空字符( '\0' )来分隔变量。 各种UNIX工具(例如find )能够以这种方式分离它们的输出项,这表明它是一种相当标准的方法。

这样做的另一个好处是你可以将流读入一个缓冲区,然后创建一个char* s数组来指向各个字符串,每个字符串将被正确'\0'终止,而不必更改任何内容缓冲区手动。 这意味着更少的内存分配开销,这可能会使您的程序运行速度明显更快,具体取决于您正在读取的变量数量。 当然,只有当你需要同时在内存中保存所有变量时才需要这样做 – 如果你一次一个地处理它们,你就不会获得这个特殊的优势。

EOF根本不可能你在尝试什么。

虽然它在某些方面表现得像一个,但EOF不是流中的字符,而是表示流结束的环境定义的宏。 我还没有看到你的代码,但我知道你做的是这样的:

 while ((c=getchar()) != EOF) { // do something } while ((c=getchar()) != EOF) { // do something else } 

当您第一次键入EOF字符时,要结束第一个字符串,流将不可撤销地关闭。 也就是说,流的状态是它被关闭。

因此,第二个while循环的内容永远不会运行。

而不是停止在EOF读取输入 – 这不是一个字符 – 停止在ENTER。

 while((c = getchar()) != '\n') { if (c == EOF) /* oops, something wrong, input terminated too soon! */; a[x] = c; x++; } 

EOF是输入终止的信号。 您几乎可以保证来自用户的所有输入都以’\ n’结尾:这是用户键入的最后一个键!


编辑:您仍然可以使用Ctrl-D和clearerr()来重置输入流。

 #include  int main(void) { char a[100], b[100]; int c, k; printf("Enter a: "); fflush(stdout); k = 0; while ((k < 100) && ((c = getchar()) != EOF)) { a[k++] = c; } a[k] = 0; clearerr(stdin); printf("Enter b: "); fflush(stdout); k = 0; while ((k < 100) && ((c = getchar()) != EOF)) { b[k++] = c; } b[k] = 0; printf("a is [%s]; b is [%s]\n", a, b); return 0; } 
  $ ./a.out
输入:两个
行(在下一个ENTER后面的Ctrl + D)
输入b:三
线
现在(ENTER + Ctrl + D)
 a是[两个
行(在下一个ENTER后面的Ctrl + D)
 ]。  b是[三
线
现在(ENTER + Ctrl + D)
 ]
 $ 

你如何在程序中输入null?

您可以使用以下命令实现-print0函数:

 putchar(0); 

这将打印一个ASCII nul字符’\ 0’到sdtout。