zweidimensionales Array von Strings



  • Hy,
    ich suche schon seit einer Weile nach einer Möglichkeit ein 2Dimesionales Array mit Strings drin aufzubauen.
    Gibt es da eine Möglichkeit?
    Soll am Ende so sein dass ich ein Array habe wie eine Excel Tabelle und auf die einzelnen Strings zugreifen kann.
    Zb.

    Hallo Du Da
    Wie Geht Es
    dir denn da
    draußen vor dem
    rechner ? /0

    und ich kann auf jedes der Wörter zugreifen!
    Wichtig ist dabei halt, dass die Zeilen verschieden lang seien können und sie zusammengeordnet sind dH. wenn ich "Du" habe muss es für mich einfach sein auf "Da" und "Hallo" zuzugreifen.

    DANKE



  • Achso ich sollte dazu sagen, dass es sich um C nicht C++ oder C# handelt 🙂
    DANKE


  • Mod

    Ja, das geht. Wie genau, kommt auf deine Daten an. Du sagst, die Zeilen können unterschiedlich lang sein, aber in deinem Beispiel sind alle 3 Einträge lang. Versehen? Oder meinst du damit, dass in jeder Zeile zwar eine fixe Zahl von Beiträgen steht, aber die Beiträge unterschiedlich lang sein können?

    Variante 1: Wörter unterschiedlich groß, fixe Zahl von Worten pro Zeile (N), fixe Zahl von Zeilen (M):

    char *foo[M][N];
    

    Variante 2: Wörter unterschiedlich groß, fixe Zahl von Worten pro Zeile (N), unbekannte Zahl von Zeilen:

    char *(*foo)[N];
    

    Variante 3: Wörter unterschiedlich groß, unbekannte Zahl von Worten pro Zeile, unbekannte Zahl von Zeilen:

    char ***foo;
    

    Andere Kombinationen kannst du dir selber denken.

    Dann nutzt du malloc um die Felder unbekannter Größe zu bekommen. Du siehst schon, da sind eine Menge Sternchen drin und du musst an vielen Stellen aufpassen, wie du das Gesamtobjekt behandelst (zum Beispiel, wie man solch ein Monstrum kopiert). Hier bietet sich ein objektorientierter Ansatz an. Da schreibst du Funktionen, die auf einem solchen Objekt arbeiten und tun, was du brauchst (z.B. eben kopieren, aber auch für einfache Dinge, wie einen Eintrag zu ändern). Die Daten packst du dann nur über diese Funktionen an. So weißt du, wenn etwas schief geht, dass etwas an diesen Funktionen falsch sein muss (macht Fehlersuche einfacher) und wenn die Zugriffsfunktionen erst einmal richtig sind, dann ist automatisch jeder Zugriff richtig (vermeidet Fehler).



  • char ***foo;
    

    Auf den Zugriff, bzw. das Handling mit den 3Stars bin ich ja dann auch gespannt 😮 😕 😉



  • char *Zeile[][4] = { {"Hallo", "Du", "Da", NULL},
                         {"Wie", "Geht", "Es", NULL},
                         {"dir", "denn", "da", NULL},
                         {"draußen", "vor", "dem", NULL},
                         {"rechner", "?", NULL, NULL  },
                         { NULL } };
    
    int i ,j;
    
    for {i = 0; Zeile[i][0] != NULL; i++)
    { for {j = 0; Zeile[i][j] != NULL; j++)
      { printf("%s ", Zeile[i][j]);
      }
      putchar('\n');
    }
    


  • Hat evtl. jmd ein Bspl. für den Zugriff mit *** ?
    3fach Pointer ist mir zu hoch 😞 😕 😕


  • Mod

    newbie110 schrieb:

    Hat evtl. jmd ein Bspl. für den Zugriff mit *** ?
    3fach Pointer ist mir zu hoch 😞 😕 😕

    foo[x][y][z] ?



  • ist

    char ***foo;
    

    "nur" ein 3-Dim Array? Quatsch oder? Wie wird sowas übergeben und derefferenziert?



  • Nein, das ist kein 3D-Array.
    Ein (echtes) 3D-Array zerfällt auch nur in einen einfachen Zeiger.

    newbie110 schrieb:

    Wie wird sowas übergeben und derefferenziert?

    char **bar(char ***foo)  // ***foo ist ein char
    { putchar(foo[3][2][1]);           // das kannst du 3mal dereferenzieren
      puts (foo[3][2]);                // Einmal weniger dereferenziert ist dann char*
    
      return foo[3];                   // das ist dann char** (sowas wie argc von main)
    }
    


  • Aha...Danke!!

    Noch ne Frage... Wie würde das dann aussehne, wenn der 3-Star zb. auf ne Struktur zeigt?

    Also z.B.:

    struct v1{int t1; int t2}};
    typedef struct v1 TEST;
    
    // ginge dann sowas??:
    TEST ***tptr;
    

    Sinn und oder Unsinn sei jetzt mal dahin gestellt. Geht sowas, und wenn ja, wie handelt man das dann?

    😕 😕 😕



  • newbie110 schrieb:

    Aha...Danke!!

    Noch ne Frage... Wie würde das dann aussehne, wenn der 3-Star zb. auf ne Struktur zeigt?

    Also z.B.:

    struct v1{int t1; int t2}};
    typedef struct v1 TEST;
    
    // ginge dann sowas??:
    TEST ***tptr;
    

    Sinn und oder Unsinn sei jetzt mal dahin gestellt. Geht sowas, und wenn ja, wie handelt man das dann?

    😕 😕 😕

    Ist doch einfach:

    #include <stdio.h>
    
    typedef struct
    {
        int id;
    } T_ID;
    
    int main( void )
    {
        T_ID    myId = { 5 };
        T_ID    *fp1 = &myId;
        T_ID    **fp2 = &fp1;
        T_ID    ***fp3 = &fp2;
    
        printf( "%d", (**fp3)->id );
    
        return 0;
    }
    


  • Ui, interessant....

    Wie würde sowas dann mit SeppJ´s Beispiel aussehen??

    Variante 3: Wörter unterschiedlich groß, unbekannte Zahl von Worten pro Zeile, unbekannte Zahl von Zeilen:

    C:
    char ***foo;
    

    Wie "schreibt" man da rein und kann das auslesen??



  • beginner88888 schrieb:

    Ui, interessant....

    Wie würde sowas dann mit SeppJ´s Beispiel aussehen??

    Variante 3: Wörter unterschiedlich groß, unbekannte Zahl von Worten pro Zeile, unbekannte Zahl von Zeilen:

    C:
    char ***foo;
    

    Wie "schreibt" man da rein und kann das auslesen??

    Wo ist das Problem? Das geht ganz normal:

    ***foo = 'c';
    
    // oder
    
    char c = ***foo;
    

  • Mod

    beginner88888 schrieb:

    Wie "schreibt" man da rein und kann das auslesen??

    SeppJ schrieb:

    Dann nutzt du malloc um die Felder unbekannter Größe zu bekommen.

    Du solltest wirklich mal an kleineren Beispielen üben, wenn du solche Fragen stellen musst. An den gezeigten Techniken ist nicht anders als an "normalen" eindimensionalen Strukturen. Nur eben dreifach verschachtelt und jede Ebene ist dann entweder dynamisch oder statisch. Sie wird aber jeweils genau so behandelt wie im einfachen Fall. Das nützt dir natürlich herzlich wenig, wenn du den einfachen Fall nicht beherrscht, was ich mal anhand deiner Fragen annehme. Falls du Probleme mit mit der dreifachen Verschachtelung hast, gilt ebenfalls weiter üben. Denn Verschachtelungen brauchst du andauernd beim Programmieren, damit darfst du keine Schwierigkeiten haben. Beide Themenbereiche sollten in jedem Lehrbuch drankommen.



  • SeppJ schrieb:

    Du solltest wirklich mal an kleineren Beispielen üben, wenn du solche Fragen stellen musst. An den gezeigten Techniken ist nicht anders als an "normalen" eindimensionalen Strukturen. Nur eben dreifach verschachtelt und jede Ebene ist dann entweder dynamisch oder statisch. Sie wird aber jeweils genau so behandelt wie im einfachen Fall. Das nützt dir natürlich herzlich wenig, wenn du den einfachen Fall nicht beherrscht, was ich mal anhand deiner Fragen annehme. Falls du Probleme mit mit der dreifachen Verschachtelung hast, gilt ebenfalls weiter üben. Denn Verschachtelungen brauchst du andauernd beim Programmieren, damit darfst du keine Schwierigkeiten haben. Beide Themenbereiche sollten in jedem Lehrbuch drankommen.

    In diesem Zusammenhang fällt mir folgendes kleines Beispiel ein.
    Wie man ja weiß werden Arrays nicht "by value" an Funktionen übergeben sondern stattdessen wird deren Adresse übergeben. D.h.

    func( char *x ) {}
    

    und

    func( char x[] ) {}
    

    sind identisch.

    Jetzt könnte ein Anfänger auf die Idee kommen, bei mehrdimensinalen Arrays kann man einfach alle Arrayindizes durch das Zeigersymbol ersetzen. also statt

    func( char x[][10][20] ) {}
    

    geht auch

    func( char ***x ) {}
    

    Das ist aber falsch. Erste Funktion erwartet einen Zeiger auf ein zweidimensinales Array und die zweite erwartet einen Zeiger auf einen Zeiger auf einen Zeiger. Die Dereferenzierung erzeugt daher völlig unerschiedlichen Code.

    func( char x[][10][20] )
    {
       return x[0][0][0];
    }
    
    func( char ***x )
    {
       return x[0][0][0];
    }
    

    Für diejenigen, die da mal selber rumspielen wollen, habe ich meinen Code von vorher etwas erweitert:

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct
    {
        int id;
    } T_ID;
    
    char ReadMultiArray( char array[][200][300], int x, int y, int z )
    {
        return array[x][y][z];
    }
    
    char ReadMultiArray2( char ***array, int x, int y, int z )
    {
        return array[x][y][z];
    }
    
    int main( void )
    {
        char    my3Darray[100][200][300];
        char    (*myDynamic3Darray)[200][300] = calloc( 100 * 200 * 300, sizeof( char) );
        char    *myDynamic3Darray2[200][300];
    
        T_ID    myId = { 5 };
        T_ID    *fp1 = &myId;
        T_ID    **fp2 = &fp1;
        T_ID    ***fp3 = &fp2;
    
        printf( "%d\n", (**fp3)->id );
    
        printf( "%d\n", (int)sizeof( myDynamic3Darray ) );
        printf( "%d\n", (int)sizeof( myDynamic3Darray2 ) );
    
        printf( "%d\n", (int)ReadMultiArray( my3Darray, 5, 5, 5 ) );
        printf( "%d\n", (int)ReadMultiArray( myDynamic3Darray, 5, 5, 5 ) );
        printf( "%d\n", (int)ReadMultiArray2( my3Darray, 5, 5, 5 ) );       // <--- das gibt 'nen Absturz
    
        return 0;
    }
    

    In Zeile 21 deklariere ich ein 3-dimensionales Array.
    Brauche ich das aber dynamnisch, muß ich eine Deklaration wie in Zweile 22 verwenden. Man beachte die Klammern. In Zeile 23 wird nämlich ein zweidimensonales Array von Zeigern deklariert. Das sieht man sehr schön an der Ausgabe der Zeilen 32 und 33.

    Die Zeilen 35 und 36 demonstrieren den Zugriff auf die beiden dreidimensionalen Arrays. Zeile 37 erzeugt einen Absturz. Diese wird aber auch schon vom Compiler angemahnt (In C++ wäre das sogar ein Fehler).

    Will man ein 3-dimensinales Array bei dem alle drei Arraygrenzen dynamisch festgelegt werden können, muß man in C schon etwas mehr Aufwand betreiben.

    mfg Martin



  • mgaeckler schrieb:

    Will man ein 3-dimensinales Array bei dem alle drei Arraygrenzen dynamisch festgelegt werden können, muß man in C schon etwas mehr Aufwand betreiben.

    Auch dafür habe ich ein Beispiel gemacht:

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct
    {
        size_t  maxX, maxY, maxZ;
        char    start[];
    } ARRAY_3d;
    
    ARRAY_3d *createArray( size_t maxX, size_t maxY, size_t maxZ )
    {
        ARRAY_3d    *newArray = malloc( sizeof( ARRAY_3d ) + maxX * maxY * maxZ );
        newArray->maxX = maxX;
        newArray->maxY = maxY;
        newArray->maxZ = maxZ;
    
        return newArray;
    }
    
    size_t getIndex( ARRAY_3d*array, size_t x, size_t y, size_t z )
    {
        return x + y*array->maxX + z * array->maxX * array->maxY;
    }
    
    void setChar( ARRAY_3d*array, size_t x, size_t y, size_t z, char c )
    {
        array->start[getIndex( array, x, y, z )]=c;
    }
    
    char getChar( ARRAY_3d*array, size_t x, size_t y, size_t z )
    {
        return array->start[getIndex( array, x, y, z )];
    }
    
    int main( void )
    {
        size_t      x, y, z;
        ARRAY_3d    *array = createArray(5,5,5);
    
        for( x=0;x<5;x++ )
        {
            for( y=0;y<5;y++ )
            {
                for( z=0;z<5;z++ )
                {
                    setChar( array, x, y, z, z+'A' );
                }
            }
        }
    
        for( x=0;x<5;x++ )
        {
            for( y=0;y<5;y++ )
            {
                for( z=0;z<5;z++ )
                {
                    putchar( getChar( array, x, y, z ) );
                }
            }
            putchar ('\n' );
        }
    
        return 0;
    }
    

    Fehlerprüfung etc. habe ich jetzt nicht gemacht.

    mfg Martin



  • Danke für die tollen Beispiele.

    Das nützt dir natürlich herzlich wenig, wenn du den einfachen Fall nicht beherrscht, was ich mal anhand deiner Fragen annehme. Falls du Probleme mit mit der dreifachen Verschachtelung hast, gilt ebenfalls weiter üben.

    Die einfachen gehen mittlerweile realtiv gut. Hab das Thema hier einfach entdeckt und bin hald bisschen neugierig geworden. Reine Interessesache


Anmelden zum Antworten