Lista jednostronna - konstrukcja while

0

Witam. Poniżej przedstawię funkcję do listy, który liczy sumę elementów znajdujących się na liście, następnie kopiuje na na koniec listy tyle elementów, ile wynosi ich pierwotna suma.

 void suma (mode *&head)
{
    if (head)
    {
        int suma = 0;
        int licznik = 0;

        mode*p = head;

        mode*p2 = head;

        while (p->next) // nie wejdzie do ostatniego elementu, stąd dodanie go po pętli
        {
            suma = p->vol + suma;
            p = p->next;
        }
        suma = p->vol + suma;
        
        while (suma > licznik)
        {
            p -> next = new mode;
            p -> next -> vol = p2 ->vol;
            p2 = p2->next;

            p = p->next;
            licznik++;
        }

        p->next = NULL;
    
    }
}

Przy obecnej formie kodu nie będzie zsumowany ostatni element, który jest dodawany już poza pętlą. Próbowałem zrobić tam while (p), następnie, kiedy pierwsza pętla przy ostatnim elemencie przesunęłaby wskaźnik pomocniczy na puste miejsce, w następnej pętli deklarowałbym nowe miejsce po prostu dla p, a nie p->next. To jednak nie działa, Visual wszystko buguje, nie mam pojęcia, dlaczego. Alternatywna wersja kodu, która wydaje mi się o wiele bardziej poprawna, wyglądałaby tak:

 void suma (mode *&head)
{
    if (head)
    {
        int suma = 0;
        int licznik = 0;

        mode*p = head;

        mode*p2 = head;

        while (p)
        {
            suma = p->vol + suma;
            p = p->next;
        }
        
        while (suma > licznik)
        {
            p = new mode;
            p -> vol = p2 ->vol;
            p2 = p2->next;

            p = p->next;
            licznik++;
        }

        p->next = NULL;
    
    }
}
0
  1. daj caly kod
  2. wyjasnij co to znaczy ze vs 'buguje' wszystko
  3. 'wiele bardziej poprawna' - cos jest albo poprawne albo nie, nie ma ze mniej lub bardziej :)
0

Że buguje, to znaczy, że kompilator wykrywa mi błędy, z tego, co widzę, przyczepia się do rezerwacji pamięci, ale nie ma dokładnego komunikatu.

Ad. 3 - z logicznego punktu widzenia tak, ale można zrobić algorytm bardziej czytelny i mniej czytelny, a chyba każdemu chodzi o to pierwsze : ).

Poniżej zamieszczam cały kod.

#include <iostream>
#include <stdio.h>
using namespace std;

struct mode
{ int vol;
 mode *next;
};

void push(mode *&head,int x)
{    mode *pon= new mode;
    pon->vol=x;
    pon-> next=head;
    head=pon;
}

void show(mode *head)
{ 
      cout<<"head-> ";
      mode *p=head;

      while(p!=NULL)
      { 
        cout<<p->vol<<" -> ";
        p=p->next;
      }
      cout<<"NULL"<<endl;
}

void suma (mode *&head)
{
    if (head)
    {
        int suma = 0;
        int licznik = 0;

        mode*p = head;

        mode*p2 = head;

        while (p->next)
        {
            suma = p->vol + suma;
            p = p->next;
        }
        suma = p->vol + suma;
        
        while (suma > licznik)
        {
            p -> next = new mode;
            p -> next -> vol = p2 ->vol;
            p2 = p2->next;

            p = p->next;
            licznik++;
        }

        p->next = NULL;
    
    }
}

int main()
{
        mode*head=NULL;

        push(head,4);
        push(head,2);
        push(head,5);
        push(head,6);

        show (head);

        suma(head);
        show(head);
        system ("pause");
 }
1

mysle ze to jest ok, zamien tylko

#include <stdio.h>

na

#include <cstdlib>
0

Niestety zmiana biblioteki nic nie pomogła.

0

bo używasz w bardzo brzydki sposób funkcji system... wtedy musisz dodać:

#include <cstdlib> 
0

Nie chodzi o system - po prostu w pierwotnej wersji programu wszystko działa, a po zmianie we while'ach już nie : ). Btw. a co nie tak z używaniem "system"? Wszelkie wskazówki mile widziane.

0

podziel sie tym co wywala kompilator.

0

Niestety nic nie pokazuje, program po prostu stopuje (aktualnie jestem na Dev C++). Na laborkach pracowałem na Visualu i pojawiały się same dziwne kody błędu. Myślałem, że to adresy, ale po dłuższym namyśle stwierdzam, że to adresy faktycznie nie były, także nie jestem pewien, czy ma to z pamięcią coś wspólnego :).

0

u mnie dziala - http://ideone.com/GEpm3L

0

Działa, bo wprowadziłaś poprzednią wersję, którą akurat miałem wtedy w programie, gdy przepisywałem kod : ).

1

to w takim razie nie do konca rozumiem problem, masz dzialajacy program ale chcesz go zepsuc?

tak czy siak tutaj masz dziwna rzecz:

 
            p = new mode;
            p -> vol = p2 ->vol;
            p2 = p2->next;
 
            p = p->next;

czyli

  1. zrob nowy obiekt
  2. ustaw mu pole
  3. blablabla
  4. nadpisz obiekt jakims smieciem

takze namieszane i tyle :)

2

bląd jest w funkcji suma masz

void suma (mode *&head) 

a powinno być

 void suma (mode *head)

aczkolwiek to nie tyle bład, co niepotrzebne miejsce przyszłych kłopotów

0

Chcę zmienić tamto, bo mam dopisaną jedną rzecz poza pętlą, a chciałbym, żeby wszystko się w pętli zmieściło. Przy większym programie mogłoby być dosyć dużo kłopotów. No i zapis jest po prostu czytelniejszy.

  1. deklaracja pola dla pustego miejsca,
  2. przypisanie wartości począwszy od pierwszej wartości głowy,
  3. przesunięcie wskaźnika głowy na następny element - dzięki temu w następnej wersji przepisze drugą wartość od głowy.
  4. przesunięcie p na nulla - wracamy do punktu pierwszego.
0

reasumujac:

  1. brakuje ci elementarnej wiedzy, przerob sobie jakis tutorial do c++
  2. poeksperymentuj troche, naucz sie interpretowac komunikaty bledow
  3. daj sobie spokoj z dev c++, lepiej jednak sciagnij tego visuala
0

Ale w pierwotnej formie programu wszystko przecież działa na tej zasadzie. Gdzie więc błąd w rozumowaniu popełniam? Proszę mi nie proponować tutoriali, bo to ogólne stwierdzenie i w nijak ma się do zrozumienia przeze mnie problemu.

0
Ceplusplus napisał(a):

Ale w pierwotnej formie programu wszystko przecież działa na tej zasadzie. Gdzie więc błąd w rozumowaniu popełniam?

nie, implementacja jest inna, przeciez to oczywiste 1) dziala 2) nie
napisalam ci w punktach gdzie lezy problem. nadpisujesz wskaznik do nowo stworzonego obiektu na stercie.

Ceplusplus napisał(a):

Proszę mi nie proponować tutoriali, bo to ogólne stwierdzenie i w nijak ma się do zrozumienia przeze mnie problemu.

jak najbardziej sie ma, aby zrozumiec co do ciebie pisze potrzebna jest znajomosc srodowiska w ktorym pracujesz. tej znajomosci nie posiadasz, dlatego zaproponowalam najlepsze moim zdaniem rozwiazanie - zdobycie troche wiedzy i doswiadczenia

0

