Mehrdimensionales String-Array dynamisch reservieren + Sortieren



  • Hallo,

    ich hab' jetzt schon so lange danach gesucht, aber ich find' einfach nirgends wie man ein mehrdimensionales String- Array richtig mit new anlgegt. Das ganze soll auch noch sortiert werden...
    (ich wusste nicht, ob das jetzt in C oder C++ Forum gehört, da man new verwenden soll).

    So, der Code für das Programm:
    (Eine Schülerverwaltung)

    /* Beispiel Binaerdatei2.cpp */
    /* Schülerkartei verwalten */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h>
    #include <ctype.h>
    
    struct Datum
      { int tag;
        char mon[4];
        int jahr;
      };
    
    struct Schueler
      { char name[41],adr[41];
        Datum geburt;
      };
    
    typedef enum {erstellen,erweitern} Aktion;
    typedef enum {Montag, Dienstag, Mittwoch} Wochentag;
    
    void ausgabe(Schueler schuelerdaten);
    void eingabe(Schueler *schuelerdaten);
    void lesen(char dateiname[]);
    void dateischreiben
      (Aktion aktion,char dateiname[]);
    void aendern(char dateiname[]);
    
    const int satzlaenge=sizeof(Schueler);
    
    void ausgabe(Schueler schuelerdaten)
    { printf("Name: %s\n",schuelerdaten.name);
      printf("Adr:  %s\n",schuelerdaten.adr);
      printf(
        "Geburtsdatum:\ntt/mmm/jjjj %2d %3s %4d\n\n",
        schuelerdaten.geburt.tag,
        schuelerdaten.geburt.mon,
        schuelerdaten.geburt.jahr);
    } /* ausgabe */
    
    void eingabe(Schueler *schuelerdaten)
    { printf("Name: ");
      gets(schuelerdaten->name);
      printf("Adr:  ");
      gets(schuelerdaten->adr);
      printf("Geburtsdatum\n");
      printf("   TT:");
      scanf("%2d",&(schuelerdaten->geburt.tag));
      printf("  MMM:");
      scanf("%3s",&(schuelerdaten->geburt.mon));
      printf(" JJJJ:");
      scanf("%4d",&(schuelerdaten->geburt.jahr));
      fflush(stdin);
    } /* eingabe */
    
    void lesen(char dateiname[])
    { FILE *kartei;
      Schueler schuelerdaten;
      kartei=fopen(dateiname,"rb");
      while (fread(&schuelerdaten,satzlaenge,1,kartei))
      { 
        ausgabe(schuelerdaten);
    
        printf("Eine Taste drcken");
        getch();
      }
      fclose(kartei);
    } /* lesen */
    
    void dateischreiben(Aktion aktion,char dateiname[])
    { FILE *kartei;
      Schueler schuelerdaten;
      char antwort;
      if (aktion==erstellen)
        kartei=fopen(dateiname,"wb");
      else /* erweitern */
      { kartei=fopen(dateiname,"ab");
        fseek(kartei,0L,2);
      }
    
      do
      { 
        eingabe(&schuelerdaten);
        fwrite(&schuelerdaten,satzlaenge,1,kartei);
        printf("\nWeitere Eingaben (J/N)");
        antwort=toupper(getche());
      } while (antwort != 'N');
      fclose(kartei);
    } /* dateischreiben */
    
    void aendern(char dateiname[])
    { FILE *kartei;
      Schueler schuelerdaten;
      int katnr;
    
      printf("Katalognummer:");
      scanf("%2d",&katnr);
      printf("\n\n");
    
      kartei=fopen(dateiname,"r+b");
      fseek(kartei,(long)(katnr-1)*satzlaenge,0);
      fread(&schuelerdaten,satzlaenge,1,kartei);
      ausgabe(schuelerdaten);
      printf("\n\n");
      eingabe(&schuelerdaten);
    
      fseek(kartei,(long)(-satzlaenge),1);
      fwrite(&schuelerdaten,satzlaenge,1,kartei);
      fclose(kartei);
    } /* aendern */
    
    /***************** Vergleichsfunktion *******************************/
    int strcmp( const void *a,  const void *b)
    {          
    	// Typumwandlung für Vergleichsfunktion
      return (strcmp(*(char**)a, *(char**)b));
    }
    
    void sortieren (char dateiname[])
    {  
      char *array;     // für das mehrdimensionale Array
    
      int len,          // Anzahl der Datenblöcke
    	  i;            // Schleifenzähler    
      FILE *kartei;     // Dateizeiger
      struct Schueler *schuelerdaten = new struct Schueler;  // Struktur (new: C++)
    
      int spalte = 40;  // Länge eines Strings
    
      kartei = fopen(dateiname, "rb");
    
      /* Anzahl der Datensätze berechnen */
      fseek(kartei, 0L, SEEK_END);
    
      len = ftell(kartei)/sizeof(Schueler);
    
      printf("Laenge = %i\n\n", len);
      array = new char[len];    /* ? */
    
      /* Jetzt noch Speicher reservieren für die einzelnen Spalten */
      for(i = 0; i < len; i++) 
      {
    	array[i] = new char[spalte];
    
           if(NULL == array[i])
    	   {
             printf("Kein Speicher mehr...");
    
    	   }
      }
    
      /* Setze Dateizeiger wieder auf Anfang (zum Lesen) */
      fseek(kartei, 0L, SEEK_SET);
    
      i = 0;
    
      /* Lese aus Liste und schreibe auf Array */
      while (fread(schuelerdaten,satzlaenge,1,kartei))
      { 
        printf("\n\n%s", schuelerdaten->name);
    	strcpy(array[i], schuelerdaten->name);
    
        i++;
      }
    
      /************** SORTIERE ****************/
      qsort (array, len, sizeof(array[0]), strcmp);
    
      printf("\n\nSortiere...\n");
      for (i = 0; i < len; i++)
      {
    	  printf("%s\n", array[i]);
      }
    
      //delete ...  // angeforderten Speicher wieder freigeben
    
      fclose(kartei);  // Datei schließen
    }
    
    void main()
    { int antwort;
      char dateiname[30];
      strcpy(dateiname,"KARTEI");
    
      do
      { 
        printf("\n\n");
        printf("Erstellen......<E>\n");
        printf("Erweitern......<W>\n");
        printf("Lesen..........<L>\n");
        printf("Žndern.. ......<A>\n");
        printf("Fertig.........<F>\n");
    	printf("Sortieren......<S>\n\n\n");
        printf("Auswahl........< >\n");
    
        antwort=toupper(getche());
        printf("\n");
    
        switch (antwort)
        { case 'E':
    	dateischreiben(erstellen,dateiname); break;
          case 'W':
    	dateischreiben(erweitern,dateiname); break;
          case 'L':
    	lesen(dateiname); break;
          case 'A':
    	aendern(dateiname); break;
    	  case 'S':
    	sortieren(dateiname); break;
        }
      } while (antwort != 'F');
    } /* Binaerdatei */
    

    Danke schonmal für die Hilfe.

    Thomas (verzweifle...)



  • Vorerst eins: Dein Code ist reines C und kein C++. Deswegen wundert es mich sehr, dass du mit new/new[] (und somit delete/delete[]) arbeiten sollst.

    Ganz sicher das es nicht malloc(), realloc(), free() etc. ist?

    Falls ja:

    T* ptr = new T;
    

    Bewirkt, dass der Operator new ein Objekt Vom Typ T auf dem Heap anlegt und seine Adresse zurückgibt. Diese wird in ptr gespeichert.

    Wenn du Arrays dynamisch (und auf die 'alte' Art) reservieren möchtest sieht die Syntax so aus:

    T* ptr = new T[10];
    

    Hier werden 10 Elemente vom Typ T neu auf dem Heap angelegt und die Startadresse an ptr übergeben.

    Bei mehrdimensionalen, dynamischen Arrays brauchst du auch einen Mehrfachzeiger. (Für jede Dimension einen Zeiger).

    T** ptr = new T*[10];
    
    for(unsigned int i = 0; i < 10; ++i)
           ptr[i] = new T[10];
    

    Hier legst du zuerst 10 Elemente vom Typ Zeiger auf T auf dem Heap an und speicherst die Startadresse in ptr.
    Jetzt sprichst du in einer Schleife aber jedes Element (welches ja ein Zeiger auf T ist) nochmals an und reservierst nochmals 10 Elemente vom Typ T deren Startadresse du an ebendieses Element zurückgibst.

    In einer Grafik würde das etwa so aussehen:

    **ptr
        /
       /             
      /             
    ptr[0] - ptr[1] - ptr[2] - ptr[3] - ptr[4] - ptr[...] - ptr[9]
     |         |        |                      ....
     |         |        |             ...
     |         |       ptr[2][0] - ptr[2][1] - ... - ptr[2][9]
     |         |
     |       ptr[1][0] - ptr[1][1] - ... - ptr[1][9]
     |        
    ptr[0][1] - ptr[0][2] - ptr[0][3] - ptr[0][...] - ptr[0][9]
    

    Natürlich darfst du die Freigabe des Speichers auf keinen Fall vergessen! Für jedes 'new obj' setzt du am Ende ein 'delete obj', für jedes 'new obj[SIZE]' ein 'delete[] obj'.

    /edit: Hier im Forum gibt es auch einen FAQ-Beitrag zu dem Thema Arrays und Pointer
    Ansonsten hoffe ich dass es dir nun klarer ist...

    Caipi



  • Danke für die Antwort. Hat mir geholfen. Jetzt hab' ich es hingebracht.

    Zu deiner Frage: Zuerst haben wir mit cin und cout begonnen, dann scanf und printf verwendet. Dann mit new und delete und dann wieder mit malloc und free. Ist halt mit new ein wenig einfacher...

    Thomas

    Ps.: Das über Arrays und Zeiger hab ich mir angesehen - war aber nichts über mehrdimensionale Arrays dabei, die mir jetzt noch ein wenig Probleme bereiten...

    Ps2.: Die Erklärung war Spitze und sollte zu diesem Thread Arrays und Zeiger hinzugefügt werden.


Log in to reply