为什么我需要两次键入Ctrl-D来标记文件结尾?

char **query; query = (char**) malloc ( sizeof(char*) ); int f=0; int i=0,j=0,c; while((c=getchar())!=EOF) { if(!isalpha(c)) continue; if(f==1) query=(char**) realloc(query,(i+1)*sizeof(char*)); query[i]=(char*) malloc(sizeof(char)); query[i][j]=c; j++; while( (c=getchar())!=EOF&&c!=' '&&c!='\t' ) { query[i]=(char*) realloc(query[i],(j+1)*sizeof(char)); query[i][j]=c; ++j; } query[i][j]='\0'; printf("%s\n",query[i]); if(c==EOF){ break; } ++i; f=1; j=0; } 

我希望上面的代码片段读取由空格和制表符分隔的一串字符串,直到ONE EOF,但它需要2个EOF才能结束循环。 此外,字符串只能由字母字符组成。

我在约2天内挣扎。 请提供一些反馈。

编辑:最有可能的原因是我在写完最后一个字符串而不是输入键后按CTRL + D键,但现在我按Enter键然后按CTRL + D,它按预期工作。 但是,在按下最后一个字符串后按CTRL + D后,如何将其更改为完成?

在类Unix系统上(至少在默认情况下),通过在行的开头键入Ctrl-D 通过键入Ctrl-D 两次触发(如果您不在行的开头)来触发文件结束条件。

在后一种情况下,您阅读的最后一行在其末尾没有'\n' ; 你可能需要考虑到这一点。

这是由POSIX / Open Group Base Specifications Issue 7( 第11节 ,特别是11.1.9)指定(而非间接):

EOF
输入上的特殊字符,如果设置了ICANON标志,则会识别该字符。 收到后,等待读取的所有字节将立即传递给进程,而不等待,并丢弃EOF。 因此,如果没有字节等待(即,EOF发生在一行的开头),则应从read()返回字节计数为零,表示文件结束指示。 如果设置了ICANON,则处理时应丢弃EOF字符。

POSIX read()函数通过返回零字节计数向其调用者指示文件结束(或错误)条件,表示没有更多字节的数据要读取。 (C的是在POSIX系统上构建的,基于read()和其他POSIX特定的函数。)

EOF(不要与C EOF宏混淆)默认映射到Ctrl-D 。 在行的开头键入EOF字符(在输入的最开始或紧接在换行之后)会触发立即结束文件的条件。 键入EOF字符而不是行的开头会导致该行上的先前数据立即被下一个要求足够字节的read()调用返回; 再次输入EOF字符会做同样的事情,但在这种情况下,没有剩余的字节需要读取,并且触发了文件结束条件。 丢弃一行中间的单个EOF字符(如果ICANON ,通常是这样)。

如果有人看到这个需要我一直需要的帮助的机会……我一直在寻找,试图弄清楚为什么我会用我的while(scanf)获得这种奇怪的行为。 好吧,事实certificate我有while (scanf("%s\n", string) > 0) 。 我正在使用的编辑器(Atom)会自动在我的扫描中放入一个“\ n”,但我注意到了。 这花了我几个小时,幸运的是有人指出了我。

Return键不会产生EOF,这就是条件getchar() != EOF无法识别它的原因。 您可以通过在Windows中按CTRL + Z或在Unix中按CTRL + D来执行此操作。