C语言fscanf循环无法终止问题求助(含结构体存二进制文件需求)
解决fscanf无法终止及代码中的其他问题
首先,你的while循环停不下来的核心原因是错误判断了fscanf的返回值。fscanf在读取失败或到达文件末尾时返回的是EOF,而不是NULL——NULL是指针类型的空值,和fscanf的整数返回值完全不匹配,这就导致循环永远不会终止。
除此之外,代码里还有几个需要修正的细节问题,我来逐一拆解并给出修复方案:
主要错误点分析
fscanf返回值判断错误:应该用!= EOF替代!= NULL,更严谨的做法是检查读取的项数是否符合预期,避免出现部分读取的异常情况。fscanf传参错误:linha是字符数组名,本身就是指向数组首元素的指针,不需要加&,写成fscanf(f, " %s", linha)才是正确的写法。fwrite参数错误:你每次只需要写入1个struct paragem实例,第三个参数应该是1而不是2,否则会重复写入两次相同的数据。- 文件打开失败未终止程序:如果打开文件失败(比如
f或p为NULL),后续的文件操作会导致未定义行为,应该在报错后立即终止程序。 - 未关闭文件:操作完成后需要用
fclose关闭文件,确保缓冲区的数据完全写入磁盘,避免资源泄漏。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define TAM 20 struct paragem{ char local[TAM]; float hora; }; int main() { FILE *f, *p; struct paragem c; char linha[TAM]; int read_result; // 打开文本文件,失败则退出程序 f = fopen("perc.txt", "rt"); if(f == NULL) { printf("erro ao abrir ficheiro txt\n"); exit(1); } // 打开二进制文件,失败则关闭已打开的文本文件并退出 p = fopen("rota.bin", "wb"); if(p == NULL) { printf("erro ao abrir ficheiro bin\n"); fclose(f); exit(1); } // 读取开头的编号(如"23A45"),不需要处理则直接跳过 read_result = fscanf(f, "%s", linha); if(read_result != 1) { printf("Erro ao ler o cabeçalho do ficheiro\n"); fclose(f); fclose(p); exit(1); } // 循环读取地点和时间对,直到文件末尾或读取失败 while(1) { // 读取地点 read_result = fscanf(f, " %s", linha); if(read_result != 1) { break; // 读取失败或到文件末尾,退出循环 } strcpy(c.local, linha); // 读取时间 read_result = fscanf(f, " %f", &c.hora); if(read_result != 1) { break; } // 写入二进制文件,检查是否写入成功 if(fwrite(&c, sizeof(struct paragem), 1, p) != 1) { printf("Erro ao escrever no ficheiro binário\n"); break; } } // 关闭所有打开的文件 fclose(f); fclose(p); return 0; }
关键修改说明
- 返回值判断优化:用
read_result变量接收fscanf的返回值,判断是否成功读取了1项,这样能更精准地处理文件格式错误等异常情况。 - 修复
fscanf传参:去掉linha前的&,避免指针类型不匹配的潜在问题。 - 修正
fwrite参数:第三个参数改为1,确保每次只写入一个结构体实例,避免重复写入。 - 完善错误处理:文件打开失败后立即终止程序,中途出错时关闭已打开的文件,避免资源泄漏。
- 添加文件关闭操作:确保所有打开的文件都被正确关闭,保证数据完全写入磁盘。
这样修改后,程序就能正确读取文本文件中的地点和时间对,写入二进制文件,并且循环会在文件末尾正常终止。
内容的提问来源于stack exchange,提问作者Walter Palma
相关产品推荐
相关产品推荐

