[C]Wskaźnik jako argument funkcji

Witam, poniższy kod nie funkcjonuje (w wyniku zastosowaniu *last i *first jako argumenty).

 

Zdaję sobie sprawę, że najlepiej byłoby zastosować tutaj wskaźnik na wskaźnik, tylko dlaczego? Wskaźnik jest pusty, więc powinien spokojnie zadziałać. 

#include <stdio.h>
#include <stdlib.h>

typedef struct Liczby
{
    int liczba;
    struct Liczby *next;
}Liczby;


Liczby *first, *last;

void dodaj(int liczba, Liczby* first, Liczby* last)
{
    Liczby *nowy;
    nowy=(Liczby*) malloc (sizeof(Liczby));
    nowy->liczba=liczba;

    if (first==NULL)
        first=nowy;
  
    else last->next=nowy;
    last=nowy;
    nowy->next=NULL;
}

void przegladaj(Liczby *first)
{
    Liczby *tmp;
    tmp=(Liczby*) malloc(sizeof(Liczby));
    for (tmp=first; tmp!=NULL; tmp=tmp->next)
    {
        printf("%d\n", tmp->liczba);
    }
}


int main()
{
int l;
int *tab=calloc(5, sizeof(*tab));
for (l=0; l<5; l++)
{
    scanf("%d", &tab[l]);
    dodaj(tab[l], first, last);
}
przegladaj(first);

}

:arrow: http://gynvael.coldwind.pl/?id=408

A tak szybciej :smiley: ?

Ale co ty chcesz zrobić bo nie bardzo zrozumiałem? Wygląda na pierwszy rzut oka jak próba implementacji listy jedno kierunkowej, ale nie chce mi się dokładnie analizować.

Majstersztyk to zaallokować tmp aby w następnej linijce nadpisać tmp=first :wink:

tmp=(Liczby*) malloc(sizeof(Liczby));
for (tmp=first; tmp!=NULL; tmp=tmp->next)

To by miało sens gdyby tmp był wskaźnikiem do wskaźnika(tablicą wskaźników) Liczby **tmp;

tmp = (Liczby**)malloc(ilość*sizeof(Liczby*)); by następnie używać tmp[0], tmp[ilość-1].

Przed ich użyciem tmp[0] = first lub tmp[0] = (Liczby*)malloc(sizeof(Liczby));

Nie wiem skąd Ci ten malloc dla tmp przyszedł do głowy(niepotrzebny w tym mejscu) bo mi taki kwiatek daje mi zawsze wrażenie jakbym brał udział w teście Turinga :slight_smile:

http://www.filmweb.pl/film/Ex+Machina-2015-686419

 

Stworzyłeś tablice int w której rozmiar elementu zamiast być sizeof(int)=2 lub 4 jest sizeof(wskaźnik_int) tj 4 do 8B :slight_smile:

int *tab=calloc(5, sizeof(*tab));

Liczysz na szczęście że first, last będą wyzerowane same będąc NULL, nexty mając NULL :slight_smile:

int l;
int *tab=calloc(5, sizeof(*tab));
for (l=0; l<5; l++)
{
scanf("%d", &tab[l]);
dodaj(tab[l], first, last);
}

Dodaj samo w sobie działa poprawnie, mimo że jest dziwacznie napisane.

Mierzi mnie nazewnictwo, ta zmienna pomocnicza last oraz kolejność parametrów w funkcjach,

Dla przejrzystosci warto dodać dwie struktury zamiast jednej i zmiennych globalnych:

typedef struct Lista
{
Element(zamiast nazwy Liczby w mylącej formie mnogiej) *start, *zmienna_pomocnicza_koniec;
}
}Lista;

void dodaj(Lista *lista, int liczba);
void dodaj(Lista *lista, char *tekścior) {
int liczba = atoi(tekścior,);
dodaj(lista, liczba); }

Wówczas jest opcja wywołania dodaj(lista,coś) bez pałętającego się wszędzie last, które masz globalne, tak samo nazywasz zmienne lokalne… dla ułatwienia jest poprawnie ale niezbyt elegancko. Z czasem możesz dodać w ciele Lista pomocniczą zmienną count, sorted itp. dziwactwa jakie przyjdą do głowy a które będą wpływać na działanie funkcji listy Będzie wtedy jasne czego dotyczą, przyspieszą liste, nie będą się mieszać globalne z lokalnymi i nie będą się pałętać w wywołaniach funkcji.

 

Jeżeli Ci zależy na nauczeniu, to rozpracuj swój kod i nie szukaj gotowców, błędy masz conajmniej dwa gotowiec jest już w formie biblioteki standardowej C++ albo boost, jak już opanujesz C :slight_smile:

Chodzi mi o wyjaśnienie dlaczegi w tej konkretnej funkcji dodaj nie działają wskaźniki jako argumenty, ponieważ jeżeli ‘wrzucę je’ do funkcji to wszystko śmiga. @fufus faktycznie jest trochę do poprawki jeśli chodzi o przejrzystość, ale tutaj nacisk kładę na ww problem.

I błędy zdarzają się każdemu :slight_smile:

:arrow: https://pl.wikibooks.org/wiki/C/Funkcje#Za_pomoc.C4.85_wska.C5.BAnik.C3.B3w_.28parametr.C3.B3w.29 (a najlepiej przeczytaj calość: http://pl.wikibooks.org/wiki/C).

Jeśli nie rozumiesz czym są wskaźniki: http://xion.org.pl/2008/03/06/wskaznik-to-tylko-adres/ + http://gynvael.coldwind.pl/?id=408

Dodatkowo polecam:

Zdaje się, że oczekujesz zmiany wartości wskaźnika przekazanego jako argument funkcji. Ale funkcja przekazuje kopię tego wskaźnika. To oznacza, że nawet jak zmienisz tę kopię to orginalny wskaźnik nie ulegnie zmianie i będzie pokazywać na ten sam adres. W przypadku przekazania wskaźnika na wskaźnik możeż zmieniać na co pokazuje oryginalny wskaźnik.

Dziękuję!