Usuwanie elementu z listy - pomocy!

0

Witam, jestem początkujący w C i postanowiłem nauczyć się pisać listy. Jednak przy usuwaniu wybranego elementu z listy napotkałem pewien problem. Program po prostu wywala w momencie próby usunięcia elementu. Poniżej zamieszczam kod, byłbym wdzięczny za pomoc.

typedef struct l_samochody
{
    struct l_samochody *next;
    char marka[10];
    char model[10];
    char vin[18];
    char nr_r[18];
    char status[10];

}samochody;
void del_samochod(samochody *conductor, char dana[18])
{
  samochody *wsk;
  wsk=conductor;
while(wsk->vin != dana)
{

    wsk=wsk->next;
}
while (wsk->next!=NULL)
    {
        strcpy(wsk->marka,wsk->next->marka);
        strcpy(wsk->model,wsk->next->model);
        strcpy(wsk->nr_r,wsk->next->nr_r);
        strcpy(wsk->vin,wsk->next->vin);
        strcpy(wsk->status,wsk->next->status);
        wsk = wsk->next;
    }
    wsk->next=NULL;
} 
2
while(wsk->vin != dana)

Tak się nie porównuje tablic znaków w C. Zapoznaj się z strcmp.
Po drugie należy dodać warunek sprawdzający czy nie doszedłeś do końca listy na wypadek gdy nigdzie na liście nie ma elementu z vin == dana.

Samo usuwanie jest bez sensu. Po to masz listę, żeby nie kopiować elementów jak w tablicy. Usuwanie z listy polega na jednej modyfikacji wskaźnika next, żeby pominąć ten element, który ma być usunięty.

2

jeśli tu:

while(wsk->vin != dana) 

chceszs porównać ciągi znaków, to rachej musisz użyć strcmp do tego.

Dodatkowo - chyba nie zrozumiałeś na czym polegają listy i dlaczego wstawianie u usuwanie tam elementów jest szybkie, nie wykorzystujesz tego w tym kodzie!

0

W takim razie jak przykładowo powinno wyglądać usuwanie z takiej listy?

0

Usuwasz element, "przepinając" powiązania, ten który na niego wskazywał wskazywać teraz ma na obiekt następny/poprzedni (w zależności od rodzaju listy)

0

Czy właśnie nie jest to tam tak wykonywane? Czy źle rozumiem to co napisałem?
strcpy(wsk->marka,wsk->next->marka); - do tego co mam teraz przepisuje to co było następne i tak dalej do końca i na końcu ustawiam null.

1

przykład opisowy:

poprzedni->next = usuwany->next;
freeobject(usuwany);

tak mniej więcej powinno to wyglądać. Nie znam większej ilości szczegółów implementacji, dlatego dokładniej nie napiszę, tylko ogólnikowo.

0

Bardzo Panom dziękuje. Udało mi się rozwiązać problem i zrozumiałem idee przepięcia wskaźnika. Efekt zmiany kodu:

 int del_samochod(samochody *conductor, char dana[18])
{
    int tmp=0;
  samochody *wsk;
  wsk=conductor;
while(strcmp(wsk->vin,dana)!=0)
{
    wsk=wsk->next;
    tmp +=1;
    if(tmp==all)
    {
    printf("Nie znaleziono danej");
    return 0;
    }
}
while (wsk->next!=NULL)
    {
     wsk->next=wsk->next->next;
    }
    wsk->next=NULL;
    return 0;
0

Nadal niedobrze. Przepięcie wskaźnika powinno występować raz, a nie w pętli.

Zamiast liczenia tmp i porównania z jakąś zmienną globalną all (be!), lepiej po prostu sprawdzić

while (wsk && strcmp...)
0

Ale ja i tak potrzebuje tej zmiennej globalnej all aby przechowywać w niej cały czas ilość posiadanych samochodów. Czy wystarczy usunąć pętle przepięć?

1

Zmienne globalne są brzydkie i powinieneś ich unikać. Jestem pewien, że możesz wywalić all, a liczbę posiadanych samochodów przekazywać jako argument tam gdzie potrzebujesz.

Czy wystarczy usunąć pętle przepięć?

Nie wystarczy. Bo w tej chwili nie rozumiesz co należy przepiąć na co. Poświęć godzinę czy dwie i przeczytaj dokładnie ten artykuł, który podlinkowałem. Tam masz wszystko wyjaśnione z obrazkami i przykładowym kodem.

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