Lista jednokierunkowa na wkaźnikach

0

Witajcie. Otóż mam za zadanie napisać bazę danych, która będzie wczytywać i zapisywać dane do pliku csv. Jednak pierwszy problem pojawił się przy wyświetlaniu listy.

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

struct lista {
    int val;
    struct lista *next;
};

void pokaz_baze(struct lista *element) {
    if(element==NULL) {
        printf("\nBaza danych jest pusta!\n");
    }else{
        while(element!=NULL) {
            printf("%d \n", element->val);
            element = element->next;
        }
    }
}



void dodaj_rekord(struct lista *element) {
   struct lista *nowy = (struct lista*)malloc(sizeof(struct lista));
   printf("Podaj numer indeksu: ");
   scanf("%d", &(nowy->val));
   nowy->next = NULL;
     if((element)==NULL)
     {
      element = nowy;
                     }
     else{
    struct lista *osoba = element;
    while(osoba->next!=NULL) {
        osoba = osoba->next;
        }
    osoba -> next = nowy;
     }
}

int main()
{

    struct lista *head = (struct lista*)malloc(sizeof(struct lista));

    int wybor = 0;
    do{
    printf("\n1. Wyswietl baze\n");
    printf("2. Dodaj rekord\n");
    printf("3. Modyfikuj rekord\n");
    printf("4. Usun rekord\n");
    printf("5. Zakoncz program\n");
    printf("Twoj wybor: ");
    scanf("%d", &wybor);
    switch(wybor) {
        case 1:
        pokaz_baze(head);
        break;
        case 2:
        dodaj_rekord(head);
        break;
        case 3:
        break;
        case 4:
        break;
        case 5:
        printf("\nKonczenie programu!\n");
        break;
        default:
        printf("\nZly wybor. Sprobuj ponownie.\n");
        break;
        }
    }while(wybor!=5);
    return 0;
}

Już pierwszy element jest 0 (podejrzewam, że to przez malloc) ale inne próby kombinowania np. struct lista *head = NULL; pokazywały mi SEGMENTATION FAULT. Nie mogę doszukać się błędu. Domyślam się, że jest śmieszny, ale go nie widzę i trochę się gubię.

0

0

Błędem jest to, że gdy tworzysz head w mainie, nie zerujesz head->next i pokazuje on na śmieci.

Dodawanie jest przekombinowane: dlaczego dodajesz na końcu listy, przez co z każdym dodaniem musisz ją całą przechodzić? Dodawanie na początku wykonuje się w czasie stałym:

void dodaj_record(struct lista** head) {
    struct lista* nowy = malloc(sizeof(struct lista));
    scanf("%d", &(nowy->val));
    nowy->next = *head;
    *head = nowy;
}
0

Dobrze, ogarnąłem większość rzeczy. Dzięki wielkie. Pozostała mi tylko jedna rzecz do zrobienia. Mam sczytać wcześniej zapisaną do pliku csv baze do programu przed wykonaniem jakiejkolwiek czynnosci z menu.

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

FILE *plik;

struct lista {
    char imie[64];
    char nazwisko[64];
    int indeks;
    struct lista *next;
};

int dlugosc(struct lista *element) {
    int i = 0;
    struct lista *wsk = element->next;
    while(wsk) {
        i++;
        wsk=wsk->next;
    }
    return i;
}

void wczytaj_z_pliku(struct lista *element) {
    plik = fopen("baza.csv", "r");
    
    
    fclose(plik);
}

void pokaz(struct lista *element) {
    int i = 1;
    struct lista *wsk = element->next;
    if(wsk == NULL) {
        printf("\nBAZA DANYCH JEST PUSTA\n");
    }else{
         printf("Liczba rekordow w bazie: %d\n", dlugosc(element));
    while(wsk) {
        printf("%d %d %s %s\n",i, wsk->indeks, wsk->imie, wsk->nazwisko);
        wsk=wsk->next;
        i++;
        }
    }
}

void dodaj(struct lista *element) {
    int indeks=0;
    struct lista *wsk = malloc(sizeof(struct lista));
    printf("Podaj imie: ");
    scanf("%s", wsk->imie);
    printf("Podaj nazwisko: ");
    scanf("%s", wsk->nazwisko);
    printf("Podaj numer indeksu: ");
    scanf("%d", &indeks);
    wsk->indeks = indeks;
    wsk->next=element->next;
    element->next=wsk;
}

