为什么从文件中读取结构时,fread()函数未到达文件末尾并且循环无限地继续?

时间:2019-07-17 05:47:12

标签: c structure file-handling data-files

下面给出的代码段是我用C语言编写的“客户计费系统”项目的一部分。在这里,我将客户数据输入到“客户”结构中,并将整个结构保存在“ CustomerRecord.dat”中使用我的代码中定义的writefile()函数创建文件。在将客户数据成功写入文件后,我试图遍历文件并为每条记录分配客户编号。为此,我使用了代码中定义的setCustomerNo()函数。

问题是setCustomerNo()函数内部的while循环无限运行,甚至在文件结束后仍会读取。

请帮助我解决此问题。

我尝试替换:

  1. while(!feof(fp){// LOOP BODY}
  2. while(!feof(fp)&&!ferror(fp)){// LOOP BODY}
  3. while(fread(&x,sizeof(Customer),1,fp)||!feof(fp)){// LOOP BODY}

但以上所有替代方法都不适合我。

#define RECORD CustomerRecord.dat
typedef struct
{
    int customerNo;
    unsigned int phoneNo;
    char name[20];
    char address[32];
    float balance;
}Customer;

void writefile(Customer x)
{
    FILE *fp;
    fp = fopen("CustomerRecord.dat", "ab");
    fwrite(&x, sizeof(Customer), 1, fp);
    fclose(fp);
}

Customer setCustomerNo()
{
    FILE *fp;
    Customer x, y;
    int k = 1;

    fp = fopen(RECORD, "rb+");
    while(!feof(fp) && !ferror(fp))
    {
        fread(&x, sizeof(Customer), 1, fp);
        x.customerNo = k++;
        y = x;
        fseek(fp, -sizeof(Customer), SEEK_CUR);
        fwrite(&x, sizeof(Customer), 1, fp);
    }
    fclose(fp);
    return y;
}

预期结果是函数setCustomerNo()从头开始读取文件中存储的所有结构,并从1开始更新customerNo,以此类推,直到文件中存储的结构。最后返回最后更新的结构。

1 个答案:

答案 0 :(得分:1)

您绝对不希望您的循环测试feof(fp)(实际上就是practically never right),因为如果发生循环,feof(fp)在结尾处总是为false,所以循环永远不会结束。为什么? fseek联机帮助页将其说明如下:

  

成功调用fseek()函数将清除流的文件结束指示符。

无论如何,如果您考虑一下,您想在fread报告没有数据时完全终止循环。您当然不希望处理fread尚未读取的不存在的数据。因此,即使feof(fp)实际上返回了一个有用的值,在处理可能的未读数据之后测试是否存在EOF也不对。


其他一些注意事项:

  1. 最好使用ftell来调用read之前的读取光标,然后fseek指向保存的点。这样就避免了很多极端情况,并且可以轻松升级以使用更通用的fseeko/ftello函数,该函数可以正常处理大文件。 (或者,您可以直接使用fseekoftello

  2. 考虑一下如果最后一个read是不完整的,您想做什么。当然,如果您始终创建固定长度的记录,则“不可能发生”。但是由于某种原因或其他原因,所有“不可能发生”的事情最终都会发生。最好处理它。