C - Problem med pekare till länkade listor

Permalänk
Medlem

C - Problem med pekare till länkade listor

Hej,

Har problem med en uppgift (ingen skoluppgift) där jag inte riktigt förstår varför det inte fungerar som jag vill. Enligt boken jag jobbar i så skriver dom att det är bra att ha en struct-pekare till början av listan som man använder sig av när man ska stega igenom den (vilket boken också använder sig av i alla exempel). Det har fungerat bra tidigare men inte nu.

Använder jag mig av

printEntries (listHeader.next);

som jag har nedan fungerar det och det skrivs ut korrekt i terminalen. Men så fort jag försöker använda min pekare istället

printEntries (listPointer);

så får jag segmenteringsfel.

Vad gör jag för fel?

PS. Anledningen till

struct entry listHeader;

är för att funktionen insertEntry ska kunna lägga till något innan första elementet i listan

// Function "insertEntry" inserts new entry to linked list #include <stdio.h> struct entry { int value; struct entry *next; }; // Function inserts new entry to linked list after listelement taken as argument void insertEntry (struct entry *entryToAdd, struct entry *prevPos) { (*entryToAdd).next = (*prevPos).next; (*prevPos).next = entryToAdd; } // Function to print a sequence of linked lists void printEntries (struct entry *ptr) { while ( ptr != (struct entry *) 0 ) { printf("%i\n", (*ptr).value); ptr = (*ptr).next; } printf("\n"); } int main (void) { struct entry listHeader; // Dummy entry as start of list struct entry n1; struct entry n2; struct entry n3; struct entry newEntry; struct entry *listPointer; // Pointer to struct entry... listPointer = listHeader.next; // ...Used as pointer to start of linked list /* Initializing the struct entries*/ listHeader.value = 0; listHeader.next = &n1; n1.value = 100; n1.next = &n2; n2.value = 200; n2.next = &n3; n3.value = 400; n3.next = 0; newEntry.value = 50; printEntries (listHeader.next); insertEntry (&newEntry, &listHeader); printEntries (listHeader.next); return 0; }

Permalänk
Medlem

Raden listPointer = listHeader.next; gör inte att listPointer pekar på listHeader.next, den tilldelar bara värdet på listHeader.next (som där är oinitialiserad) till listPointer. Du måste alltså flytta ner den raden till nedanför listHeader.next = &n1; för att det ska fungera.

Permalänk
Medlem
Skrivet av perost:

Raden listPointer = listHeader.next; gör inte att listPointer pekar på listHeader.next, den tilldelar bara värdet på listHeader.next (som där är oinitialiserad) till listPointer. Du måste alltså flytta ner den raden till nedanför listHeader.next = &n1; för att det ska fungera.

Ok, borde förstått att nåt blivit knas där. Men jag vet inte riktigt hur jag ska lösa det där på ett bra sätt. Om jag använder mig av liknande sätt som tidigare exempel och uppgifter och skriver

listPointer = &listHeader;

så blir problemet att när jag printar ut listan så tas även den med. Jag skulle vilja kunna peka på det listHeader.next pekar på.
Just nu har jag löst det genom att i funktionen printEntries lagt till denna rad även innan while-loopen.

void printEntries (struct entry *ptr) { ptr = (*ptr).next; while ( ptr != (struct entry *) 0 ) { printf("%i\n", (*ptr).value); ptr = (*ptr).next; } printf("\n"); }

Men det borde gå att lösa på något bättre sätt än att göra ett hopp inne i den funktionen. Det jag antar att jag försöker göra är att listPointer ska peka till det listHeader.next pekar till och inte peka till själva listHeader.

Permalänk
Medlem
Skrivet av Perfn:

Det jag antar att jag försöker göra är att listPointer ska peka till det listHeader.next pekar till och inte peka till själva listHeader.

Det är vad du försöker göra, MEN vid det tillfället så pekar inte listHeader.next på någonting alls eftersom du inte har gett listHeader.next något värde ännu när du försöker sätta listPointer.

