Problem z listą jednokierunkową i strukturami

0

Witam. Jestem raczej początkującym programistą, więc miejcie trochę wyrozumiałości ;).

Mam takie pytanie: czy do listy jednokierunkowej można bezproblemowo dorzucać strukturę (zamiast jakiejś liczby)? Czyli przykładowo (będę okrajał moje kawałki kodu):

struct postac  // struktura postaci - część kodu jako globalna definicja
{
    int id;
    int maxHP;
    ...  // jest wiecej elementow listy, ale juz nie bede ich podawal
};     // tak jest czytelniej :) 

struct lista
{
    struct postac przeciwnik;
    struct lista *nast;
};

typedef struct lista ELEMENT;
typedef ELEMENT *LISTA;

LISTA NPC, biezacyNPC;

Obecnie piszę jako projekt tekstowego RPGa. Niestety, program mi się wywala przy przewijaniu listy do jej ostatniego elementu (kompiluje się bezproblemowo). Napisałem prawie identyczny kod, tylko że przyjmujący dane do liczby, zamiast do struktury - wtedy wszystko działało elegancko (mogę podesłać ten kod ewentualnie do sprawdzenia), ale tutaj nie mam pomysłu, co mogę zrobić dalej:

void dodajNPCdolisty(int i)
{
    biezacyNPC=NPC;
    LISTA nowy=malloc(sizeof(nowy));
    if (!nowy)
    {
        printf("Nie udalo sie utworzyc nowej listy!\n");
        return 0;
    }

    nowy->przeciwnik.id=tablica_NPC[i][0]; // tablica_NPC istnieje i dziala bezproblemowo - sprawdzalem to
    nowy->przeciwnik.maxHP=tablica_NPC[i][1];
    ...

    while(biezacyNPC->nast!=NULL) biezacyNPC=biezacyNPC->nast;  // NA TEJ LINII WYWALA SIĘ PROGRAM
    nowy->nast=NULL;
    biezacyNPC->nast=nowy;
    wypiszlisteNPC();
    czekajnaznak();
}

void wypiszlisteNPC()
{
    biezacyNPC=NPC;
    printf("%d ", biezacyNPC->przeciwnik.id);
    while (biezacyNPC->nast!=NULL)
    {
        biezacyNPC=biezacyNPC->nast;
        printf("%d ", biezacyNPC->przeciwnik.id); // wybralem przykladowe wypisywanie jednego pola ze struktury 
    }
    printf("\n");
}

void usunostzlistyNPC ()
{
    biezacyNPC = NPC;
    LISTA tmp;
    if (biezacyNPC->nast==NULL)
    {
        biezacyNPC->przeciwnik.id=NULL;
        biezacyNPC->przeciwnik.maxHP=NULL;
        ...
        free(biezacyNPC);
    }
    else
    {
        while (biezacyNPC->nast!=NULL)
        {
            tmp=biezacyNPC; biezacyNPC=biezacyNPC->nast;
        }
        tmp->nast=NULL;
        free(biezacyNPC);
    }
}

void czysclisteNPC()  // tutaj funkcja czysci cala liste poza pierwszym jej elementem
{                            // o to chodzilo, na liczbach dziala, ale nie wiem czy na strukturach
    biezacyNPC=NPC;
    while (biezacyNPC->nast!=NULL) usunostzlistyNPC();
}

I w funkcji main() (aby wyeliminować problem pustej listy przy dodawaniu/usuwaniu z niej elementów) dodałem pierwszy element:

    NPC=malloc(sizeof(NPC));
    NPC->przeciwnik.id=-1;
    NPC->przeciwnik.maxHP=-1;
    ...
    NPC->nast=NULL;

Byłbym bardzo wdzięczny, jeśli udałoby się komuś pomóc mi z tym problemem.

0

typedef struct lista ELEMENT;

tu mi się coś nie podoba. dlaczego robisz typedefa z lista na ELEMENT? to w końcu to jest lista czy element?

if (!nowy)
{
printf("Nie udalo sie utworzyc nowej listy!\n");
może zabrzmię jak heretyk, ale chyba można sobie darować sprawdzanie. błąd może być tylko gdy zabraknie wolnej pamięci, ale jeśli do tego dojdzie, to program (albo i cały system) i tak się wywali, marne szanse żeby twój komunikat się w ogóle wyświetlił.

while(biezacyNPC->nast!=NULL) biezacyNPC=biezacyNPC->nast; // NA TEJ LINII WYWALA SIĘ PROGRAM
prawdopodobnie któreś z kolei nast nie jest inicjalizowane, i zawiera śmieci. więc jako różne od NULL zostanie przypisane, i w następnym przebiegu pętli przy próbie dereferencji program się wywala.
pamiętaj że malloc nie zeruje przydzielanej pamięci. calloc – owszem.

0
typedef struct lista ELEMENT;

Tutaj to jest pomysł gościa prowadzącego ćwiczenia z programowania. Czy to ma wielkie znaczenie w kodzie? (czy można by napisać np. typedef struct lista *LISTA; ?)

 if (!nowy)
{
 printf("Nie udalo sie utworzyc nowej listy!\n");

Oczywiście. Tutaj to ten kod dałem na wszelki wypadek (sprawdzałem wszystko co się da, gdzie mi się wywala program, co parę linijek pisałem printf'y, pokazujące mi pomyślne wykonanie ostatniej operacji).

Czyli powinienem użyć calloca?

LISTA nowy=calloc(1,sizeof(nowy));

^ Sprawdziłem to, ale nic się nie zmieniło. Czy może źle coś rozumuję (calloc'a nigdy poprzednio nie używałem).

0

Mniejsza o poprzedni problem (chociaż w sumie chciałbym się dowiedzieć, dlaczego coś nie chciało poprawnie działać przy przewijaniu listy).

EDIT: Kolejny problem z kodem rozwiązałem, ale powyższy został (niestety, nie widzę tutaj opcji wygaszania postu, ani usuwania postu)

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