下面给出的代码片段是我用 C 编写的客户计费系统项目的一部分。在这里,我在客户结构中输入客户数据并将整个结构保存在“CustomerRecord.dat”中使用我的代码中定义的 writefile() 函数写入文件。在我的文件中成功写入客户数据后,我尝试遍历文件并为每条记录分配客户编号。为此,我使用了代码中定义的 setCustomerNo() 函数。
问题是 setCustomerNo() 函数内的 while 循环无限运行,甚至在文件结束后读取。
请帮我解决这个问题。
我试过替换:
- while(!feof(fp) {//循环体 }
- while(!feof(fp) && !ferror(fp)) {//循环体 }
- while(fread(&x, sizeof(Customer), 1, fp) || !feof(fp)) {//循环体 }
但以上这些替代品都不适合我。
#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(s)等到文件中存储的结构。最后返回最后更新的结构。
最佳答案
您肯定不希望您的循环测试feof(fp)
——事实上,那是practically never right -- 因为 feof(fp)
在循环结束时总是 false,所以循环永远不会结束。为什么? fseek
联机帮助页详细说明:
A successful call to the
fseek()
function clears the end-of-file indicator for the stream.
无论如何,如果您考虑一下,您希望恰好在 fread
报告它没有数据时终止循环。您当然不想处理 fread
未读取的不存在的数据。因此,即使 feof(fp)
实际上返回了一个有用的值,在处理完可能未读的数据后测试是否存在 EOF 也是不正确的。
一些其他注意事项:
您最好使用
ftell
在read
之前调用读取游标,然后使用fseek
ing 保存观点。这避免了一堆极端情况,并且很容易升级为使用更通用的fseeko/ftello
函数,这些函数可以正常处理大文件。 (或者您可以直接使用fseeko
和ftello
。想想如果最后的
read
是部分的,你想做什么。当然,如果您总是创建固定长度的记录,那“不可能发生”。但是,出于某种原因,“不可能发生”的一切最终都会发生。最好处理一下。
关于c - 为什么 fread() 函数没有到达文件末尾并且在从文件读取结构时循环无限继续?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57069236/