fscanf读取数据丢失值求助:CLion与PellesC运行结果不一致
问题分析与解决:fscanf读取数据时surname字段为空的问题
问题根源
你的代码中char gender[1]是核心错误:fscanf的%s格式符会读取连续的非空白字符,然后自动在末尾添加空终止符'\0'来标记字符串结束。但gender[1]只有1字节的存储空间,存入'F'后没有多余空间存放'\0',这会触发C语言中的未定义行为——溢出的'\0'会覆盖相邻变量sname的末尾空终止符,导致printf输出sname时无法识别有效字符串的结束位置,最终表现为空字符串。
为什么PellesC能正常运行?
这只是编译器差异导致的巧合:不同编译器的栈变量排列顺序、内存布局可能不同,PellesC的栈布局刚好让溢出的'\0'没有破坏sname的关键数据,但这种行为完全不可靠,代码本身依然不符合C语言规范,换环境随时可能出错。
修正方案
有两种可靠的修正方式:
方案1:扩容gender数组
将char gender[1]改为char gender[2],预留出空终止符的空间:
FILE *fp; char fname[20]; char sname[20]; char gender[2]; // 扩容为2字节,容纳字符+空终止符 int ID; int age; fp = fopen("C:\\Users\\Catlover\\Desktop\\DSA\\Program2\\StudentList.txt", "r"); if (fp == NULL) { perror("Failed to open file"); return 1; } // 用返回值等于5判断是否成功读取所有字段,比!=EOF更可靠 while(fscanf(fp, "%s %s %s %d %d", fname, sname, gender, &ID, &age) == 5) { printf("%s,%s,%s,%d,%d\n", fname, sname, gender, ID, age); } fclose(fp); return 0;
方案2:用%c读取单个字符(更推荐)
因为gender是单个字符,不需要用字符串格式读取,改用%c格式符,同时注意跳过前面的空白(%c不会自动跳过空白,格式串前加空格即可):
FILE *fp; char fname[20]; char sname[20]; char gender; // 改为单个char变量 int ID; int age; fp = fopen("C:\\Users\\Catlover\\Desktop\\DSA\\Program2\\StudentList.txt", "r"); if (fp == NULL) { perror("Failed to open file"); return 1; } // %c前加空格,自动跳过换行、空格等空白字符 while(fscanf(fp, "%s %s %c %d %d", fname, sname, &gender, &ID, &age) == 5) { printf("%s,%s,%c,%d,%d\n", fname, sname, gender, ID, age); } fclose(fp); return 0;
额外注意事项
- 永远确保字符串数组大小足够容纳内容+空终止符,避免缓冲区溢出,这是C语言中常见的安全隐患。
- 用
fscanf时,建议检查返回值是否等于预期读取的字段数(比如这里的5),而非仅判断!=EOF,这样能及时发现文件格式错误等读取失败的情况。 - 处理单个字符时,
%c不会自动跳过空白(空格、换行等),格式串前加空格可以解决这个问题,确保读取到正确的目标字符。
内容的提问来源于stack exchange,提问作者catlover
相关产品推荐
相关产品推荐

