Verkettete Liste



  • Vielen Dank für Eure Hilfe. Ich werde die Sachen jetzt mal ausprobieren.



  • Ich bin etwas weiter, aber so richtig kapiert hab ich es noch nicht. Deswegen sind da oben mit Sicherheit einige Sachen falsch oder es Fehlen Dinge.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Knot* Liste;
    
    typedef struct
        {
            char Name[30];
            double Einwohner; /*Einwohner in Millionen*/
    
        }Land;
    
    typedef struct Knot
        {
            Land eintrag;
            Liste vorgaenger;
            Liste nachfolger;
        }Knoten;
    
    typedef struct
        {
            Liste anfang;
            Liste ende;
        }anfang_ende_liste;
    
    einfuegen(anfang_ende_liste* liste, char c, double anzahl){
    
    if(liste->anfang==NULL){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        liste->anfang=tmp;
        liste->ende=tmp;
        liste->anfang->nachfolger=NULL;
        liste->anfang->vorgaenger=NULL;
        tmp->eintrag.Name=c;
        tmp->eintrag.Einwohner=anzahl;
    }
    
    if (anzahl<100){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        tmp->eintrag.Name=c;
        tmp->eintrag.Einwohner=anzahl;
        tmp->vorgaenger=NULL;
        tmp->nachfolger=liste->anfang;
        liste->anfang=tmp;
    
    }
    
    if (anzahl>=100){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        tmp->eintrag.Name=c;
        tmp->eintrag.Einwohner=anzahl;
        tmp->nachfolger=NULL;
        tmp->vorgaenger=liste->ende;
        liste->ende=tmp;
    
    }
    
    }
    
    int main(void){
    
    char c[30];
    int anzahl;
    anfang_ende_liste liste;
    
    printf("Geben sie Land und Bevölkerungsgröße ein\n");
    scanf("%s %d",c,&anzahl);
    
    einfuegen(&liste,c,anzahl);
    
    while(c!='ende'|c!='Ende'){
    
        printf("Geben sie Land und Bevölkerungsgröße ein\n");
        scanf("%s %d",c,&anzahl);
    
        einfuegen(&land,c,anzahl);
    
    }
    
    return 0;
    }
    


  • Ich habe noch ein paar Fehler, die mir aufgefallen sind, verbessert.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Knot* Liste;
    
    typedef struct
        {
            char Name[30];
            double Einwohner; /*Einwohner in Millionen*/
    
        }Land;
    
    typedef struct Knot
        {
            Land eintrag;
            Liste vorgaenger;
            Liste nachfolger;
        }Knoten;
    
    typedef struct
        {
            Liste anfang;
            Liste ende;
        }anfang_ende_liste;
    
    einfuegen(anfang_ende_liste* liste, char c, double anzahl){
    
    if(liste->anfang==NULL){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        liste->anfang=tmp;
        liste->ende=tmp;
        liste->anfang->nachfolger=NULL;
        liste->anfang->vorgaenger=NULL;
        tmp->eintrag.Name=c;
        tmp->eintrag.Einwohner=anzahl;
    }
    
    if (anzahl<100){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        tmp->eintrag.Name=c;
        tmp->eintrag.Einwohner=anzahl;
        tmp->vorgaenger=NULL;
        tmp->nachfolger=liste->anfang;
        liste->anfang=tmp;
        tmp->nachfolger->vorgaenger=tmp
    }
    
    if (anzahl>=100){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        tmp->eintrag.Name=c;
        tmp->eintrag.Einwohner=anzahl;
        tmp->nachfolger=NULL;
        tmp->vorgaenger=liste->ende;
        liste->ende=tmp;
        tmp->vorgaenger->nachfolger=tmp
    
    }
    
    }
    
    int main(void){
    
    char c[30];
    int anzahl;
    anfang_ende_liste liste;
    
    printf("Geben sie Land und Bevölkerungsgröße ein\n");
    scanf("%s %d",c,&anzahl);
    
    einfuegen(&liste,c,anzahl);
    
    while(c!='ende'||c!='Ende'){
    
        printf("Geben sie Land und Bevölkerungsgröße ein\n");
        scanf("%s %d",c,&anzahl);
    
        einfuegen(&land,c,anzahl);
    
    }
    
    return 0;
    }
    


  • Und was ist jetzt die Frage? Warum prüfst du auf die Anzahl beim Einfügen? Das ist einfach unnötige Codeduplizierung und der Liste kann es egal sein welcher Inhalt wo liegt. Später kannst du immer noch eine sort-funktion schreiben.

    Es ist genauso schlecht umgesetzt wie die main. Kennst du do while?

    Und das compiliert/funktioniert bei dir?



  • In der main ist doch eine while Schleife, oder?

    Nein, es compiliert nicht. Denn es sind ne menge Fehler drin, die ich gerade zu finde veruche. Ich bin Anfänger und das ist meine erste Liste. Und überhaupt bin ich so ziehmlich am Anfang von allem. Klar, ich würds auch schon direkt gerne mit verbundenen Augen super elegant reintippen können, kann ich aber nicht. 🙂 Deswegen bin ich hier.

    Eine Sache, die ich bisher z.B. noch nicht geschafft habe, ist den String zu übergeben. Außerdem glaube ich auch, dass die Liste zu kpmliziert ist. Das geht bestimmt auch einfacher.



  • Gute Einsicht, aber du kannst dir Zeilen sparen wenn du Do-while verwendest. Um auf ende/Ende zu prüfen musst du strcmp verwenden am beste in der Kombination mit tolower oder toupper.

    Nur als Beispiel gedacht:

    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    int main ()
    {
    	char szKey[] = "ende";
    	char szInput[80];
    	int i;
    
    	do
    	{
    		printf ("\"ende\" zum Beenden eingeben: ");
    		scanf ("%s", szInput);
    
    		//Groß/Kleinschreibung egal machen
            i = 0;
    		while (szInput[i])
    		{
    			szInput[i] = tolower(szInput[i]);
    			i++;
    		}
    	} while (strcmp (szKey, szInput) != 0);
    
    	printf("Programm beendet!");
    	return 0;
    }
    


  • Wenn man diese Sache jetzt mal bei Seite lässt (ich werds im Endeffekt so machen wie Du gesagt hast), wie kann ich dann diesen String in die Funktion einfuegen übergeben? Ich komme nicht drauf.



  • #include <stdio.h>
    
    void f(char *str)
    {
        printf("%s", str);
    }
    
    int main ()
    {
        char c[] = "ende";
    
        f(c);
    
        return 0;
    }
    

    Achtung: Ich übergebe keine Größe noch prüfe ich auf Gültigkeit oder Länge des Zeigers. In der Regel musst du dieses machen.

    void f(char *str, int size)
    


  • psigh schrieb:

    Außerdem glaube ich auch, dass die Liste zu kpmliziert ist. Das geht bestimmt auch einfacher.

    Super Einsicht. Nimm für den Anfang ein Array mit einer max. Anzahl Elemente und mitlaufendem Elementezähler. Das lässt sich auch sehr einfach sortieren.



  • Super, vielen vieln Dank. Jetzt ist der Fehler schonmal weg. Ich verstehe nur einfach nicht genau warum ich *c schreiben muss. Ich dachte wenn man sowas wie char c schreibt, dann IST c schon ein Pointer auf den ersten Buchstaben. Deswegen schreibt man doch auch immer scanf("%s", c) und nicht scanf("%s", &c).

    Außerdem sagt er in Zeile 54 und 64 (habe ich daneben geschrieben) "assignment makes integer from pointer without a cast."

    Das dritte Problem ist, dass der ganze Editor beim Ausführen abstürzt, was mir aber erstmal egal ist. Compilieren ist momentan erstmal mein Hauptziel.

    Es gibt diverse Programm die in der Uni laufen und bei mir (Windows) komischer Weise nicht.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Knot* Liste;
    
    typedef struct
        {
            char Name;
            double Einwohner; /*Einwohner in Millionen*/
    
        }Land;
    
    typedef struct Knot
        {
            Land eintrag;
            Liste vorgaenger;
            Liste nachfolger;
        }Knoten;
    
    typedef struct
        {
            Liste anfang;
            Liste ende;
        }anfang_ende_liste;
    
    einfuegen(anfang_ende_liste* liste, char *c, double anzahl){
    
    if(liste->anfang==NULL){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        liste->anfang=tmp;                                 
        liste->ende=tmp;                     
        liste->anfang->nachfolger=NULL;
        liste->anfang->vorgaenger=NULL;
        tmp->eintrag.Name=c;
        tmp->eintrag.Einwohner=anzahl;
    }
    
    if (anzahl<100){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        tmp->eintrag.Name=c;                             /*54*/
        tmp->eintrag.Einwohner=anzahl;
        tmp->vorgaenger=NULL;
        tmp->nachfolger=liste->anfang;
        liste->anfang=tmp;
        tmp->nachfolger->vorgaenger=tmp;
    }
    
    if (anzahl>=100){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        tmp->eintrag.Name=c;                              /*64*/
        tmp->eintrag.Einwohner=anzahl;
        tmp->nachfolger=NULL;
        tmp->vorgaenger=liste->ende;
        liste->ende=tmp;
        tmp->vorgaenger->nachfolger=tmp;
    
    }
    
    }
    
    int main(void){
    
    char c;
    int anzahl;
    anfang_ende_liste liste;
    
    printf("Geben sie Land und Bevölkerungsgröße ein\n");
    scanf("%s %d",c,&anzahl);
    
    einfuegen(&liste,c,anzahl);
    
    while(c!='ende'||c!='Ende'){
    
        printf("Geben sie Land und Bevölkerungsgröße ein\n");
        scanf("%s %d",c,&anzahl);
    
        einfuegen(&liste,c,anzahl);
    
    }
    
    return 0;
    }
    


  • char c ist eine Variable und demnach musst du die Adresse dieser an scanf übergeben. Hast du vergessen daraus einen festen Array zu machen?

    char c[80];
    

    Und das:

    while(c!='ende'||c!='Ende')
    

    wird auch weiterhin NICHT kompilieren weil es illegal ist. Du musst strcmp verwenden.



  • Ich habs jetzt mal versucht, es schöner zu machen. Ich habe auch nur noch zwei Warnungen jetzt. "assignment makes integer from pointer without a cast".

    Eben hatte ich ja noch acht Warnungen. Und abschützen tut auch nichst mehr. Ich muss jetzt nur noch versuchen, die Liste auszulesen. Ich weiß ja noch nicht, ob das funktioniert.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Knot* Liste;
    
    typedef struct
        {
            char Name;
            double Einwohner; /*Einwohner in Millionen*/
    
        }Land;
    
    typedef struct Knot
        {
            Land eintrag;
            Liste vorgaenger;
            Liste nachfolger;
        }Knoten;
    
    typedef struct
        {
            Liste anfang;
            Liste ende;
        }anfang_ende_liste;
    
    einfuegen(anfang_ende_liste* liste, char *c, double anzahl){
    
    if(liste->anfang==NULL){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        liste->anfang=tmp;
        liste->ende=tmp;
        liste->anfang->nachfolger=NULL;
        liste->anfang->vorgaenger=NULL;
        tmp->eintrag.Name=*c;
        tmp->eintrag.Einwohner=anzahl;
    }
    
    if (anzahl<100){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        tmp->eintrag.Name=c;
        tmp->eintrag.Einwohner=anzahl;
        tmp->vorgaenger=NULL;
        tmp->nachfolger=liste->anfang;
        liste->anfang=tmp;
        tmp->nachfolger->vorgaenger=tmp;
    }
    
    if (anzahl>=100){
        Liste tmp=(Liste) malloc(1*sizeof(Knoten));
        tmp->eintrag.Name=c;
        tmp->eintrag.Einwohner=anzahl;
        tmp->nachfolger=NULL;
        tmp->vorgaenger=liste->ende;
        liste->ende=tmp;
        tmp->vorgaenger->nachfolger=tmp;
    
    }
    
    }
    
    int main(void){
    
    char c[40];
    int anzahl;
    anfang_ende_liste liste;
    char ende[]="ende";
    
    do{
    
        printf("Geben sie Land und Bevoelkerungsgroeße ein\n");
        scanf("%s %d",c,&anzahl);
    
        einfuegen(&liste,c,anzahl);
    
    }
    while(strcmp(ende,c) !=0);
    
    return 0;
    }
    


  • Es muss void einfuegen sein Rückgabewert fehlt.

    void einfuegen(....)
    

    Im struct für Land hast du nur ein Char du brauchst einen Array!

    typedef struct
    {
        char Name[100]; //<--- ARRAY
        double Einwohner; /*Einwohner in Millionen*/
    
    }Land;
    

    Du kannst nicht den Inhalt eines Pointers einem Array zuweisen. Benutze strcpy!

    strcpy(tmp->eintrag.Name, c);
    

    UND RÜCKE ENDLICH DEINEN TEXT GESCHEIT EIN. Die gesamte Einfuegen Funktion ist nicht gut...

    Bevor du weitermachst eine Liste vergeblich zu implementieren schau dir doch erstmal BITTE die Grundlagen an.

    Edit: Wenn du das Buch "C von A bis Z von J.W." hast, dann tue dir einen Gefallen und wirf es endlich weg. Verbrenne es!



  • #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Knot* Liste;
    
    typedef struct
        {
            char Name[30];
            double Einwohner; /*Einwohner in Millionen*/
    
        }Land;
    
    typedef struct Knot
        {
            Land eintrag;
            Liste vorgaenger;
            Liste nachfolger;
        }Knoten;
    
    typedef struct
        {
            Liste anfang;
            Liste ende;
        }anfang_ende_liste;
    
    void einfuegen(anfang_ende_liste* liste, char *c, double anzahl){
    
        if(liste->anfang==NULL){
            Liste tmp=(Liste) malloc(1*sizeof(Knoten));
            liste->anfang=tmp;
            liste->ende=tmp;
            liste->anfang->nachfolger=NULL;
            liste->anfang->vorgaenger=NULL;
            strcpy(tmp->eintrag.Name, c);
            tmp->eintrag.Einwohner=anzahl;
        }
    
        if (anzahl<100){
            Liste tmp=(Liste) malloc(1*sizeof(Knoten));
            strcpy(tmp->eintrag.Name, c);
            tmp->eintrag.Einwohner=anzahl;
            tmp->vorgaenger=NULL;
            tmp->nachfolger=liste->anfang;
            liste->anfang=tmp;
            tmp->nachfolger->vorgaenger=tmp;
        }
    
        if (anzahl>=100){
            Liste tmp=(Liste) malloc(1*sizeof(Knoten));
            strcpy(tmp->eintrag.Name, c);
            tmp->eintrag.Einwohner=anzahl;
            tmp->nachfolger=NULL;
            tmp->vorgaenger=liste->ende;
            liste->ende=tmp;
            tmp->vorgaenger->nachfolger=tmp;
    
        }
    
    }
    
    int main(void){
    
    char c[30];
    int anzahl;
    anfang_ende_liste liste;
    char ende[]="ende";
    
    do{
    
        printf("Geben sie Land und Bevoelkerungsgroesse ein\n");
        scanf("%s %d",c,&anzahl);
    
        einfuegen(&liste,c,anzahl);
    
    }
    while(strcmp(ende,c) !=0);
    
    return 0;
    }
    

    Ist es jetzt etwas besser eingerückt?

    Das mit dem void hätte ich echt wissen müssen. Klar, ohne Rückgabewert. Das mit char ist mir nicht klar. Ich meine mir ist klar, dass oben im Struct ein Array stehen sollte. Hab ich ja jetzt auch. Aber den Rest durchblicke ich noch nicht so ganz. Ich kenne die Befehle aus der Stringbibliothek auch noch nicht. Aber ok...man lernt. Ich hab strcmp vielleicht auch falsch eingesetzt. Denn jetzt habe ich zwar keine Warnung mehr, aber wieder einen Absturz



  • Da du das Ganze zur Übung machst, solltest du jetzt lieber einen cut machen und dir erstmal die Standardlibs anschauen. Es sind ja nicht mal viele Funktionen dort enthalten. Des weiteren ist dir wärmstens zu empfehlen den Umgang mit Array und Variablen zu verbessern. Danach schaue dir nochmals die Pointer an und warum Pointer und Arrays so ähnlich sind. Fange an einfache Programme mit steigendem Schwierigkeitsgrad zu programmieren und wenn du damit gut zurecht kommst, versuche dich an einer "Einfach verketteten Liste". Wenn diese klar und einfach für dich scheint, dann mache die doppelte.

    Nützlicher Link zu C-Libs mit Beispielen:
    http://www.cplusplus.com/reference/clibrary/

    Einrücken ist Geschmackssache aber dein Gebracuh und die etlichen Leerzeilen sind anstrengen 😉

    //KEINE FEHLERVERBESSERUNG NUR EINRÜCKEN
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    
    typedef struct Knot* Liste; 
    
    typedef struct Land
    { 
        char Name[100]; 
        double Einwohner; /*Einwohner in Millionen*/ 
    }Land; 
    
    typedef struct Knot 
    { 
        Land eintrag; 
        Liste vorgaenger; 
        Liste nachfolger; 
    }Knoten; 
    
    typedef struct 
    { 
        Liste anfang; 
        Liste ende; 
    }anfang_ende_liste; 
    
    void einfuegen(anfang_ende_liste* liste, char *c, double anzahl)
    {
    	if(liste->anfang == NULL)
    	{ 
    		Liste tmp = (Liste) malloc(1*sizeof(Knoten)); 
    		liste->anfang = tmp; 
    		liste->ende = tmp; 
    		liste->anfang->nachfolger = NULL; 
    		liste->anfang->vorgaenger = NULL; 
    		strcpy(tmp->eintrag.Name, c); 
    		tmp->eintrag.Einwohner = anzahl; 
    	}
        else
        {
            //....
        }
    } 
    
    int main()
    { 
    	char c[100]; 
    	int anzahl; 
    	anfang_ende_liste liste; 
    	char ende[]="ende"; 
    
    	do
    	{ 
    		printf("Geben sie Land und Bevoelkerungsgroeße ein\n"); 
    		scanf("%s %d",c,&anzahl); 
    
    		einfuegen(&liste,c,anzahl); 
    	} while(strcmp(ende,c) !=0); 
    
    	return 0; 
    }
    


  • Ich danke Dir nochmal vielmals für Deine Hilfe und Deine Ratschläge sind auch sicher absolut richtig. Aber ich habe nicht mehr so viel Zeit und ich muss jetzt einfachmal ein paar Eveolutionsstufen überspringen. Und heute war ja auch ein erfolgreicher Tag. Heute morgen wusste ich noch nicht was ne Liste ist und vorgestern habe ich im wesentlichen noch Programme geschrieben, die die Zahlen von 1 bis 10 addieren konnten, oder sowas 🙂 Ich bin jetzt gerade an der Ausgabe.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct Knot* Liste;
    
    typedef struct
        {
            char Name[30];
            double Einwohner; /*Einwohner in Millionen*/
    
        }Land;
    
    typedef struct Knot
        {
            Land eintrag;
            Liste vorgaenger;
            Liste nachfolger;
        }Knoten;
    
    typedef struct
        {
            Liste anfang;
            Liste ende;
        }anfang_ende_liste;
    
    void einfuegen(anfang_ende_liste* liste, char *c, double anzahl){
    
        if(liste->anfang==NULL){
            Liste tmp=(Liste) malloc(1*sizeof(Knoten));
            liste->anfang=tmp;
            liste->ende=tmp;
            liste->anfang->nachfolger=NULL;
            liste->anfang->vorgaenger=NULL;
            strcpy(tmp->eintrag.Name, c);
            tmp->eintrag.Einwohner=anzahl;
        }
    
        if (anzahl<100){
            Liste tmp=(Liste) malloc(1*sizeof(Knoten));
            strcpy(tmp->eintrag.Name, c);
            tmp->eintrag.Einwohner=anzahl;
            tmp->vorgaenger=NULL;
            tmp->nachfolger=liste->anfang;
            liste->anfang=tmp;
            tmp->nachfolger->vorgaenger=tmp;
        }
    
        if (anzahl>=100){
            Liste tmp=(Liste) malloc(1*sizeof(Knoten));
            strcpy(tmp->eintrag.Name, c);
            tmp->eintrag.Einwohner=anzahl;
            tmp->nachfolger=NULL;
            tmp->vorgaenger=liste->ende;
            liste->ende=tmp;
            tmp->vorgaenger->nachfolger=tmp;
    
        }
    
    }
    
    void ausgeben(anfang_ende_liste liste){
    
        Liste tmp=liste.anfang;
        while (tmp!=0){
            printf("%s %d", tmp->eintrag.Name, tmp->eintrag.Einwohner);
            tmp=tmp->nachfolger;
    
        }
    }
    
    int main(void){
    
    char c[30];
    int anzahl;
    anfang_ende_liste liste;
    char ende[]="ende";
    
    do{
    
        printf("Geben sie Land und Bevoelkerungsgroesse ein\n");
        scanf("%s %d",c,&anzahl);
    
        einfuegen(&liste,c,anzahl);
    
    }
    while(strcmp(ende,c) !=0);
    
    ausgeben(liste);
    
    return 0;
    }
    


  • psigh schrieb:

    .... Heute morgen wusste ich noch nicht was ne Liste ist und vorgestern habe ich im wesentlichen noch Programme geschrieben, die die Zahlen von 1 bis 10 addieren konnten, oder sowas 🙂 ...

    Da hast du dann aber das ganz wichtige Kapitel Felder und Zeiger (Arrays/Pointer) übersprungen. Zumindest nicht verstanden und vertieft.

    Wiederhole das Thema nochmal!
    Dann kannst du dich an dynamische Speicherverwaltung und Listen wagen.



  • Ok. Ich werds sowieso machen müssen. Aber was mich jetzt abschließend mal interessieren würde:

    Ist das ganze Programm denn so falsch? Ich denke immer, dass da doch nicht mehr so viel fehlen kann, um die Sache ans laufen zu kriegen. Oder doch?

    Dom



  • Es sind viele kleine Dinge die zeigen das du nicht weißt was du tust.

    In "Rund um die Programmierung" war ein Link (http://www.c-plusplus.net/forum/281353). Da wird versucht Fahrzeuge durch Versuch und Irrtum zu bauen.
    Die meisten Fahrzeuge fahren irgendwie.
    Du könntest mit deiner Erfahrung sofort ein Fahrzeug bauen das vernünftig fährt.

    Genauso ist dein Programm irgendwie nicht so falsch.



  • Vielleicht hilft dir das für das Verständnis, leider ohne gescheite Funktionen: http://www.gia.rwth-aachen.de/Lehre/Cpp/script/online/node80.html


Anmelden zum Antworten