Reading unknown number of structs from file - C

ⅰ亾dé卋堺 提交于 2019-12-13 07:28:05

问题


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. 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.

Is there a way to read in an unknown number of structs (up to 10) from the file?

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);
}

回答1:


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)) {
      /* ... */
    }



回答2:


Yes, you can do it:

  • You need to check the value returned by fopen to make sure the file exists
  • You need to check the number of items read - the size_t value returned by fread



回答3:


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.

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. 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;
}



回答4:


The code looks fine (have not give it a go though). See fread man page - it returns the number of items read.




回答5:


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);
}



回答6:


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. Also I don't exactly understand how the line stock books[10]; compiles, it should be struct stock books[10];.

I would suggest two things: 1. replace to struct stock books[10]; 2. An important thing to do is check that fptr is not 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.



来源:https://stackoverflow.com/questions/9837506/reading-unknown-number-of-structs-from-file-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!