额外的EOF角色

时间:2013-09-25 18:50:49

标签: c feof

我有一个程序将文件读​​入缓冲区结构。我遇到的问题是,当我查看文件的输出时,最后会有一个额外的EOF字符。发布相关功能:(注意:我删除了参数检查,只在与问题相关的功能中发布了代码)

b_load

int b_load(FILE * const fi, Buffer * const pBD){
    unsigned char character; /*Variable to hold read character from file*/
    Buffer * tempBuffer; /*Temparary Bufer * to prevent descruction of main Buffer*/
    short num_chars = 0; /*Counter of the amount of characters read into the buffer*/

    /*Assigns main Buffer to tempBuffer*/
    tempBuffer = pBD;

    /*Infinite loop that breaks after EOF is read*/
    while(1){
        /*calls fgetc() and returns the char into the character variable*/
        character = (unsigned char)fgetc(fi);

        if(!feof(fi)){
            tempBuffer = b_addc(pBD,character);

            if(tempBuffer == NULL)
                return LOAD_FAIL;
            ++num_chars;
        }else{  
            break;
        }
    }
    return num_chars;
}    

b_print

int b_print(Buffer * const pBD){
    int num_chars = 0;

    if(pBD->addc_offset == 0)
        printf("The buffer is empty\n");
    /*Sets getc_offset to 0*/
    b_set_getc_offset(pBD, 0);

    pBD->eob=0;

    /*b_eob returns the structures eob field*/
    while (!b_eob(pBD)){
        printf("%c",b_getc(pBD));
        ++num_chars;
    }
    printf("\n");

    return num_chars;
}

b_getc

char b_getc(Buffer * const pBD){
    if(pBD->getc_offset  == pBD->addc_offset){
        pBD->eob = 1;
        return R_FAIL_1;
    }   
    pBD->eob = 0;
    return pBD->ca_head[(pBD->getc_offset)++];
}

最后我最终得到:

“一只猫” (y是EOF字符)

它打印一个EOF字符,但从未添加到缓冲区。当驱动程序代码将EOF字符添加到缓冲区的末尾时,会出现2。知道是什么导致了这个吗?我可能使用feof()错误,因此可能是错误的,但在代码中需要它

2 个答案:

答案 0 :(得分:6)

没有“EOF角色”。 EOFgetchar()和相关函数返回的值,表示它们没有更多要读取的输入。它是一个扩展为负整数常量表达式的宏,通常为(-1)

(对于Windows文本文件,文件结束条件可能由文件中的Control-Z字符触发。如果您在文本模式中读取此类文件,则不会看到那个角色;它就像它到达文件末尾一样。)

不要使用feof()函数来检测没有更多要读取的输入。相反,请查看您正在使用的任何输入函数返回的值。不同的输入函数使用不同的方式来表示它们无法读取任何内容;阅读您正在使用的文档。例如,fgets()返回空指针,getchar()返回EOFscanf()返回它能够读取的项目数。

例如,

getchar()会返回 刚刚读取的字符(视为unsigned char并转换为intEOF表示它无法读取任何内容。选择EOF的负值是为了避免与类型unsigned char的任何有效值发生冲突。这意味着您需要将getchar()返回的值存储在int对象中;如果您将其存储在charunsigned char中,则可能会丢失信息,而值为0xff的实际字符可能会被误认为是EOF

feof()函数返回您正在读取的文件的文件结束指示符的值。 之后,该指示符变为true,并且无法从文件中读取。如果由于错误导致输入用完,而不是因为文件结束条件,feof() 永远不会成为真。

您可以使用feof()和/或ferror()来确定无法读取更多输入的原因,但只有在您通过其他方式检测到输入后才能确定。

推荐阅读:comp.lang.c FAQ的第12节,其中包括stdio。 (以及其余部分。)

更新:

我没有看到足够的代码来了解您对Buffer对象所做的事情。你的输入看起来实际上看起来(几乎)是正确的,尽管它是以笨拙的方式写的。

从文件中读取字符的通常习惯是:

int c;   /* `int`, NOT `char` or `unsigned char` */
while ((c = fgetc(fi)) != EOF) {
    /* process character in `c` */
}

但你的方法,我可能会像这样重新安排:

while (1) {
    c = fgetc(fi);
    if (feof(fi) || ferror(fi)) {
        /* no more input */
        break;
    }
    /* process character in c */
}

应该真的有效。请注意,我添加了对ferror(f1)的检查。可能是你输入错误(你没有检测到)?这会导致c包含EOF,或EOF的值转换为c类型。但这是值得怀疑的,因为它可能会给你一个无限循环。

建议的方法:使用交互式调试器或添加的printf调用,每次循环显示character的值。如果您的输入循环正常工作,那么使用硬连线的b_addc()调用序列构建程序的精简版本,并查看是否可以通过这种方式重现问题。

答案 1 :(得分:-1)

你去......

int b_load(FILE * const fi, Buffer * const pBD){
    int character; /*Variable to hold read character from file*/
    Buffer * tempBuffer; /*Temparary Bufer * to prevent descruction of main Buffer*/
    short num_chars ; /*Counter of the amount of characters read into the buffer*/


    /*Infinite loop that breaks WHEN EOF is read*/
    while(num_chars = 0; 1; num_chars++ ) {

        character = fgetc(fi);
        if (character == EOF || feof(fi)) break; // since you insist on the silly feof() ...

        tempBuffer = b_addc(pBD, (unsigned char) character);
        if(tempBuffer == NULL) return LOAD_FAIL;
        }
    }
    return num_chars;
}