[GELÖST] Ich verzweifele an einem Pointer
-
Hi Community,
ich bin gerade dabei in LIFO Programm zu schreiben. Also mit einer push Prozedur werden werte in eine Liste gespeichert und mit der pop Funktion wieder ausgelesen, wobei immer der letzt gespeicherte Wert als erstes Ausgelesen wird. Also Last In First Out.
Nun soll aber auch eine copy Funktion mit der internen Hilfsfunktion recCopy implementiert werden. Dies klappt auch für einen Leeren Stack. Für einen mit gefüllten Inhalten denke ich habe ich alles richtig gemacht, aber bin mit den Pointern noch nicht so vertraut. Somit habe ich bestimmt nur einen denk oder Syntaxfehler im Code bei copy und somit auch recCopy.
Hier ein Auszug aus meinem Code, ich hoffe ihr könnt mir helfen bzw. einen Tipp geben warum das so nicht funktioniert.
Mein Compiler sagt bei Zeile 8 und 24 folgende Fehlermeldung die mir leider nicht weiter hilft:
error: assigning to 'struct listItem *' from incompatible type 'struct listItem'
struct stack copy(struct stack *pStk1){ printf("Copy...\n"); struct stack pStk2; pStk2.size=pStk1->size; printf("Copy Size: %d\n",pStk1->size); if(pStk1->pFirst==NULL) pStk2.pFirst=pStk1->pFirst; else pStk2.pFirst = recCopy(pStk1->pFirst); if(pStk2.pFirst==NULL) printf("Copy NULL...\n"); else printf("Copy != NULL...\n"); return pStk2; } struct listItem recCopy(struct listItem *pLI){ struct listItem *tmp; tmp = (struct listItem*) malloc(sizeof(struct listItem)); if(tmp != NULL){ tmp->value = pLI->value; if(pLI->pNext==NULL) tmp->pNext = pLI->pNext; else tmp->pNext = recCopy(pLI->pNext); } else printf("Fehler in push: Kein Speicher!\n"); return *tmp; }
Wenn ihr noch andere Angaben braucht oder etwas fehlt, fragt mich bitte. Ich hoffe ih könnt mir helfen...
Vielen Dank schon mal !
-
Dotmatrix schrieb:
Wenn ihr noch andere Angaben braucht oder etwas fehlt,
Die Definition von der
struct stack
bzwstruct listItem
wäre sicher ganz hilfreich.reCopy gibt eine struct zurück (struct listItem). Die willst du aber in einem Zeiger (pFirst) auf so eine struct (struct listItem
ablegen.
(struct listItem
und (struct listItem) sind inkompatible Typen.
So wie char* und char.
-
Hi, das habe ich jetzt auch grad verstanden und konnte die beiden Fehler korrigieren, jetzt habe ich aber das Problem das meine Rückgaben nicht stimmen und das Programm abstürzt. Es ruft recCopy auf und das ruft sich auch selbst nochmal auf bei zwei werten. bei der ersten Rückgabe gibt es eine Null zurück, was auch ok ist, aber bei der zweiten gibt es nicht die richtige Adresse zum Speicher zurück und stürzt ab.
Hier mal der ganze Code zum nachvollziehen. Ich bin denke ich sehr nah dran und es ist bestimmt nur ein kleiner Fehler in der Rückgabe.
main.c
#include <stdio.h> #include "lifo.h" int main(){ struct stack myStack1; struct stack myStack2; myStack1 = init(); //myStack1 initialisieren /* 2 Werte in den Stack schreiben */ push(&myStack1,8); push(&myStack1,9); /* Stack1 mit 2 Elementen in Stack2 kopieren */ myStack2=copy(&myStack1); /* Stack Groesse anzeigen */ printf("myStack1.size aktuell: %d\n",myStack1.size); printf("myStack2.size aktuell: %d\n",myStack2.size); /* 2 Werte aus kopiertem Stack2 auslesen */ pop(&myStack2); pop(&myStack2); return 0; }
lifo.c
#include <stdio.h> #include <stdlib.h> #include "lifo.h" struct listItem recCopy(struct listItem *pLI); struct stack init(){ //Stack Initialisieren und zurückgeben struct stack stk; stk.size=0; //Größe auf 0 setzen stk.pFirst=NULL; //Pointer auf nächstes Element auf NULL setzen return stk; } /*Nicht benötigten CODE entfernt*/ struct stack copy(struct stack *pStk1){ printf("Copy...\n"); struct stack pStk2; pStk2.size=pStk1->size; printf("Copy Size: %d\n",pStk1->size); if(pStk1->pFirst==NULL) pStk2.pFirst=pStk1->pFirst; else *pStk2.pFirst = recCopy(pStk1->pFirst); if(pStk2.pFirst==NULL) printf("Copy NULL...\n"); else printf("Copy != NULL...\n"); return pStk2; } struct listItem recCopy(struct listItem *pLI){ struct listItem *tmp; tmp = (struct listItem*) malloc(sizeof(struct listItem)); if(tmp != NULL){ tmp->value = pLI->value; if(pLI->pNext==NULL) tmp->pNext = pLI->pNext; else *tmp->pNext = recCopy(pLI->pNext); } else printf("Fehler in push: Kein Speicher!\n"); return *tmp; }
lifo.h
#ifndef LIFO_H_ #define LIFO_H_ struct listItem{ //Struktur des Listenelements int value; struct listItem *pNext; }; struct stack{ //Struktur des Stacks int size; struct listItem *pFirst; }; struct stack init(); void deleteStack(struct stack *pStk); void push(struct stack *pStk, int input); int pop(struct stack *pStk); struct stack copy(struct stack *pStk); #endif /* LIFO_H_ */
-
Dotmatrix schrieb:
Es ruft recCopy auf und das ruft sich auch selbst nochmal auf bei zwei werten. bei der ersten Rückgabe gibt es eine Null zurück, was auch ok ist, aber bei der zweiten gibt es nicht die richtige Adresse zum Speicher zurück und stürzt ab.
Weder copy noch recCopy geben Adressen zurück.
Die geben komplette structs zurück.
Und die struct in der aufrufenden Funktin hat eine andere Adresse.Wo gibst du den Speicher frei, den du in recCopy anforderst?
Da du *tmp zurück gibst, geht jeder Verweis darauf verloren: Speicherleck.Du solltest dein Design nochmal überdenken.
Evtl. reicht es auch, nur mit Zeigern zu arbeiten:struct listItem *recCopy(struct listItem *pLI){ ... return tmp; }
so war es ja wohl auch gedacht.
-
WOW SUPER GENIAL DAAAAANNNNNKKEEEE !!!!!!
Genau das war mein Problem.
Du könntest mir nicht nochmal eine kurze Erläuterung geben wann was was bedeutet ? ich glaube das ich da was falsch gespeichert habe in meinem Hirn
Was ändert sich wenn anstatt
struct listItem *recCopy(struct listItem *pLI){
das da steht
struct listItem recCopy(struct listItem *pLI){
und was ist nochmal hier der unterschied zwischen
tmp->pNext = recCopy(pLI->pNext);
und
*tmp->pNext = recCopy(pLI->pNext);
ich befürchte das ich da was verwechsle. Oder hast du eine Seite im Netz wo das anschaulich erklärt wird die du mir empfehlen könntest ?!
ABER TROTZDEM ERST MAL TAUSEND DANK !!!! Hab schon seit 2 Stunden gesucht.
-
Allgemein (vereinfacht):
Rückgabetyp Funktionsname(Parameterliste);
Der Funktionsname ist recCopy. Also ist alles davor der Rückgabetyp.
Was ist der Unterschied zwischen **struct listItem *** und struct listItem.
Das eine ist ein Zeiger (mit dem *), das andere eine ganze Variable.Was ist der Unterschied zwischen tmp->pNext und *tmp->pNext
Hier ist der * der Derefernzierungsoperator. Du greifst auf das Objekt zu, auf das der Zeiger verweist. Ohne * hast du den Zeiger (die Adresse von dem Objekt)
(Das -> bindet stärker, darum bekommst du den Zeiger von pNext)Das ist auch nicht anders als bei char und char* oder int und int*
Lies dir mal die Referenzen zu der Standardbibliothek durch: Z.B . http://www.cplusplus.com/reference/clibrary/
Schau dir die Prototypen an und lies dir denReturn Value
dazu durch.
-
Alles klar, das hat mir schon sehr geholfen.
Werde es mir definitiv durchlesen !Allen noch einen schönen Abend !!!