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

解决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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 11:35:19