简体   繁体   English

从文件中读取未知数量的结构-C

[英]Reading unknown number of structs from file - C

I'm having a bit of trouble getting my program to read in data from a file. 让我的程序从文件中读取数据时遇到麻烦。 The issue is that the file is currently empty. 问题是该文件当前为空。 Each time the program is run, a single array of books[] will be populated and written to the file later on in the code. 每次运行该程序时,将填充单个book []数组,并稍后在代码中将其写入文件。 While I'm sure it will work when all 10 structs are in the file, at the moment it's crashing since the file is empty and it's trying to read in 10 structs. 虽然我确定所有10个结构都在文件中时它可以工作,但是由于文件为空并且正在尝试读取10个结构,此刻它崩溃了。

Is there a way to read in an unknown number of structs (up to 10) from the file? 有没有办法从文件中读取未知数量的结构(最多10个)?

struct stock
{
    char name[31];
    int stock;
};

int main (void)
{
    stock books[10];

    FILE *fptr;
    fptr = fopen("stock.dat", "rb");
    fread(books, sizeof(struct stock), 10, fptr);

    fclose (fptr);
}

Yes, you can do it: 是的,您可以这样做:

  • You need to check the value returned by fopen to make sure the file exists 您需要检查fopen返回的值以确保文件存在
  • You need to check the number of items read - the size_t value returned by fread 您需要检查读取项目的数量-在size_t的返回值fread

If you know the maximum possible number of structures in the file and can afford to have them all in memory: 如果您知道文件中结构的最大数量,并且有能力将它们全部存储在内存中:

int main (void)
{
    #define MAX_BOOKS 10
    stock books[MAX_BOOKS];
    size_t cnt_books = 0;
    FILE *fptr;
    fptr = fopen("stock.dat", "rb");
    cnt_books = fread(books, sizeof(struct stock), MAX_BOOKS, fptr);
    fclose (fptr);
    return 0;
}

otherwise loop and read in chunks: 否则循环并分块读取:

    while (cnt_books = fread(books, sizeof(struct stock), MAX_BOOKS, fptr)) {
      /* ... */
    }

Crashing? 崩溃? Not those statements, I hope, unless the file's not there at all. 我希望这些语句不行,除非文件根本不存在。 It may be crashing if you assume you have ten valid items in your array, since the name fields probably won't be valid C strings. 如果您假设数组中有十个有效项,则可能会崩溃,因为name字段可能不是有效的C字符串。

The way you figure out how many you actually read is with: 弄清楚您实际阅读多少书的方式是:

num = fread(books, sizeof(struct stock), 10, fptr);

although I would prefer: 尽管我希望:

num = fread (book, sizeof(*book), sizeof(book) / sizeof(*book), fptr);

since that means you don't have to change lots of code in the event the type name or array size changes. 因为这意味着您不必在类型名称或数组大小发生更改的情况下更改大量代码。

If it's possible the the file doesn't even open, you need to check the fopen return value as well. 如果有可能文件甚至无法打开,则还需要检查fopen返回值。 Complete code would look something like: 完整的代码如下所示:

#include <stdio.h>

typedef struct {
    char name[31];
    int stock;
} tStock;

int main (void) {
    tStock book[10];
    size_t num, i;

    FILE *fptr = fopen ("stock.dat", "rb");
    if (fptr == NULL) {
        num = 0;
    } else {
        num = fread (book, sizeof(*book), sizeof(book) / sizeof(*book), fptr);
        fclose (fptr);
    }

    printf ("Read %d items\n", num);
    for (i = 0; i < num; i++) {
        printf ("   Item %d is %s, %d\n", book[i].name, book[i].stock);
    }

    return 0;
}

The code looks fine (have not give it a go though). 该代码看起来不错(尽管没有尝试)。 See fread man page - it returns the number of items read. 请参阅fread手册页-它返回读取的项目数。

fptr = fopen("stock.dat", "rb");
if(fptr == NULL)
{
  // error
}
else
{
  for(int i=0; i<10 && !feof(fptr); i++)
  {
    fread(&books[i], sizeof(struct stock), 1, fptr);
  }
  fclose(fptr);
}

I'm not sure, but fread() is not supposed to crash, but to return the number of items read, which is 0 in this case. 我不确定,但是fread()不应该崩溃,而是返回读取的项目数,在这种情况下为0。 Also I don't exactly understand how the line stock books[10]; 另外,我也不完全了解行stock books[10]; compiles, it should be struct stock books[10]; 编译时,应该是struct stock books[10]; .

I would suggest two things: 1. replace to struct stock books[10]; 我建议两件事:1.替换以struct stock books[10]; 2. An important thing to do is check that fptr is not NULL. 2.重要的事情是检查fptr是否不为NULL。 Perhaps it couldn't open the file (maybe not in same directory or doesn'e exist yet), which results in a NULL fptr, and using it in fread would crash the app. 可能无法打开文件(可能不在同一目录中或尚不存在),这将导致NULL fptr,并且在fread中使用它会使应用程序崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM