• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

[C++] Lista powiązana

0 głosów
1,028 wizyt
pytanie zadane 17 lutego 2018 w C i C++ przez AnastaZIuk Początkujący (330 p.)
edycja 17 lutego 2018 przez AnastaZIuk

Witam, mam pewien problem.

Nie mogę zrozumieć pewnej rzeczy związanej z przestawianiem wskaźników w liście jednokierunkowej, chciałbym o wytłumaczenie tego zagadnienia, a oto kod:

 

#include <iostream>
#include <cstdlib>
#include <windows.h>

using namespace std;

void usun_obiekt(string nazwa_obiektu);

struct Obiekt
{
    string nazwa;
    string polozenie;
    int ilosc;
    int masa;
    int moc;
    int indeks;
    Obiekt *nowy_obiekt;
};
Obiekt *dostepny_obiekty = NULL;

    Obiekt *generujObiekt(string nazwa, string polozenie, int ilosc, int masa, int moc, int indeks)
    {
        Obiekt *cos = new Obiekt;
        cos->nazwa = nazwa;
        cos->polozenie = polozenie;
        cos->ilosc = ilosc;
        cos->masa = masa;
        cos->moc = moc;
        cos->indeks = indeks;
        cos->nowy_obiekt = dostepny_obiekty;
        dostepny_obiekty = cos;
        return cos;
    }

int main()
{
    Obiekt *lista_obiektow; lista_obiektow = dostepny_obiekty;
    Obiekt *ten_obiekt;

    string nazwa;
    string polozenie;
    int ilosc;
    int masa;
    int moc;
    int indeks = 1;


    while(true)
    {
        cout << "Witaj uzytkowniku! Stworz obiekt :)"; Sleep(3000); system("cls");
        cout << "Nazwa obiektu: "; cin >> nazwa; if(nazwa == "stop") break;
        cout << "Polozenie obiektu: "; cin >> polozenie;
        cout << "Ilosc tego obiektu: "; cin >> ilosc;
        cout << "Masa tego obiektu: "; cin >> masa;
        cout << "Moc tego obiektu: "; cin >> moc;

        ten_obiekt = generujObiekt(nazwa, polozenie, ilosc, masa, moc, indeks);
        indeks++;
    }

    system("cls");
    lista_obiektow = dostepny_obiekty;  //Aktualizujemy liste obiektow
    cout << "+--------------------------------------------+\n\n                STATYSTYKI\n\n";
    while(lista_obiektow != NULL)
    {
        cout << "Obiekt: " << lista_obiektow->nazwa << " [" << lista_obiektow->indeks << "]\n\n";
        cout << "  *Polozenie obiektu: " << lista_obiektow->polozenie << "\n";
        cout << "  *Dostepna ilosc tego obiektu: " << lista_obiektow->ilosc << "\n";
        cout << "  *Masa tego obiektu: " << lista_obiektow->masa << "\n";
        cout << "  *Moc tego obiektu: " << lista_obiektow->moc << "\n";
        lista_obiektow = lista_obiektow->nowy_obiekt; cout << "\n\n";
    }
    cout << "+--------------------------------------------+\n\n"; string nazwa_usun;
    Sleep(8000); cout << "\n\n\nJaki element chcesz usunac?\nWpisz jego nazwe: ";
    cin >> nazwa_usun;
    usun_obiekt(nazwa_usun); cout << "\n\nA oto aktualna lista obiekow!"; Sleep(1500); cout << "\n\n\n";

    lista_obiektow = dostepny_obiekty;
    cout << "+--------------------------------------------+\n\n                STATYSTYKI\n\n";
    while(lista_obiektow != NULL)
    {
        cout << "Obiekt: " << lista_obiektow->nazwa << " [" << lista_obiektow->indeks << "]\n\n";
        cout << "  *Polozenie obiektu: " << lista_obiektow->polozenie << "\n";
        cout << "  *Dostepna ilosc tego obiektu: " << lista_obiektow->ilosc << "\n";
        cout << "  *Masa tego obiektu: " << lista_obiektow->masa << "\n";
        cout << "  *Moc tego obiektu: " << lista_obiektow->moc << "\n";
        lista_obiektow = lista_obiektow->nowy_obiekt; cout << "\n\n";
    }
    cout << "+--------------------------------------------+\n\n";


}


void usun_obiekt(string nazwa_obiektu)
{
    Obiekt *lista_obiektow;
    lista_obiektow = dostepny_obiekty;
    Obiekt *zapisz_tymczasowo;

    while(true)
    {
        lista_obiektow = lista_obiektow->nowy_obiekt;
        if(lista_obiektow->nowy_obiekt->nazwa == nazwa_obiektu)              //Dochodzimy do wskaznika, za ktorym jest obiekt, ktorego szukamy
        {

            // ---> Dlaczego nie mozna tak zrobic? 
            lista_obiektow = lista_obiektow->nowy_obiekt->nowy_obiekt;

            //zapisz_tymczasowo = lista_obiektow->nowy_obiekt;
            //lista_obiektow = lista_obiektow->nowy_obiekt->nowy_obiekt;
            //delete zapisz_tymczasowo->nowy_obiekt;
            break;   
        }

    }

}

 

Nie mogę zrozumieć w jaki sposób mam usunąć element z takiej listy, próbowałem już na różne sposoby, ale nie mogłem do tego dojść. Za każdym razem próbuję się dostać do pamięci, której już nie ma/nie mam do niej dostępu, ponieważ nie mogę tego dobrze ustawić. Czy mógłby mi ktoś podpowiedzieć, w jaki prawidłowo przestawić wskaźniki i wytłumaczyć mi pokrótce, dlaczego akurat tak? To miejsce znajduje się w warunku funkcji usun_obiekt(string nazwa_obiektu). Z góry dziękuję!

W poleceniu mam napisane (jest to polecenie do zadania, którym jest ten kod) tak: "(...) Funkcja usuwająca powinna przyjmować tylko element przeznaczony do skasowania. Czy taka funkcja jest łatwa do napisania i czy będzie szybka? Czy można ją uprościć albo przyspieszyć, umieszczając w niej dodatkowy wskaźnik do listy?"

Nie wiem czy dobrze rozumiem, ale autorowi chodziło o wskaźnik do poprzedniego elementu listy, mylę się? Ja coś próbowałem z zapisem elementu, który znajduje się idealnie przed elementem, który chcę usunąć, ale raczej nie o to chodzi, bo nie działało to wcale w dobry sposób :D 
 

3 odpowiedzi

0 głosów
odpowiedź 17 lutego 2018 przez Programista 22 Bywalec (2,270 p.)
Chyba używasz jeden wskaznik do każdej zmiennej. Czyli ta zmienna może się zmieniać z np. Adam do Północ.
komentarz 17 lutego 2018 przez AnastaZIuk Początkujący (330 p.)
Tak, tylko czy da radę w taki sposób przestawić wskaźniki i usunąć element czy będę musiał zaimplementować drugi wskaźnik, który będzie mi również wskazywać w każdym obiekcie na poprzedni obiekt?
komentarz 17 lutego 2018 przez Programista 22 Bywalec (2,270 p.)
A co się stanie jeżeli kliniesz "build and run"?
0 głosów
odpowiedź 17 lutego 2018 przez AnastaZIuk Początkujący (330 p.)

Wyskrobałem coś, co nie zatrzymuje mi programu, ale teraz działa to tak, że usuwa mi element wybrany ze środka, który chciałem, tylko, że usuwa również całą resztę elementów, które są za tym elementem usuwanym. Nie mogę tego dalej zrozumieć, czekam na podpowiedź :/

 

void usun_obiekt(string nazwa_obiektu)
{
    Obiekt *lista_obiektow;
    lista_obiektow = dostepny_obiekty;
    Obiekt *zapisz_tymczasowo;
    Obiekt *zapisz_przed_usunieciem;

    while(true)
    {
        lista_obiektow = lista_obiektow->nowy_obiekt;
        if(lista_obiektow->nowy_obiekt->nazwa == nazwa_obiektu)              //Dochodzimy do wskaznika, za ktorym jest obiekt, ktorego szukamy
        {
            zapisz_przed_usunieciem = lista_obiektow->nowy_obiekt->nowy_obiekt;
            lista_obiektow->nowy_obiekt = NULL;
            delete lista_obiektow->nowy_obiekt;
            lista_obiektow = zapisz_przed_usunieciem;

            break;
        }

    }
}

 

0 głosów
odpowiedź 18 lutego 2018 przez AnastaZIuk Początkujący (330 p.)

Udało mi się napisać dzisiaj coś, co działa, tylko nie jestem pewny, czy na pewno pozbywam się tego elementu, a zostaje on w pamięci. Jeśli ktoś miałby kiedyś ten sam problem co ja, to umieszczam kod, w jaki sposób udało mi się do tego dojść z wytłumaczeniem w komentarzach. A ja proszę o sprawdzenie tego, nie jestem w 100% pewny poprawności tego kodu.

Pozdrawiam :)

 

void usun_obiekt(string nazwa_obiektu)
{
    Obiekt *lista_obiekty = dostepny_obiekty;
    Obiekt *test = dostepny_obiekty;
    Obiekt *test2;

    while(true)
    {
        lista_obiekty = lista_obiekty->nowy_obiekt;
        
        if(lista_obiekty->nowy_obiekt->nazwa == nazwa_obiektu)
        {
            test = lista_obiekty;     //Ustawiamy oba wskazniki na miejsce przed elementem, ktory chcemy usunac
            test2 = lista_obiekty;
            
            test2 = test2->nowy_obiekt;                   //Jednym ze wskaznikow przechodzimy   do elemtu, ktory chcemy usunac
            test = test->nowy_obiekt->nowy_obiekt;      //Z kolei drugim przechodzimy do elemtu, ktory znajduje sie za elementem usuwanym
            lista_obiekty->nowy_obiekt = test;        //Teraz przestawiamy wskaznik (ten przed elementem usuwanym), aby wskazywal na element, ktory znajduje sie za elementem usuwanym
            delete test2;                           //Usuwamy element, ktory chcielismy usuanc

            break;
        }
    }
}

 

A i proszę nie przejmować się nazwami typu "test","test2", one służyły mi tylko po to, aby upewnić się czy to co chcę zrobić zadziała. Ich nazwy można podmienić, jeśli ktoś chciałby skorzystać :D

Podobne pytania

0 głosów
1 odpowiedź 533 wizyt
pytanie zadane 9 maja 2020 w C i C++ przez chomik1 Nowicjusz (140 p.)
0 głosów
1 odpowiedź 2,540 wizyt
pytanie zadane 14 listopada 2019 w C i C++ przez baromeister Nowicjusz (140 p.)
0 głosów
1 odpowiedź 1,081 wizyt
pytanie zadane 21 maja 2018 w C i C++ przez Sylwek4321 Nowicjusz (160 p.)

93,599 zapytań

142,524 odpowiedzi

322,993 komentarzy

63,082 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...