Dynamische Datenstrukturen



  • Hast Du alle includes die Du brauchst richtig geschrieben? und werden diese gefunden?



  • Also es gibt 2 Datein die über ein Button HEADER generieren erzeugt werden (man kann die Datein auch löschen und diese werden dann neu erstellt)

    Einmal APDEFAP.H in der nur auf AP_PBIB.H gelinkt wird.
    Dann gibt es die AP_PBIB.H in der meine Header eingetragen wurden.

    .
    .
    .
    BOOL IPKQKDynListStringAnhaengen (char* value, struct IPKQKDynListString* zeiger);	//GSC_NAME:IPKQKDynListStringAnhaengen	GSC_PROTOTYPE:\ipkqk\ipkqkdynliststringanhaengen.fct
    BOOL IPKQKDynListStringAusgabe (struct IPKQKDynListString* zeiger);	//GSC_NAME:IPKQKDynListStringAusgabe	GSC_PROTOTYPE:\ipkqk\ipkqkdynliststringausgabe.fct
    .
    .
    .
    

    Also da hab ich die Tage auch kein Problem gesehen.

    Also man muss auch dazusagen das diese Fehlermeldung nichtssagend ist. Ich hatte diese auch schon als ich ein printf gemacht hatte und ich glaube als wert einen String hatte aber als ausgabe %d gemacht habe.

    Das ist glaube ich sowas wie eine Standartfehlermeldung bei dem SIEMENS Compiler 😡

    Was sagst du zum aufruf der Funktion bei meinen oben beschriebenen Beispiel?

    Siehst du dort ein kritisches Problem? oder würdest du sagen neeee so geht das nicht?

    Weil die Funktionen ansich Funktionieren ja nur das ich es nicht getrent hinbekomme.

    Vielleicht zerhaue ich...... ach ich hab keine Idee oder Ahnung mehr .... so langsam frustet es einen. 😞



  • Übrigens wenn jeman es Testen würde oder möchte.

    Das Beispiel im ersten Eintrag ist alles was benötigt wird bzw. was ich dazu verwende.

    Es sollte immer der gleiche Text in die Liste geschrieben werden und es wird immer die ganze Liste wieder ausgegeben. (also zumindest in der Theorie).



  • Also ich glaube langsam wirklich das es irgendwo ein Speicherproblem ist, weil ich habe jetzt die VM Heruntergefahren und gestartet und jetzt geht die Funktion IPKQKDynListStringAnhaengen wieder.

    Aber dafür IPKQKDynListStringAusgabe nicht. Da bekomme ich jetzt wieder die Fehlermeldung 'IPKQKDynListStringAusgabe': unresolved external function

    Kann jemand mal bitte das am Anfang beschriebene Programm testen? So langsam verzweifel ich. Vielen Dank



  • Also ich habe nun mal folgendes gemacht:

    Ich habe das beispiel von Galileo Computing genommen und den Dev-C++ Compiler

    Das beispiel funktioniert.

    Nun habe ich es etwas abgespeckt und den Header in eine eigene Datei gelegt. (um langsam an mein Beispiel herran zu kommen.)

    Header (Dateiname: angestellt.h)

    struct angestellt{
       char name[MAX];
       struct angestellt *next;
    };
    
    struct angestellt *next   = NULL;
    struct angestellt *anfang = NULL;
    

    Main: (Dateiname: main.c)

    /* linear_list2.c */
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <angestellt.h>
    #define MAX 20
    
    void anhaengen(char *n) {
       struct angestellt *zeiger;
    
       if(anfang == NULL) {
    
          if((anfang =
           malloc(sizeof(struct angestellt))) == NULL) {
             fprintf(stderr, "Kein Speicherplatz vorhanden "
                             "für anfang\n");
             return;
          }
          strcpy(anfang->name, n);
    
          anfang->next=NULL;
       }
    
       else {
          zeiger=anfang; 
          while(zeiger->next != NULL)
             zeiger=zeiger->next;
    
          if((zeiger->next =
           malloc(sizeof(struct angestellt))) == NULL) {
              fprintf(stderr,"Kein Speicherplatz für das "
                             "letzte Element\n");
              return;
          }
          zeiger=zeiger->next; 
          strcpy(zeiger->name,n);
          zeiger->next=NULL;
       }
    }
    
    /* Funktion zum Ausgeben der Dateien */
    void ausgabe(void) {
       struct angestellt *zeiger = anfang;
    
       while(zeiger != NULL) {
          printf("%12s\n",
             zeiger->name);
             zeiger=zeiger->next;
       }
    }
    
    int main(void) {
       int wahl;
       char dname[MAX];
    
       do {
          printf("\n1 : Eingabe\n");
          printf("2 : Ausgabe\n");
          printf("9 : Ende\n");
          printf("Ihre Wahl : ");
          scanf("%d",&wahl);
          getchar();
          switch(wahl) {
             case 1 : anhaengen("TestX");
                      break;
             case 2 : ausgabe();
                      break;
             case 9 : break;
             default: printf("Falsche Eingabe!!!\n");
          }
       } while(wahl != 9);
       return EXIT_SUCCESS;
    }
    

    Soweit so gut alles Funktioniert:

    nun wollte ich die Funktion anhaengen in eine eigene Datei legen:

    Also:

    Main Datei (Dateiname main.c)

    /* linear_list2.c */
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <angestellt.h>
    #define MAX 20
    
    /* Funktion zum Ausgeben der Dateien */
    void ausgabe(void) {
       struct angestellt *zeiger = anfang;
    
       while(zeiger != NULL) {
          printf("%12s\n",
             zeiger->name);
             zeiger=zeiger->next;
       }
    }
    
    int main(void) {
       int wahl;
       char dname[MAX];
    
       do {
          printf("\n1 : Eingabe\n");
          printf("2 : Ausgabe\n");
          printf("9 : Ende\n");
          printf("Ihre Wahl : ");
          scanf("%d",&wahl);
          getchar();
          switch(wahl) {
             case 1 : anhaengen("TestX");
                      break;
             case 2 : ausgabe();
                      break;
             case 9 : break;
             default: printf("Falsche Eingabe!!!\n");
          }
       } while(wahl != 9);
       return EXIT_SUCCESS;
    }
    

    und Funktion Anhängen (Dateiname: anhaengen.c)

    /* linear_list2.c */
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <angestellt.h>
    #define MAX 20
    
    void anhaengen(char *n) {
       struct angestellt *zeiger;
    
       if(anfang == NULL) {
    
          if((anfang =
           malloc(sizeof(struct angestellt))) == NULL) {
             fprintf(stderr, "Kein Speicherplatz vorhanden "
                             "für anfang\n");
             return;
          }
          strcpy(anfang->name, n);
    
          anfang->next=NULL;
       }
    
       else {
          zeiger=anfang; 
          while(zeiger->next != NULL)
             zeiger=zeiger->next;
    
          if((zeiger->next =
           malloc(sizeof(struct angestellt))) == NULL) {
              fprintf(stderr,"Kein Speicherplatz für das "
                             "letzte Element\n");
              return;
          }
          zeiger=zeiger->next; 
          strcpy(zeiger->name,n);
          zeiger->next=NULL;
       }
    }
    

    nun wollte ich es compilieren aber bekomme folgende Fehlermeldung:

    multiple definition of next' first defined here multiple definition ofanfang'
    first defined here
    ld returned 1 exit status
    C:\Dev-Cpp\Projekt Denis\Makefile.win [Build Error] [Projekt1.exe] Error 1

    Was muss ich machen damit ich diese Meldung nicht mehr bekomme bzw. wie würde der Lösungsweg aussehen?

    vielleicht ist dies mein Problem was ich auch beim SIEMENS Compiler habe aber er es nicht richtig anzeigt...

    Vielen lieben Dank an euch schon mal
    MfG



  • Der Compiler (in diesem Fall sogar der Linker) hat wie immer Recht.
    Du inkludierst die Definition von next+anfang 2 mal durch 2 maliges Inkludieren von <angestellt.h>, was üblicherweise "angestellt.h" heissen sollte.
    Ich kann immer noch keinen Compilerfehler entdecken.



  • Mit

    struct angestellt *next   = NULL;
    struct angestellt *anfang = NULL;
    

    legst du die Variablen (Zeiger) next und anfang an.

    Das passiert jedesmal wenn die Datei includiert wird.

    Schreib das einfach an den Anfang der Datei mit main. Nach den #include und #define.



  • Also Danke schon mal an DirkB das werde ich gleich einmal außprobieren, aber erst noch einmal zu Wutz:

    Was ist der Unterschied zwischen <> und ""

    und wie soll ich das jetzt nach deiner Meinung machen, damit ich das nicht doppelt Includiere?

    Weil ich hätte das schon gerne im Header, außer das ist nicht möglich dann mach ich es halt wie DirkB es beschreibt.



  • <> sucht die includes im Compilerpfad.
    "" sucht auch im aktuellen Verzeichnis (da wo die C-Datei steht).

    Variablendeklarationen haben in Headerdateien nichts zu suchen.



  • Falsch.
    Deklarationen gehören genau in Headerdateien.
    Definitionen gehören da nicht hin.



  • Ich habe das beispiel von Galileo Computing genommen und den Dev-C++ Compiler

    2 Fehler auf einmal, Gratulation 👍
    Sind die Initialen des Autors zufälligerweise J.W.? 🤡


  • Mod

    314159265358979 schrieb:

    Sind die Initialen des Autors zufälligerweise J.W.? 🤡

    Ja, sind sie, wie man am Link im ersten Beitrag sieht.



  • Ah, stimmt, danke. 😃



  • Also entweder stelle ich mich zu blöde an oder ich versteh das nicht richtig.

    ich habe jetzt

    struct angestellt *next = NULL; UND
    struct angestellt *anfang = NULL;

    aus den Header genommen und in der main Funktion eingefügt

    main.c

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "angestellt.h"
    #define MAX 20
    
    struct angestellt *next   = NULL;
    struct angestellt *anfang = NULL;
    
    /* Funktion zum Ausgeben der Dateien */
    void ausgabe(void) {
       struct angestellt *zeiger = anfang;
    
       while(zeiger != NULL) {
          printf("%12s\n",
             zeiger->name);
             zeiger=zeiger->next;
       }
    }
    
    int main(void) {
       int wahl;
       char dname[MAX];
    
       do {
          printf("\n1 : Eingabe\n");
          printf("2 : Ausgabe\n");
          printf("9 : Ende\n");
          printf("Ihre Wahl : ");
          scanf("%d",&wahl);
          getchar();
          switch(wahl) {
             case 1 : anhaengen("TestX");
                      break;
             case 2 : ausgabe();
                      break;
             case 9 : break;
             default: printf("Falsche Eingabe!!!\n");
          }
       } while(wahl != 9);
       return EXIT_SUCCESS;
    }
    

    jetzt würde ich davon ausgehen das alles richtig ist oder?

    Warum bekomme ich immernoch den Fehler?

    multiple definition of next' first defined here multiple definition ofanfang'
    first defined here
    ld returned 1 exit status



  • So jetzt hab ich glaube ich verstanden was Ihr meint.

    Moment Post kommt gleich.



  • Also ich würde sagen ich fasse das mal alles zusammen.

    Zunächst der Quellcode:

    Header: angestellt.h

    struct angestellt{
       char name[20];
       struct angestellt *next;
    };
    
    struct angestellt *next;
    struct angestellt *anfang;
    

    Main: main.c

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "angestellt.h"
    #define MAX 20
    
    struct angestellt *next   = NULL;
    struct angestellt *anfang = NULL;
    
    /* Funktion zum Ausgeben der Dateien */
    void ausgabe(void) {
       struct angestellt *zeiger = anfang;
    
       while(zeiger != NULL) {
          printf("%12s\n",
             zeiger->name);
             zeiger=zeiger->next;
       }
    }
    
    int main(void) {
       int wahl;
       char dname[MAX];
    
       do {
          printf("\n1 : Eingabe\n");
          printf("2 : Ausgabe\n");
          printf("9 : Ende\n");
          printf("Ihre Wahl : ");
          scanf("%d",&wahl);
          getchar();
          switch(wahl) {
             case 1 : anhaengen("TestX");
                      break;
             case 2 : ausgabe();
                      break;
             case 9 : break;
             default: printf("Falsche Eingabe!!!\n");
          }
       } while(wahl != 9);
       return EXIT_SUCCESS;
    }
    

    und Anhängen: anhaengen.c

    /* linear_list2.c */
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "angestellt.h"
    #define MAX 20
    
    void anhaengen(char *n) {
       struct angestellt *zeiger;
    
       if(anfang == NULL) {
    
          if((anfang =
           malloc(sizeof(struct angestellt))) == NULL) {
             fprintf(stderr, "Kein Speicherplatz vorhanden "
                             "für anfang\n");
             return;
          }
          strcpy(anfang->name, n);
    
          anfang->next=NULL;
       }
    
       else {
          zeiger=anfang; 
          while(zeiger->next != NULL)
             zeiger=zeiger->next;
    
          if((zeiger->next =
           malloc(sizeof(struct angestellt))) == NULL) {
              fprintf(stderr,"Kein Speicherplatz für das "
                             "letzte Element\n");
              return;
          }
          zeiger=zeiger->next; 
          strcpy(zeiger->name,n);
          zeiger->next=NULL;
       }
    }
    

    Also in der Header datei dürfen nur die Deklarationen stehen aber keine Zuweisung von Werten auch nich NULL da sonnst dieser Variable bei jeden Funktion angelegt wird indem das Include vorhanden ist. (Was beim Übersetzen auch ein guter (etwas besserer) Compiler auch nicht zulässt.

    Somit darf also der Header nur so aussehen wie oben beschrieben und nicht so wie in den anderen Beispielen dieses Beitrages.

    Damit aber next und Anfang zu beginn auf NULL stehen muss dies bei Aufruf Definiert werden. (also wie in der Main.)

    So und nun geht auch alles 😃

    Danke für die Hilfe Leute, auch wenn Ihr mir das schon etwas schwer gemacht habt. Aber ich glaube das werde ich nicht so schnell vergessen 😃



  • PS: ich finde das Buch C von A bis Z garnicht so schlecht, leider habe ich nicht die Zeit es von Anfang bis Ende zu lesen.

    Aber so ist es gut gut und übersichtlich geschrieben. An stelle zu maulen wie schlecht der Gute Mann ist, solltet Ihr lieber auch dazu schreiben welches Buch Ihr empfehlen würdet.

    Dann kann ich als 0815 ANSI-C Programmierer das auch mal kaufen und werde vielleicht dann auch ein 4711 ANSI-C Programmierer.

    Gruß an euch alle und noch einmal vielen lieben Dank.



  • Aus dem Header muss das raus:

    struct angestellt *next;
    struct angestellt *anfang;
    

    denn auch damit legst du die Variablen an. Das hat mit dem zuweisen von Werten nichts zu tun.

    Dafür muss in anhaengen.c folgendes rein:

    extern struct angestellt *next;
    extern struct angestellt *anfang;
    

    Damit sagst du dem Compiler, dass die Variablen schon woanders angelegt wurden.
    (bei dir in main.c).



  • Es hat glaub ich noch keiner darauf Aufmerksam gemacht (und vielleicht weißt du es sogar und hast es nur wegen dem simplen Beispiel ignoriert), aber das programm ist anfällig für einen Buffer Overflow.

    struct angestellt{
       char name[20];
       struct angestellt *next;
    }
    ...
    void anhaengen(char *n){
    ...
    /* keine Längenprüfung von n */
    strcpy(anfang->name,n);
    ...
    }
    

    Wenn n hier länger als 20 Zeichen ist (NUL inklusive) wird dein Programm im besten Fall abstürzen, im schlimmsten Fall gekapert werden können



  • LHBL2003 schrieb:

    PS: ich finde das Buch C von A bis Z garnicht so schlecht, leider habe ich nicht die Zeit es von Anfang bis Ende zu lesen.

    Aber so ist es gut gut und übersichtlich geschrieben. An stelle zu maulen wie schlecht der Gute Mann ist, solltet Ihr lieber auch dazu schreiben welches Buch Ihr empfehlen würdet.

    Also subjektiv didaktisch gut aufbereitete Fachbücher, die inhaltlich überwiegend nachweisbar falsche Aussagen präsentieren, sind gute Bücher?
    Nein, das stimmt nicht.
    Der Autor JW verbreitet überwiegend Pfusch, und wenn DU dir mal die Mühe gemacht haben würdest, hier im Forum zu suchen, wäre dir u. vielen anderen Beiträgen auch der aktuelle Parallelbeitrag "Hoffungslos" aufgefallen, in dem der Autor entsprechend abgehandelt wird.
    Wie schwer es ist, aus euch Anfängerköpfen diesen JW Pfusch herauszubekommen, merkt man an vielen Beiträgen hier im Forum.
    Ich habe dort z.B. auch Alternativliteratur benannt, also: eine Suche in diesem Forum lohnt sich, und nehme nicht immer gleich die Top-Googletreffer als gottgegeben hin.


Anmelden zum Antworten