Lista jednokierunkowa [C]

2012-05-18 15:38
0

Cześć wszystkim. Muszę zrobić bazę danych osób w czystym C. Coś tam naskrobałem, ale przy wpisywaniu 3 osoby program się wysypuje. Siedzę nad tym już parę godzin i już mi się pomysły kończą co może być źle. Z góry dzięki za pomoc.

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

typedef struct Osoba
{

       char imie[100];
       char nazwisko[100];
       int wiek;
       char plec;
       struct Osoba* next;
              } Osoba ;

// zlicza dlugosc listy
int dlugosc_listy(Osoba* lista)
{
    int d = 0;
    Osoba* wsk = lista;
    while(wsk != NULL)
    {
              d++;
              wsk = wsk->next;
              }
    return d;
    }

// dodaje nowy wezel do listy
void dodaj(Osoba** lista, Osoba* nowa)
{
     nowa->next=NULL;

     if((*lista)==NULL)
     {
      *lista = nowa;
                     }
     else
     {
         Osoba* wsk = *lista;
         while((*lista)->next != NULL)
         {
         wsk = wsk->next;

         }
         wsk->next = nowa;

         }
     }              

// dodaje osobe do listy              
void dodajOsobe(Osoba** lista)
{    char line[500];
     Osoba* nowa = (Osoba*)malloc(sizeof(Osoba));
     printf("Podaj imie: ");
     scanf("%s", nowa->imie);

     printf("Podaj nazwisko: ");
     scanf("%s", nowa->nazwisko);

     printf("Podaj wiek: " );
     scanf("%d", &(nowa->wiek));

     printf("Podaj plec: " );
     gets(line);
     gets(line);
     nowa->plec=line[0];

     dodaj(lista, nowa);     
}

//Wypisuje cala liste
void wypisz_liste(Osoba* lista)
{

     Osoba* wsk = lista;

     if(lista == NULL)
     printf("LISTA JEST PUSTA");
     else
     printf("Lista zawiera %d elementow: \n", dlugosc_listy(lista) );
     int i = 1;
     while( wsk != NULL)
     {
            printf("%d %s %s %d %c\n", i, wsk->imie, wsk->nazwisko, wsk->wiek, wsk->plec);
            wsk=wsk->next;
            i++;
     }
}

//Usuwa element z listy
void usun(Osoba** lista, int ID)
{
             Osoba* poprzedni = NULL;
             Osoba* wsk = *lista;
             int i;            
             for(i = 1; i < ID; i++)
             {
                     poprzedni=wsk;
                     wsk=wsk->next;

                     }
             if(poprzedni==NULL)
             {
             (*lista)=(*lista)->next;
             free(wsk);                               
             }
             else
             {
                 poprzedni->next=wsk->next;
                 free(wsk);
                 }
}

// Usuwa osobe po indexie
void usun_osobe(Osoba** lista)
{
     int ID;
     printf("Podaj indeks osoby: " );
     scanf("%d", &ID);

     if((ID > dlugosc_listy(*lista)) || (ID < 1))
     {
           printf("Nie ma takiego indeksu");

           }
     else
     {
         usun(lista,ID);         
         }
     }
     int usun_imnaz_lista(char* im, char* naz, Osoba** lista)
     {
          Osoba* poprzedni=NULL;
          Osoba* wsk= *lista;

          while((wsk != NULL) && ( ( strcmp(wsk->imie, im)!=0) || (strcmp(wsk->nazwisko, naz )!=0) ))
          {
                     poprzedni=wsk;
                     wsk=wsk->next;
          }
          if(wsk == NULL )
          {
                 return 0;
                 }
          else 
          {
                if(poprzedni==NULL)
             {
             (*lista)=(*lista)->next;
             free(wsk);                               
             }
             else
             {
                 poprzedni->next=wsk->next;
                 free(wsk);
                 }
               return 1;
               }
     }

//usuwa po imieniu i nazwisku
     void usun_imnaz(Osoba** lista)
     {
          char im[100];
          char naz[100];

           printf("Podaj imie: ");
     scanf("%s", im);

     printf("Podaj nazwisko: ");
     scanf("%s", naz);

          if(usun_imnaz_lista(im, naz, lista))

          printf("Osoba zostala usunieta");
          else
          printf("Osoba nie zostala usunieta, nie ma takiej osoby");

          }

         void wypisz_osobe_lista(Osoba* lista, int ID)
          {
              int i;
              Osoba* wsk = lista;
          for(i = 1; i < ID; i++)
             {
                     wsk=wsk->next;

                     }
             printf("%d %s %s %d %c\n", i, wsk->imie, wsk->nazwisko, wsk->wiek, wsk->plec);     
                                    }

          //wypisz osobe o podanym indexie
          void wypisz_osobe(Osoba* lista)
          {
               int ID;

               printf("Podaj numer osoby: " );
               scanf("%d", &ID);

               if((ID > dlugosc_listy(lista)) || (ID < 1))
                 {
           printf("Nie ma takiego indeksu");

           }
           else
           wypisz_osobe_lista(lista, ID);    

               }

