Operowanie na wskaźniku na wskaźnik na strukturę

0

Powiedzmy, że mam taką strukturę:

struct Node {
	int value;
	struct Node *next;
};

I teraz, jeśli zdefiniuję sobie typ List w ten sposób:

typedef struct Node List;

To nie mam problemu z przekazuwaniem wskaźnika na listę do funkcji drukujących / sortujących itd.

Jednak jeśli użyję:

typedef struct Node *List;

Zaczynają się problemy, np.

request for member ‘next’ in something not a structure or union

Czy może ktoś napisać jakiś prosty przykład, jak powinno się w takich sytuacjach konstruować funkcje, odczytywać i edytować pola struktury? Najlepiej od samej deklaracji listy, poprzez przekazanie do funkcji aż po przykład funkcji. Może być nawet proste drukowanie listy, po prostu potrzebuję jakiegoś przykładu.

0

No bo jest różnica pomiędzy:
struct Node
a
struct Node *
.
W pierwszym przypadku jak piszesz:
List *tmp; // tmp ma typ struct Node *
W drugim przypadku:
List *tmp; // tmp ma typ struct Node **
Trzeba pisać:
List tmp; // tmp ma typ struct Node *

0

Dzięki, bardzo zwięzłe ale pomocne wytłumaczenie. Już wszystko działa jak trzeba.
Czyli stosowanie

typedef struct Node *List;

Nieco usprawnia pisanie, ponieważ *** przy nazwach zmiennych już nie wstępuje.

0

W zasadzie mam jeszcze jeden problem z usuwaniem pierwszego elementu z listy, wtedy podobno muszę użyć wskaźnika na wskaźnik na listę?

typedef struct Node *List;
...
void usun(List *ptr, int i){...}//musi byc void...
...
List ptr = malloc(sizeof(List));
...
usun(&ptr, 1);

Nie ważne, co wymyślę w funkcji usun pierwszy element nie zostaje wyrzucony z listy. Jego wartość jest ustawiana na 0 (domyślny int) a pole next dalej działa jak powinno.
Czyli z listy:
1, 2, 3, 4, 5
dostaję
0, 2, 3, 4, 5

I taki kwiatek mi wyszedł kiedy pozbywałem się warningów o niezgodności typów:

void usun(List *ptr, int i)
{
	List *current = ptr;
	List *prev = NULL;

	while (current != NULL)
	{
		if ((*current)->value == i)
		{
			if (prev == NULL)
			{
				ptr = &(*ptr)->next;
				printf("usuwam pierwszy\n");
				free(*current);
				current = ptr;
			}
			else
			{
				printf("usuwam kolejny\n");
				(*prev)->next = (*current)->next;
				free(*current);
				current = &(*current)->next;
			}
		}
		else
		{
			printf("przechodze\n");
			prev = current;
			if ((*current)->next == NULL)
			{
				current = NULL;
			}
			else
			{
				current = &(*current)->next;	
			}
		}
	}
}
0

Mieszasz dwa podejścia, rób albo tak:

void usun(List *ptr, int i)
  {
   List current=*ptr;
   List prev=NULL;
 
   while((current)&&(current->value!=i)) { prev=current; current=current->next; }
   if(current)
     {
      if(prev) prev->next=current->next;
      else *ptr=current->next;
      free(current);
     }
  }

albo tak:

void usun(List *ptr, int i)
  {
   List tmp;
   while((*ptr)&&((*ptr)->value!=i)) ptr=&((*ptr)->next);
   if(*ptr)
     {
      tmp=*ptr;
      *ptr=(*ptr)->next;
      free(tmp);
     }
  }
0

Działa jak w zegarku, dodam jeszcze opcję usuwania kilku takich samych elementów na liście i będzie idealnie. Właśnie przed chwilą stworzyłem własne rozwiązanie ale wykorzystywało ono 4 ify i pętlę na 50 linii kodu więc trochę kiepsko ;)
Dziękuję.

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