Varför vill du ha ett dummy entry först? Livet blir enklare om alla element i listan är riktiga element, utan några dummies.

Permalänk
Medlem
Skrivet av Erik_T:

Det är vad du försöker göra, MEN vid det tillfället så pekar inte listHeader.next på någonting alls eftersom du inte har gett listHeader.next något värde ännu när du försöker sätta listPointer.

Varför vill du ha ett dummy entry först? Livet blir enklare om alla element i listan är riktiga element, utan några dummies.

Jag tror det är enklast om jag skriver ned uppgiften.

Write a function called insertEntry() to insert a new entry into a linked list. Have the procedure take as arguments a pointer to the list entry to be inserted (of type struct entry as defined in this chapter), and a pointer to an element in the list after which the new entry is to be inserted.

Då fick jag till denna

// Function inserts new entry to linked list after listelement taken as argument void insertEntry (struct entry *entryToAdd, struct entry *prevPos) { (*entryToAdd).next = (*prevPos).next; (*prevPos).next = entryToAdd; }

The function developed in excersice 2 only inserts an element after an existing element in the list, thereby preventing you from inserting a new entry at the front of the list. How can you use this same function and yet overcome this problem? (Hint: Think about setting up a special structure to point to the beginning of the list.)

Med hänseende till det fetstilade gjorde jag ett till element som las först som skulle kunna fungera som ett tomt "0-element". Men det kanske är helt fel sätt att tänka på?

Permalänk
Medlem
Skrivet av Perfn:

Det jag antar att jag försöker göra är att listPointer ska peka till det listHeader.next pekar till och inte peka till själva listHeader.

En lösning på det är att göra listPointer till en pekare till pekare, d.v.s. struct entry **listPointer;, och låta den peka på listHeader.next. Bra övning för att utöka sin förståelse för pekare om inget annat. Men en bättre lösning är som sagt att inte krångla till det med dummy-element.

Permalänk
Medlem
Skrivet av perost:

En lösning på det är att göra listPointer till en pekare till pekare, d.v.s. struct entry **listPointer;, och låta den peka på listHeader.next. Bra övning för att utöka sin förståelse för pekare om inget annat. Men en bättre lösning är som sagt att inte krångla till det med dummy-element.

TACK! Det existerar alltså en pekare till en pekare. Tänkte att det var nåt sånt jag försökte hitta men sköt mest blint från höften med lite olika kod. Ska genast se om jag kan få det att fungera.

Angående det senare så skrev jag ned uppgiften i ett annat svar alldeles precis innan du svarade nu. Det kanske klargör hur det blev som det blev. Om jag missförstått den delen och boken inte syftade på ett "dummy-element" så tar jag gärna emot tips på hur man hade kunnat gjort det bättre. Ju mer man kan lära sig desto bättre!

Permalänk
Medlem
Skrivet av Perfn:

Jag tror det är enklast om jag skriver ned uppgiften.

Write a function called insertEntry() to insert a new entry into a linked list. Have the procedure take as arguments a pointer to the list entry to be inserted (of type struct entry as defined in this chapter), and a pointer to an element in the list after which the new entry is to be inserted.

Då fick jag till denna

// Function inserts new entry to linked list after listelement taken as argument void insertEntry (struct entry *entryToAdd, struct entry *prevPos) { (*entryToAdd).next = (*prevPos).next; (*prevPos).next = entryToAdd; }

The function developed in excersice 2 only inserts an element after an existing element in the list, thereby preventing you from inserting a new entry at the front of the list. How can you use this same function and yet overcome this problem? (Hint: Think about setting up a special structure to point to the beginning of the list.)

Med hänseende till det fetstilade gjorde jag ett till element som las först som skulle kunna fungera som ett tomt "0-element". Men det kanske är helt fel sätt att tänka på?

Med de restriktionerna så är det helt rätt sätt att tänka på. Gör livet lite krångligare i allmänhet, men nödvändigt i just den här situationen.