解决sscanf读取文本文件时字符串被追加后续数据的问题
问题描述
使用sscanf从文本文件读取数据时,出现后续列数据被追加到字符串类型字段的异常。例如读取student.txt时,第一行的国家字段本该是KOR,却被读成了KORCE。
输入文件 student.txt 内容
Donald 23 KOR CE Mitchell 24 USA EE John 22 KOR CE
当前错误输出
Donald 23 KORCE CE Mitchell 24 USAEE EE John 22 KORCE CE
现有代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LINE_LENGTH 100 typedef struct { char name[20]; int age; char country[3]; char dept[2]; } STUDENT; int main() { int i = 0; STUDENT student[15]; // Initialize the student array for (i = 0; i < 15; i++) { memset(student[i].name, 0, sizeof(student[i].name)); student[i].age = 0; memset(student[i].country, 0, sizeof(student[i].country)); memset(student[i].dept, 0, sizeof(student[i].dept)); } // Open the file for reading FILE *fp = fopen("student.txt", "r"); if (fp == NULL) { puts("Error: Could not open file 'student.txt'"); return 1; } // Read the file line by line char line[MAX_LINE_LENGTH]; while (fgets(line, MAX_LINE_LENGTH, fp) != NULL) { // Parse the line and fill the structure if (sscanf(line, "%s %d %s %s", student[i].name, &student[i].age, student[i].country, student[i].dept) != 4) { printf("Error: Invalid data in file 'student.txt'\n"); return 1; } // Print the structure printf("Name: %s\n", student[i].name); printf("Age: %d\n", student[i].age); printf("Country: %s\n", student[i].country); printf("Dept: %s\n", student[i].dept); i++; } // Close the file fclose(fp); return 0; }
问题根源
C语言中字符串必须以**空字符\0**作为结束标志,否则用%s打印时会持续读取内存直到遇到空字符,导致相邻字段的内容被追加输出。
你的代码里:
country[3]只能存3个字符,没多余空间放结束符,sscanf用%s读取KOR后无法自动添加\0;- 后续读取的
CE存在相邻的dept字段中,打印country时就会把dept的内容也读出来,形成KORCE。
修复方案
方案1:调整结构体数组长度,预留结束符空间
修改结构体定义,给字符串字段多分配1个字节用于存储结束符:
typedef struct { char name[20]; // 已有足够空间 int age; char country[4]; // 3个字符 + 1个结束符 char dept[3]; // 2个字符 + 1个结束符 } STUDENT;
方案2:在sscanf中限制读取字符数(推荐结合方案1)
在sscanf的格式控制符中指定最大读取字符数,避免内存越界,即使数组长度足够也能防止意外的超长输入:
// 修改sscanf的格式字符串 if (sscanf(line, "%s %d %3s %2s", student[i].name, &student[i].age, student[i].country, student[i].dept) != 4) { printf("Error: Invalid data in file 'student.txt'\n"); return 1; }
完整修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LINE_LENGTH 100 typedef struct { char name[20]; int age; char country[4]; // 预留结束符空间 char dept[3]; // 预留结束符空间 } STUDENT; int main() { int i = 0; STUDENT student[15]; // Initialize the student array for (i = 0; i < 15; i++) { memset(student[i].name, 0, sizeof(student[i].name)); student[i].age = 0; memset(student[i].country, 0, sizeof(student[i].country)); memset(student[i].dept, 0, sizeof(student[i].dept)); } // Open the file for reading FILE *fp = fopen("student.txt", "r"); if (fp == NULL) { puts("Error: Could not open file 'student.txt'"); return 1; } // 初始化循环后i变为15,重置为0才能正确填充数组 i = 0; // Read the file line by line char line[MAX_LINE_LENGTH]; while (fgets(line, MAX_LINE_LENGTH, fp) != NULL) { // Parse the line with limited character reads if (sscanf(line, "%s %d %3s %2s", student[i].name, &student[i].age, student[i].country, student[i].dept) != 4) { printf("Error: Invalid data in file 'student.txt'\n"); return 1; } // Print the structure printf("Name: %s\n", student[i].name); printf("Age: %d\n", student[i].age); printf("Country: %s\n", student[i].country); printf("Dept: %s\n", student[i].dept); i++; } // Close the file fclose(fp); return 0; }
内容的提问来源于stack exchange,提问作者Charlie
相关产品推荐
相关产品推荐

