Odczyt i zapis struktur do plików

1

Witam.
Mam pytanie dotyczące zapisu i odczytu struktur do/z pliku binarnego. Jest to potrzebne do edytora pytań. Program wykonuję w języku C. Jeśli chodzi o tej język jestem dosyć początkujący.

#include<stdio.h>

/* Our structure */
struct rec
{
    char tresc[100];
    char odpA[50];
    char odpB[50];
    char odpC[50];
    char odpD[50];
    char prawidlowa[1];
};

int main()
{
    int n;
    int counter;
    FILE *ptr_myfile;
    struct rec my_record;
    char zmienna[50];
    ptr_myfile=fopen("pyta.bin","a+b");

    if (!ptr_myfile)
    {
        printf("Unable to open file!");
        return 1;
    }
    printf("Podaj ile pytan chcesz dodac:");
    scanf("%d", &n);
    for ( counter=1; counter <= n; counter++)
    {
        printf("Podaj pytanie nr. %d\n", counter);
        fgets((my_record.tresc), 100, stdin);
        fwrite(&my_record, sizeof(struct rec), 1, ptr_myfile);
    }
    fclose(ptr_myfile);
    ptr_myfile=fopen("pyta.bin","rb");
    while(fread(&my_record,sizeof(struct rec),1,ptr_myfile)==1)
        printf("%s\n",my_record.tresc);
    fclose(ptr_myfile);
    return 0;
}

W pliku mam zamiar zapisywać treść pytania z 4 odpowiedziami. I tutaj mam problem, jak zapisywać cały łańcuch znaków - łącznie ze spacjami?
Druga sprawa, jak najlepiej zorganizować edytor pytań, by można było powrócić do zapisanych wcześniej pytań - użyć listy czy coś w tym stylu?

0

Zapisuj binarnie i wczytuj tak samo cala strukture. Co do grupowania, to moze byc to lista, moze byc tablica, cokolwiek.

0

Z tego co myślałem, to właśnie zapisuję i odczytuję binarnie.
W tym kodzie mam problem, że po wybraniu ilości pytań do dodania nie reaguje na fgets - program wykonuje się już do końca.

0
struct rec {
    char tresc[100];
    char odpA[50];
    char odpB[50];
    char odpC[50];
    char odpD[50];
    char prawidlowa[1];
};

void wczytajzstdin(struct rec*, size_t n) {
    for(int i = 0; i < n; ++i)
        scanf (
            "%99s %49s %49s %49s %49s %c",
            rec[i].tresc, rec[i].odpA, rec[i].odpB,
            rec[i].odpC, rec[i].odpD, rec[i].prawidlowa
        );
}

void zapiszdopliczku(struct rec*, size_t n, FILE* f) {
    for(int i = 0; i < n; ++i)
        fwrite(&rec[i], sizeof(struct rec), 1, f);
}

void wczytajzpliczku(struct rec*, size_t n, FILE* f) {
    for(int i = 0; i < n; ++i)
        fread(&rec[i], sizeof(struct rec), 1, f);
}

void pokazmimojkochany(struct rec*, size_t n) {
    for(int i = 0; i < n; ++i)
        printf (
            "Ludzka forma:\n %s\n%s\n%s\n%s\n%c\n\n\n",
            rec[i].tresc, rec[i].odpA, rec[i].odpB,
            rec[i].odpC, rec[i].odpD, rec[i].prawidlowa
        );
}

int main() {
    // ...
}

Dodajesz obsluge bledow i piszesz sobie maina i masz gotowca. Na przyszlosc srednio sie komus chce patrzec w kod upakowany w jednej funkcji robiacej milion rzeczy. Poza tym robisz to strasznie dziwnie...

0

Witam. Dziękuję za pomoc. Tak się do tego zastosowałem, niewielkie zmiany poczyniłem bo kompilator wywalał błędy - np. w void wczytajzstdin(struct rec* x, int n) nie było nazwy.Ten kod się kompiluje, ale taki sam problem jak był - przy treści pytań gdy są spacje to są zaliczane do kolejnych zmiennych.

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

struct rec
{
    char tresc[100];
    char odpA[50];
    char odpB[50];
    char odpC[50];
    char odpD[50];
    char prawidlowa[1];
};

void wczytajzstdin(struct rec* x, int n)
{
    int i;
    for(i = 0; i < n; ++i)
        scanf (
            "%99s %49s %49s %49s %49s %c",
            x[i].tresc, x[i].odpA, x[i].odpB,
            x[i].odpC, x[i].odpD, x[i].prawidlowa
        );
}

void zapiszdopliczku(struct rec* x, int n, FILE* f)
{
    int i;
    for(i = 0; i < n; ++i)
        fwrite(&x[i], sizeof(struct rec), 1, f);
}

void wczytajzpliczku(struct rec* x, int n, FILE* f)
{
    int i;
    for(i = 0; i < n; ++i)
        fread(&x[i], sizeof(struct rec), 1, f);
}

void pokazmimojkochany(struct rec* x, int n)
{
    int i;
    for(i = 0; i < n; ++i)
        printf (
            "Ludzka forma:\n %s\n%s\n%s\n%s\n%c\n\n\n",
            x[i].tresc, x[i].odpA, x[i].odpB,
            x[i].odpC,  x[i].odpD, x[i].prawidlowa
        );
}

int main()
{
    int n;
    FILE *ptr_myfile;
    struct rec my_record;
    char zmienna[50];
    ptr_myfile=fopen("pytania.bin","a+b");

    if (!ptr_myfile)
    {
        printf("Unable to open file!");
        return 1;
    }

    printf("Podaj:");
    wczytajzstdin(&my_record,1);
    zapiszdopliczku(&my_record,1,ptr_myfile);
    fclose(ptr_myfile);
    ptr_myfile=fopen("pytania.bin","rb");
    wczytajzpliczku(&my_record,1,ptr_myfile);
    pokazmimojkochany(&my_record,1);
    return 0;
}

0

%s - Any number of non-whitespace characters, stopping at the first whitespace character found. A terminating null character is automatically added at the end of the stored sequence.

To wczyta odpowiednią ilość znaków, chyba że napotka enter. Wcztyta też spacje (podzieliłem, ze względu na czytelność, ale możesz upchać ;) )

scanf("%99[^\n]s", x[i].tresc);
scanf("%49[^\n]s", x[i].odpA);
scanf("%49[^\n]s", x[i].odpB);
scanf("%49[^\n]s", x[i].odpC);
scanf("%49[^\n]s", x[i].odpD);
scanf("%c", x[i].prawidlowa);
0

Wiem, że to dziwne trochę jest. Ale ta wersja też mi nie działa. Gdy wpisuję w programie treść pytania - jedno zdanie np. "Jaki kolor ma niebo?" i naciskam enter - przechodzi do kolejnych funkcji, czyli zapisuje do pliku, odczytuje i wyświetla na ekranie. Nie reaguje na te kolejne scanf'y.

0

W buforze zostaje znak nowej lini. Po każdym scanf musisz dać

getchar();

Albo funkcję:

fflush(stdin);
0
struct rec record;
FILE *file = fopen("pyt.bin", "w");
fwrite(&record, sizeof(record), 1, file); // cała magia
fclose(file);

struct rec records[256];

FILE *file = fopen("pyt.bin", "r");
int read = fread(records, sizeof(struct rec), 256, file); // w zmiennej ilosc rekordow
fclose(file);

Można zapisać całą tablicę - poczytaj o fwrite.

1 użytkowników online, w tym zalogowanych: 0, gości: 1