Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Funkcja kasująca listę jednokierunkową [C++]. Prośba o sprawdzenie.

Ostatnio zmodyfikowano 2017-06-09 14:02
Autor Wiadomość
pieter111
Temat założony przez niniejszego użytkownika
Funkcja kasująca listę jednokierunkową [C++]. Prośba o sprawdzenie.
» 2017-06-09 09:51:00
Witam, sprawa dotyczy funkcji kasującej listę jednokierunkową. Gdzieś jest błąd bo kasuje tylko pierwszy element z listy, jakby Ktoś mógł zerknąć na poniższy kod z góry dzięki.
C/C++
void skasuj( lista * adres )
{
    lista * poprzedni, * aktualny, * temp;
    poprzedni = adres;
    aktualny = adres;
    while( adres != NULL )
    {
        if( aktualny == adres )
        {
            temp = adres;
            adres = adres->wsk_nastepnika;
            delete temp;
        }
        else
        {
            poprzedni->wsk_nastepnika = aktualny->wsk_nastepnika;
            temp = aktualny;
            aktualny = aktualny->wsk_nastepnika;
            delete temp;
        }
    }
}
P-162282
ArgonZapan
» 2017-06-09 10:51:59
aktualny = adres;

a za chwilę

if( aktualny == adres )

jak wygląda, deklaracja typu lista ?

Nie jestem pewien czy to będzie działać:)

C/C++
if { adres != nulltptr ) {
        while( adres->nastepnika != nullptr ) {
            temp = adres;
            adres = adres > nastepnika;
            delete temp;
        }
        delete adres;
    }
P-162283
pieter111
Temat założony przez niniejszego użytkownika
» 2017-06-09 11:17:13
Deklaracja typu lista, też tak próbowałem jak Ty, ale kasuje tylko pierwszy element z węzła pierwszego i reszta pozostaje bez zmian, nawet pierwszy węzeł.
P-162284
ArgonZapan
» 2017-06-09 11:24:31
C/C++
void skasuj( lista * adres ) {
    lista * temp;
    if { adres != nulltptr ) {
            while( adres->nastepnika != nullptr ) {
                temp = adres;
                adres = adres->nastepnika;
                delete temp;
            }
            delete adres;
        }
    }

Teraz zauważyłem że uciekł mi myślnik :P
A tak jak jest teraz działa?
P-162285
pieter111
Temat założony przez niniejszego użytkownika
» 2017-06-09 11:41:01
Też nie działa, sytuacja bez zmian, dzięki za podpowiedzi.
P-162286
ArgonZapan
» 2017-06-09 11:53:50
Pokaż więcej kodu
P-162287
pieter111
Temat założony przez niniejszego użytkownika
» 2017-06-09 12:16:55
Zadanie: wprowadzic n figur z ilością boków, polem powierzchni i nazwą. Skasować co drugą figurę której liczba boków jest większa od trzech i dopisać jedną figurę na końcu listy. Na koniec skasować listę funkcją kasującą tą listę. I tu jest właśnie problem. @ArgonZapan jak masz chwilę spróbuj skompilować na swoim kompie, ja to kompilowałem w codeblocks.
C/C++
#include <iostream>
#include <limits>
#include <string>
#include <cstdlib>

using namespace std;
const int n = 2;
struct lista
{
    string nazwa;
    double pole_pow;
    int ile_bokow;
    lista * wsk_nastepnika;
};
void drukuj( lista * adres )
{
    cout << "Zawartosc listy:\n";
    while( adres != NULL )
    {
        cout << adres->nazwa << "  " << adres->ile_bokow << "  " << adres->pole_pow;
        adres = adres->wsk_nastepnika;
        cout << endl;
    }
}

void skasuj( lista * adres )
{
    lista * temp, * aktualny;
    aktualny = adres;
    while( adres != NULL )
    {
       
        if( aktualny == adres )
        {
            temp = adres;
            adres = adres->wsk_nastepnika;
            delete temp;
        }
        else
        {
            temp = aktualny;
            aktualny = aktualny->wsk_nastepnika;
            delete temp;
        }
    }
}

