Zapis/odczyt do pliku binarnego

0

Witam!

void zapisz_do_pliku_bin (dane_produktu *lista){

typedef struct produkt_do_pliku {
   char nazwa_prod[50];
   int kalorie_prod;
 }produkt_do_pliku;


    FILE *plik_bin;
    plik_bin=fopen("baza.bin", "wb");
    
    if (lista==NULL){/*lista pusta*/}
    else{
        while(lista!=NULL){
            
            strcpy(produkt_do_pliku->nazwa_prod,lista->nazwa);
            produkt_do_pliku.kalorie_prod=lista->kalorie;
            
            fwrite(produkt_do_pliku,sizeof(produkt_do_pliku),1,plik_bin);
            
            lista=lista->nast;   
        }
             
        }
    fclose(plik_bin);
   }

bład mi wywala przy tym
strcpy(produkt_do_pliku->nazwa_prod,lista->nazwa);
fwrite(produkt_do_pliku,sizeof(produkt_do_pliku),1,plik_bin);

kalorie.c error: parse error before "produkt_do_pliku"

Czy używając fwrite wskaźnik po pliku przesówa się sam?
Czy nadpisuję 1 elem?
Dzięki
Pozdrawiam
Daniel

0
strcpy(produkt_do_pliku.nazwa_prod,lista->nazwa);
fwrite((char*)&produkt_do_pliku,sizeof(produkt_do_pliku),1,plik_bin);

Wskaźnik pliku przesuwa się sam.
Nie rozumiem po kiego ci ten if(lista==NULL) przecież while(lista!=NULL) i tak nic nie zrobi jeżeli jest NULL, poza tym czemu nie zapisać po prostu:
while(lista)
nie rozumiem po kiego ci dodatkowa struktura, możesz pisać wprost z listy:

fwrite(lista->nazwa,1,50,plik_bin);
fwrite((char*)&lista->kalorie,sizeof(int),1,plik_bin);
0
while(feof(plik_bin)==0){
        fread(z_pliku->nazwa,1,50,plik_bin);
        fread((char*)&z_pliku->kalorie,sizeof(int),1,plik_bin);
        dodaj(lista,z_pliku);
        }

Zapętla się :/ czy warunek w pętli jest poprawny?
Jest jakaś lepsza metoda by dowiedzieć się że to koniec pliku.

Albo to wina.
F. wyświetlającej.

void wyswietl_liste(dane_produktu **lista){
    
    dane_produktu *wsk = *lista;
    ClrScr();
    if (wsk==NULL){
        printf("Lista pusta!");
    }
    else{
        do{
            printf("%s ",wsk->nazwa);
            printf("%d",wsk->kalorie);
            printf("\n");
                        
            wsk=wsk->nast;
                        }
        while(wsk!=NULL);
        }  
    
    fflush(stdin);
    getchar();
    getchar();                    
}
0
  while(true){
        fread(z_pliku->nazwa,1,50,plik_bin);
        fread((char*)&z_pliku->kalorie,sizeof(int),1,plik_bin);
        if(feof(plik_bin)) break;
        dodaj(lista,z_pliku);
        }

lub:

while((fread(z_pliku->nazwa,1,50,plik_bin)==50)&&(fread((char*)&z_pliku->kalorie,sizeof(int),1,plik_bin)==1)) dodaj(lista,z_pliku);

o tym że jest w stanie EOF strumień się dowiaduje dopiero przy nieudanej próbie odczytu.

0

taka kosmetyczna uwaga:

fflush(stdin);

stosowanie fflush'a dla strumieni wejściowych jest troszkę bezsensowne. fflush jest zdefiniowany przez standard tylko dla strumieni wyjściowych i stosowanie go w innym przypadku daje w zasadzie niezdefiniowane zachowanie - jego działanie jest zależne od implementacji.

edit:

_13th_Dragon napisał(a)

Czy możesz podać przykład implementacji w której to nie zadziała odpowiednio?

mogę:
u mnie nie działa: gcc version 4.6.3 (Debian 4.6.3-1)
przykładowy kod:

    int n;
    char c, f;
    scanf("%d", &n);
    fflush(stdin);
    /*while(f = getchar() != '\n' && f != EOF);*/
    scanf("%c", &c);
    printf("%d - %c", n, c);
    return 0;

inaczej sprawa ma się pod windowsem.

0

Doczytałem że to bezsensu, ale nie wiem jak inaczej zatrzymać program by reagował po naciśnięciu ENTER-a. //ok będę testował to pod Debianem.

Nie wiem dlaczego po wczytaniu listy z pliku po wyświetleniu zapętla się program. Wyświetla ostatni element.
Coś jest nie tak bo chyba gdzieś tracę głowę listy. I powoduje chyba to wczytaj_z_pliku_bin(&lista);

