Problem z listą i wskaźnikami

0

Witam wszystkich użytkowników forum.
NA projekt z programowania postanowiłem napisać prostą grę w C z użyciem biblioteki SDL.
Jednak podczas pisana napotkałem na pewien problem z wskaźnikiem do struktury i listą dwukierunkową.

W main mam strukturę na głowę listy (w liście są przechowywane adresy do struktórę informujący przeciwnikach znajdujących się na planszy)

struct ListaPrzeciwnicy * glowaPrzeciwnikow = NULL; 

Następnie dodaje za pomocą funkcji jednego przeciwnika(jak już będzie wszystko działało będę dodawał w pętli ich więcej).
Z każdym przebiegiem głównej pętli pozycja przeciwnika jest aktualizowana i kiedy wyjdzie on poza teren mapy ma być on usunięty z listy. I tutaj własnie mam problem.

Wywołąnie funkcji autalizacji pozycji

zmienPolozenie_przeciwnikow(glowaPrzeciwnikow); 

a oto jej ciało:

 void  zmienPolozenie_przeciwnikow(struct ListaPrzeciwnicy * glowa)
{

  struct ListaPrzeciwnicy * tmp = NULL;
  tmp = glowa;



	while(tmp != NULL) // przelatuje wszystkich przeciwnikow, cala liste
	{
		if( tmp->przeciwnik.wsp.y < JEZDNIA_H + PRZECIWNIK_H)// dopoki nie znajduje sie poza plansza
		{
			scal_powierzchnie(tmp->przeciwnik.wsp.x,tmp->przeciwnik.wsp.y,obrazekPrzeciwnika,ekran,NULL);
			tmp->przeciwnik.wsp.y = tmp->przeciwnik.wsp.y + tmp->przeciwnik.szybkosc;
			tmp = tmp->nast;
		}
		else //jesli poza plansza to usowa z listy
		{

			tmp = usun_przeciwnika(tmp);
		}
	}


}

Kiedy przeciwnik wychodzi za plansze wywoływana jest funkcja usuń_przeciwnika:

 struct ListaPrzeciwnicy * usun_przeciwnika(struct ListaPrzeciwnicy * przeciwnik) // zwraca nastepnego przeciwnika jesli jest
{
    
	if( przeciwnik != NULL)
	{
		struct ListaPrzeciwnicy * usowany = przeciwnik;

		if(przeciwnik->poprz == NULL && przeciwnik->nast == NULL) // jesli jedyny przeciwnik
		{
			przeciwnik = NULL;
		}
		
		else if(przeciwnik->poprz != NULL && przeciwnik->nast != NULL) // jesli sa i przed i za
		{
			
			przeciwnik->poprz->nast = przeciwnik->nast;
			przeciwnik->nast->poprz = przeciwnik->poprz;
			przeciwnik = przeciwnik->nast;

		}

		else if (przeciwnik->nast == NULL) // jesli sa elementy przed danym elemetem
		{
			
			przeciwnik->poprz->nast = NULL;
			przeciwnik = NULL;
		}
		else   // jesli sa elementy tylko za elementem
		{
			przeciwnik = przeciwnik->nast;
		}

		free(usowany); // zwalanianie pamieci
		usowany = NULL;

		return przeciwnik;

	}
}

I moim problemem jest to że jeśli mam narzazie jednego przeciwnika w całej liście i go usunę to chciałbym przypisać mu adres NULL a nie wiem za bardzo jak to zrobić. Funkcja free zwalnia mi opszar po obiekcie ale przypisuje przypadkowe wartości i kiedy poraz kolejny wywołujemy zmieńPozycje program się sypię bo w głowie znajdują się przypadkowe adresy. Próbowałem wielu sposobów i nie wiem gdzie to umieścić, jak użyć zmiennej pomocniczej itp żeby program działął.

Z góry dziękuje za pomoc

0

Możesz to opakować w kolejną strukturę, która przechowuje głowę. Wtedy w funkcji usunięcia zmieniasz tę głowę.

0

ogółem jeśli przekazujesz głowę do funkcji, która może zmienić adres wskazywany przez tą głowę (np na NULL) to powinieneś przekazać ją przez wskaźnik. W tym wypadku jeśli głowa jest wskaźnikiem to powinieneś w funkcji użyć wskaźnika na wskaźnik. Trudno mi jednak powiedzieć czy to jest twoim problemem, strzelam z odpowiedzią bo nie jestem przekonany do końca czy zrozumiałem problem.

edit:
w ogóle jak tak patrze na ten kod to wydaje mi się, że nie obsługujesz sytuacji, w której to usuwanym elementem byłaby głowa. Jeśli z listy usuwasz głowę (bądź w jakikolwiek sposób ją zmieniasz) to wymaga to specjalnego potraktowania to znaczy musisz operować bezpośrednio na niej, a nie na jej kopii, bo po wyjściu z funkcji pomimo zwolnienia pamięci wskaźnik (głowa) będzie dalej wskazywał na obszar (w tej sytuacji już nie należący do ciebie). Błąd ten prawdopodobnie powielasz w pozostałych funkcjach modyfikujących twoją listę, których tutaj nie zamieściłeś. Jednak tak jak napisałem wyżej, to tylko strzał.

edit2:

viruss3000 napisał(a)

Masz racje co do tego drugiego błędu. Nie wiem za bardzo jak to zrobić. Próbowałem używać ** i wysyłać głowę za pomocą &. Nie bardzo zrozumiałem te wskaźniki za wskaźnik a w S.Pratha czy też artykułach w sieci nie znalazłem fajnego wytłumaczenia tego problemu.

no masz co najmniej dwie możliwości. Jedną jest przekazanie głowy przez wskaźnik oraz wykrycie i obsłużenie sytuacji gdy zmienia się sama głowa, drugą natomiast opakowanie w strukturę jak pisał @Zjarek. Ewentualną trzecią mogłoby być utworzenie globalnego wskaźnika do listy ale nie jest to fajne rozwiązanie.

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