Skoro w książce czegoś nie przerobiłem, coś mi umknęło, to przecież najlepszym weryfikatorem powinna być właśnie taka dyskusja, żeby uzupełnić luki. Ty z kolei odsyłasz mnie do książek, sugerując, że nawet nie aspiruję do dialogu z Tobą. Chcesz się wywyższyć, coś mi udowodnić? Zaprzeczasz idei forum dyskusyjnego. A starczy mi kulturalnie wytłumaczyć, gdzie dokładnie jest błąd, zamiast budować jakąś hierarchię.
Jeśli p jest nullem (a będzie nullem po wykonaniu pierwszej pętli) to chyba poprawnym działaniem jest przyporządkowanie mu miejsca w pamięci, żeby przypisać jakąś wartość i stworzyć nexta, którym potem nadpiszemy nasze p (które zaś będzie wskazywało na null, po czym powtórzymy kroki)? Oczywiście gdzieś popełniam błąd w rozumowaniu i prosiłbym o jego weryfikację. Ręczę przy tym, że wałkowanie Praty mi w tej konkretnej sytuacji nie pomoże : ).

1

Nie zrozumielismy sie, musisz wybaczyc mi forme jesli cie to urazilo. Nie jest moja intencja wywyzszanie sie, zdecydowanie nie mam ku temu powodow jako ze moje doswiadczenie z c++ nie jest imponujace. Nie traktuj odsylania cie do tutoriali czy IDE jako zlosliwosc, po prostu mowie swoje zdanie - najlepszym sposobem na nauke programowania jest praktyka czyli napisanie, skompilowanie i zdebugowanie programu (przynajmniej 2 ostatnich krokow chyba nie zrobiles, nie?) a nie dyskutowanie 'na sucho'.

Tak jak napisalam to co robisz z p w petli while:

  1. przypisujesz wskaznik do nowo zaalokowanego obszaru pamieci
  2. ustawiasz wartosc pola
  3. nadpisujesz wskaznik przypisany w 1) nowa wartoscia, obiekt stworzony w 1) jest bezpowrotnie tracony
    Mysle ze gdybys przeszedl debuggerem przez druga petle while to pomogloby ci to zrozumiec gdzie lezy blad.
0

W porządku, nic się nie stało, na forum niestety nie ma mimiki i tonu głosu : ).
Już rozumiem. Czyli po prostu zamiast przypisać nowe pole do nexta, po prostu nadpisuję p, który zamiast być nextem pierwotnego p, bezsensownie nadpisuje wartość?

1

tak, zatem kluczowa w tym wypadku byla by zamiana

p = new mode;

na p->next = new mode;

0

W porządku, elegancko. Czyli pierwszy ze składników zaimplementować w takim wypadku przed pętlą (bo nie przypiszemy nexta do pustego elementu)?

1

zgadza sie, przed drugim while, p jest rowne 0

0

Tak zrobiłem, niestety program nadal nie działa. Poniżej przedstawiam kod.

#include <iostream>
#include <cstdlib>
using namespace std;

struct mode
{ int vol;
 mode *next;
};

void push(mode *&head,int x)
{    mode *pon= new mode;
    pon->vol=x;
    pon-> next=head;
    head=pon;
}

void show(mode *head)
{ 
      cout<<"head-> ";
      mode *p=head;

      while(p!=NULL)
      { 
        cout<<p->vol<<" -> ";
        p=p->next;
      }
      cout<<"NULL"<<endl;
}

void suma (mode *&head)
{
    if (head)
    {
        int suma = 0;
        int licznik = 0;
 
        mode*p = head;
        mode*p2 = head;
 
        while (p) // nie wejdzie do ostatniego elementu, stąd dodanie go po pętli
        {
            suma = p->vol + suma;
            p = p->next;
        }
 		
 		p = new mode;
 		
        while (suma > licznik)
        {
            p->next = new mode;
            p -> vol = p2 ->vol;
            p2 = p2->next;
 
            p = p->next;
            licznik++;
        }
 
        p->next = NULL;
 
    }
}

int main()
{
        mode*head=NULL;

        push(head,4);
        push(head,2);
        push(head,5);
        push(head,6);

        show (head);

        suma(head);
        
        show(head);
 }
1

przeanalizuj krok po kroku w debuggerze, bez problemu zauwazysz problem :)

0

Napiszę więc ponownie po zainstalowaniu Visuala :).

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