Страницы

Поиск по вопросам

воскресенье, 29 декабря 2019 г.

Как записывать и считывать структуру в файл с расширением *.dat?

#c #структуры


Мне необходимо создать файл, содержащий сведения о личной коллекции книголюба. Структура
записи: шифр книги, автор, название, год издания, местоположение (номер стеллажа и т.п.).

Причем, запись (input()) и чтение (output()) структур производятся в файл/из файла
с расширением *.dat .
При каждой новой записи у нас, по сути, добавляется новая структура.
Так вот, у меня не выходит никак нормально считывать. Выводит только последнюю записанную. 
Так же не получается вводить новый шифр книги для следующей структуры, он просто
gets(B.key); пропускает.

#include 
#include 
#include 
#include 


void input(void);
void output(void);

struct cd
{
    char key[12];
    char author[30];
    char title[20];
    int year;
    int location;
} B;

FILE *f;

void main(void)
{
    int n = 0;
    system("cls");
    setlocale(LC_CTYPE, "rus");
    while(n != 3)
    {
        puts("1. Ввод данных в базу");
        puts("2. Вывод всех авторов");
        puts("Для выхода из программы нажмите любую другую клавишу...");
        puts("\nВаш выбор: ");
        scanf("%d",&n);
        fflush(stdin);
        switch(n)
        {
            case 1: input(); break;
            case 2: system("cls"); output(); break;
            default: exit(1);
        }
    }
}

void input(void)
{
    setlocale(LC_CTYPE, "rus");
    int k = 0;
    if(( f = fopen("knigolub.dat","w")) == NULL)
    {
        puts("Невозможно открыть файл");
        exit(1);
    }
    while (k != 10) {
        system("cls");
        puts("Введите сведения о книге...\n\n");
        printf("Введите шифр книги: ");
        gets(B.key);
        printf("Введите автора: ");
        gets(B.author);
        printf("Введите название: ");
        gets(B.title);
        printf("Введите год издания: ");
        scanf("%i", &B.year);
        printf("В какой стеллаж поместить? Введите его номер: ");
        scanf("%i", &B.location);
        fwrite(&B, sizeof(B), 1, f);
        puts("Продолжить работу?[y/n]");
        char s;
        scanf("%s", &s);
        switch ((int) s) {
            case (int) 'y': return input();
            case (int) 'n': return main();
        }
    }
}

void output (void)
{
    char letter;
    setlocale(LC_CTYPE, "rus");
    if((f=fopen("knigolub.dat","r")) == NULL)
    {
        puts("Невозможно открыть файл");
        exit(1);
    }
    printf("Шифр книги\tАвтор\tНазвание\tГод издания\tНомер стеллажа\n\n");
    while ((letter == fgetc(f)) != EOF) {
        printf("%s\t%s\t%s\t%i\t%i\t\n", B.key, B.author, B.title, B.year, B.location);
    }
    getch();
    system("cls");
    fclose(f);
}

    


Ответы

Ответ 1



Под *.dat обычно подразумевают некий бинарный псевдоформат. Потому fw = fopen("knigolub.dat","wb")) и fr = fopen("knigolub.dat","rb")) и чтение-запись выполняем через fread и fwrite. Пусть в начале файла идет число записей (size_t): size_t count = 0; cd *buffer = NULL; fread (&count, sizeof(size_t), 1, fr); buffer = (cd*)malloc(sizeof(cd) * count); fread (buffer, sizeof(cd), count, fr); Записываем, соответственно, наоборот - сначала пишем число, затем структуры. Если нужно добавить структуру в файл - определяем смещение (sizeof(size_t) + sizeof(cd)*count), а затем записываем записываем в число в начале файла значение count + 1

Ответ 2



Выводит только последнюю записанную. Дело не в том, что ВЫВОДИТ последнюю записанную структуру, а в том, что при записи очередной структуры Вы затираете (!!!) предыдущую. Каждый раз, когда выполняется вызов input(...), Вы выполняете повторное открытие файла: f = fopen("knigolub.dat","w") При этом предыдущее содержимое файла ЗАТИРАЕТСЯ. Надо либо: Открывать один раз в начале работы всей программы Открывать с атрибутом добавления "a" (Open for appending: writing at end of file)

Комментариев нет:

Отправить комментарий