0

我有一个将文件读入缓冲区结构的程序。我遇到的问题是,当我查看文件的输出时,末尾有一个额外的 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)++];
}

最后我得到:

“a catÿ”(y 是 EOF 字符)

它打印一个 EOF 字符,但从不添加到缓冲区中。当驱动程序代码将 EOF 字符添加到缓冲区的末尾时,会出现 2。知道是什么原因造成的吗?我可能用feof()错了,所以可能是这样,但在代码中是必需的

4

2 回答 2

6

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

(对于 Windows 文本文件,文件中的 Control-Z 字符可能会触发文件结束条件。如果您以文本模式读取此类文件,您将看不到该字符;它的行为就像此时已到达文件末尾。)

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

getchar()例如,返回它刚刚读取的字符(被视为 an并转换为)指示它无法读取任何内容值。专门选择负值是为了避免与 type 的任何有效值发生冲突。这意味着您需要将返回的值存储在一个对象中;如果将其存储在or中,则可能会丢失信息,并且具有该值的实际字符可能会被误认为.unsigned charintEOFEOFunsigned chargetchar()intcharunsigned char0xffEOF

feof()函数返回您正在读取的文件的文件结束指示符的值。在您尝试读取文件但未能成功,该指示符变为真。如果您因为错误而不是因为文件结束条件而用完输入,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(),并查看是否可以通过这种方式重现问题。

于 2013-09-25T20:10:21.323 回答
-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;
}    
于 2013-09-25T21:07:02.573 回答