Fehler in Verkettete Liste
-
Hallo seit meinem Problem von Gestern bin ich ziemlich vorangekommen, aber nun hänge ich wieder an einem Problem. Ich versuche eine verkettete Liste zu implementieren. Es ist nicht die erste Liste aber die wohl wiederspenstigste.
Erst mal den Code:
1. den Header:#ifndef _TESTSCANNER_H_ #define _TESTSCANNER_H_ typedef struct { int nummer; char zeichenkette[128]; struct zeichen_kette *next; } zeichen_kette; int schreibe_in_kette ( char* zeichen ); void gebe_kette_aus ( zeichen_kette* anfangs_zeiger ); #define LEN_ZEILE 256 #endif
Und der Quellcode:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<testscanner.h> zeichen_kette* meine_kette; int main ( int argc, char *argv[] ) { int zeilen_zahler = 0, laenge_zeile = LEN_ZEILE -1; FILE *eingabe_datei; /*ausgabe_datei;*/ //char *ausgabe_datei_name = "bullshit.out"; char *eingabe_datei_name; char *bullshit = "bullshit"; char eingabe_zeile[LEN_ZEILE]; char *pToken; /* Überprüfe die Eingabeparameter */ if ( argc < 2 ) { printf ("usage: testscanner <infile outfile>\n" ); exit (-1); } else if ( argc == 2 ) { eingabe_datei_name = argv[1]; } else if ( argc == 3 ) { // ausgabe_datei_name = argv[2]; } /* Öffne die Dateien */ if ( ( eingabe_datei = fopen ( eingabe_datei_name, "r" ) ) == NULL ) { perror ("Konnte Datei nicht oeffnen!\n"); exit(-1); } /* Durchsuche die Eingabedatei */ while ( ( fgets( eingabe_zeile, laenge_zeile, eingabe_datei) ) != NULL ) { fputs ( eingabe_zeile, stdout ); if ( zeilen_zahler == 0 ) { if ( strstr ( eingabe_zeile, bullshit) != NULL) { printf ("Hurra, ein Bullshit-Script!\n"); } else { printf ("Kein Bullshit-Script! Ich breche ab!\n"); exit ( -1 ); } } if ( zeilen_zahler >= 1 ) { pToken = strtok(eingabe_zeile, " "); while( pToken != NULL ) { //printf ("bis hierhin\n"); schreibe_in_kette ( pToken ); printf( "%s\n", pToken ); pToken = strtok( NULL, " " ); } } zeilen_zahler++; } gebe_kette_aus(meine_kette); exit(0); } int schreibe_in_kette ( char *zeichen ) { static int zaehler = 0; zeichen_kette* neu; zeichen_kette* alt; if ( zaehler == 0 ) { if ( ( neu = ( zeichen_kette * ) calloc ( 1,sizeof ( zeichen_kette ) ) ) == NULL ) { perror ( "Fehler beim Aufbau der Liste!\n" ); exit (-1); } else { printf ("bis hier 101"); *neu->zeichenkette = *zeichen; neu->nummer = zaehler; neu->next = NULL; meine_kette = neu; alt = neu; } } else { if ( ( neu = ( zeichen_kette * ) calloc ( 1,sizeof ( zeichen_kette ) ) ) == NULL ) { perror ( "Fehler beim Aufbau der Liste!\n" ); exit (-1); } else { alt->next = neu; /* hierauf zeigt übrigens der ddd */ neu->next = NULL; *neu->zeichenkette = *zeichen; neu->nummer = zaehler; alt = alt->next; } } //printf ( "Zaehler jetzt bei: %d \n", zaehler ); zaehler++; return 1; } void gebe_kette_aus ( zeichen_kette *anfangs_zeiger ) { zeichen_kette *zeiger; zeiger = anfangs_zeiger; printf ( "Zeiger: %x\n", &zeiger->next ); while ( zeiger->next != NULL ) { printf ( "Das Zeichen: %s\n", zeiger->zeichenkette ); zeiger = zeiger->next; } }
Das Programm liest eine Datei mit einem Quellcode ein. Eine imaginäre Sprache namens Bullshit. Jaja ich weis
Die verschiedenen Ausdrücke werden zunächst tokenized und diese Tokens dann in eine verkettete Liste abgespeichert.
Im jetztigen Zustand lässt sich das ganze compilieren, jedoch mit warnings (da ich -Wall als Option gesetzt habe )
Das sagt der Compiler:chris@venus:~/c/compiler$ gcc -Wall -o testscanner testscanner.c -I.
testscanner.c: In function 'schreibe_in_kette':
testscanner.c:119: warning: assignment from incompatible pointer type
testscanner.c:123: warning: assignment from incompatible pointer type
testscanner.c: In function 'gebe_kette_aus':
testscanner.c:139: warning: format '%x' expects type 'unsigned int', but argument 2 has type 'struct zeichen_kette **'
testscanner.c:143: warning: assignment from incompatible pointer typeErklärung: Zeile 139 ist diese:
printf ( "Zeiger: %x\n", &zeiger->next );
Das hat eigentlich keine Funktion, hier schaue ich nur ob überhaupt eine Adresse in dem Zeiger abgelegt ist.
Was wichtig ist: es wird überhaupt nichts von der verketteten Liste ausgegeben. Es kommt zu einem segmentation fault!Puhh das ist ein Haufen Code (für ein Forum), ich hoffe es steigt jemand durch und kann mir Helfen.
Vielen Dank vorab...Gruss Christian
Eine Veränderung: ich habe schon einen Fehler behoben. Die Funktion schreibe_in_kette wir iterativ aufgerufen, d.h. jedes mal wenn mein Programm ein Token hat wird diese Funktion aufgerufen und versucht auf die Zeiger "neu" und "alt" zuzugreifen, diese sind natürlich inzwischen wieder leer. Gut ich habe diese Zeiger jetzt den Scope "static" gegeben und schon gehts ein bischen weiter! Die Kette wird unten wirklich ausgegeben, aber es sind nur die Anfangsbuchstaben der Zeichen drin, hmmm vielleicht der gleiche Fehler von Gestern?... Nein das ist was anderes. Die Funktion "gebe_kette_aus" gibt nur Bullshit
Das Zeichen: 0
Das Zeichen: 0
Das Zeichen: 3
Das Zeichen: =
Das Zeichen: ?
Das Zeichen: 0
Das Zeichen: 0
-
Dein Problem ist, daß der typedef-Alias für deinen Typ erst nach der Deklaration definiert wird. Das heißt, du hast einen 'struct zeichen_kette', über den nichts weiter bekannt ist und deinen Typedef 'zeichen_kette' als Alias für einen anonymen Strukturtyp (in C sind das zwei verschiedene Namen).
Die Lösung sieht etwa so aus:
typedef struct ZK { int nummer; char zeichenkette[128]; struct ZK *next; } zeichen_kette;
Damit dürften die meisten der Warnungen auch verschwinden (die printf()-Warnung kannst du ignorieren).
PS: Du bist nicht zufällig von C++ nach C gewechselt?
-
CStoll schrieb:
PS: Du bist nicht zufällig von C++ nach C gewechselt?
wieso sollte er?
-
Nein, ich habe zuerst C dann C++ gelernt. Mit dem typedef bin ich nie so richtig warm geworden. Wahrscheinlich weil ich vorher Jahre lang Module-2 programmiert habe, da hatte ich wohl ein falsche Erwartungshaltung oder wie sollte ich sowas nennen. Auf jeden Fall danke ich Euch, das Problem ist gelöst.
Gruss Christian