Jeżeli nie mam pliku to działa wszystko prawidłowo. Dodaje prod. i wyświetlam.
Po zapisaniu danych, wygląda na ok.
Ale przy wczytaniu widzę że jest tylko ostatni dodany produkt i przy wyświetlaniu listy następuję zapętlenie.

void wczytaj_z_pliku_bin (dane_produktu **lista){
    
    dane_produktu *z_pliku = (dane_produktu*)malloc(sizeof(dane_produktu));
    
    
    FILE *plik_bin;
    
  plik_bin = fopen ("baza.bin", "rb");
    if( plik_bin == NULL )
  {
        fclose(plik_bin);
        printf("Niepowodzenie otwarcia pliku! ");
       
  }
    else{
  /*plik istnieje*/
        
        while(1){
        fread(z_pliku->nazwa,1,50,plik_bin);
        fread((char*)&z_pliku->kalorie,sizeof(int),1,plik_bin);
        if(feof(plik_bin)) break;
        
        dodaj(lista,z_pliku);
        }    
  }
  fclose(plik_bin);
}
void zapisz_do_pliku_bin (dane_produktu *lista){
     
    FILE *plik_bin;
    plik_bin=fopen("baza.bin", "wb");

        while(lista!=NULL){
            
            fwrite(lista->nazwa,1,50,plik_bin);
            fwrite((char*)&lista->kalorie,sizeof(int),1,plik_bin);
            
            
            lista=lista->nast;   
        }
              
    fclose(plik_bin);
   }
void dodaj(dane_produktu **lista, dane_produktu *nowa){
    
    nowa->nast=NULL;
 
     if((*lista)==NULL)
     {
        *lista = nowa;
     }
     else
     {
         dane_produktu* wsk = *lista;
         
         while(wsk->nast != NULL)
         {
                wsk = wsk->nast;
         }
         wsk->nast = nowa;
     }
}
int main(int argc, char** argv) {    
    dane_produktu *lista;
    lista=NULL;
    
    wczytaj_z_pliku_bin(&lista);
    menu(&lista);
    zapisz_do_pliku_bin(lista);      
    
    return (EXIT_SUCCESS);
}
0

Po dodaniu z pliku głową jest ostatni element i jako że jest to lista 1-kier poprzednie już nie dostępne.
Mam rację? Tylko gdzie jest feler?

0

Feler jest w położeniu wiersza:
dane_produktu z_pliku = (dane_produktu)malloc(sizeof(dane_produktu));
przydzielasz pamięć na jeden element i próbujesz jego doczepiać do samego siebie.

0

Mam jeszcze malutki problem z wyciekiem pamięci:

