/* Programm: list2.cpp Funktion: Demonstration dynamischer Listen und Strukturen Autor: Gerhard Zapf Beschreibung: http://travel.to/ProjectX/ */ #include #include #include // Für malloc // Definition der Struktur typedef struct node { struct node *next; // Zeiger auf eine Struktur selben Typs struct node *search; // Zeiger für die Suchkette char name[20]; char vorname[20]; char datum[10]; }element; // Name der Struktur typedef element *ptr; // Typdendefinition ZEIGER AUF STRUKTUR /************************************************************************ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ************************************************************************/ /*** Definition der Funktionsköpfe ***/ // *** Person von der Tastatur einlesen *** // ptr LiesPerson( void ); // ** Liste auf den Bildschirm ausgeben (mit od. ohne Filter ) ** // int SchreibeListe( ptr anker ); // *** Liste nach Elementen durchsuchen und entsprechend *** // // *** die suchzeiger in der Liste neu setzen *** // ptr SucheElemente( ptr anker, char *suchdatum ); // *** Hängt eingelesene Daten in dei Liste ein *** // int PersonEinhaengen( ptr *anker, ptr neues ); // *** Schreibt die Listendaten in eine Datei *** // int SchreibeDatei( ptr anker ); // *** Liest Listendaten aus einer Datei aus *** // int LeseDatei( ptr *anker ); /************************************************************************ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ************************************************************************/ /*** Liest Personendaten ein ***/ ptr LiesPerson( void ) { /** Neues Element erzeugen ***/ ptr neues = (ptr)malloc( sizeof(element) ); /*** Nur wenn allozierung erfolgreich ***/ if( neues != NULL ) { /*** Zeiger vorbelegen ***/ neues->next = NULL; neues->search = NULL; /*** Daten einlesen ***/ printf(" Nachname: "); scanf("%20s", neues->name ); printf(" Vorname: "); scanf("%20s", neues->vorname ); printf(" Datum: "); scanf("%10s", neues->datum ); rewind( stdin ); // *** Tastaturpuffer leeren } return neues; // *** Zeiger auf neues Element zurückgeben } /************************************************************************ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ************************************************************************/ /*** Gibt die Liste auf den Bildschirm aus ***/ int SchreibeListe( ptr start ) { ptr zeiger; int i; // ** Zählvariable if( start == NULL ) // ** Liste leer { printf("Liste ist leer!"); i = 0; } else // ** Elemente ausgeben { /*** Kopfzeile ausgeben ***/ printf("Nr. Name Vorname Datum\n"); /*** Elemente ausgeben ***/ for( zeiger = start, i=1; zeiger != NULL; zeiger = zeiger->search, i++ ) { /*** Das - in der Formatangabe steht für linksbündige ausgabe ***/ printf("%-3d %-20s %-20s %-10s\n", i, zeiger->name, zeiger->vorname, zeiger->datum ); } } return i; } /************************************************************************ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ************************************************************************/ /*** Setzt die Search-Zeiger der Listenelemente so, dass die Daten, die auf das Suchdatum zutreffen direkt miteinander verkettet werden Gibt einen Zeiger auf das erste passende Element zurück ***/ ptr SucheElemente( ptr anker, char *suchdatum ) { ptr start=NULL; // Zeiger auf das erste passende Element ptr zeiger=NULL; // Interner durchlaufzeiger ptr altes=NULL; // Zeiger auf das zuletzt gefundene Element int status = 0; // <> 0 --> noch kein element gefunden if( strcmp( suchdatum, "\0" ) != 0 ) { /*** Richtiges datum übergeben: ***/ for( zeiger = anker; zeiger != NULL; zeiger = zeiger->next ) { if( strcmp( zeiger->datum, suchdatum ) == 0 ) { /*** Passendes Element gefunden ***/ if( status == 0 ) // ** Erstes Element? { /** Dann Startzeiger setzten **/ start = zeiger; altes = zeiger; zeiger->search=NULL; status = 1; } else { /*** Bel. Element (nicht 1. ) ** *** dann zeiger des vorgängers setzten **/ altes->search = zeiger; altes = zeiger; zeiger->search = NULL; } } } } else { /** Wird \0 übergeben, so soll der originalzustand ** wieder hergestellt werden ***/ for( zeiger = anker; zeiger != NULL; zeiger=zeiger->next) zeiger->search = zeiger->next; start = anker; } return start; } /************************************************************************ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ************************************************************************/ /*** Hängt ein neues Element in die Liste einn ***/ int PersonEinhaengen( ptr *anker, ptr neues ) { ptr suchzeiger; // Zeiger für die Suche ptr nachlauf; // Zeiger auf den Suchzeiger int status = 0; // Status für IN DIE LISTE EINGEHÄNGT int erg=0; // Adresse des neuen Elementes gültig? if( neues != NULL ) { // Ist noch kein Element in der Liste ? if( *anker == NULL ) { // Ja, dann so *anker = neues; erg = 1; } else // sonst suchen, wo es hingehört { if( strcmp(neues->name ,(*anker)->name) < 0 ) { // An den Listenanfang hängen? neues->next = *anker; neues->search = *anker; *anker = neues; erg=1; } else // Nein, dann { // In die Listenmitte hängen ? // Vorbelegung für suchzeiger und nachlauf suchzeiger = (*anker)->next; nachlauf = *anker; // Solange unser suchzeiger nicht ins leere zeigt // und das zeichen noch nicht in die liste gehängt wurde while( suchzeiger != NULL && status == 0 ) { // vergleiche das neue zeichen mit der aktuellen position if( strcmp(neues->name,suchzeiger->name) < 0 ) { neues->next = suchzeiger; neues->search = suchzeiger; nachlauf->next = neues; nachlauf->search = neues; status = 1; // In die Liste aufgenommen! } // setze den suchzeiger auf das nächste listenelement suchzeiger = suchzeiger->next; // ziehe den nachlaufzeiger ebenfalls um eins nach vorne nachlauf = nachlauf->next; erg++; } if( status == 0 ) { // Listenende erreicht aber noch nicht // neues element eingehängt, dann // Ans Listenende nachlauf->next = neues; nachlauf->search = neues; erg++; } } // Ende LISTENMITTE/ENDE } // Ende der Suche } // ENDE MALLOC-Abfrage else { erg = -1; } return erg; } /************************************************************************ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ************************************************************************/ /*** Schreibt die Liste auf die Festplatte ***/ int SchreibDatei( ptr anker ) { FILE *datei; // *** Zeiger auf die Datei ptr zeiger; int i, erg = -1; if( (datei = fopen("daten.txt","wt")) != NULL ) { for( zeiger = anker, i=1; zeiger != NULL; zeiger=zeiger->next, i++ ) fprintf( datei, "%20s %20s %10s\n", zeiger->name, zeiger->vorname, zeiger->datum ); fclose( datei ); erg = i; } return erg; } /************************************************************************ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ************************************************************************/ /*** Liest die Datei in die Liste ein ***/ int LeseDatei( ptr *anker ) { FILE *datei; // Zeiger auf die Datei ptr zeiger; int i=0, erg = -1; if( (datei = fopen("daten.txt","rt")) != NULL ) { /*** Erstes Element einlesen ***/ zeiger = (ptr)malloc( sizeof(element) ); // Speicher reservieren zeiger->next = NULL; // Zeiger vorbelegen zeiger->search = NULL; /*** Erster Leseversuch ***/ fscanf(datei, " %20s %20s %10s", zeiger->name, zeiger->vorname, zeiger->datum ); if( !feof( datei ) ) { /*** Wenn die Datei nicht leer ist ***/ while ( !feof( datei ) ) // Solange Datei nicht am Ende { /*** Person in die Liste einhängen ***/ PersonEinhaengen( anker, zeiger ); i++; // *** Zähler um eins erhöhen /*** Speicher für nächstes Element reservieren ***/ zeiger = (ptr)malloc( sizeof(element) ); zeiger->next = NULL; zeiger->search = NULL; fscanf(datei, " %20s %20s %10s", zeiger->name, zeiger->vorname, zeiger->datum ); } erg = i; } else { /*** Wenn die Datei leer ist, dann Speicher wieder freigeben ***/ free( zeiger ); } } return erg; } /************************************************************************ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ************************************************************************/ int main ( void ) { ptr anker=NULL; // Der Anker für die Struktur ptr ausgabe=NULL; // Für die Ausgabe der Liste ptr neues=NULL; // Platz für neues Element int auswahl; // Für unser Menü die Auswahl char datum[10]; LeseDatei( &anker ); do { /*** Menüausgabe ***/ printf("Bitte waehlen Sie eine Aktion:\n"); printf(" 1 - Ein Element in die Liste einfuegen\n"); printf(" 2 - Die Liste ausgeben\n"); printf(" 3 - Nach Geburtsdatum suchen\n"); printf(" 4 - Programm beenden\n"); printf("Ihre Wahl (1-4)? "); scanf("%d", &auswahl ); rewind( stdin ); // Die Klassische Menüauswahl switch( auswahl ) { case 1: // Neues Zeichen neues = LiesPerson(); if( PersonEinhaengen( &anker, neues ) == -1 ) printf("FEHLER: Einhaengen fehlgeschlagen!\n"); break; case 2: // Liste drucken if( anker == NULL ) printf("Liste leer!"); else { SchreibeListe( anker ); } break; case 3: printf("Zu suchendes Geburtsdatum: "); scanf("%10s", datum ); ausgabe = SucheElemente( anker, datum ); SchreibeListe( ausgabe ); SucheElemente ( anker, "\0" ); break; } }while( auswahl != 4 ); SchreibDatei( anker ); return 0; }