Element in einer Liste abspeichern schlägt fehl

EDIT: Oder möchtest du eine selbstgeschirebene Klasse benutzen? Danach siehts nämlich aus.

Ja, ich möchte die Klasse selbst schreiben - rein zu Übungszwecken. Aber trotzdem Danke für deinen Tipp! :-)

Wenn du auch "links" einfügen willst brauchst du eine mehfach verkettete Liste, also eine Liste mit einem Zeiger aufs nächte und auf vorherige Element, wenn ich mich nicht irre. Wie du vllt schon gemerkt hast ist pointer-programmierung so ne Sache... benutz lieber die schöne und komfortable List klasse;)

Oh, ich hoffe, dass du mit dieser Aussage falsch liegst. Wenn nicht, habe ich etwas falsch verstanden und das wäre ärgerlich. ;-)

Um bei einer einfach verketteten Liste rechts anzufügen, erstelle ich einen neuen Knoten mit neu->k = die zu speichernde Zahl und neu->rest = NULL. Nun gehe ich die Liste durch und verweise bei dem letzten Eintrag den Pointer, der auf NULL zeigt, auf den Knoten neu.

Um einen Eintrag links hinzuzufügen, erstelle ich einen neuen Knoten. neu->k ist die Zahl, neu->rest = list. Anschließend setze ich den Anfang der Liste auf neu, also *list = neu.

Müsste doch so funktionieren, oder? Und das ohne doppelte Verkettung.

Schon, aber er hat eben Probleme mit dem ganzen Pointerwerk dabei

Genau! Die Liste ist mittlerweile nicht mehr das Problem. :-)

Okay, ich habe mal das Programm, welches Problemlos funktioniert durchkommentiert, so wie ich den Ablauf verstehe. Kann mal jemand drüber schauen ob ich es richtig verstanden habe? Ich weiß, dass es ein kleiner Aufwand ist. Ich wäre demjenigen sehr dankbar. Wenn nicht, ist es auch nicht schlimm...
C:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

/* Liste = Zeiger auf einen Knoten */
typedef struct Knot * Liste;

/* Knoten enthaelt eine eingelesene Zahl */
typedef struct Knot{
	int k;
	Liste rest;
} Knoten;

Liste list = NULL;

void add_element (int eingabe, Liste *list)
/* 
Es steht nun zur Verfuegung, der Inhalt einer "Kopie" der Variable eingabe und ein Zeiger  auf den Zeiger Knot *list, der auf den Speicherbereich 2345 zeigt 
*/
{
	Liste neues_element = malloc(sizeof(Knoten));
	/* Sagen wir der Zeiger neues element zeigt nun auf den Adressbereich = 3456 */

	neues_element->k = eingabe;
	neues_element->rest = *list;
	/* in dem Speicherbereich 3456(.rest) wird die Adresse 2345 abgelegt */
	*list	= neues_element;
	/* Der Zeiger (zeigt auf 2345) auf den Zeiger (zeigt auf 1234) wird einmal dereferenziert, also wird in die Speicherstelle mit der Adresse 1234 der Wert 3456 abgelegt*/

}

int main (void){

	int eingabe = 1;

	while (eingabe != 0)
	{
	/*
	Meine Kommentare nehmen jetzt einfachheitshalber nur einen Schleifendurchlauf an
	*/
		printf("Zahl eingeben (0 fuer Ende): ");
		scanf("%d", &eingabe);
		
		add_element(eingabe, &list);
		/* 
		Ich uebergebe den Inhalt der Variable eingabe und die Adresse des Zeigers list vom Typ Knoten -
		Sagen wir Knot *list zeigt auf den Speicherbereich 1234
		Sagen wir &list ist 2345 
		*/
	}	

	printf("Zahlen in umgekehrter Rheinefolge:\n");
	print(list);
	printf("\n");

	return 0;

}

