fprintf und zeiger (und andere obskure probleme)
-
Hi!
dies ist mein erster post bei euch. ich hoffe ihr könnt mir helfen. ich bin mit meinem latein am ende. ich programmiere schon etwas länger mit c++ und java. ich studiere informatik im zweiten semester und bin durch eine veranstaltung an c gekommen. bis jetzt hatte ich auch keine großen probleme, abgesehen von den kleinen "einschränkungen" die man erfährt, wenn man vorher mit einer moderneren sprache gearbeitet hat. c hat aber natürlich auch seine vorteile ;).
hier mein problem: ich muss für ein praktikum ein programm schreiben, welches mit hilfe einer einfach verketteten liste ein rennen simulieren soll, heißt datensätze vergleichen und nach zeit sortieren. die realisierung der datensatz struktur muss mit zeigern gemacht werden. ich stoße jedoch schon vor der hauptaufgabe auf ein paar probleme mit den zeigern. ich zeig euch am besten einfach mal den (leicht zusammen gefassten (aber lauffähigen)) code:/* Verkettete Liste zur Darstellung eines Rennens */ #include <stdio.h> #include <stdlib.h> void Input( void ); typedef struct datenSatz { char *Name; char *FName; struct datenSatz *next; } ; struct datenSatz *current = NULL; /* zeiger auf aktuelles element */ struct datenSatz *prev = NULL; /* zeiger auf vorheriges element */ int counterSportler = 0; int main() { printf("TechProg 2 Aufgabe 5 von Heiko Westermann\n"); printf("Verkettete Liste zur Darstellung eines Rennens\n\n"); Input(); /* eingabe von zwei elementen/sportlern */ Input(); while(counterSportler > 0) { fprintf(stdout, "#%d, Name: %s Vorname: %s \n", counterSportler, current->Name, current->FName); counterSportler--; if( current->next != NULL ) /* wenn liste NICHT zuende, spring zum naechsten element */ { current = current->next; } } } void Input(void) /*eingabe funktion zur erstellung eines neuen lsiten elements */ { struct datenSatz hui; /* neuer datensatz */ current = &hui; /* zeiger auf den aktuellen datensatz */ char temp[30] = {0}; printf("-- Hinzufuegen eines Sportlers --\n"); printf("Nachname: "); fgets( temp, 30, stdin); temp[strlen(temp)-1] = '\0'; current->Name = calloc(strlen(temp), sizeof(char)); /* moelichst platzsparend abspeichern */ strcpy(current->Name, temp); /* kopiere string zu gesichertem speicher */ printf("Vorname: "); /* ...hier das gleiche nochmal... */ fgets( temp, 30, stdin); temp[strlen(temp)-1] = '\0'; current->FName = calloc(strlen(temp), sizeof(char)); strcpy(current->FName, temp); if( counterSportler == 0 ) /* wenn erstes element in liste, nichts verlinken */ current->next = NULL; else current->next = prev; /* ansonsten an vorheriges element linken */ prev = current; /* prev zeiger auf aktuelles element setzen */ counterSportler++; }
ein problem ist, das ich nach der eingabe der daten mit fprintf die daten ausgebe und die zeiger, die VORHER auf richtige daten zeigen, DANACH total zerschossen sind. weiß jemand woran das liegen kann? ich gebe die daten ja nur aus und verändere sie nicht.
das zweite problem ist, das die verkettung der liste nicht funktioniert, da die struktur hui in der funktion Input() bei jedem aufruf die gleiche adresse hat/bekommt, und so immer auf den gleichen speicher gezeigt wird und die daten einfach nur überschrieben werden.
hängen die beiden probleme vielleicht irgendwie zusammen?
ich habe ne menge mit dem gnu debugger rumgespielt, aber mir ist nichts aufgefallen. ich bin in der hinsicht wohl noch ein wenig zu unerfahren. ich würde mich freuen, wenn mir jemand bei dem problem helfen könnte, da ich auch ansonsten keine ahnung hab wo ich eine lösung für das problem finden könnte.ich benutze den gcc 3.3.6 und gentoo-linux-2.6.15. falls irgendwas unverständlich ist, bitte ich das zu entschuldigen. ich werde versuchen mich dann besser auszudrücken.
mfg
Heiko/mrklumpen
-
Das Problem dürfte sein, dass du current auf eine lokale Variable (hui) zeigen lässt, die beim Austritt aus der Funktion zerstört wird. Du arbeitest aber danach damit weiter, als würde sie noch existieren. Du solltest deine Listenknoten dynamisch allozieren.
Was mir noch auffällt:
- Das 'typedef' vor der Strukturdeklaration hat keinen Effekt bei dir, erstens gibst du überhaupt kein Typalias an, und zweitens schreibst du eh überall 'struct datenSatz'.
- deine globalen Variablen sind extrem unschön
-
hmm, ja sowas habe ich mir gedacht. ich dachte aber das ich durch den zeiger weiter mit den daten arbeiten kann, da sie ja noch im speicher sind. mag aber dann wohl der falsche ansatz sein. aber wie kann ich die elemente dynamisch allozieren? mir fällt da jetzt spontan nichts ein. für einen kleinen denkanstoß wäre ich sehr dankbar ;).
das typedef ist noch n überbleibsel. und die lobalen variablen... ja hast schon recht :). aber im rausche des schreibens... ;). ich versreche mich zu bessern. danke für deine hilfe!mfg
heiko/mrklumpen
-
mrklumpen schrieb:
hmm, ja sowas habe ich mir gedacht. ich dachte aber das ich durch den zeiger weiter mit den daten arbeiten kann, da sie ja noch im speicher sind. mag aber dann wohl der falsche ansatz sein.
Sie liegen schon noch im Speicher, und zwar hinter dem oberen Ende des Stacks. Wenn der Stack das nächste mal wächst (z.B. aufgrund eines Funktionsaufrufes) werden sie überschrieben. Am besten ist es, wenn man von vornherein davon ausgeht, dass die Daten weg sind.
aber wie kann ich die elemente dynamisch allozieren?
mit malloc und Konsorten ... du hast calloc benutzt, deshalb war ich davon ausgegangen, das sei dir ein Begriff.
current = malloc(sizeof(struct datenSatz)); /* ... */
-
ok, danke. mit der erklärung verstehe ich jetzt auch wieso der pointer gelegentlich auf den string parameter des fprintf befehls gezeigt hat. und ich dachte schon der wahnsinn hätte mich gepackt. glück gehabt. danke
ich habe bei diesem programm das erste mal speicher dynamisch reserviert. ich hatte nicht daran gedacht das ich das auch bei den elementen auch so machen kann. danke für die tips