Einfach verkettete Liste



  • Hi, wollte einfach mal zum testen eine Einfach verkettete Liste schreiben...

    Bisher hat es mit einer Struktur wunderbar funktioniert, jedoch sollen wir das so Splitten das wir eine Struktur für die Liste haben und eine für die Nutzdaten, tjo und genau jetzt funzt es nicht mehr 🙂

    Code von der list.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "list.h"
    
    struct list *start = NULL;
    struct list *help = NULL;
    struct list *new_element = NULL;
    
    void create_list(char *n, double c)
    {
    	if(start == NULL)
    	{
    		if(start = calloc(1, sizeof(struct list)) == NULL)
    		{
    			fprintf(stderr, "Memory not available");
    		}
    		printf("\n%s", start->info->name);
    
    		strncpy(start->info->name, n, MAX);	// Namen in Struktur kopieren
    		start->info->counter = c;
    
    		start->next = NULL;	// Listenende initialisieren
    	}
    	/* Wird ausgeführt wenn noch kein Element in der Liste existiert */
    	else
    	{
    		help = start;
    
    		while(help->next != NULL)
    		{
    			help = help->next;
    		}
    		/* Läuft die Liste durch bis zum Ende (NULL) */
    
    		if(new_element = calloc(1, sizeof(struct list)) == NULL)
    		{
    			fprintf(stderr, "Memory not available");
    		}
    
    		help->next = new_element;		// Das vormals letzte Element zeigt nun auf das neu erzeugte Element
    		new_element->next = NULL;		// Neues Listenende
    
    		strncpy(start->info->name, n, MAX);	// Namen in Struktur kopieren
    		start->info->counter = c;
    
    	}
    
    }
    
    void print_list(void)
    {
    	while(start->next != NULL)
    	{
    		printf("\n Der Name ist %s mit der zugehörigen ID: %i", start->info->name, start->info->counter);
    	}
    }
    

    Code von der list.h

    #define MAX 20					// Legt eine Konstante mit dem Wert 20 an
    
    typedef struct usedata
    {
    	int counter;
    	char name[MAX];
    
    } UseData;
    
    typedef struct list
    {
    	UseData *info;				// Pointer mit welchem zugriff auf die Struktur der Nutzdaten ermöglicht
    	struct list *next;			// Pointer auf das nächste Listenelement
    } List;
    
    extern void create_list(char *, double);
    extern void print_list(void);
    

    Code von der main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "list.h"
    
    int main(void)
    {
    	int anz = 0;
    	int z = 0;
    	double id = 0;
    	char Name[MAX];
    
    	printf("\nWieviele Datenstrukturen moechten Sie erzeugen: ");
    	scanf("%i", &anz);
    	fflush(stdin);
    
    	for(z; z < anz; z++)
    	{
    		printf("\nBitte geben Sie Name und ID ein: ");
    		scanf("%s", Name);
    		fflush(stdin);
    		scanf("%lf", &id);
    		fflush(stdin);
    
    		create_list(Name, id);
    	}
    
    	return 0;
    }
    

    Also beim Debuggen stürzt er immer an der stelle in der list.c ab bei welcher ich den übergebenen Namen in die Struktur mit string copy kopieren will, nehme an das es an dem Ausdruck (start->info->name) liegt, denke mal es geht deshalb nicht. Verstehe allerdings nicht warum 😞



  • Erstmal ne Frage stürtzt dein Programm direkt beim ersten durchlauf deines Programms ab wenn ja dann liegt es daran das du printf aufrufst wo nix drinne steht.



  • Ne, stürzt auch ab wenn das printf nicht drinne ist, war nur zum testen da. beim debuggen stürzt er genau bei der strcpy stelle ab, wenn ich die auskommentiere bleibt er bei der nächsten Zeile hängen, es muss irgendwas mit den Pointern net stimmen, aber seh einfach nicht was



  • Dein Programm enthält noch mehrere Fehler ändere erstmal Deine list.h sollte so aussehen.

    #define MAX 20                    // Legt eine Konstante mit dem Wert 20 an 
    
    typedef struct usedata 
    { 
        int counter; 
        char name[MAX]; 
    
    } UseData; 
    
    typedef struct list 
    { 
        UseData  info;                // UseData  *info; << Fehler 
        struct list *next;            // Pointer auf das nächste Listenelement 
    } List; 
    
    extern void create_list(char *, double); 
    extern void print_list(void);
    

    Du musst für UseData Speicher reservieren, Speicher für einen Zeiger auf UseData reicht nicht - war ein Fehler!
    Statt start->info->name muss es jetzt start->info.name heissen, und zwar überall im Quelltext - dto. start->info.counter
    statt
    if(start = calloc(1, sizeof(struct list)) == NULL)
    und
    if(new_element = calloc(1, sizeof(struct list)) == NULL)
    schreibe

    new_element = calloc(1, sizeof(struct list));
            if(new_element == NULL)
    

    so kommste erst mal weiter mit Deinem Programm.

    mfg



  • Ok es scheint zu funktionieren, aber in einem anderen Programm habe ich die Calloc bzw Malloc funktion auch in der If Abfrage drinstehen und es funktionierte, warum hier nicht?

    worin besteht der unterschied zwischen strcpy() und strncpy()?

    wie müsste ich es schreiben wenn ich UseData *info benutzen will, also info ein Pointer sein soll?



  • Um mit einem Zeiger auf die zweite Struktur in der ersten Struktur arbeiten zu können, musst Du Speicher für die zweite Struktur gesondert anfordern
    und den Zeiger darauf der ersten Struktur übergeben.

    if(start = calloc(1, sizeof(struct list)) == NULL)
    

    hattest wohl ein paar Klammern vergessen.

    if((start = calloc(1, sizeof(struct list))) == NULL)
    

    strcpy() brauchst Du in Deinem Programm nicht, zeig Dir mal ein Beispiel:

    #include <stdio.h> 
    #include <stdlib.h> 
    
    #define MAX 20  
    
    typedef struct usedata { 
        int counter; 
        char name[MAX]; 
    } UseData; 
    typedef struct list { 
        UseData  info;                 
        struct list *next;             
    } List; 
    
    void create_list(char*, int);
    void print_list(int);
    void free_all(int);
    
        struct list*  start; 
        struct list*  help = 0; 
        struct list*  temp = 0; 
    
    int main(void) 
    { 
        int z = 0; 
        int anz = 0;
    
            printf("\nWieviele Datenstrukturen moechten Sie erzeugen: "); 
            scanf("%i", &anz), fflush(stdin); 
    
            create_list("", 0); 
    
            for (z; z < anz; z++) 
            { 
                    printf("\nBitte geben Sie Name und ID ein: "); 
                    scanf("%s", start->info.name), fflush(stdin); 
                    scanf("%d", &start->info.counter), fflush(stdin); 
                    create_list(start->info.name, start->info.counter); 
            } 
            print_list(anz); 
            free_all(anz);
            return 0; 
    }
    
    void create_list(char *n, int c) 
    { 
            start = malloc(sizeof(struct list));
    
            if(start == NULL) 
                    fprintf(stderr, "Memory not available"); 
    
            if (help == 0 )
                    help = start;
            else
                    temp->next = start;
            temp = start;
    } 
    
    void print_list(int anz) 
    { 
            start = help;
            while(anz--) 
            { 
                    printf(" Der Name ist %s mit der zugehoerigen ID: %d\n", start->info.name,
                                          start->info.counter);
                    start = start->next;
            } 
    }
    
    void free_all(int anz)
    {
            start = help;
            while(--anz) 
            { 
                    free(start);
                    start = start->next;
            }
    }
    

    mfg



  • Danke,

    joar stimmt den speicher sollte man auch wieder freigeben!



  • void free_memory(int z);
    {
    	while(--z)
    	{
    		free(start);
    		start = start->next;
    	}
    	printf("\n\nMemory has been successfully erased");
    }
    

    hmm warum klappt des bei mir nicht? der start ist ja immer noch auf das erste Element gerichtet, aber er startet das programm jetzt gar nicht mehr. Kann das sein weil ich das erste Element lösche? somit kann ich ja gar net auf das nächste kommen oder? aber wie realisiere ich die funktion dann? ist ja soziemlich die gleiche wie oben..



  • mazeli schrieb:

    Kann das sein weil ich das erste Element lösche? somit kann ich ja gar net auf das nächste kommen oder?

    Richtig.

    temp = start;
    start = start->next;
    free( temp );
    


  • start = start->next;
    

    jetzt crashed das programm an dieser stelle...hmm versteh das nicht...start zeigt auf das erste element, temp dann auch...ich lasse start auf das zweite zeigen und lösche dann das erste usw...theoretisch muss es gehen 😃



  • hmm so, nun will ich die Liste in ne Datei Speichern,

    Inhalt der io.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "io.h"
    #include "list.h"
    
    void write_Data(struct List * write)
    {
    	FILE *fp;
    
    	fp = fopen("TEST.BIN", "a+");
    
    	fwrite(write, sizeof(Usedata), 1, fp);
    
    	fclose(fp);
    }
    

    Inhalt der io.h

    extern void write_Data(struct List *);
    

    ich rufe die Funktion in der list.c folgendermaßen auf:

    void print_list(void)
    {
    	while(start != NULL)
    	{
    		printf("\n Der Name ist %s mit der zugehoerigen ID: %lf", start->info.name, start->info.counter);
    		start = start->next;
    		write_data(start->info);
    	}
    
    }
    

    jetzt sagt der mir das er Usedata nicht kennt?
    ich versteh das nicht, müsste so doch funktionieren



  • Du mußt schon auf die Groß- und Kleinschreibung achten - die Struktur heißt "UseData" (zumindest in deinen bisherigen Beiträgen).



  • hmm verdammt, Danke 😃

    naja geht jetzt trotzdem noch nicht



  • Schreib doch das was Du mit printf() ausgibst gleich nochmal mit fprintf() in die Datei und fertig.



  • hmm so einfach gehts irgendwie net

    fprintf(fp, "%s", write);
    

    da kommt en fatal error...unresolved externals...was auch immer das heisen mag



  • erstens: ist 'write' ein String? Wenn nein, dürftest du dir spätestens bei der Ausführung ein Problem einfangen.

    zweitens: zeig mal etwas mehr Code - und die genaue Fehlermeldung.



  • write ist ein Pointer vom Typ List.

    void write_Data(struct List * write)
    {
    	FILE *fp;
    
    	fp = fopen("TEST.BIN", "a+");
    
    	//fwrite(write, sizeof(UseData), 1, fp);
    
    	fprintf(fp, "%s", write);
    
    	fclose(fp);
    }
    
    void print_list(void)
    {
    	while(start != NULL)
    	{
    		write_data(start->info);
    		printf("\n Der Name ist %s mit der zugehoerigen ID: %lf", start->info.name, start->info.counter);
    		start = start->next;
    	}
    
    }
    

    ich übergebe der Funktion den Info Pointer auf meine Nutzdaten struktur



  • Hab ich's mir doch gedacht 🙂 Da mußt du dich natürlich durchhangeln bis zu dem Teil der Struktur, die dich interessiert:

    fprintf(fd,"%i:%s ",write->info->counter,write->info->name);
    //oder
    fwrite(write->info,sizeof(UseData),1,fd);
    

    Aber was genau ist eigentlich der Fehler?

    (btw solltest du der print_list den Startpunkt als Parameter übergeben - du operierst auf globalen Daten und das könnte unangenehm werden)



  • hmm deinen letzten satz versteh ich nicht. was meinst mit unangenehm? wieso?



  • Du schiebst den globalen Zeiger 'start' im Laufe der Funktion durch die gesamte Liste. Das bedeutet, daß am Ende vermutlich niemand mehr weiß, wo deine Liste angefangen hat.

    (außerdem schränkt es das Design sehr ein, wenn du nur EINE EINZIGE Liste ausgeben kannst)


Anmelden zum Antworten