==5037== Invalid read of size 1
==5037== at 0x4029100: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x40A978D: _IO_default_xsputn (genops.c:468)
==5037== by 0x40A6C50: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1380)
==5037== by 0x409C9ED: fwrite (iofwrite.c:45)
==5037== by 0x8048BB2: zapisz_do_pliku_bin (kalorie.c:114)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x41871b8 is 0 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 1
==5037== at 0x402910E: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x40A978D: _IO_default_xsputn (genops.c:468)
==5037== by 0x40A6C50: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1380)
==5037== by 0x409C9ED: fwrite (iofwrite.c:45)
==5037== by 0x8048BB2: zapisz_do_pliku_bin (kalorie.c:114)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x41871ba is 2 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 1
==5037== at 0x40A6C88: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1349)
==5037== by 0x409C9ED: fwrite (iofwrite.c:45)
==5037== by 0x8048BD7: zapisz_do_pliku_bin (kalorie.c:115)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x41871ec is 52 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 1
==5037== at 0x40A6C94: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1348)
==5037== by 0x409C9ED: fwrite (iofwrite.c:45)
==5037== by 0x8048BD7: zapisz_do_pliku_bin (kalorie.c:115)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x41871ee is 54 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 4
==5037== at 0x8048BDB: zapisz_do_pliku_bin (kalorie.c:118)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x41871f4 is 60 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 1
==5037== at 0x4029100: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x40A6D31: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1337)
==5037== by 0x409C9ED: fwrite (iofwrite.c:45)
==5037== by 0x8048BB2: zapisz_do_pliku_bin (kalorie.c:114)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x4187228 is 0 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 1
==5037== at 0x402910E: mempcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x40A6D31: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1337)
==5037== by 0x409C9ED: fwrite (iofwrite.c:45)
==5037== by 0x8048BB2: zapisz_do_pliku_bin (kalorie.c:114)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x418722a is 2 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 1
==5037== at 0x40A9728: _IO_default_xsputn (genops.c:480)
==5037== by 0x40A6C50: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1380)
==5037== by 0x409C9ED: fwrite (iofwrite.c:45)
==5037== by 0x8048BB2: zapisz_do_pliku_bin (kalorie.c:114)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x41892b6 is 46 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 1
==5037== at 0x40A9735: _IO_default_xsputn (genops.c:479)
==5037== by 0x40A6C50: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1380)
==5037== by 0x409C9ED: fwrite (iofwrite.c:45)
==5037== by 0x8048BB2: zapisz_do_pliku_bin (kalorie.c:114)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x41892b8 is 48 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 1
==5037== at 0x40A6C88: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1349)
==5037== by 0x409C9ED: fwrite (iofwrite.c:45)
==5037== by 0x8048BB2: zapisz_do_pliku_bin (kalorie.c:114)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x4191788 is 0 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 1
==5037== at 0x40A6C94: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1348)
==5037== by 0x409C9ED: fwrite (iofwrite.c:45)
==5037== by 0x8048BB2: zapisz_do_pliku_bin (kalorie.c:114)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x419178a is 2 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 1
==5037== at 0x40A9728: _IO_default_xsputn (genops.c:480)
==5037== by 0x40A6C50: _IO_file_xsputn@@GLIBC_2.1 (fileops.c:1380)
==5037== by 0x409C9ED: fwrite (iofwrite.c:45)
==5037== by 0x8048BD7: zapisz_do_pliku_bin (kalorie.c:115)
==5037== by 0x8049BF0: main (kalorie.c:601)
==5037== Address 0x41959ce is 54 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid read of size 4
==5037== at 0x8049B98: zwolnij_pamiec (kalorie.c:590)
==5037== by 0x8049BFC: main (kalorie.c:602)
==5037== Address 0x41871f4 is 60 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== Invalid free() / delete / delete[] / realloc()
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8049BA8: zwolnij_pamiec (kalorie.c:591)
==5037== by 0x8049BFC: main (kalorie.c:602)
==5037== Address 0x41871b8 is 0 bytes inside a block of size 64 free'd
==5037== at 0x402540C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048B5C: wczytaj_z_pliku_bin (kalorie.c:102)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037==
==5037== FILE DESCRIPTORS: 3 open at exit.
==5037== Open file descriptor 2: /dev/pts/0
==5037== <inherited from="from" parent="parent">
==5037==
==5037== Open file descriptor 1: /dev/pts/0
==5037== <inherited from="from" parent="parent">
==5037==
==5037== Open file descriptor 0: /dev/pts/0
==5037== <inherited from="from" parent="parent">
==5037==
==5037==
==5037== HEAP SUMMARY:
==5037== in use at exit: 64 bytes in 1 blocks
==5037== total heap usage: 622 allocs, 1,240 frees, 40,384 bytes allocated
==5037==
==5037== 64 bytes in 1 blocks are definitely lost in loss record 1 of 1
==5037== at 0x4026208: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==5037== by 0x8048ADC: wczytaj_z_pliku_bin (kalorie.c:94)
==5037== by 0x8049BD8: main (kalorie.c:599)
==5037==
==5037== LEAK SUMMARY:
==5037== definitely lost: 64 bytes in 1 blocks
==5037== indirectly lost: 0 bytes in 0 blocks
==5037== possibly lost: 0 bytes in 0 blocks
==5037== still reachable: 0 bytes in 0 blocks
==5037== suppressed: 0 bytes in 0 blocks
==5037==
==5037== For counts of detected and suppressed errors, rerun with: -v
==5037== Use --track-origins=yes to see where uninitialised values come from
==5037== ERROR SUMMARY: 417827 errors from 19 contexts (suppressed: 11 from 6)

void wczytaj_z_pliku_bin (dane_produktu **lista){

FILE *plik_bin;  

plik_bin = fopen ("baza.bin", "rb");

if( plik_bin == NULL ){
fclose(plik_bin);
printf("Niepowodzenie otwarcia pliku! ");

}
else{
    while(1){ 
    dane_produktu *z_pliku = (dane_produktu*)malloc(sizeof(dane_produktu));
    
    fread(z_pliku->nazwa,1,50,plik_bin);
    fread((char*)&z_pliku->kalorie,sizeof(int),1,plik_bin);
    if(feof(plik_bin)) break;
    
    z_pliku->w_raporcie=0;
    dodaj(lista,z_pliku);
    }    

}
fclose(plik_bin);
}

void zwolnij_pamiec(dane_produktu **lista){
dane_produktu *wsk = *lista;
dane_produktu *wsk2 = *lista;

while(wsk!=NULL){
    wsk2=wsk;
    wsk=wsk->nast;
    free(wsk2);
} 

}
//////////////
Problem rozwiązany wystarczyło dodać przed break free(z_pliku) bo poprzedni był ostatnim elementem.
Dziękuję za każdą pomoc. Dzięki wam udało mi się zrozumieć wiele rzeczy.

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