为何fscanf未读取首行首个字符串,反而将末行内容存入首字符串?
C语言fscanf读取异常问题分析与修复
问题根源
核心问题是数组索引越界,导致内存被非法覆盖,进而让date数组的内容被最后一条学生数据篡改:
- 定义的
studenid[10][100]和using_hour[10]仅能存储10条学生数据(索引范围0~9) - 第一个循环执行11次(
i < 11):第1次读取首行日期,第2~11次读取学生数据时,用studenid[i]和using_hour[i],当i=10时,访问的是数组第11个元素(超出边界) - 栈内存布局导致越界写入的内容覆盖了
date数组,最终date[0]被最后一条学生ID41051替换
此外还有两个次要问题:
#define宏定义后多加了分号,会引发后续语法错误main函数最后返回1,正常退出应返回0
修复后的代码
#include <stdio.h> #include <string.h> #include <ctype.h> // 移除宏定义后的分号 #define first_ten_hours 7.99 #define after_ten_hours 1.99 double charges_all(int hour); double charges_avg(int money, int hour_use); double round_money(double sum); int main() { FILE *f_read, *f_write; f_read = fopen("usage.txt", "r"); f_write = fopen("charges.txt", "w"); if(f_read == NULL) { printf("Error to open the file.\n"); return 1; } char date[2][10]; char studenid[10][100]; double using_hour[10]; int current_line = 1; for(int i = 0; i < 11; i++) { if(current_line == 1) { fscanf(f_read, "%s %s", date[0], date[1]); current_line++; } else { // 用i-1作为学生数组索引,避免越界 fscanf(f_read, "%s %lf", studenid[i-1], &using_hour[i-1]); current_line++; } } current_line = 1; for(int i = 0; i < 11; i++) { if(current_line == 1) { printf("%s %s\n", date[0], date[1]); current_line++; } else { // 同样用i-1作为索引 printf("%s %lf\n", studenid[i-1], using_hour[i-1]); current_line++; } } fclose(f_read); fclose(f_write); // 正常退出返回0 return 0; }
修复说明
- 修正数组索引:读取和输出学生数据时,使用
i-1作为数组索引,确保仅访问0~9的合法范围,避免越界覆盖内存 - 移除宏定义分号:
#define是预处理指令,无需分号,否则会引入语法错误 - 修正返回值:
main函数正常执行完成后返回0,符合C语言规范
修改后,printf输出的首行会正确显示12 2022,所有学生数据也能正常读取和输出。
内容的提问来源于stack exchange,提问作者LunaticCoder
相关产品推荐
相关产品推荐