Nun weiß ich aber immernoch nicht, warum folgende Variante nicht läuft. Das würde ich wirklich gerne verstehen, weil das müsste sie nach meinem Verständnis.

C:
.
.
.


typedef struct Knot * Liste;


typedef struct Knot{
	int k;
	Liste rest;
} Knoten;

void add_left(int eingabe, Liste list)
/*
Es steht nun zur Verfuegung: eine "Kopie" der Variablen eingabe und Der Zeiger Knot* list, der nun auf den Adressbereich 1234 zeigt
*/
{

	Liste neues_element = malloc(sizeof(Knoten));
	/*
	Zeiger Knot * neues_element zeigt auf den Adressbereich 2345
	*/
	neues_element->k = eingabe;
	neues_element->rest = list;
	/*

	In den Adressbereich 2345(.rest) wird nun die Adresse 1234 geschrieben.
	***
	 Liegt hier ein Fehler vor? Muss das nicht heissen neues_element->rest = *list ? 
	***

	*/
	list	= neues_element;
	/*
	Der Zeiger list soll nun auf Adressbereich 2345 zeigen
	*/

}
.
.
.
int main (void)
{
.
.
.
add_left(eingabe, list);
/*
Es wird uebergeben der Wert der Variablen eingabe und der Zeiger list
Nehmen wir an list zeigt auf 1234, also wird auch 1234 uebergeben
*/
.
.
.
}

Die zweite Funktion würde reichen, wenn du nur den knot hinter der list ändern würdest
Angenommen, es geht um einen Knot, der im RAM auf Platz 1234 liegt

Du hast das zwar ausführlich erklärt, aber ich verstehe immer noch nicht, warum ich mit der zweiten Funktion mein Ziel nicht erreichen würde. Ich übergebe bei der zweiten Funktion doch auch einen Zeiger, oder etwa nicht? Ich übergebe ja eingabe und list. list wurde definiert als Liste list, und dies als per typedef als Knot *liste.

Mit der zweiten Funktion kann man eben gut auf den knot zugreifen;
wenn man aber list ändert, wird nur die Kopie angepasst und das Original denkt noch immer, ihm gehört 1234, auch wenn der neu zugeteilte Platz ein paar Millionen Byte daneben liegt

Also habe ich hier wirklich den Denkfehler? Ich dachte mit add_left (eingabe, list) übergebe ich eien Zeiger (list ist doch nun mal ein Zeiger). Demnach sollte dieser Adressbereich bearbeitet werden, und keine Kopie in der Funktion bearbeitet werden
Marschal hat gesagt.:
@Cherrycoke: wenn du mochtest kann ich mal in alten Projekten suchen. Da durfte ich eine funktionierende Liste haben.

Danke! Das ist nett von dir! Aber ich denke nicht, dass es notwendig ist. Meine Liste funktioniert ja nun. Nur habe ich sie an ein paar Stellen noch nicht so ganz verstanden. :-)
 
Hi.

Beim ersten Programm übergibst du ja einen Knot** (Zeiger auf einen Zeiger auf eine Knot Struktur) als Liste. Damit kannst du eben nicht nur auf eine Liste zugreifen, sondern eben auch auf die Variable die die Liste speichert.

Deswegen funktioniert dein zweites Programm nicht, du hast keine Möglichkeit auf die Variable zuzugreifen, da du deren Adresse nicht hast:
C:
int foo(int *ptr) {
   int* p = malloc(sizeof(int));
   (*ptr) = 55; // Wert auf den x in main() zeigt wird geändert.
   ptr = p; // ändert aber nichts an x in main()
}

int bar(int **ptr) {
  (*ptr) = malloc(sizeof(int));
}

int main(void) {
  int* x = NULL;

  foo(x); // NULL wird übergeben, x kann nicht verändert werden.

  bar(&x); // Adresse von x wird übergeben, der Wert von x kann geändert werden.
}
Gruß
 
Zurück