Чтение неизвестного количества структур из файла - C - PullRequest
0 голосов
/ 23 марта 2012

У меня возникли некоторые проблемы с получением моей программы для чтения данных из файла.Проблема в том, что файл в настоящее время пуст.Каждый раз, когда программа запускается, один массив книг [] будет заполняться и записываться в файл позже в коде.Хотя я уверен, что он будет работать, когда все 10 структур находятся в файле, в настоящий момент происходит сбой, поскольку файл пуст и он пытается прочитать 10 структур.неизвестное количество структур (до 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);
}

Ответы [ 6 ]

2 голосов
/ 23 марта 2012

Если вы знаете максимально возможное количество структур в файле и можете позволить себе все их в памяти:

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

в противном случае зациклите и прочитайте кусками:

    while (cnt_books = fread(books, sizeof(struct stock), MAX_BOOKS, fptr)) {
      /* ... */
    }
2 голосов
/ 23 марта 2012

Да, вы можете сделать это:

  • Вам нужно проверить значение, возвращаемое fopen, чтобы убедиться, что файл существует
  • Вам нужно проверить количество прочитанных элементов - значение size_t, возвращаемое fread
1 голос
/ 23 марта 2012

сбои?Надеюсь, не те заявления, если файла нет вообще.Это может привести к сбою, если вы предполагаете, что в вашем массиве есть десять допустимых элементов, поскольку поля name, вероятно, не будут корректными строками C.

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

, хотя я бы предпочел:

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

, поскольку это означает, что вам не нужно менять много кода в случае изменения имени типа или размера массива.

Если возможно, что файл даже не открывается, вам нужно также проверить возвращаемое значение fopen.Полный код будет выглядеть примерно так:

#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;
}
0 голосов
/ 23 марта 2012

Я не уверен, но fread() не должен аварийно завершать работу, но должен возвращать количество прочитанных элементов, которое в данном случае равно 0.Также я не совсем понимаю, как строка stock books[10]; компилируется, она должна быть struct stock books[10];.

Я бы предложил две вещи: 1. заменить на struct stock books[10]; 2. Важная вещь, которую нужно сделать, это проверитьэтот fptr не NULL.Возможно, он не может открыть файл (может быть, не в том же каталоге или еще не существует), что приводит к NULL fptr, и использование его в fread приведет к сбою приложения.

0 голосов
/ 23 марта 2012
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);
}
0 голосов
/ 23 марта 2012

Код выглядит хорошо (хотя и не пытайтесь).См. fread справочную страницу - она ​​возвращает количество прочитанных элементов.

...