int main()
{
    lista * glowa, * aktualny, * poprzedni, * ogon;
    bool fail, fail1;
    glowa = new lista;
    int i = 0;
    do
    {
        cout << "Nazwa? ";
        cin >> glowa->nazwa;
        while( glowa->nazwa[ i ] )
        {
            if( isalpha( glowa->nazwa[ i ] ) ) fail1 = false;
            else
            {
                fail1 = true;
                cout << "Nieprawidlowa nazwa, wprowadz nazwe skladajaca sie z samych liter. ";
                break;
            }
            i++;
        }
    } while( fail1 == true );
   
    do
    {
        cout << "Ile bokow? ";
        cin >> glowa->ile_bokow;
        fail = cin.fail();
        if( fail == true )
        {
            cout << "Liczba bokow musi byc liczba, wprowadz liczbe.\n";
        }
        cin.clear();
        cin.ignore( numeric_limits < streamsize >::max(), '\n' );
       
    } while( fail == true );
   
    do
    {
        cout << "Powierzchnia?";
        cin >> glowa->pole_pow;
        fail = cin.fail();
        if( fail == true )
        {
            cout << "Pole powierzchni musi byc liczba, wprowadz liczbe.\n";
        }
        cin.clear();
        cin.ignore( numeric_limits < streamsize >::max(), '\n' );
    } while( fail == true );
   
    glowa->wsk_nastepnika = NULL;
    ogon = glowa;
    for( int i = 1; i < n; i++ )
    {
        aktualny = new lista;
        do
        {
            cout << "Nazwa? ";
            cin >> aktualny->nazwa;
            while( aktualny->nazwa[ i ] )
            {
                if( isalpha( aktualny->nazwa[ i ] ) ) fail1 = false;
                else
                {
                    fail1 = true;
                    cout << "Nieprawidlowa nazwa, wprowadz nazwe skladajaca sie z samych liter. ";
                    break;
                }
                i++;
            }
        } while( fail1 == true );
       
        do
        {
            cout << "Ile bokow? ";
            cin >> aktualny->ile_bokow;
            fail = cin.fail();
            if( fail == true )
            {
                cout << "Liczba bokow musi byc liczba, wprowadz liczbe.\n";
            }
            cin.clear();
            cin.ignore( numeric_limits < streamsize >::max(), '\n' );
        }
        while( fail == true );
       
        do
        {
            cout << "Powierzchnia? ";
            cin >> aktualny->pole_pow;
            fail = cin.fail();
            if( fail == true )
            {
                cout << "Pole powierzchni musi byc liczba, wprowadz liczbe.\n";
            }
            cin.clear();
            cin.ignore( numeric_limits < streamsize >::max(), '\n' );
        }
        while( fail == true );
       
        aktualny->wsk_nastepnika = NULL;
        ogon->wsk_nastepnika = aktualny;
        ogon = aktualny;
    }
    drukuj( glowa );
    cout << endl;
    lista * tmp, * nowy;
    int l = 0;
    aktualny = glowa;
    poprzedni = glowa;
    while( aktualny != NULL )
    {
        if( aktualny->ile_bokow > 3 )
        {
            if( aktualny == glowa )
            {
                l++;
                poprzedni = aktualny;
                aktualny = aktualny->wsk_nastepnika;
            }
            else
            {
                l++;
                if( l == 2 )
                {
                    poprzedni->wsk_nastepnika = aktualny->wsk_nastepnika;
                    tmp = aktualny;
                    aktualny = aktualny->wsk_nastepnika;
                    delete tmp;
                    l = 0;
                    nowy = new lista;
                    cout << "Nazwa? ";
                    cin >> nowy->nazwa;
                    do
                    {
                        cout << "Nazwa? ";
                        cin >> nowy->nazwa;
                        while( nowy->nazwa[ i ] )
                        {
                            if( isalpha( nowy->nazwa[ i ] ) ) fail1 = false;
                            else
                            {
                                fail1 = true;
                                cout << "Nieprawidlowa nazwa, wprowadz nazwe skladajaca sie z samych liter. ";
                            }
                            i++;
                        }
                    }
                    while( fail1 == true );
                   
                    do
                    {
                        cout << "Ile bokow? ";
                        cin >> nowy->ile_bokow;
                        fail = cin.fail();
                        if( fail == true )
                        {
                            cout << "Liczba bokow musi byc liczba, wprowadz liczbe.\n";
                        }
                        cin.clear();
                        cin.ignore( numeric_limits < streamsize >::max(), '\n' );
                    }
                    while( fail == true );
                   
                    do
                    {
                        cout << "Powierzchnia? ";
                        cin >> nowy->pole_pow;
                        fail = cin.fail();
                        if( fail == true )
                        {
                            cout << "Pole powierzchni musi byc liczba, wprowadz liczbe.\n";
                        }
                        cin.clear();
                        cin.ignore( numeric_limits < streamsize >::max(), '\n' );
                    }
                    while( fail == true );
                   
                    nowy->wsk_nastepnika = NULL;
                    ogon->wsk_nastepnika = nowy;
                }
                else
                {
                    poprzedni = aktualny;
                    aktualny = aktualny->wsk_nastepnika;
                }
               
            }
        }
        else
        {
            poprzedni = aktualny;
            aktualny = aktualny->wsk_nastepnika;
        }
    }
    drukuj( glowa );
    skasuj( glowa );
    cout << endl;
    drukuj( glowa );
    return 0;
}
P-162288
ArgonZapan
» 2017-06-09 13:41:20
C/C++
void drukuj( lista * adres )
{
    cout << "Zawartosc listy: \n";
    while( adres != NULL )
    {
        cout << adres->nazwa << "  " << adres->ile_bokow << "  " << adres->pole_pow;
        adres = adres->wsk_nastepnika;
        cout << endl;
    }
}

void skasuj( lista * & adres ) { // operowanie na oryginalnym wskaźniku
    lista * temp;
    if( adres != nullptr ) {
        while( adres->wsk_nastepnika != nullptr ) {
            temp = adres;
            adres = adres->wsk_nastepnika;
            delete temp; // usuwanie zawartości
            temp = nullptr; // zerowanie wskaźnika
        }
        delete adres;
        adres = nullptr;
    }
}

Jeśli użyjesz delete do wskaźnika, usuwa on zawartość tego na co wskazuje.
Lecz dalej wskazuje on na jakąś komórkę w pamięci. Dlatego używamy nullptr, by nadać mu wartość zerową.
W funkcji "drukuj", przyrównywałeś do zera, ale wskaźnik wciąż wskazywał, na jakąś komórkę. Więc program się sypał w tamtym miejscu, gdy chciałeś się odwołać do skasowanej komórki.

W dodatku, jeśli w funkcji argument wygląda tak
lista * adres
. Oznacza że operujesz na kopii wskaźnika.
Dodając ampersand
lista * & adres
, wtedy działasz na oryginalnym wskaźniku.

Pierwszy od drugiego różni się tym, że na kopii, jeśli użyjesz adres = nullptr. To po wyjściu z funckji, to co przekazałeś, dalej będzie wskazywać, tam gdzie gdzie wcześniej. Na oryginalnym wskaźniku, po wyjściu z funckji, będzie nullptr.
P-162291
« 1 » 2
  Strona 1 z 2 Następna strona