C 编程:读取文件并存储在结构数组中

Posted

技术标签:

【中文标题】C 编程:读取文件并存储在结构数组中【英文标题】:C Programming: Reading a file and storing in array of struct 【发布时间】:2016-11-28 00:42:10 【问题描述】:

我正在尝试通过 fscanf 读取文件 test.txt 并将其存储在结构数组中。这是我尝试过的。这里的问题是fscanf 没有按预期工作。读取文件后,我也尝试在屏幕上打印,但它不起作用。

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

struct Item 
   double value;
   int unit;
   char name[50];
;

int load(struct Item* item, FILE* data);
void display(struct Item item, int variableA);

int main()

  struct Item I;
  int i;
  char ck;
  ck =  fopen("test.txt", "r");
  if (ck)
  
    for (i = 0; i < 3; i++)
    
        load(&I, ck);
        display(I, 0); //DISPLAY FUNCTION THAT READS test.txt and DISPLAYS
    
    fclose(ck);
  
return 0;



int load(struct Item* item, FILE* data)

    fscanf(data, "%d,%.2lf,%s\n", &(*item).unit,&(*item).value,&(*item).name);
    return 0;


void display(struct Item item, int variableA)

printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
return;

这是我在 test.txt 文件中的内容:

205,11.20,John Snow
336,23.40,Winter is coming
220,34.20,You know nothing

错误: 程序编译时出现一些警告,但执行代码时出现分段错误。

知道为什么吗?

输出预期:应该从 test.txt 文件中读取 OUTPUT 并显示在屏幕上。

【问题讨论】:

可能是因为“John”不正确;那是“乔恩”斯诺…… @ringø 哈哈 :D :D :D 您必须调试程序以查看错误发生的位置(读取或显示),并查看您是否得到了您认为应该得到的结果。 好吧,一方面,fopen 不返回 char,它返回 FILE*。不要忽视警告。他们在那里告诉你有什么问题。所以修复他们。 【参考方案1】:

程序中的多个问题:

1.

char ck;
ck =  fopen("test.txt", "r");

fopen 返回 FILE*,而不是 char,使用

FILE* ck = fopen(...);

2.

fscanf(data, "%d,%.2lf,%s\n", &(*item).unit,&(*item).value,&(*item).name);

始终检查fscanf 的返回值,如果它小于您请求的字段数,则对fscanf 的以下调用不太可能达到您的预期。另外,*item.unititem-&gt;unit 一样,使用item-&gt;unit,因为它更短更干净:

int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
if (ret != 3)  // error 

第三,%s 匹配一系列非空白字符,因此当fscanf 读取“John”时,它将停止,并且下一个 fscanf 调用将读取“Snow”,同时期待整数。

所以要输入带有空格的字符串,请改用fgets,并记住最后删除换行符。

尝试以下操作:

int main(void)

    struct Item I;
    int i;
    FILE* ck;
    int ret;
    ck =  fopen("test.txt", "r");
    if (ck)
    
            for (i = 0; i < 3; i++)
            
                    ret = load(&I, ck);
                    if (ret < 0)
                            break;
                    display(I, 0); //DISPLAY FUNCTION THAT READS test.txt and DISPLAYS
            
            fclose(ck);
    
    return 0;


int load(struct Item* item, FILE* data)

    int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
    if (ret != 2) 
            return -1;
    
    fgets(item->name, sizeof item->name, data);
    item->name[strlen(item->name)-1] = '\0';
    return 0;


void display(struct Item item, int variableA)

    printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
    return;

它输出:

$ ./a.out
|205 |       11.20|            John Snow |***
|336 |       23.40|     Winter is coming |***
|220 |       34.20|     You know nothing |***

【讨论】:

Ty 提示解释。 :) 我仍然得到黑色输出。 @John 你能展示一下你是如何编译程序以及如何运行它的吗? gcc -Wall test.c 然后 ./a.out @John test.txt 存在吗?【参考方案2】:

您可以尝试这种不同的方法。

它使用:

malloc,realloc 为结构数组分配和重新分配内存。我假设将使用具有更多行的更大文本文件,这允许数组在需要时调整大小以容纳更多信息。 strtok 解析, 分隔符之间的每个数据,然后将它们存储到结构数组中。 检查指针的返回值以避免分段错误。 使用fgets 将文件的每一行读入一个字符串,之后我们可以从中解析自己。

这是建议的代码:

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

#define NAMESTRLEN 50
#define INITSIZE 3
#define MAXSIZE 100

typedef struct 
    int unit;
    double value;
    char name[NAMESTRLEN+1];
 item_t;

typedef struct 
    item_t *items;
    int numlines;
 allitems_t;

allitems_t *initialize_arraystructs(void);
void print_arraystructs(allitems_t *allitems);
void read_insert_items(FILE *filestream, allitems_t *allitems);
void check_ptr(void *ptr, const char *msg);

int 
main(void) 
    allitems_t *allitems;
    FILE *fp;

    fp = fopen("test.txt", "r");
    if (fp == NULL) 
        fprintf(stderr, "%s\n", "Error reading file!\n");
        exit(EXIT_FAILURE);
    

    allitems = initialize_arraystructs();

    read_insert_items(fp, allitems);

    print_arraystructs(allitems);

    return 0;


void
read_insert_items(FILE *filestream, allitems_t *allitems) 
    int count = 0;
    char line[MAXSIZE];
    char *unit, *value, *name;
    size_t numitems = INITSIZE;

    allitems->items = malloc(numitems * sizeof(item_t));
    check_ptr(allitems->items, "Initial Allocation");

    while (fgets(line, MAXSIZE, filestream) != NULL) 
        unit = strtok(line, ",");
        value = strtok(NULL, ",");
        name = strtok(NULL, "\n");

        if (count == numitems) 
            numitems *= 2;
            allitems->items = realloc(allitems->items, numitems * sizeof(item_t));
            check_ptr(allitems->items, "Reallocation");

        

        allitems->items[count].unit = atoi(unit);
        allitems->items[count].value = atof(value);
        strcpy(allitems->items[count].name, name);

        count++;
        allitems->numlines++;
    


allitems_t
*initialize_arraystructs(void) 
    allitems_t *allitems;

    allitems = malloc(sizeof(allitems_t));
    check_ptr(allitems, "Initial Allocation");

    allitems->items = NULL;
    allitems->numlines = 0;

    return allitems;


void
print_arraystructs(allitems_t *allitems) 
    int i;

    for (i = 0; i < allitems->numlines; i++) 
        printf("%d,%.2f,%s\n", 
               allitems->items[i].unit, 
               allitems->items[i].value, 
               allitems->items[i].name);
    


void
check_ptr(void *ptr, const char *msg) 
    if (!ptr) 
        printf("Unexpected null pointer: %s\n", msg);
        exit(EXIT_FAILURE);
    

【讨论】:

以上是关于C 编程:读取文件并存储在结构数组中的主要内容,如果未能解决你的问题,请参考以下文章

C程序:从文件中读取矩阵数据,并显示出来,利用链式存储结构。

C编程:从文件中读取并在屏幕上打印

C# 从 .txt 读取并拆分为结构数组

C 语言文件操作 ( 将结构体写出到文件中并读取结构体数据 | 将结构体数组写出到文件中并读取结构体数组数据 )

C - 文件的读取()错误,存储在数组中并正确打印输出

从文本文件中读取单词并存储到 C 中的动态数组 Valgrind 错误中