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

mua*_*loc 14 c eof getchar

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Kei*_*son 29

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

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

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

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

POSIX read()函数通过返回零字节计数向其调用者指示文件结束(或错误)条件,指示不再有要读取的数据字节.(<stdio>在POSIX系统上,C 是建立在read()其他POSIX特定功能之上的.)

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