是否在返回EOF后定义了getc()?

时间:2011-01-20 23:28:33

标签: c io

我在C练习中使用getc();,在回顾该程序后,我发现了一些奇怪的东西。我假设在命令行参数上给出的文件至少包含一个字节。 (它连续两次调用getc();而不检查EOF。在空文件上尝试后,它仍能正常运行。我的问题是:getc();的行为一个已经用尽的文件指针(已达到EOF而未被复卷)未定义或是否会继续返回EOF?

我想我可以将这个问题扩展到C STL中的所有I / O函数,请在答案中澄清这一点。

这是该程序的代码。该程序应该从所有注释中删除C / C ++源文件(并且它完美地工作)。

#include <stdio.h>

int main(int argc, char *argv[]) {
    int state = 0; // state: 0 = normal, 1 = in string, 2 = in comment, 3 = in block comment
    int ignchar = 0; // number of characters to ignore
    int cur, next; // current character and next one
    FILE *fp; // input file

    if (argc == 1) {
        fprintf(stderr, "Usage: %s file.c\n", argv[0]);
        return 1;
    }

    if ((fp = fopen(argv[1], "r")) == NULL) {
        fprintf(stderr, "Error opening file.\n");
        return 2;
    }

    cur = getc(fp); // initialise cur, assumes that the file contains at least one byte
    while ((next = getc(fp)) != EOF) {
        switch (next) {
            case '/':
                if (!state && cur == '/') {
                    state = 2; // start of comment
                    ignchar = 2; // don't print this nor next char (//)
                } else if (state == 3 && cur == '*') {
                    state = 0; // end of block comment
                    ignchar = 2; // don't print this nor next char (*/)
                }
                break;
            case '*':
                if (!state && cur == '/') {
                    state = 3; // start of block comment
                    ignchar = 2; // don't print this nor next char (/*)
                }
                break;
            case '\n':
                if (state == 2) {
                    state = 0;
                    ignchar = 1; // don't print the current char (cur is still in comment)
                }
                break;
            case '"':
                if (state == 0) {
                    state = 1;
                } else if (state == 1) {
                    state = 0;
                }
        }

        if (state <= 1 && !ignchar) putchar(cur);
        if (ignchar) ignchar--;
        cur = next;
    }

    return 0;
}

3 个答案:

答案 0 :(得分:6)

Stdio文件保留一个“eof”标记,该标记在第一次到达文件结束时设置,并且只能通过调用clearerr或执行成功fseekrewind来重置。因此,一旦getc返回EOF一次,它将继续返回EOF,即使新数据可用,除非您使用上述方法之一清除eof标志。

某些不符合要求的实施可能会立即提供新数据。这种行为是有害的,可能会破坏符合要求的应用程序。

答案 1 :(得分:1)

如果设置了流上的EOF标记,则getc应该返回EOF(如果您继续致电getc,则应该继续EOF )。

答案 2 :(得分:1)

逻辑上,我认为它应该永远返回EOF

getc是根据fgetc定义的。

  

getc()函数应该等效于fgetc(),除非它是   作为宏实现它可以多次评估流,所以   论证永远不应该是一个有副作用的表达。

fgetc的文档说:

  

如果设置了流的文件结束指示符,或者是流   在文件结尾处,应设置流的文件结束指示符   和fgetc()将返回EOF。

并且“在文件结尾处”可以通过调用feof来确定。

feof的文档说:

  

feof()函数当且仅当返回非零时才返回非零值       为流设置了文件结束指示符。

因此,除非发生某些事情以清除文件结束指示符,否则它应该继续永久地返回EOF