int main()
{
    Osoba* lista = NULL;

              int option;

 while(option != 0)
           {
printf("\n\n MENU");
printf("\n\n\n 0 Wyjscie z programu");
printf("\n 1 Wpisz dane osoby do bazy");
printf("\n 2 Usun osobe o podanym indeksie");
printf("\n 3 Usun osobe o podanych imieniu i nazwisku");
printf("\n 4 Wyswietl osobe o podanym indeksie");
printf("\n 5 Wyswietl cala liste\n");

           scanf("%d", &option);

           switch(option)
           {             

                         case 1: 
                              printf("DODAWANIE OSOBY\n");
                              dodajOsobe(&lista);
                              break;

                         case 2: 
                              printf("USUWANIE OSOBY O PODANYM INDEKSIE\n");
                              usun_osobe(&lista);
                              break;

                        case 3: 
                              printf("USUWANIE OSOBY NA BAZIE IMIENIA I NAZWISKA");
                              usun_imnaz_lista(im, naz, &lista);
                              menu();

                         case 4: 
                              printf("WYSWIETL OSOBE O PODANYM INDEKSIE\n");
                              wypisz_osobe(lista);
                              break;

                         case 5: 
                              printf("WYSWIETL CALA BAZE\n");
                              wypisz_liste(lista);
                              break;
                         }
          }

   int key;
   scanf("%d", &key);

    }

Pozostało 580 znaków

2012-05-18 19:51
0

Tu jest źle:

         Osoba* wsk = *lista;
         while((*lista)->next != NULL)
         {
         wsk = wsk->next;

         }
         wsk->next = nowa;

         }

Zamiast (*lista)->next powinno być wsk->next:

         Osoba* wsk = *lista;
         while(wsk->next != NULL)
         {
         wsk = wsk->next;

         }
         wsk->next = nowa;

         }

Tak poza tym to można to prościej zrobić:

void dodaj(Osoba** lista, Osoba* nowa)
{
     while (*lista != NULL) lista = &((*lista)->next);
     *lista = nowa;
     nowa->next = NULL;
}
edytowany 7x, ostatnio: adf88, 2012-05-18 19:57

Pozostało 580 znaków

2012-05-18 21:28
0

A jeszcze ładniej wygląda z użyciem referencji:

void dodaj(Osoba *&lista,Osoba* nowa)
  {
   while(lista) lista=lista->next;
   // lista=nowa;
   // nowa->next=0; // to powinno być zrobione w funkcji wywołującej.
   // ale jeżeli już to:
   (lista=nowa)->next=0;
  }

Oczywiście wywoływanie takiej funkcji też jest ładniejsze.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
Tak. Referencje w C. - Endrju 2012-05-19 15:29
Referencja w ANSI C? - _13th_Dragon 2012-05-19 18:38

Pozostało 580 znaków

2012-05-19 01:56
0

Dzięki wielkie, wszystko działa :)

Pozostało 580 znaków

2012-05-19 08:39
0
_13th_Dragon napisał(a):

void dodaj(Osoba *&lista,Osoba* nowa)
  {
   while(lista) lista=lista->next;
W ten sposób zniszczysz wskaźnik głowy listy.

##### [_13th_Dragon napisał(a)](http://4programmers.net/Forum/846964):
(lista=nowa)->next=0;
Nieczytelne, lepiej rozbić na 2 linijki. No i jeśli wskaźniki to `NULL` a nie 0!
edytowany 2x, ostatnio: adf88, 2012-05-19 08:41
1. Racja: coś przekombinowałem - niszczy się wskaźnik. 2. Wątpliwie: to akurat dla kogo co dla początkujących może być mniej czytelne. 3. Absolutnie NIE: wskaźnik w C++ inicjalizujemy wartością 0, NULL zachowany wyłącznie do kompatybilności z C, a skoro już są referencje to znaczy jest to C++. - _13th_Dragon 2012-05-19 12:08
ad 3. Czy używać 0, czy NULL to kwestia stylu. 0 pokazuje jawnie, że to jest jednak int (czy long), a nie wskaźnik, ale za to NULL pokazuje, że chodzi Ci o wskaźnik do niczego. Stroustrup jest zwolennikiem jawnego 0, z kolei w K&R preferują NULL. W nowym VS próbowali zdefiniować NULL jako nullptr, ale niestety ze względu na złe używanie przez programistów NULL (np. jako '\0') psuło to za dużo programów. Nie wpływa to na żadną kompatybilność, nie słyszałem o implementacji, w której NULL nie był by 0 (lub (void *) 0 w C). - Zjarek 2012-05-19 13:21
K&R nie preferują NULL tylko że nie mają wyboru, K&R to czysty C, musi być NULL. Ba kiedy pisali tą swoją książkę zapomnieli zajrzeć do szklanej kuli która by powiedziała że wiele lat później pojawi się C++. Więc to nie jest kwestia stylu tylko kwestia: pisania w C lub pisania w C++ lub pisania bez stylu. - _13th_Dragon 2012-05-19 15:00
W C++ żaden NULL, żadne 0. nullptr jest od tego. W C żadne 0, NULL. - Endrju 2012-05-19 15:30
W C90 już na pewno NULL jest zdefiniowany jako 0 (lub (void *) 0). Z faq Stroustrupa: "In C++, the definition of NULL is 0, so there is only an aesthetic difference. I prefer to avoid macros, so I use 0.", oczywiście w C++11 należy używać tylko nullptr. - Zjarek 2012-05-19 18:23

Pozostało 580 znaków

Liczba odpowiedzi na stronę

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