Lista jednokierunkowa - C

0

Witam. Po skompilowaniu nie mogę wyszukać rekordów, ani też wyświetlić całej listy. Ktoś widzi gdzie i jaki jest tutaj błąd?

 #include <stdio.h>
#include <stdlib.h>
#define ROZMIAR 100

struct Osoba
{
  char imie [ROZMIAR];
  char nazwisko [ROZMIAR];
  int wiek;
  struct Osoba* next;
};

void usun_liste (struct Osoba* head);
int wypisz (struct Osoba* head);
int dodaj (struct Osoba* head);
void wyszukaj (struct Osoba* head, int rok);
void usun (struct Osoba* head);
void drukuj (struct Osoba* wsk);

int main()
{
  struct Osoba* head = NULL;
  int menu = -1, rok;

  while (menu != 0)
  {
    printf ("\nPodaj numer operacji: \n"
        "\n1. Wypisz liste."
        "\n2. Dodaj nowy na początek."
        "\n3. Dodaj nowy na koniec."
        "\n4. Wyszukaj wedłuk roku urodzenia."
        "\n5. Usuń element z początku listy."
        "\n0. Wyjdź.\n");
    scanf ("%d", &menu);

        switch (menu){
          case 1:
          {
        if ( wypisz (head) == -1)
          printf ("Nie udało się zaalokować pamięci");
        break;
          }
          case 2:
          {
        if ( dodaj (head) == -1)
          printf ("Nie udało się zaalokować pamięci");
        break;
          }
          case 3:
        break;
          case 4:
          {
        printf ("Podaj rok urodzenia: ");
        scanf ("%d", &rok);
        wyszukaj (head, rok);
        break;
          }
          case 5:
          {
        usun (head);
        break;
          }

        }


  }
  usun_liste (head);
}

int wypisz (struct Osoba* head)
{
  struct Osoba* wsk;
  wsk = malloc(sizeof(struct Osoba));
    if (wsk == 0)
      return -1;

  for (wsk = head; wsk != NULL; wsk = wsk-> next)
  {
    drukuj (wsk);
  }
  return 0;
}

int dodaj (struct Osoba* head)
{
  struct Osoba* wsk;
  wsk = malloc(1*sizeof(struct Osoba));
  if (wsk == NULL)
    return -1;

  printf ("Podaj imie: ");
  scanf ("%s", wsk->imie);
  printf ("\nPodaj nazwisko: ");
  scanf ("%s", wsk->nazwisko);
  printf ("\nPodaj rok urodzenia: ");
  scanf ("%d", &(wsk->wiek));

  wsk->next = head;
  head = wsk;

  return 0;

}

void usun (struct Osoba* head)
{
  struct Osoba* wsk;

  wsk = head;
  wsk->next = head;
  free (wsk);
}

void wyszukaj (struct Osoba* head, int rok)
{
  struct Osoba* wsk;
  for (wsk = head; wsk != NULL; wsk = wsk->next)
    if (rok == wsk->wiek)
    drukuj (wsk);
}
void drukuj(struct Osoba* wsk)
{
    printf ("\n%s", wsk->imie);
    printf ("\n%s", wsk->nazwisko);
    printf ("\nRok urodzenia: %d\n", wsk->wiek);
}

void usun_liste (struct Osoba* head)
{
  struct Osoba* wsk;
  wsk = head;
  wsk->next = head;
  free (wsk);
  for (wsk = head; wsk != NULL; wsk = wsk->next)
    free (wsk);
}
2
int wypisz (struct Osoba* head)
{
    struct Osoba* wsk;
    wsk = malloc(sizeof(struct Osoba));

Po co alokować? Wyciek pamięci za każdym razem.

wsk = malloc(1*sizeof(struct Osoba));

Po co 1*?

void usun (struct Osoba* head)
{
  struct Osoba* wsk;
 
  wsk = head;
  wsk->next = head;
  free (wsk);
}

Po co ustawiać next czegoś, co zaraz i tak zniknie? Po co wsk skoro można free(head)? Poza tym to nie jest wcale head, więc nazwa parametru wprowadza w błąd.

 
void usun_liste (struct Osoba* head)
{
  struct Osoba* wsk;
  wsk = head;
  wsk->next = head;
  free (wsk);

Najpierw zwalniasz początek listy, a potem:

  for (wsk = head; wsk != NULL; wsk = wsk->next)
    free (wsk);
}

próbujesz lecieć po liście idąc od zwolnionego początku. W pętli robisz ten sam myk, czyli najpierw zwalniasz, a potem próbujesz się odwołać do next zwolnionego elementu.

0
  1. Z mallockiem chciałem poćwiczyć przed kolosem alokację i zapomniałem skasować przed wysłaniem. Rzeczywiście bez sensu.
  2. Ale i tak Twoje sugestie nie rozwiązują problemu niedziałającego programu. Dalej nie wypisuje mojej listy.
    3 Ostatniej sugestii nie rozumiem do końca. tam powinno być
free (head)

, a potem powtórzyć w pętli ponownie?

2

Nic nie wypisuje, bo masz źle utworzoną listę.

int dodaj (struct Osoba* head)
{
    ...
    head = wsk;
    ...
}

head to tylko kopia, więc po wyjściu z funkcji head nie wskazuje na początek listy, tylko nadal na NULL.

void usun_liste(struct Osoba* head)
{
    if (!head) return;

    struct Osoba* wsk = head->next;
    while (wsk)
    {
        free(head);
        head = wsk;
        wsk = head->next;
    }
}
2

Radzę takie rozwiązanie, łatwo się synchronizuje przy wielowątkowości.

void usun_liste(struct Osoba* head)
{
    while(head)
    {
        struct Osoba* tmp=head;
        head=tmp->next;
        free(tmp);
    }
}
0

@twonek - dzięki wielkie. Znalazłem i poprawiłem. Duży plus dla Ciebie.
@up dzięki za cenną wskazówkę :)

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