【问题标题】:Reading a file with multiple lines into a struct in C89将多行文件读入C89中的结构
【发布时间】:2017-11-26 12:56:17
【问题描述】:

我试图读取一个大约 200 行的文件,然后将不同的行保存到一个结构中。结构如下:

struct person_data{
  char name[20];
  char lastname[30];
  int age;
  char country[3]
};

文件中的行设置为:

"Tom HALL"                            32   ENG
"Ryan SMITH"                          24   USA

所以我的问题是我不确定我应该如何读取该文件,并将信息放入结构中。我一直在尝试将文件保存到我的结构中并打印它,但结果是我的计算机上的目录路径和许多奇怪的符号在它崩溃之前。 我的代码是:

int main(){
FILE *fp;
fp = fopen("person.txt", "r");
person_data *person = malloc(sizeof(struct person_info));
int i = 0;
if(fp != NULL) {
    while ( i < 200 ) {
        fscanf(fp, "%[A-Za-z] %[A-Z] %d %[A-Z]",
               person[i].name,
               person[i].lastname,
               &person[i].age,
               person[i].country);

        i++;
    }
}
else{
    perror(fp);
}
for (i = 0; i < 200; i++) {
    printf("%s %s  %d %s",
           person[i].name,
           person[i].lastname,
           person[i].age,
           person[i].country);

}
fclose(fp);
return 0;
}

我不确定出了什么问题,因此想问一下是否有人知道我做错了什么以及如何解决这个问题。当我运行程序时,它看起来像这样:

【问题讨论】:

  • 你的国家太短了。您需要 4 个字符来存储 3 个字符字符串

标签: c struct c89


【解决方案1】:

首先查看您的malloc 并认为有什么问题?您只为一个结构分配了内存。分配对所有类型的工作方式相同。如果你需要分配一个struct person 的数组,你可以这样做:

struct person_data *person = malloc(number_of_elements * sizeof(struct person_data));

顺便说一句,你在sizeof(sturct person_info) 中有错字,你没有person_info struct

我测试了你的代码,但这个语句不起作用fscanf(fp, "%[A-Za-z] %[A-Z] %d %[A-Z]") 我不知道为什么......但我只是将它重写为fscanf(fp, "%s %s %d %s") 并且一切正常

perror() 中,你传递了FILE*,但它期望来自人的const char *s

perror() 函数在标准错误上生成消息 描述在调用系统或库函数期间遇到的最后一个错误。

首先(如果 s 不是 NULL 并且 *s 不是空字节 ('\0')),则打印参数字符串 s,然后 用冒号和空格表示。然后是errno的当前值对应的错误信息 和一条新线。 最常用的是,参数字符串应该包含引起 错误。

你还需要 + 1 的字符串大小,因为最后一个字符是 '\0'; 在您的情况下,国家/地区有 [3] 需要 [4];

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

struct person_data {
    char name[20];
    char lastname[30];
    int age;
   char country[4];
};


int main(){
    FILE *fp;
    fp = fopen("person.txt", "r");
    struct person_data *person = malloc(sizeof(struct person_data) * 4);
    int i = 0; 
    if(fp != NULL) {
         while ( i < 4 ) {
           fscanf(fp, "%s %s %d %s",
                person[i].name,
                person[i].lastname,
                &person[i].age,
                person[i].country);
                i++;
        }
    }
    else{
      perror("FP ERROR: ");
    }
    for (i = 0; i < 4; i++) {
        printf("%-8s %-10s  %-10d %-10s\n",
        person[i].name,
        person[i].lastname,
        person[i].age,
        person[i].country);

   }
   fclose(fp);
   return 0;
}

我尝试在我的 person.txt 中使用四个人,它可以工作。并打印:

"Tom     HALL"       32    ENG  
"Ryan    SMITH"      24    USA  
"Hal     Al"         25    UKR  
"Peter   Peters"     99    ENG 

【讨论】:

  • 感谢您的帮助。你对 perror 的看法是对的,我改变了它。我让它工作,它打印出所有的名字。但我也有一个问题,对于某些人来说,这些行被分成 3 位,从 i 到 i+3,而其余的工作正常。
  • 非常感谢,我现在可以正常使用了。
【解决方案2】:

如果需要 200 个该结构,则需要分配 200 倍于该结构的大小

#define NUMBER 200

person_data *person = malloc(NUMBER * sizeof(struct person_info));

或使用calloc(将分配的内存初始化为零 - 在您的情况下不是必需的,但更易于阅读)

person_data *person = calloc(NUMBER, sizeof(struct person_info));

如果您在其中存储 3 个字符字符串(由于尾随零),country 还需要至少 4 个字符(@PeterJ_01 注释)。

【讨论】:

  • 我试过了,但程序只打印了一个单词和很多零。我读取文件并将其存储在结构中的方式是否正确?
  • fscanf 替换为fscanf(fp, "%s %s %d %s");
  • 感谢帮助,它现在打印出第一人称,但之后我一直打印出零。
  • 检查输入文件 - 它是否适合 fscanf?我个人更喜欢使用fgets + strtok
  • 我现在开始工作了,它会打印出所有的名字,但一切都没有格式化,而且多人在同一行。你知道有什么解决办法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-13
  • 2016-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多