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

时间:2014-01-21 14:18:56

标签: 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;
}

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

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

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

3 个答案:

答案 0 :(得分:29)

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

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

这是由section 11中的POSIX / The Open Group Base Specifications Issue 7指定(而非间接),具体为11.1.9:

  

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

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

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

答案 1 :(得分:1)

有人看到这个需要我需要的帮助的机会......我一直在寻找,试图弄清楚为什么我会用我的while(scanf)获得这种奇怪的行为。好吧,事实证明我有while (scanf("%s\n", string) > 0)。我正在使用的编辑器(Atom)会自动添加一个&#34; \ n&#34;在我的扫描中,没有注意到我。这花了我几个小时,幸运的是有人向我指出。

答案 2 :(得分:0)

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