Pliki elementowe (binarne), dlaczego tak się dzieje?

0

Kochani, mam taką funkcję, poznaną na zajęciach i chciałabym się dowiedzieć dlaczego w pliku wynikowym outv2.txt nie mam tego samego co w in.txt. Jaka jest tego przyczyna? Co robię źle?
screenshot-20200103152006.png

0
  1. Nie wrzucaj nigdy zdjęć kodu źródłowego, a tekst.
  2. Pokaż cały kod.
2

Przecież dumpujesz strukturę binarnie. Więc dla czego w ogóle oczekujesz, że int (bo zakładam, że tym jest osoba.rok) będzie tekstowo przedstawiony jako 2000? Przecież to zupełnie różne reprezentacje.

1
Patryk27 napisał(a):
  1. Nie wrzucaj nigdy zdjęć kodu źródłowego, a tekst.
  2. Pokaż cały kod.

przepraszam, mój pierwszy wpis :/

#include <string.h>
#define X 10
#define MAX 20

typedef struct
{
    char imie [MAX+1];
    char nazwisko [MAX+1];
    char rok [MAX+1];
} osoba;

int OdczytPliku(const char* nazwa,osoba tab[])
{
    int i;
    FILE *plik=fopen(nazwa, "r");
    for( i=0; i<X; i++)
    {
        if((fscanf(plik, "%s%s%s", tab[i].imie, tab[i].nazwisko, tab[i].rok))==EOF)
            break;
    }
    return i;
    fclose(plik);
}

int MinRok(osoba tab[], int Y)
{
    int i,j=0,minrok;
    int mini=atoi(tab[0].rok);
    for(i=0; i<Y; i++)
    {
        if(atoi(tab[i].rok)<mini)
        {
            mini=atoi(tab[i].rok);
        }
    }
    return mini;
}

void TworzPlikWynikowy_v2(const char *nazwa, osoba tab[], int Y, int mini)
{
    FILE *plik=fopen(nazwa, "wb");
    if(plik==NULL)return;
    for(int i=0; i<Y; i++)
    {
      fwrite(tab+i,sizeof(osoba), 1, plik);
      fprintf(plik,"\n");
    }
    fclose(plik);
}
int main()
{
    int licznik, min_rok;
    osoba tab[X];
    licznik=OdczytPliku("in.dat", tab);
    if(licznik==0)
        return 1;
    //printf("%s", tab[1].imie);
    min_rok=MinRok(tab,licznik);
    // printf("%d", min_rok);
    //TworzPlikWynikowy("out5.txt",tab,licznik, min_rok);
    TworzPlikWynikowy_v2("out_v2_5.txt",tab, licznik,min_rok);
    return 0;

}

to cały program, a osoba.rok nie może być u mnie int'em skoro muszę wziąć dane z pliku testowego. Chyba że da się to jakoś zrobić ?

2

Dla wytłumaczenia uprośćmy nieco Twój kod:

typedef struct
{
    char imie [32];
} osoba;

/* ... */

fscanf(plik, "%s", tab[i].imie)

/* ... */

fwrite(tab+i,sizeof(osoba), 1, plik);

Pierwszy "problem" stanowi instrukcja fscanf: załóżmy, że wczytane imię ma 5 znaków - jak myślisz, co będzie znajdowało się pod imie[6]?

...śpiesząc z odpowiedzią: wszystko za imie[5] (w którym znajduje się null terminator) zawiera śmieci, które akurat przypadkiem znalazły się w tym miejscu pamięci; dzieje się tak ponieważ fscanf automatycznie nie czyści buforu wyjściowego.

Drugi problem: nawet gdybyś w jakiś sposób dopełniła imie spacjami (czyli mielibyśmy np. Wojtek\0\spacja\spacja\spacja\spacja), wystąpiłby problem z fwrite, które nie wiedziałoby, że tak naprawdę tych spacji w swoim pliku wyjściowym nie potrzebujesz :-)

Rozwiązanie jest jednak proste i wymaga raptem drobnych zmian w części zapisującej dane do pliku:

fwrite(tab[i].imie, strlen(tab[i].imie), 1, plik);
// + ewentualnie `fwrite` dla spacji
// fwrite(tab[i].nazwisko, strlen(tab[i].nazwisko), 1, plik);
// + ewentualnie `fwrite` dla spacji
// fwrite(tab[i].rok, strlen(tab[i].rok), 1, plik);

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