Problem mit Zeiger Convertierung



  • Das Programm soll Personen verwalten. In der Bibliothek ist die Struktur definiert. Die hier aufgeführte Unterfunktion(nur ein Ausschnitt) liest die Daten von der Tastatur ein und speichert sie in einem Hilfsfeld ab. Danach wird ein dynamisches Feld erzeugt, mit der Größe der eingegebenen Datensätze.
    Mein Problem ist die Konvertierung der Zeiger: Der Kompiler spuckt andauernd char* kann nicht in int konvertiert werden.
    Über Hilfe würde ich mich sehr freuen.

    Bibliothek

    typedef struct person_e {         // Etikett: Struktur Person
                ui_t  identNr;
                nam_t fNam, vNam;
                gd_t  gebDat;
                } person_t; 
    
    typedef person_t*  pperson_t;     // Typname: Zeiger auf Struktur
    typedef pperson_t* ppperson_t;    // Typname: Zeiger auf Zeiger auf Struktur
    

    Funktion Personenverwaltung

    pperson_t person;
      int datenAnz;
    
    pperson_t *pPerArr = {0};
      pPerArr = (char**) calloc (datenAnz, sizeof(char*));
    
      for(int j=0; j <= datenAnz; j++) {
        pPerArr[j] = person[j];
    


  • Das Problem hat mit dem Forumstitel nichts zu tun.
    Es ist eine reine C-Problematik.

    pperson_t *pPerArr = {0};
    

    Ist schon mal sinnfrei, Zeiger initialisiert man

    pperson_t *pPerArr = NULL;
    oder auch gleich
    pperson_t *pPerArr = 0;
    
    pPerArr = (char**) calloc (datenAnz, sizeof(char*));
    

    ist auch sinnfrei in Sinn von C, nur C++ler, die auf C Code nicht verzichten können, benutzen den Cast.

    pPerArr = calloc (datenAnz, sizeof *pPerArr );
    

    z.B. reicht völlig aus.

    for(int j=0; j <= datenAnz; j++) {
    

    Hier stimmt auch schon wieder was nicht, denn du läufst über die Grenzen hinaus, besser und portabler ist:

    int j;
    for(j=0; j < datenAnz; j++) {
        pPerArr[j] = person[j];
    


  • Vielen Dank erstmal für deine Antwort.
    Wenn ich das so mache wie du sagst bekomme ich die Meldung:

    error C2440: '=': 'void *' kann nicht in 'pperson_t *' konvertiert werden

    Also so ähnlich wie vorher auch.
    Und dann hatte ich noch eine weitere Meldung:

    error C2228: Links von ".fNam" muss sich eine Klasse/Struktur/Union befinden. Typ ist 'pperson_t'

    Diese Verschwindet wenn ich es wie folgt mache (Code mit der kompletten Funktion). Die obere Meldung jedoch bleibt:

    error C2440: '=': 'void *' kann nicht in 'pperson_t' konvertiert werden

    pperson_t ReadPerFromKbd (void) {
    
      pperson_t person;
      int datenAnz;
    
      for(int i=0; i < 10; i++) {
        datenAnz = i;
        printf("Familiennamen: ");  fgets(person[i].fNam, NAMLEN+1, stdin);
        if(strlen(person[i].fNam) != 1) {
          printf("Vorname      : ");  fgets(person[i].vNam, NAMLEN+1, stdin);     
          printf("Geburt Tag   : ");  scanf_s("%u", &person[i].gebDat.gdTag);  
          printf("Geburt Monat : ");  scanf_s("%u", &person[i].gebDat.gdMonat);
          printf("Geburt Jahr  : ");  scanf_s("%u", &person[i].gebDat.gdJahr);
          printf("Personal-Nr. : ");  scanf_s("%u", &person[i].identNr);
        }//if
        else i=10;
      }//for
    
      pperson_t pPerArr = 0;
      pPerArr = calloc (datenAnz, sizeof pPerArr);
    
      for(int j=0; j < datenAnz; j++) {
        pPerArr[j] = person[j];
      }//for
    
    }//ReadPerFromKbd
    

    In der oberen for-Schleife brauchst du nichts zu korrigieren(außer da liegt das eigentliche Problem), da kommen wir schon selber hinter(ist aber vllt für den Zusammenhang wichtig). Aber für den Rest wärs echt cool. Und mit den Grenzen hattest du natürlich Recht.



  • pincerepa schrieb:

    Wenn ich das so mache wie du sagst bekomme ich die Meldung:

    error C2440: '=': 'void *' kann nicht in 'pperson_t *' konvertiert werden

    Dann verwendest du den C++-Compiler, obwohl dein Code eigentlich ziemlich nach C aussieht. In dem Fall ist der Cast schon nötig. Wenn du bei reinem C bleiben willst, kannst du deine cpp-Datei einfach nach .c umbenennen (oder in den Projektsettings auf C-Compiler umschalten).



  • ui_t  identNr;
                nam_t fNam, vNam;
                gd_t  gebDat;
    

    Diese Typnamen halte ich für dringend verbesserungswürdig.
    Irgendjemand außer dir soll die Code ja vielleicht auch noch mal lesen und verstehen können ohne gleich einen größeren Vorrat Betablocker aufzubrauchen.

    #ifdef __cplusplus
    #error Ich übersetze C Code mit einem C++ Compiler, was Anfängerschrott ist
    #endif
    
    pperson_t ReadPerFromKbd (void) {
    
      person_t person[10]; /* ein temporäres 10er Array zum Einlesen der Daten */
      pperson_t pPerArr = 0; /* Definition eines Zeigers mit NULL-Initialisierung */
      int datenAnz,i;
    
      for(datenAnz=i=0; i < 10; i++,datenAnz++) {
        printf("Familiennamen: ");  fgets(person[i].fNam, NAMLEN+1, stdin); /* evtl. vorhandenes abschließendes '\n' muss hier noch entfernt werden... */
        if(strlen(person[i].fNam) != 1) {
          printf("Vorname      : ");  fgets(person[i].vNam, NAMLEN+1, stdin); /* evtl. vorhandenes abschließendes '\n' muss hier noch entfernt werden... */ 
          printf("Geburt Tag   : ");  scanf("%u", &person[i].gebDat.gdTag);  
          printf("Geburt Monat : ");  scanf("%u", &person[i].gebDat.gdMonat);
          printf("Geburt Jahr  : ");  scanf("%u", &person[i].gebDat.gdJahr);
          printf("Personal-Nr. : ");  scanf("%u", &person[i].identNr);
        }
      }
    
      pPerArr = calloc (datenAnz, sizeof *pPerArr); /* '*' hast du hier entfernt, ohne zu wissen warum; */
    
      for(i=0; i < datenAnz; i++) {
        pPerArr[i] = person[i]; /* hier werden die StrukturelementINHALTE in den vorbereiteten calloc-Speicherplatz kopiert */
      }
    
      return pPerArr;  /* return hast du auch noch vergessen */ 
    }
    

    Eine robuste Eingabepufferlöschung für DAU-Eingaben fehlt natürlich noch.



  • Hey,

    @_matze: Der Cast hat geholfen. Danke:)

    @Wutz: Die Typnamen sind so vorgegeben. Wir arbeiten mit VisualStudio2008 und machen da eine CLR-Konsolenanwendung unter C++. Es ist also ein C++ Compiler. Wir sollen aber trotzdem C programmieren. Mein Professor meinte das C auch komplett unter C++ funktioniert.

    Das ich das return vergessen hatte war mir auch schon aufgefallen :). Und vielen Dank für die anderen Tipps.



  • Wenn ich die Funktion jetzt aufrufe kommen folgende Fehlermeldungen mit welchen ich nun wirklich gar nix mehr anfangen kann.

    error LNK2028: Nicht aufgelöstes Token (0A00000F) ""struct person_e * __cdecl ReadPerFromKbd(void)" (?ReadPerFromKbd@@$$FYAPAUperson_e@@XZ)", auf das in Funktion ""int __cdecl main(void)" (?main@@$$HYAHXZ)" verwiesen wird.
    error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""struct person_e * __cdecl ReadPerFromKbd(void)" (?ReadPerFromKbd@@$$FYAPAUperson_e@@XZ)" in Funktion ""int __cdecl main(void)" (?main@@$$HYAHXZ)".
    


  • pincerepa schrieb:

    Mein Professor meinte das C auch komplett unter C++ funktioniert.

    Das ist kompletter Blödsinn. C ist eine Schnittmenge mit C++ keine Untermenge von, und dass das so ist hast du selbst erfahren.



  • pincerepa schrieb:

    Wenn ich die Funktion jetzt aufrufe kommen folgende Fehlermeldungen mit welchen ich nun wirklich gar nix mehr anfangen kann.

    Der Compiler mit person_e auch nicht ...



  • merano schrieb:

    pincerepa schrieb:

    Wenn ich die Funktion jetzt aufrufe kommen folgende Fehlermeldungen mit welchen ich nun wirklich gar nix mehr anfangen kann.

    Der Compiler mit person_e auch nicht ...

    Der Compiler hat mit person_e kein Problem. Es ist der Linker, der meckert. Da fehlt die Definition.


Anmelden zum Antworten