void edytuj(struct lista *element) {
    int i;
    int el;
    printf("Podaj numer id elementu do edycji: ");
    scanf("%d", &el);
    if(el < 1 || el > dlugosc(element)){
        printf("Brak podanego elementu w bazie");
    }else{
    struct lista *wsk = element;
    for(i=0; i < el; i++) {
        wsk=wsk->next;
    }
    int indeks=0;
    printf("Podaj imie: ");
    scanf("%s", wsk->imie);
    printf("Podaj nazwisko: ");
    scanf("%s", wsk->nazwisko);
    printf("Podaj numer indeksu: ");
    scanf("%d", &indeks);
    wsk->indeks = indeks;
    }
}

void usun(struct lista *element) {
    int i;
    int el;
    printf("Podaj numer id elementu do usuniecia: ");
    scanf("%d", &el);
    if(el < 1 || el > dlugosc(element)){
        printf("Brak podanego elementu w bazie");
    }else{
    struct lista* poprzedni = NULL;
    struct lista* wsk = element;
    for(i=0; i < el; i++) {
        poprzedni = wsk;
        wsk=wsk->next;
    }
    if(poprzedni == NULL) {
        element = element->next;
        free(wsk);
    }else{
        poprzedni->next=wsk->next;
        free(wsk);
        }
    }
}

void zapis_do_pliku(struct lista *element) {
    struct lista *wsk = element->next;
    plik = fopen("baza.csv", "w");
    while(wsk) {
        fprintf(plik, "%s;%s;%d\n", wsk->imie, wsk->nazwisko, wsk->indeks);
        wsk=wsk->next;
        }
    fclose(plik);

}

int main()
{
    int wybor = 0;
    struct lista *head = malloc(sizeof(struct lista));
    head->next=NULL;
    //wczytaj_z_pliku(head);
    do{
        printf("\n\n#########################\n");
        printf("       Baza Danych       \n");
        printf("#########################\n");
        printf("1. Wyswietl baze danych  \n");
        printf("2. Dodaj element do bazy \n");
        printf("3. Modyfikuj element bazy\n");
        printf("4. Usun element bazy     \n");
        printf("5. Zamknij program       \n");
        printf("#########################\n");
        printf("Twoj wybor: ");
        scanf("%d", &wybor);
        printf("\n");
        switch(wybor) {
        case 1:
            pokaz(head);
            break;
        case 2:
            dodaj(head);
            break;
        case 3:
            edytuj(head);
            break;
        case 4:
            usun(head);
            break;
        case 5:
            printf("Zamykanie programu");
            zapis_do_pliku(head);
            break;
        default:
            printf("Zly wybor.");
            break;
        }
    }while(wybor!=5);
    return 0;
}

Czy ktoś może mnie naprowadzić?

0

fscanf(plik, "%s;%s;%d ", wsk->imie, wsk->nazwisko, &(wsk->indeks)); // uwaga, spacja po %d jest niezbędna.
Jeżeli to nie zadziała (patrz [2] w komentarzu @rincewind) to zostaje wczytanie wiersza przez fgets() rozbijanie go np przez strtok, lub czytanie znak po znaku.

0

Hm, no ok. Podjąłem się więc rozbijania łańcucha strtok'iem. Mam coś takiego.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFOR 1024
char buf[BUFOR];

FILE *plik;

struct lista {
    char imie[64];
    char nazwisko[64];
    int indeks;
    struct lista *next;
};

int dlugosc(struct lista *element) {
    int i = 0;
    struct lista *wsk = element->next;
    while(wsk) {
        i++;
        wsk=wsk->next;
    }
    return i;
}

void wczytaj_z_pliku(struct lista *element) {
    int ind;
    plik = fopen("baza.csv", "r");
    fgets(buf,sizeof(buf),plik);
    char *tok = strtok(buf, ";");
    strcpy(element->imie, tok);
    tok = strtok(NULL, ";");
    strcpy(element->nazwisko, tok);
    tok = strtok(NULL, ";");
    ind = atoi(tok);
    element->indeks = ind;
    fclose(plik);
}

