使用!feof搜索文件是否安全?do/while+!feof的写法可行吗?
关于使用!feof作为do/while循环退出条件的问题分析
你这种写法依然存在严重问题,本质上还是没避开!feof的经典陷阱,下面具体拆解问题并给出改进方案:
为什么!feof不能作为循环终止条件?
feof()的作用是检查文件结束标志是否被设置,而这个标志只会在**读取操作失败(比如尝试读取文件末尾之后的内容)**时才会被触发。也就是说,当你读完文件最后一条有效数据后,feof()依然会返回假,只有当你再次尝试读取(此时读取失败),feof()才会返回真。
你的do/while逻辑是先执行fscanf再判断!feof,这就会导致:当fscanf已经读到文件末尾并失败时,你还是会执行后续的strcmp操作——此时e.fname里的内容是未定义的(可能是上一次读取的残留值,也可能是内存垃圾),这会导致错误的比较结果,甚至触发未定义行为。
你的代码还有这些额外问题
- 未检查
fscanf的返回值:fscanf成功读取指定数量的参数时会返回对应的值(这里是3),如果遇到文件末尾、格式错误等情况,返回值会小于3。你直接忽略这个返回值,会导致用无效数据进行比较。 - 格式字符串多余的
\n:%s和%d本身会自动跳过空白字符(包括换行、空格),加\n会让fscanf在读取完数据后继续跳过所有空白直到遇到非空白字符,可能导致意外的阻塞或读取异常。 fopen失败后仍执行fclose:如果fopen返回NULL,后续执行fclose(f)相当于调用fclose(NULL),这是未定义行为,会导致程序崩溃。
正确的写法示例
应该以fscanf的返回值作为循环判断条件,确保只有读取到有效数据时才进入处理逻辑:
typedef struct { char lname[20] , fname[20]; int nchildren; }employee; void searchemployee(char *filename , char *str) { employee e; FILE *f; int found = 0; f = fopen(filename, "r"); if (f == NULL) { printf("file couldn't be loaded\n"); return; // 打开失败直接返回,避免后续错误操作 } // 仅当成功读取3个字段时,才进入循环处理 while (fscanf(f, "%s %s %d", e.fname, e.lname, &e.nchildren) == 3) { if (strcmp(e.fname, str) == 0) { found = 1; printf("employee : %s %s| children : %d\n", e.fname, e.lname, e.nchildren); break; // 找到目标后直接退出循环,无需继续读取 } } if (!found) { printf("employee not found\n"); } fclose(f); }
关键改进点说明
- 用
fscanf的返回值控制循环,彻底避免了处理无效数据的情况; - 找到目标员工后直接
break退出循环,提升效率; - 修复了
fopen失败后的流程,避免调用fclose(NULL); - 去掉格式字符串中多余的
\n,符合scanf系列函数的使用规范。
内容的提问来源于stack exchange,提问作者ayoub hmani
相关产品推荐
相关产品推荐

