使用fgets和sscanf读取文件内容时copies变量无法正确取值问题
读取失败的核心原因
导致copies变量无法正确读取的问题集中在以下几点:
- sscanf格式字符串语法错误:你写的
%f[^,],%d[^ ]不符合scanf的格式规则,%f已经完成浮点数读取,后续的[^,]会被识别为独立的格式匹配符,但你没有提供对应的字符数组接收匹配结果,格式匹配从这里直接错位,后续的%d完全无法匹配到正确的整数,copies一直保留初始化的0值。 - 变量名不匹配:代码中定义的输出变量是
author、title、genre、price、copies,但你传入sscanf的是autore、titolo、genere、prezzo、copie,两组变量完全无关,哪怕格式匹配正确,输出的还是初始化的旧值。 - 其他隐藏问题:
while(!feof(fp))的写法会导致文件读完后多执行一次无效读取;未判断fopen返回值,文件不存在时会直接崩溃;字段前后的空格和title的引号没有处理,会被读取到字段内容中。
更优的实现方式
修正后的代码如下:
#include <stdio.h> int main() { FILE *fp = NULL; char string[100]; char title[30], author[30], genre[30]; float price; int copies = 0; // 打开文件并判断是否成功 fp = fopen("file.txt", "r"); if (fp == NULL) { perror("fopen failed"); return 1; } // 直接用fgets返回值判断是否读完,避免feof的问题 while(fgets(string, sizeof(string), fp) != NULL) { // 格式串适配带引号的title,限制读取长度避免缓冲区溢出 if (sscanf(string, "%29[^,], \"%29[^\"]\", %29[^,], %f, %d", author, title, genre, &price, &copies) == 5) { // 匹配成功才输出,避免无效行的干扰 printf("%s %s %s %.2f %d\n", author, title, genre, price, copies); } } fclose(fp); return 0; }
关键修改点说明:
- 格式串适配字段规则:专门处理了title的双引号,同时每个字符串读取限制29字符,预留
\0的位置避免缓冲区溢出 - 增加匹配成功判断:sscanf返回成功匹配的字段数,只有返回5时才代表所有字段都读取成功,避免无效行干扰
- 替换feof逻辑:直接用fgets的返回值判断文件是否读完,逻辑更严谨
- 增加文件打开失败判断,避免空指针访问
内容的提问来源于stack exchange,提问作者Domnik
相关产品推荐
相关产品推荐

