C Verkettete Liste - Zeiger wird nicht geändert

tkiela

Hüüüüäääh? :):)
25 August 2007
634
44
Hallo.
Ich steh glaub ich gerade auf dem Schlauch.
Ich möchte eine verkettete Liste erstellen.
Die Liste sieht so aus:
PHP:
typedef struct Liste_izahlen {
	int zahl;
	struct Liste_izahlen *next;
} Liste;

Liste *start_unsorted = NULL, *p;

Die insert-Funktion sieht so aus:
PHP:
void insert (int izahl, Liste *start)
{
	Liste *zeiger;
	if(start == NULL) {
		   if((p = (Liste *) malloc(sizeof(Liste))) == NULL) 
				{
				 printf("Kein Speicherplatz vorhanden.\n");
				 return;
				}
		   p->zahl = izahl;
		   p->next = NULL;
		   start = p;
	}
}


Rufe die funktion folgender maßen auf:
PHP:
insert(izahl, start_unsorted);
izahl ist ganznormal Integer, start_unsorted ist ein Zeiger auf die Liste. Ganz am Anfang ist dieser Zeiger natürlich NULL.
Ich hab die mal ein wenig gekürzt - das wesentliche ist allerdings noch vorhanden. Ich suche mir mit malloc eine Speicheradresse für das erste Element der Liste. Der Zeiger darauf steht dann in p.
Ich dachte eigentlich, dass ich jetzt durch start = p; auch start_unsorted auf den Wert von p setze.
Wo ist mein Denkfehler?

Ich werd jetzt erstmal paar Stunden abstand davon nehmen, damit ich das ganze danach nochmal klarer betrachten kann, danke aber soweit schonmal für Hilfe!
 
Zuletzt bearbeitet:
Ich dachte eigentlich, dass ich jetzt durch start = p; auch start_unsorted auf den Wert von p setze.
Wo ist mein Denkfehler?
Dass die Variable *start in insert() nur eine lokale Variable ist. Und lokale Variablen verlieren am Funktionsende ihre Gültigkeit.

Damit du einen Zeiger mittels einer Zeiger umbiegen kannst, brauchst du einen Zeiger auf einen Zeiger.
Code:
[FONT=Courier New][COLOR=Red]void insert (int izahl, Liste *start)[/COLOR]
[COLOR=SeaGreen]void insert (int izahl, Liste **start)[/COLOR][/FONT][FONT=Courier New]
[COLOR=Red]if(start == NULL)[/COLOR][/FONT][FONT=Courier New]
[COLOR=SeaGreen]if(*start == NULL)[/COLOR][/FONT] [FONT=Courier New]
[COLOR=Red]start = p;[/COLOR][/FONT] [FONT=Courier New]
[COLOR=SeaGreen]*start = p;[/COLOR][/FONT]
[FONT=Courier New][COLOR=Red]insert(izahl, start_unsorted);[/COLOR][/FONT]
[FONT=Courier New][COLOR=SeaGreen]
insert(izahl, &start_unsorted);[/COLOR][/FONT]
**start bleibt konstant. Eine Änderung würde nicht funktionieren. Wenn du allerdings *start änderst, funktioniert das, weil du (wie am *-Operator zu erkennen) einmal dereferenzierst und woanders einen Wert änderst.

Allerdings würd ich dir das keinesfalls empfehlen, weil du eh schon einen großen konzeptionellen Fehler drin hast:
Der Startelement start_unsorted ist bei dir eine globale Variable. Warum willst du es dann als Funktionsparameter mitgeben?

(Alle Angaben ohne Gewähr. Dein Debugger hilft dir ;))
 
Besten Dank für die schnelle Antwort!

Klingt soweit ja logisch - schade, dass ich nicht selber darauf gekommen bin.

Ich habe noch eine 2. Liste, start_sorted, und eine 2. Funktion insert_sort. Die insert_sort funktion macht nichts anderes, als im richtigen Moment die insert Funktion aufzurufen. Deswegen wird es nicht funktionieren, die globale Variable in insert direkt anzusprechen. Oder ist das ein weiterer Denkfehler?

Habe übrigens auch noch einen Ausweg gefunden, indem ich mir den Zeiger, bzw. die Adresse einfach returne und dann nach dem Funktionsaufruf die globale Variable dahingehend ändere. Funktioniert dann mit ein paar Typenumwandlungen.
Welcher Weg ist da eleganter, effizienter bzw. einfach besser? Mit den Zeigern wohl, oder?
 
Ich habe noch eine 2. Liste, start_sorted, und eine 2. Funktion insert_sort. Die insert_sort funktion macht nichts anderes, als im richtigen Moment die insert Funktion aufzurufen. Deswegen wird es nicht funktionieren, die globale Variable in insert direkt anzusprechen. Oder ist das ein weiterer Denkfehler?
Nö, das is dann korrekt.
Habe übrigens auch noch einen Ausweg gefunden, indem ich mir den Zeiger, bzw. die Adresse einfach returne und dann nach dem Funktionsaufruf die globale Variable dahingehend ändere. Funktioniert dann mit ein paar Typenumwandlungen.
Aber nicht im Sinne von funktionaler Programmierung, wenn du dir Arbeit dann nach Funktionsaufruf selber machst.
Welcher Weg ist da eleganter, effizienter bzw. einfach besser? Mit den Zeigern wohl, oder?
Der zweite Weg sicher nicht.
Der erste Weg... wenn du nur C zur Verfügung hast und kein C++ und es bei genau zwei Listen bleibt, ok. Stell dir vor, du hast 100 Listen oder 1000 Listen, dann brauchst du ein Array von Zeigern (d.h. alle ** werden zu *** 8)) oder ...

Richtig ordentlich machst du es mit einer Klasse :yes:
 
Alles klar.

Habe nur C zur Verfügung und es bleibt nur bei den beiden Listen. Werde es dann dahingehend ändern.

Besten Dank nochmal!