prayerslayer
Oar. Mh.
|
hi there. ich muss für die uni wieder c programmieren und diese hardwarenähe macht mir echt zu schaffen inzwischen. jedenfalls ist die aufgabenstellung, eine implementierung einer einfach verketteten liste zu schreiben. ich scheitere irgendwie schon an der append-funktion. void Append(IntList *l, int n)
{
IntList neu = (IntList)malloc(sizeof(elemtype));
neu->wert=n;
neu->next=NULL;
if (*l==NULL) //liste leer
{
printf("NEU\n");
*l=neu;
}
else
{
while ((*l)->next!=NULL)
{
printf("Eins weiter\n");
*l=((*l)->next);
}
(*l)->next=neu;
}
}
ich hab immer nur die letzten 2 elemente in der liste und beim einfügen hangelt er sich auch maximal 1x durch. deswegen nehm ich an, dass in zeile 18 beim anhängen der hund begraben liegt. aber ich seh den fehler einfach nicht, vielleicht steh ich auch komplett auf der leitung. hat wer einen hint? sorry, falls es wirklich zu offensichtlich ist, aber mmn sollte es so gehen. tia
|
Souly
Addicted
|
|
semteX
begehrt die rostschaufel
|
der ganze while block ist wahnsinn, ich check ehrlichgsagt im moment ned mal wieso das überhaupt geht... du setzt da den zeiger, welcher auf den listenanfang zeigen soll, ständig weiter... probier im else zweig mal folgendes: IntList *tmp = l;
while((*tmp)->next != null) {
*tmp = (*tmp)->next;
}
(*tmp)->next = neu;
somit bleibt dein l pointer schön am anfang der kette und du itterierst dennoch durch. Weiters, nur als Kosmetik: Es ist unschön wenn Liste und Knoten den selben Datentyp haben, weil es das ganze unlustig zum lesen macht. Schöner ist ma haut ein typedef drüber, welcher IntList und IntNode seperat definiert (obwohl sie beide ein und die selbe klasse sind im hintergrund). edit: ich hätt auch gern den source, irgendwie schaut das ganze gscheit merkwürdig aus (auch was das allokieren und null setzen betrifft...)
Bearbeitet von semteX am 20.12.2008, 12:10
|
aNtraXx
trailer park king
|
Jop, du brauchst eine temporäre Variable, die dir quasi immer den nächsten Knoten referenziert, denn sonst verlierst du am Ende die Referenz auf den Listenkopf.
|
jives
And the science gets done
|
Warum eigentlich (*temp)->next
und nicht temp.next
?
|
semteX
begehrt die rostschaufel
|
ja, irgendwas passt da ganz gewaltig ned zam
|
aNtraXx
trailer park king
|
Warum eigentlich (*temp)->next
und nicht temp.next
? Weil er einen Zeiger auf eine Liste hat und die wiederum auf einen Knoten zeigt l->next würde nur einmal dereferenzieren, dann dürfte er aber die Liste nicht als Referenz übergeben. Daher (*l)->next. Dynamische Objekte werden als Zeiger gehandelt, zwecks dynamischer Bindung. Und da er die Liste ja per maloc erstellt ist sie dynamisch .
Bearbeitet von aNtraXx am 20.12.2008, 13:06
|
Bowser
Addicted
|
Ich glaub du denkst einfach zu kompliziert. Das machen alle die von Java oder ähnlichem kommen. C bzw. C++ ist in vielen Belangen viel einfach konstituiert, eben genau wegen der Hardware nähe. Also du hat ein Objekt (struct nehm ich amal an) mit irgendwelchen Daten und dem Pointer zum nächsten Element. Dann hast du noch den Pointer auf das erste Element und einen auf das neue das du anhängen willst. Also: neu ist der Pointer auf das neue Element l ist der Pointer auf das erste Element current ist z.B. der Pointer auf das Aktuelle Element (zum Schleifendurchzählen) current = l; //Anfang, ist vielleicht besser in der Schleife nicht l zu nehmen um das Erste Element nicht zu verlieren
while ( current->next != NULL ) { // current ist ein Pointer, somit ist die "->" Syntax am einfachsten. Alternativ "(*current).next"
current = current->next //und zum nächsten gehen
} //So, jetzt sollten wir in current das letzte Element haben
printf("%i",current->n); //Test, haben wir wirklich das Letzte??
current->next = neu; //Anhängen vom neuen Element. Beides Pointer, also einfache Zuweisung.
Ich hab jetzt nix getestet oder so, aber es sollt ungefähr so hinhaun.
|
jives
And the science gets done
|
Und da er die Liste ja per maloc erstellt ist sie dynamisch . Ah! Ja, das ist des Rätsels Lösung
|
prayerslayer
Oar. Mh.
|
mit einer tmp variable hab ichs auch schon versucht gehabt, aber ich probier mal. thx derweil im anhang die aufgabenstellung. main und 2 andre funktionen waren gegeben. IntList *tmp = l;
while((*tmp)->next != null) {
*tmp = (*tmp)->next;
}
(*tmp)->next = neu;
somit bleibt dein l pointer schön am anfang der kette und du itterierst dennoch durch.
hab ich so auch schon probiert gehabt und deswegen haut es mit deiner lösung auch nicht hin Weiters, nur als Kosmetik: Es ist unschön wenn Liste und Knoten den selben Datentyp haben, weil es das ganze unlustig zum lesen macht. Schöner ist ma haut ein typedef drüber, welcher IntList und IntNode seperat definiert (obwohl sie beide ein und die selbe klasse sind im hintergrund). nicht auf meinem mist gewachsen @Bowser: danke für die schöne erklärung, aber wennst dir meinen code anschaust wirst sehen, dass ich es eh "so ungefähr" ausschaut
Bearbeitet von prayerslayer am 20.12.2008, 17:25
|
Bowser
Addicted
|
Es schaut ungefähr so aus, ja, aber du vermischt doch 2 Dinge miteinander. Du versuchst immer (*tmp)->new zu verwenden, was aber keinen Sinn macht. Also, mit malloc erhältst du die Adresse (Pointer) zu dem neu erstellen Element. Wenn du den Pointer dereferenzierst erhältst du das Element selbst (*tmp). Wenn du dann auf ein Element daraus zugreifen willst kannst du das mit der Punkt Syntax machen (*tmp).new oder aber die Kurzschreibweise mit dem Pfeil tmp->new. Bei dem Pfeil ist eben kein dereferenzieren mehr dabei. Übrigens ist mir da schon ein Fehler in der ersten Zeile bei deinem Append aufgefallen. Dein neu ist kein Pointer was es aber sein sollte, weil sonst ja der gesamte Sinn von malloc verloren geht.
|
DirtyHarry
aka robobimbo
|
merkst du dir irgendwo start und ende deiner liste? also zwei pointer auf das erste bzw. das letzte element?
wenn nein, das macht das ganze viel leichter, erstes bzw. letztes element aufrufen, dort den eintrag auf das neue struct setzen und fertig
|
prayerslayer
Oar. Mh.
|
Es schaut ungefähr so aus, ja, aber du vermischt doch 2 Dinge miteinander. Du versuchst immer (*tmp)->new zu verwenden, was aber keinen Sinn macht. Also, mit malloc erhältst du die Adresse (Pointer) zu dem neu erstellen Element. Wenn du den Pointer dereferenzierst erhältst du das Element selbst (*tmp). Wenn du dann auf ein Element daraus zugreifen willst kannst du das mit der Punkt Syntax machen (*tmp).new oder aber die Kurzschreibweise mit dem Pfeil tmp->new. Bei dem Pfeil ist eben kein dereferenzieren mehr dabei. Übrigens ist mir da schon ein Fehler in der ersten Zeile bei deinem Append aufgefallen. Dein neu ist kein Pointer was es aber sein sollte, weil sonst ja der gesamte Sinn von malloc verloren geht. ich hab noch viel nachzuholen, seh ich grad. danke jedenfalls
|
Bowser
Addicted
|
So schlimm is es nicht. Ich glaub dir fehlt nur der Pointer als echter Datentyp an Wissen und dann würd schon alles rennen. Wie gesagt, C ist weder kompliziert noch komplex, es ist ja gerade weil doch sehr nahe an der Hardware eher einfach. Java find ich da viel komplexer, weil jede kleine Bibliotheksfunktion in Wirklichkeit ein wahnsinns Aufand ist.
|
semteX
begehrt die rostschaufel
|
da mein rehcner endlich mal wieder rennt hab ich es noch gschwind ausprogrammiert. der "fallstrick" hier ist, dass IntList selbst schon ein zeiger ist. du hast somit beim append einen zeiger auf einen zeiger. void Append(IntList *l, int n)
{
if(*l == 0) {
*l = (IntList)malloc(sizeof(elemtype));
(*l)->next = 0;
(*l)->wert = n;
} else {
IntList tmp = *l;
while(tmp->next != 0)
tmp = tmp->next;
IntList neu = (IntList)malloc(sizeof(elemtype));
neu->next = 0;
neu->wert = n;
tmp->next = neu;
}
}
|