void pokaz(struct lista *element) {
    int i = 1;
    struct lista *wsk = element->next;
    if(wsk == NULL) {
        printf("\nBAZA DANYCH JEST PUSTA\n");
    }else{
         printf("Liczba rekordow w bazie: %d\n", dlugosc(element));
    while(wsk) {
        printf("%d %s %s %d\n",i, wsk->imie, wsk->nazwisko, wsk->indeks);
        wsk=wsk->next;
        i++;
        }
    }
}

void dodaj(struct lista *element) {
    int indeks=0;
    struct lista *wsk = malloc(sizeof(struct lista));
    printf("Podaj imie: ");
    scanf("%s", wsk->imie);
    printf("Podaj nazwisko: ");
    scanf("%s", wsk->nazwisko);
    printf("Podaj numer indeksu: ");
    scanf("%d", &indeks);
    wsk->indeks = indeks;
    wsk->next=element->next;
    element->next=wsk;
}

void edytuj(struct lista *element) {
    int i;
    int el;
    printf("Podaj numer id elementu do edycji: ");
    scanf("%d", &el);
    if(el < 1 || el > dlugosc(element)){
        printf("Brak podanego elementu w bazie");
    }else{
    struct lista *wsk = element;
    for(i=0; i < el; i++) {
        wsk=wsk->next;
    }
    int indeks=0;
    printf("Podaj imie: ");
    scanf("%s", wsk->imie);
    printf("Podaj nazwisko: ");
    scanf("%s", wsk->nazwisko);
    printf("Podaj numer indeksu: ");
    scanf("%d", &indeks);
    wsk->indeks = indeks;
    }
}

void usun(struct lista *element) {
    int i;
    int el;
    printf("Podaj numer id elementu do usuniecia: ");
    scanf("%d", &el);
    if(el < 1 || el > dlugosc(element)){
        printf("Brak podanego elementu w bazie");
    }else{
    struct lista* poprzedni = NULL;
    struct lista* wsk = element;
    for(i=0; i < el; i++) {
        poprzedni = wsk;
        wsk=wsk->next;
    }
    if(poprzedni == NULL) {
        element = element->next;
        free(wsk);
    }else{
        poprzedni->next=wsk->next;
        free(wsk);
        }
    }
}

void zapis_do_pliku(struct lista *element) {
    struct lista *wsk = element->next;
    plik = fopen("baza.csv", "w");
    while(wsk) {
        fprintf(plik, "%s ; %s ;%d \n", wsk->imie, wsk->nazwisko, wsk->indeks);
        wsk=wsk->next;
        }
    fclose(plik);

}

int main()
{
    int wybor = 0;
    struct lista *head = malloc(sizeof(struct lista));
    head->next=NULL;
    wczytaj_z_pliku(head);
    do{
        printf("\n\n#########################\n");
        printf("       Baza Danych       \n");
        printf("#########################\n");
        printf("1. Wyswietl baze danych  \n");
        printf("2. Dodaj element do bazy \n");
        printf("3. Modyfikuj element bazy\n");
        printf("4. Usun element bazy     \n");
        printf("5. Zamknij program       \n");
        printf("#########################\n");
        printf("Twoj wybor: ");
        scanf("%d", &wybor);
        printf("\n");
        switch(wybor) {
        case 1:
            pokaz(head);
            break;
        case 2:
            dodaj(head);
            break;
        case 3:
            edytuj(head);
            break;
        case 4:
            usun(head);
            break;
        case 5:
            printf("Zamykanie programu");
            zapis_do_pliku(head);
            break;
        default:
            printf("Zly wybor.");
            break;
        }
    }while(wybor!=5);
    return 0;
}

chciałem sprawdzić, czy chociaż wczyta mi pierwszy rekord, ale nie działa. Zastanawiam się co przeoczyłem.

Edit: Poprawiłem kod i teraz czyta wszystko.

void wczytaj_z_pliku(struct lista *element) {
    int ind = 0;
    plik = fopen("baza.csv", "r");
    while(fgets(buf,sizeof(buf),plik)!=NULL) {
    struct lista *wsk = malloc(sizeof(struct lista));
    char *p;
    p = strtok(buf, ";");
    strcpy(wsk->imie, p);
    p = strtok(NULL, ";");
    strcpy(wsk->nazwisko, p);
    p = strtok(NULL, ";");
    ind = atoi(p);
    wsk->indeks = ind;
    wsk->next=element->next;
    element->next=wsk;
   }
    fclose(plik);
}

została tylko estetyczna poprawka, za każdym uruchomieniem programu odwraca bazę.

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