Błąd przy wypisywaniu listy jednokierunkowej

0

Chcę napisać listę jednokierunkową, a następnie ją wypisać. Jednak nie mogę tego zrobić, bo przy drugiej wartości w funkcji print po wywołaniu pokazują mi się przypadkowe liczby. Co jest nie tak?

#include <stdio.h>
#include <mm_malloc.h>

typedef struct element
{
    int liczba;
    struct element* nastepny;
} elementptr;

elementptr* dodaj(elementptr* glowa, int liczba)
{
    elementptr* poprzedni=glowa;
    if (glowa)
        while(poprzedni->nastepny)
            poprzedni=poprzedni->nastepny;
    elementptr* nowy=calloc(1, sizeof(elementptr));
    nowy->liczba=liczba;
    nowy->nastepny=NULL;
    if(poprzedni)
    poprzedni->nastepny=nowy;
    return glowa ? glowa : nowy;
}

void main()
{
    elementptr* glowa=dodaj(NULL,7);  
    glowa=dodaj(glowa,12); 
    glowa=dodaj(glowa,18); 
    do
    {
        printf("obecny: %d=%d ", *glowa, *glowa->nastepny);
        glowa=glowa->nastepny;

    } while(glowa->nastepny);
    
}
3
printf("obecny: %d=%d ", *glowa, *glowa->nastepny);

*glowa to struct element, nie int. Powinno być:

        printf("obecny: %d=%d \n", glowa->liczba, glowa->nastepny->liczba);

Nie czytasz komunikatów kompilatora?

wb.cpp: In function ‘int main()’:
wb.cpp:32:26: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘elementptr’ {aka ‘element’} [-Wformat=]
   32 |         printf("obecny: %d=%d ", *glowa, *glowa->nastepny);
      |                         ~^       ~~~~~~
      |                          |       |
      |                          int     elementptr {aka element}
wb.cpp:32:29: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘element’ [-Wformat=]
   32 |         printf("obecny: %d=%d ", *glowa, *glowa->nastepny);
      |                            ~^            ~~~~~~~~~~~~~~~~
      |                             |            |
      |                             int          element

PS: elementptr nie jest wskaźnikiem, to bardzo myląca nazwa.

0

@kq: Mam pytanie, jak to działa, że w funkcji dodaj nie zmieniamy w żaden sposób struktury głowa, w sensie nie widzę nigdzie żebym nadpisywał tę wartość, a pomimo wszystko to działa? XD Dopiero uczę się programowania, to mój pierwszy język i nie do końca to rozumiem. Bo z tego co widzę, działamy jedynie na strukturze ostatni, a jednak to struktura głowa jest zwracana.

2

Z powyższego pytania wynika, że to nie jest twój kod! (gdyby to był twój kod to być rozumiał jak to działa - wartość zwracana).
Jeśli mam rację to zmień źródło wiedzy, bo obecne jest kiepskie.

0

@MarekR22: Masz racje, wzorowałam się na kodzie mojego nauczyciela. Niestety nie mam jak zmienić nauczyciela w szkole, jego tłumaczenia do mnie nie trafiają, dlatego szukam informacji w internecie.

2

No cóż takie życie. Szansa na to, że nauczyciel umiejący programować nadal będzie nauczycielem jest nikła. Za coś trzeba żyć, płacić rachunki.
Podstawowe pytanie, czy nauczyciel pokazał wam jak używać Debugera?

0

@MarekR22: Tak, jednak zazwyczaj nie potrafię go samodzielnie dobrze odczytać, jedynie najprostsze rzeczy. A przy wskaźnikach i strukturach totalnie się we wszystkim pogubiłam.

2

Tu masz nieco poprawiony kod (nadal mnie on boli, ale jest większa szansa, że zrozumiesz co się dzieje):

#include <stdio.h>
#include <mm_malloc.h>

struct element
{
    int liczba;
    struct element* nastepny;
};

typedef struct element *elementptr;

elementptr znajdzOstatni(elementptr element) {
    while (element->nastepny)
        element = element->nastepny;
    return element;
}


elementptr utworzNowy(int liczba)
{
    elementptr nowy=malloc(sizeof(struct element));
    nowy->liczba=liczba;
    nowy->nastepny=NULL;
    return nowy;
}

elementptr dodaj(elementptr glowa, int liczba)
{
    elementptr nowy = utworzNowy(liczba);

    if(glowa) {
        znajdzOstatni(glowa)->nastepny = nowy;
        return glowa;
    }
    return nowy;
}

void zwolnijLista(elementptr glowa)
{
    elementptr p;
    while(glowa) {
        p = glowa;
        glowa = glowa->nastepny;
        free(p);
    }
}

void wypisz(elementptr glowa)
{
    while (glowa)
    {
        printf("obecny: %d %d\n", glowa->liczba, 
            glowa->nastepny?glowa->nastepny->liczba : -1);
        glowa=glowa->nastepny;

    }
}

int main()
{
    elementptr glowa=dodaj(NULL,7);  
    glowa=dodaj(glowa,12); 
    glowa=dodaj(glowa,18);
    wypisz(glowa);

    zwolnijLista(glowa);
}

https://godbolt.org/z/vnYEE5onn

Zwróć uwagę też na opcje kompilatora jakie dodałem:

  • -Wall - włącza ostrzeżenia o prostych potencjalnych błędach logicznych w kodzie (to co ci kq napisał)
  • -Wextra- włącza ostrzeżenia o dodatkowych potencjalnych błędach logicznych w kodzie
  • -Werror traktuj ostrzeżenia jak błedy
  • -fsanitize=address - dodaj dodatkowe narzędzie, w trakcie uruchamiania aplikacji, wykrywał błędy zarządzania pamięcią (bardzo przydatne podczas nauki i testowania).

Taki zestaw opcji wykryje 95% problemów robionych przez początkujących.

0

@MarekR22: Dziękuję za pomoc, teraz już rozumiem co się dzieję:)

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