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

C语言ReadPersonData函数读取输入文件数据异常求助

问题:读取结构体数组时爱好部分异常,程序提前终止

问题现象

读取输入文件时,当遇到爱好数量与实际爱好个数不匹配的条目(如示例中Sarah的条目:标注爱好数量为2,但实际跟随4个爱好),程序会停止读取后续所有数据。输入文件每条数据格式为:姓名、国家、城市、街道、爱好数量、爱好列表,示例数据片段如下:

John Brazil Brasilia Esplanada 1 Reading

Mary Japan Tokyo Harajuku 2 Painting Swimming

David Australia Canberra Northbourne 3 Running Gardening Cycling

Sarah Norway Oslo Storgata 2 Cooking Fishing Writing Dancing

问题代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_NAME_LEN 32
#define MIN_HOBBIES 0
#define MAX_HOBBIES 10
#define MAX_PERSONS 100
#define MAX_FILE_NAME_SIZE 16

#define ARG_CNT 2
#define ARG_EXEC_NAME argv[0]
#define ARG_FILE_NAME argv[1]

typedef struct
{
  char country[MAX_NAME_LEN];
  char city[MAX_NAME_LEN];
  char street[MAX_NAME_LEN];

} address;

typedef struct
{
  char name[MAX_NAME_LEN];
  address residence;
  int hobbyCount;
  char hobbies[MAX_HOBBIES][MAX_NAME_LEN];

} person;

int ReadPersonData(person personList[] , int limit, char *fName);
void FindSameHobby(person personList[], int personCount, char hobbyName[]);
void OutPutData(person personList[], int personCount, char hobbyName[]);

int main(int argc, char **argv)
{
  if(argc != ARG_CNT)
  {
    fprintf(stderr, "Usage: %s input_file\n", ARG_EXEC_NAME);
    return EXIT_FAILURE;
  }

  person personList[MAX_PERSONS];

  int personCount = ReadPersonData(personList, MAX_PERSONS, ARG_FILE_NAME);


  return 0;
}

int ReadPersonData(person personList[] , int limit, char *fName)
{

  int persons = 0;
  int i;

  FILE *fPerson = fopen(fName, "r");
  if(fPerson == NULL)
  {
    fprintf(stderr, "Error opening input file %s", fName);
    perror(" ");
    return persons;
  }

  while(fscanf(fPerson, "%s %s %s %s %d", personList[persons].name,
                                          personList[persons].residence.country,
                                          personList[persons].residence.city,
                                          personList[persons].residence.street,
                                         &personList[persons].hobbyCount) == 5)

  {

    if(personList[persons].hobbyCount < MIN_HOBBIES ||
    personList[persons].hobbyCount > MAX_HOBBIES)
      {
        printf("ERROR! Invalid hobby count for %s, exiting now!\n",
        personList[persons].name);
        exit(1);
      }

   for(i = 0; i < personList[persons].hobbyCount; i++)
   {
     fscanf(fPerson, "%s", personList[persons].hobbies[i]);
   }

    persons++;

   if(persons > limit)
   {
     fprintf(stderr, "ERROR! Input file is too long! ALlowed "
                        "limit is %d entries. Reading of the "
                        "file has stopped, continuing within "
                        "a partial dataset\n", limit);
     break;
   }
  }

fclose(fPerson);

return persons;

}

问题根源

以Sarah的条目为例,标注的爱好数量是2,但实际有4个爱好。程序按标注的数量读取2个爱好后,剩余的Writing Dancing会留在输入缓冲区中。下一次执行fscanf读取下一条数据时,会把Writing当作姓名、Dancing当作国家,后续数据全部错位,导致fscanf返回值不等于5,读取循环直接终止,程序停止处理后续条目。

修复方案

方案1:修正输入数据

确保每条数据的爱好数量与实际爱好个数完全一致,比如将Sarah条目的爱好数量改为4,或删除多余的两个爱好。这是最直接的解决方式。

方案2:添加代码容错处理

如果无法保证输入数据完全规范,可以在读完当前条目的爱好后,清空输入缓冲区中当前行的剩余内容,避免影响下一次读取。修改ReadPersonData函数,在persons++;之前添加以下代码:

// 跳过当前行剩余的所有字符,避免残留数据干扰下一次读取
int c;
while ((c = fgetc(fPerson)) != '\n' && c != EOF);

同时,建议在读取爱好时增加返回值检查,确保读取操作成功:

int c;
for(i = 0; i < personList[persons].hobbyCount; i++)
{
  // 检查爱好读取是否成功
  if (fscanf(fPerson, "%s", personList[persons].hobbies[i]) != 1) {
      fprintf(stderr, "Warning: Failed to read hobby for %s\n", personList[persons].name);
      // 跳过当前行剩余内容,避免影响后续读取
      while ((c = fgetc(fPerson)) != '\n' && c != EOF);
      break;
  }
}
// 清空当前行剩余内容
while ((c = fgetc(fPerson)) != '\n' && c != EOF);

总结

核心问题是输入数据的爱好数量与实际个数不匹配,导致输入缓冲区残留数据破坏了后续读取逻辑。优先修正输入数据,若无法保证数据规范,则通过代码添加容错处理,清空当前行剩余内容即可解决问题。

内容的提问来源于stack exchange,提问作者CallMeSpec

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 02:48:18