[C++] Problem z funkcją przeszukującą listę


(Malalina) #1

Nie mogę poradzić sobie z funkcją, która sprawdza czy w liście struktur został już wcześniej wpisany wprowadzony przez użytkownika numer. Numery są tablicami znaków. Jeśli numer się pojawi funkcja zwraca wartość 0, jeśli nie - 1.

Pewnie napisałam zupełną głupotę... mam tylko nadzieję, że rozumowanie jest poprawne:

int sprawdz(komputer *nowy,komputer *glowa)

{ komputer *temp;

      temp=glowa;

         if(strcmp(nowy->numer,temp->numer)==0)

         {return 0;}

//od tego momentu jest posypane...

          else

         {

        do{

             temp=temp->poprzedni;

             }while((strcmp(nowy->numer,temp->numer)==0)||(temp->poprzedni!=NULL));

             if(strcmp(nowy->numer,temp->numer)==0)

             {return 0;}

             else

              {return 1;}

           }

}

Jesteście w stanie mi w tym pomóc?


(Drobok) #2

Rozumowanie dobre, ale całkowicie nie rozumiesz pojęcia pętli. Masz za dużo klamer. Jeśli masz jedną linię nie trzeba stosować klamry. Twój if ma być w pętli a nie poza nią.


(Malalina) #3
int sprawdz(komputer *nowy,komputer *glowa)

{ komputer *temp;

      temp=glowa;

         if(strcmp(nowy->numer,temp->numer)==0)

         return 0;

          else

         {

        do{

             temp=temp->poprzedni;

             if(strcmp(nowy->numer,temp->numer)==0)

             return 0;

             else

             return 1;

             }while((strcmp(nowy->numer,temp->numer)==0)||(temp->poprzedni!=NULL));


           }

}

Jest na pewno czytelniej :wink: ale wciąż się sypie jeśli wprowadzony numer jest inny od poprzedniego. Nie mogę utworzyć nawet drugiego elementu listy.


(Drobok) #4

Po pierwsze strcmp zwraca wartość więc ==0 jest zbędne, aczkolwiek w niczym nie przeszkadza.

Po drugie ja nie jestem jasnowidzem, musiałabyś dać strukturę z objaśnieniem. Albo funkcję wprowadzania danych + strukturę z której robisz listę.


(Martini M) #5

Witam,

W pierwszej kolejności to tak jak kolega drobok napisał podaj strukturę.

Dalej: pierwszy if

if(strcmp(nowy->numer,temp->numer)==0)

         return 0;

jest niepotrzebny tym samym else też jest niepotrzebne. Po co sprawdzać oddzielnie pierwszy element na liście (temp = glowa) jak za chwile i tak w petli sprawdzasz to drugi raz. Teraz kolejna rzecz: pokaż fragment odpowiedzialny za budowanie listy. Bo mam dziwne wrażenie, że wędrujesz nie w tą stronę po liście. Co to jest za lista jedno- czy dwu- -kierunkowa? Jeżeli jednokierunkowa to jak inicjujesz pole (wskaźnik poprzedni). Wydaje mi się, że w pętli do-while robisz błąd myślowy. Jeżeli temp pokazuje na pierwszy element listy (glowa) to wskaźnik glowa->poprzedni a) albo powinien być pusty = NULL b) albo pokazywać na ostatni element listy (jeżeli na liście jest tylko jeden element to to też będzie NULL). Jeżeli moje podejrzenie jest słuszne (bez funkcji wstawiającej ciężko zgadywać) to: a) następuje podstawienie

temp = temp->poprzedni

czyli temp = NULL b) próbujesz zrobić porównanie

if(strcmp(nowy->numer,temp->numer)==0)

czyli

if(strcmp(nowy->numer,NULL->numer)==0)

a to jest nieładne i prawdopodobnie tu się składa. Ja bym to przerobił tak:

int sprawdz(komputer *nowy,komputer *glowa)

{

  komputer *temp = glowa;

  if (temp == NULL) //lista pusta

  {

    return 0;

  }

  bool na_liscie = false;

  do//jezeli tu doszlo to lista ma min 1 element

  {

      na_liscie = (strcmp(nowy->numer,temp->numer) == 0);

      temp=temp->poprzedni; //dopiero po sprawdzeniu przechodzimy na ewentualny następny element listy

   }while(!na_liscie)&&(temp->poprzedni!=NULL)); //trzeba sprawdzic wszystkie z listy a nie tylko jeden jak to robiła Twoja funkcja; bedzie sprawdzac wszystkie, albo do momentu znalezienia na liscie

   int porownanie = (na_liscie ? 0 : 1);

   return porownanie

}

Dlaczego Twoja funkcja sprawdzała tylko jeden? Zapewniał to Twój warunek w do-while

if(strcmp(nowy->numer,temp->numer)==0) //sprawdz jeden (drugi, bo przed chwilą temp przesunął się o jeden)

             return 0; //drugi jest taki sam (logicznie spoko)

             else

             return 1; // drugi nie jest taki sam (a co z resztą listy?) return powoduje wyjście z funkcji przed zakończenie do-while

Napisane z pamięci, więc jeżeli coś, gdzieś pominąłem to przepraszam, ale idea jest oddana.

A nie lepiej, żeby funkcja zwracała bool (true/false) zamiast 0/1? Poza tym zwracaj uwagę na długość wprowadzanych danych do tablic znaków, żebyś nie pisał po pamięci, bo też się będzie wywalać.

Powodzenia


(Malalina) #6

Już sobie poradziłam, bardzo dziękuję opat :slight_smile: Lista jest dwukierunkowa, idzie w dobrą stronę, mam wszystko rozrysowane, żeby się nie pogubić, bo to dość długi program, a mózgu tak wspaniałego żeby wszystko pamiętać nie mam :stuck_out_tongue:

Jeszcze raz wielkie dzięki!