You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 08:10:31