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 ? /0und 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
-
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
-
newbie110 schrieb:
Hat evtl. jmd ein Bspl. für den Zugriff mit *** ?
3fach Pointer ist mir zu hochfoo[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;
-
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