odczyt danych z pliku tekstowego do listy jednokierunkowej

0

Jestem w trakcie pisania programu opartego na liście jednokierunkowej. Zatrzymałam się jednak na próbie odczytu danych z pliku tekstowego.
Ta konkretna funkcja wygląda u mnie tak:

void OdczytZPliku() {
    FILE* plik=fopen("plik.txt", "r");
    if(plik==NULL) {
        printf("brak pliku\n");
        return;
    }
    struct Dane *nowy=malloc(sizeof(struct Dane)), *pom=malloc(sizeof(struct Dane));
    while(!feof(plik)) {
        fscanf(plik, "%s %s %d-%d-%d %s %f %f %f", nowy->n, nowy->i, &nowy->rok, &nowy->msc, &nowy->d, nowy->m, &nowy->d1, &nowy->d2, &nowy->p);
        if(poczatek==NULL)
            poczatek=nowy;
        else {
            pom=poczatek;
            while(pom->nast!=NULL)
                pom=pom->nast;
            pom->nast=nowy;
        }

    }
    fclose(plik);
}

Wszystkie dane, które próbuje odczytać funkcją fscanf znajdują się w jednej linii w pliku. Cały program kompiluje mi się, ale kiedy chcę odwołać się do tej funkcji wywala mi błąd. Proszę o jakieś wskazówki, ponieważ siedzę nad tym już jakiś czas i nie mogę wymyślić nic, co by zadziałało.

0
while(fscanf(plik, "%s %s %d-%d-%d %s %f %f %f", nowy->n, nowy->i, &nowy->rok, &nowy->msc, &nowy->d, nowy->m, &nowy->d1, &nowy->d2, &nowy->p)==9
  1. Jeżeli musisz dodawać na koniec to zwyczajnie trzymaj adres ostatniego, bo inaczej tracisz całą przewagę list.
  2. Użyj struct Dane nowy; aby do niego wczytać.
  3. Skoro zwyczajnie przypisujesz: pom->nast=nowy; to musisz na każdym kroku przydzielać pamięć, jak ty sobie to wyobrażasz, dwa razy na początku przydzieliłeś pamięć a później w pętli wczytałeś milion elementów?
0
_13th_Dragon napisał(a):

Jeżeli musisz dodawać na koniec to zwyczajnie trzymaj adres ostatniego, bo inaczej tracisz całą przewagę list.

Czy mogę prosić o dokładniejsze rozwinięcie tego punktu, ponieważ nie do końca rozumiem dlaczego?

0
struct Dane *head=NULL,*tail=NULL;
...
struct Dane tmp;
while(fscanf(... ,&tmp.p)==9)
  {
   struct Dane *nowy=malloc(sizeof(struct Dane));
   *nowy=tmp;
   nowy->nast=NULL;
   if(tail) tail->nast=nowy;
   else head=nowy;
   tail=nowy;
  }
0

Dziękuję, teraz rozumiem. Jednak przy próbie otwarcia pliku wciąż wyskakuje błąd 'program przestał działać'... Natomiast kiedy plik nie istnieje, wtedy normalnie na ekranie zostaje wyświetlone 'brak pliku'.

0

Kod lub ... do wróżbitów.

0
void OdczytZPliku () {
    FILE* plik=fopen("plik.txt", "r");
    if(plik==NULL) {
        printf("brak pliku\n");
        return;
    }
    struct Dane *tail=NULL;
    poczatek=NULL;
    struct Dane nowy;
    while(fscanf(plik, "%s %s %d-%d-%d %s %f %f %f", nowy.n, nowy.i, &nowy.rok, &nowy.msc, &nowy.d, nowy.m, &nowy.d1, &nowy.d2, &nowy.p)==9) {
        struct Dane *pom=malloc(sizeof(struct Dane));
        *pom=nowy;
        pom->nast=NULL;
        if(tail!=NULL)
            tail->nast=pom;
        else
            poczatek=pom;
        tail=pom;
    }
    fclose(plik);
}
0

Pokaż strukturę.

0
struct Dane{
    char *n;
    char *i;
    int rok, msc, d;
    char *m;
    float d1;
    float d2;
    float p;
    struct Dane *nast;
};
struct Dane *poczatek=NULL;
0

Pytanie za sto punktów: Na co wskazuje wskaźnik, który nie dostał do łap żadnego adresu?

0

chyba nie potrafię powiedzieć na co wskazuje, ale wiem, że do takiego wskaźnika nie można się odwoływać ;) czyli błędem jest tu zapis zmiennych w strukturze?

0

Błędem jest niealokowanie pamięci dla napisów.

0

a czy mogę tę pamięć zalokować dynamicznie od razu w strukturze? czy lepiej w samej funkcji odczytu?

0
    char nowy_n[100], nowy_i[100], nowy_m[100];
    struct Dane nowy;
    while(fscanf(plik, "%99s %99s %d-%d-%d %99s %f %f %f", nowy_n, nowy_i, &nowy.rok, &nowy.msc, &nowy.d, nowy_m, &nowy.d1, &nowy.d2, &nowy.p)==9) {
        nowy.n=strdup(nowy_n);
        nowy.i=strdup(nowy_i);
        nowy.m=strdup(nowy_m);
        struct Dane *pom=malloc(sizeof(struct Dane));
        *pom=nowy;
        pom->nast=NULL;
0

a tak jeszcze przy okazji, jeśli chcę dodać opcję wyszukiwania elementów tej listy na podstawie trzech filtrów, których zestaw wybiera użytkownik to w jaki sposób najlepiej to zrobić?

0

Przekazujesz do funkcji wyszukującej numer wybranego filtra ewentualnie tablice numerów ewentualnie jedną liczbę której bity odpowiadają wybranym filtrom.

0

a kiedy mam już stworzone osobne funkcje dla każdego z tych trzech filtrów, a np w kryterium wyszukiwania użytkownik poda, że chce skorzystać z dwóch z nich to w jaki sposób sprawić, aby ten drugi filtr działał już tylko na tych danych, które znalazł pierwszy a nie od początku na całej liście?

0
bool FiltrA(struct Dane *d) { ... }
bool FiltrB(struct Dane *d) { ... }
bool FiltrC(struct Dane *d) { ... }
bool FiltrWspolny(struct Dane *d,unsigned mask)
  {
   if(mask&1) { if(!FiltrA(d)) return false; }
   if(mask&2) { if(!FiltrB(d)) return false; }
   if(mask&4) { if(!FiltrC(d)) return false; }
   return true;
  }
0

a czy mogę jeszcze poprosić o jakiś komentarz do kodu?

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