C语言用fscanf读取文件存数组触发Segmentation Fault问题求助
段错误(Segmentation Fault)排查与修复
问题场景
朋友备考时编写C代码读取memory.txt文件,执行while (fscanf(f, "%s %d %d", A[i].costruttore, A[i].ns, A[i].costo) != EOF)时持续触发段错误,尝试给A[i].ns和A[i].costo加&符号后问题仍未解决,以下是原代码和文件内容:
原代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define DIM 100 typedef struct { char costruttore[20]; int ns; int costo; } memoria; void lettura(memoria A[], int *n) { int i = 0; FILE *f; f = fopen("memory.txt", "r"); if( f == NULL ) { fprintf(stderr, "Couldn't open %s: %s\n", "memory.txt", strerror(errno)); exit(1); } while (fscanf(f, "%s %d %d", A[i].costruttore, A[i].ns, A[i].costo) != EOF) i++; (*n) = i; fclose(f); for (i = 0; i < (*n); i++) printf("%s %d %d\n", A[i].costruttore, A[i].ns, A[i].costo); } int main() { memoria A[DIM]; int n; lettura(A, &n); return 0; }
memory.txt内容
PerKele 56 41 AM-Silicon 49 41 JKR 33 50 Atlantic 57 62 JADA 50 50 JKR 40 51 Drast 28 35 SGUZ 73 55 JADA 29 46 FARSTIC 65 30 Drast 41 36 FRoW 48 67 FARSTIC 39 62 Drast 27 44 SGUZ 51 50 Drast 58 60 Liquid 41 71 SWP3 50 63 KRRAM 54 24 YTK 32 60 ALOE 37 57 HAL 53 39 AM-Silicon 59 50 Atlantic 24 42 ALOE 31 46 JADA 38 65 Nikit 48 49 PerKele 68 37 HAL 46 53 TOO 73 60 HAL 31 37 YTK 39 55 Nikit 57 47 FARSTIC 40 47 AM-Silicon 68 52 HAL 50 50 JADA 32 37 FRoW 47 53 SWP3 50 50 FRoW 52 52 JADA 63 58 Liquid 47 46 Drast 36 54 ALOE 44 30 HAL 39 33 Drast 48 41 SWP3 52 56 KRRAM 65 56
问题排查与修复
1. 核心错误:fscanf读取整数未传地址
fscanf读取int类型变量时,必须传递变量的内存地址(即使用&取址符)。原代码中A[i].ns和A[i].costo直接传入,这会把变量的值当作地址传递,导致非法内存访问,触发段错误。如果朋友说加了&仍未解决,大概率是修改位置错误或未保存生效。
2. 循环越界风险:未限制数组下标
当前循环没有检查i是否超过DIM-1,如果文件行数超过100,i会继续递增,访问数组A的越界内存,同样会触发段错误。
3. 返回值判断逻辑错误:不应仅判断!=EOF
fscanf的返回值是成功读取的变量个数,若仅判断!=EOF,当某行格式错误(比如缺少整数)时,fscanf会返回小于3的值但不等于EOF,导致循环一直执行,i不断增大最终越界。正确的判断应该是返回值等于3,确保每行的三个字段都读取成功。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define DIM 100 typedef struct { char costruttore[20]; int ns; int costo; } memoria; void lettura(memoria A[], int *n) { int i = 0; FILE *f; f = fopen("memory.txt", "r"); if( f == NULL ) { fprintf(stderr, "无法打开文件 %s: %s\n", "memory.txt", strerror(errno)); exit(1); } // 修复:添加数组边界检查,且判断fscanf返回值为3 while (i < DIM && fscanf(f, "%s %d %d", A[i].costruttore, &A[i].ns, &A[i].costo) == 3) i++; (*n) = i; fclose(f); for (i = 0; i < (*n); i++) printf("%s %d %d\n", A[i].costruttore, A[i].ns, A[i].costo); } int main() { memoria A[DIM]; int n; lettura(A, &n); return 0; }
修复说明
- 给
A[i].ns和A[i].costo添加&,传递正确的内存地址给fscanf - 循环条件增加
i < DIM,避免数组越界 - 将
fscanf的返回值判断改为==3,确保每行三个字段都读取成功,避免死循环
内容的提问来源于stack exchange,提问作者Keller
相关产品推荐
相关产品推荐

