Zweidimensionales Array an Funktion übergeben - Problem bei allen Spalten >1
-
Hallo,
ich mache seit einigen Wochen meine ersten Schritte in C und habe dabei ein Problem mit der Übergabe von mehrdimensionalen Arrays (ich weiß, dass es vor kurzem eine ähnliche Fragestellung gab, die Lösung dazu habe ich aber aufgrund der Speicherzuweisung etc. nicht verstanden):Ich möchte ein mehrdimensionales Array in main() erzeugen und dieses dann in einer anderen Funktion nutzen. Ich bin mit meiner Fehlereingrenzung schon so weit gekommen, dass die Übergabe nicht richtig ist (deshalb habe ich es hier am einfachen Beispiel des Ausdruckens dargestellt, der Fehler ist der Gleiche). Die erste Zeile meines Arrays wird korrekt ausgegeben, bei den folgenden Zeilen erscheinen jedoch unsinnige Zahlen (426, 1310720, o.Ä.).
Das Problem tritt nicht auf, wenn ich die Spalten des Arrays als Konstante definieren. Es muss also an "[spalten]" im Funktionsaufruf "drucken" liegen. (Leider geht das mit der Konstante nicht, wenn ich die Dimension der Matrix erst noch einlesen möchte, oder??)Alternativ habe ich auf galileocomputing gelesen, dass man auch einen Pointer übergeben kann (http://www.galileocomputing.de/openbook/c_von_a_bis_z/c_014_006.htm#RxxobKap014006040028C01F04118C). Dann bekomme ich allerdings beim kompilieren die Fehlermeldung "assignment of pointer to array 4 of int to pointer to int" für Zeile 8 im zweiten Code-Beispiel. Damit kann ich leider wenig anfangen... (Kann es sein, dass ich dem Pointer noch mitteilen muss, wieviele Spaltenelemente jedes Zeilenelement hat? Wenn ja: wie?)
Ich würde mich freuen, wenn mir jemand helfen kann, das Array korrekt zu übergeben, wenn möglich ohne struct-Anweisung.
Herzlichen Dank!
Gesamtes Programm:
#include <stdio.h> #include <stdlib.h> int spalten; //Druck-Funktion void drucken (int feld[][spalten], int zeilen, int spalten) { for ( int count_zeilen = 0; count_zeilen < zeilen; count_zeilen++ ) { for ( int count_spalten = 0; count_spalten < spalten; count_spalten++ ) { printf ( "%3d", feld[count_zeilen][count_spalten] ); } printf ("\n"); } } //Main-Funktion int main (void) { int zeilen = 2; spalten = 2; int feld [zeilen][spalten]; for ( int count_zeilen = 0; count_zeilen < zeilen; count_zeilen++ ) { for ( int count_spalten = 0; count_spalten < spalten; count_spalten++ ) { feld[count_zeilen][count_spalten] = count_zeilen + count_spalten; } } drucken (feld, zeilen, spalten); }
Änderungen für Pointer-Übergabe, Rest wie oben (den habe ich aus Platzgründen weggelassen...):
void drucken (int *feld[spalten], int zeilen, int spalten) { } int main (void) { int *pointer; pointer = feld; drucken (pointer, zeilen, spalten); }
-
probier's so:
#include <stdio.h> #include <stdlib.h> //Druck-Funktion void drucken (int *feld, int zeilen, int spalten) { int count_zeilen; int count_spalten; for ( count_zeilen = 0; count_zeilen < zeilen; count_zeilen++ ) { for ( count_spalten = 0; count_spalten < spalten; count_spalten++ ) { printf ( "%3d", feld[count_zeilen+zeilen*count_spalten] ); } printf ("\n"); } } //Main-Funktion #define ZEILEN 5 #define SPALTEN 10 int main (void) { int count_zeilen; int count_spalten; int feld [ZEILEN][SPALTEN]; int x = 0; for ( count_zeilen = 0; count_zeilen < ZEILEN; count_zeilen++ ) { for ( count_spalten = 0; count_spalten < SPALTEN; count_spalten++ ) { feld[count_zeilen][count_spalten] = x++; } } drucken ((int*)feld, ZEILEN, SPALTEN); }
-
online codegenerator schrieb:
probier's so:
...das ist ein schönes beispiel vie man flexibel mit arrays verschiedener anzahl von zeilen und spalten arbeiten kann.
wenn man noch den index ändern würde, dann würden die zahlen auch in der richtigen reihenfolge ausgegeben werden,
z.b. so:void drucken_reprogged( int *feld, int zeilen, int spalten ) { int count_zeilen; int count_spalten; for ( count_zeilen = 0; count_zeilen < zeilen; count_zeilen++ ) { for ( count_spalten = 0; count_spalten < spalten; count_spalten++ ) { printf ( "%3d", feld[count_zeilen*spalten+count_spalten] ); // !!! } printf ("\n"); } }
wenn die größe des arrays aber feststeht und sich nicht ändert, gehts aus so:
void drucke2Darr( int arr[ZEILEN][SPALTEN] ) { int z,s; for( s=0; s<SPALTEN; s++ ) { for ( z=0; z<ZEILEN; z++ ) { printf( "%3d", arr[z][s] ); } puts(""); } } void init2Darr( int arr[ZEILEN][SPALTEN] ) { int i = 0,z,s; for( s=0; s<SPALTEN; s++ ) for ( z=0; z<ZEILEN; z++ ) arr[z][s] = i++; } // aufruf init2Darr(arr); drucke2Darr(arr); drucken_reprogged( arr, ZEILEN, SPALTEN )
-
Die Lösung setzt aber voraus, dass ich ZEILEN und SPALTEN vorher per "#define" definiert habe, oder? Sonst funktioniert es nämlich bei mir nicht...
Kann ich statt des festen Wertes denn auch den Wert für ZEILEN und SPALTEN während des Programmaufrufs festlegen (z.B. durch eine Eingabe)? Das muss ich nämlich: das Array kann für jeden Programmaufruf eine andere Größe haben
Trotzdem danke...
-
Übrigens ist mir grade aufgefallen, dass ich das Thema falsch benannt habe: ich habe natürlich Schwierigkeiten in allen Zeilen > 1
-
c-anfaenger schrieb:
Kann ich statt des festen Wertes denn auch den Wert für ZEILEN und SPALTEN während des Programmaufrufs festlegen (z.B. durch eine Eingabe)? Das muss ich nämlich: das Array kann für jeden Programmaufruf eine andere Größe haben
Trotzdem danke...das kannst du mit 'malloc' machen:
... int zeilen = ...; int spalten = ...; int *feld = malloc (zeilen * spalten * sizeof(int)); ... if (feld) // nur benutzen wenn feld != 0 { feld[x+zeilen*y] = ...; // setzt einen wert an position x/y ... free (feld); // 'free' aufrufen wenn feld nicht mehr gebraucht wird }
-
c-anfaenger schrieb:
Alternativ habe ich auf galileocomputing gelesen, dass man auch einen Pointer übergeben kann (http://www.galileocomputing.de/openbook/c_von_a_bis_z/c_014_006.htm#RxxobKap014006040028C01F04118C). Dann bekomme ich allerdings beim kompilieren die Fehlermeldung...
btw: vergiss 'galileo-computing' am besten ganz schnell. das ist voller fehler. frag' lieber uns.
-
falls dir die indexschreibweise eher zusagt:
void init_arr2D( int **arr, int zeilen, int spalten ) { int i = 0,z,s; for( z=0; z<zeilen; z++ ) for ( s=0; s<spalten; s++ ) arr[z][s] = i++; } void drucken_arr2D( int **arr, int zeilen, int spalten ) { int z; int s; for ( z = 0; z < zeilen; z++ ) { for ( s = 0; s < spalten; s++ ) { printf ( "%3d", arr[z][s] ); } puts(""); } } int main() { int i=0,j=0,z=3,s=5; int** arr2D=NULL; arr2D = malloc( z*sizeof(int**) ); if ( !arr2D ) { puts("out of memory"); return 1; } for ( i=0; i<z; i++ ) { arr2D[i] = malloc( s*sizeof(int)); if ( !arr2D[i]) break; } if ( i<z ) { puts("out of memory"); for ( j=0; j<=i; j++ ) free ( arr2D[j] ); free( arr2D ); return 1; } init_arr2D(arr2D, z, s); drucken_arr2D(arr2D, z, s ); // aufräumen for ( i=0; i<z; i++ ) { free(arr2D[i]); // spalten freigeben } free(arr2D); // zeilenzeiger freigeben return 0; }
-
Vielen Dank!
-
Das beispiel von easy array II reprogged funktioniert leider nicht. Ich bekomme jede Menge Fehler:
Fehler 1 error C3861: "printf": Bezeichner wurde nicht gefunden. h:\visual studio 2010\projects\basics\basics\main.cpp 18
Fehler 2 error C3861: "puts": Bezeichner wurde nicht gefunden. h:\visual studio 2010\projects\basics\basics\main.cpp 20
Fehler 3 error C2065: 'NULL': nichtdeklarierter Bezeichner h:\visual studio 2010\projects\basics\basics\main.cpp 27
Fehler 4 error C3861: "malloc": Bezeichner wurde nicht gefunden. h:\visual studio 2010\projects\basics\basics\main.cpp 29
Fehler 5 error C3861: "puts": Bezeichner wurde nicht gefunden. h:\visual studio 2010\projects\basics\basics\main.cpp 32
Fehler 6 error C3861: "malloc": Bezeichner wurde nicht gefunden. h:\visual studio 2010\projects\basics\basics\main.cpp 37
Fehler 7 error C3861: "puts": Bezeichner wurde nicht gefunden. h:\visual studio 2010\projects\basics\basics\main.cpp 43
Fehler 8 error C3861: "free": Bezeichner wurde nicht gefunden. h:\visual studio 2010\projects\basics\basics\main.cpp 44
Fehler 9 error C3861: "free": Bezeichner wurde nicht gefunden. h:\visual studio 2010\projects\basics\basics\main.cpp 45
Fehler 10 error C3861: "free": Bezeichner wurde nicht gefunden. h:\visual studio 2010\projects\basics\basics\main.cpp 58
Fehler 11 error C3861: "free": Bezeichner wurde nicht gefunden. h:\visual studio 2010\projects\basics\basics\main.cpp 60
12 IntelliSense: PCH-Warnung: Es wurde keine geeignete Stelle für das Header-Ende gefunden. Es wurde keine Intellisense-PCH-Datei generiert. h:\visual studio 2010\projects\basics\basics\main.cpp 1
13 IntelliSense: Der Bezeichner ""printf"" ist nicht definiert. h:\visual studio 2010\projects\basics\basics\main.cpp 18
14 IntelliSense: Der Bezeichner ""puts"" ist nicht definiert. h:\visual studio 2010\projects\basics\basics\main.cpp 20
15 IntelliSense: Der Bezeichner ""NULL"" ist nicht definiert. h:\visual studio 2010\projects\basics\basics\main.cpp 27
16 IntelliSense: Der Bezeichner ""malloc"" ist nicht definiert. h:\visual studio 2010\projects\basics\basics\main.cpp 29
17 IntelliSense: Der Bezeichner ""puts"" ist nicht definiert. h:\visual studio 2010\projects\basics\basics\main.cpp 32
18 IntelliSense: Der Bezeichner ""puts"" ist nicht definiert. h:\visual studio 2010\projects\basics\basics\main.cpp 43
19 IntelliSense: Der Bezeichner ""free"" ist nicht definiert. h:\visual studio 2010\projects\basics\basics\main.cpp 44
20 IntelliSense: Der Bezeichner ""free"" ist nicht definiert. h:\visual studio 2010\projects\basics\basics\main.cpp 45
21 IntelliSense: Der Bezeichner ""free"" ist nicht definiert. h:\visual studio 2010\projects\basics\basics\main.cpp 58
22 IntelliSense: Der Bezeichner ""free"" ist nicht definiert. h:\visual studio 2010\projects\basics\basics\main.cpp 60
-
Da fehlen Header:
#include <stdio.h>
#include <stdlib.h>ganz oben sollte helfen.
-
Leichenfledderer.
Liebe Kinder, so nicht machen
#include <stdio.h> #include <stdlib.h> int spalten; //Druck-Funktion void drucken (int feld[][spalten], int zeilen, int spalten) { for ( int count_zeilen = 0; count_zeilen < zeilen; count_zeilen++ ) { for ( int count_spalten = 0; count_spalten < spalten; count_spalten++ ) { printf ( "%3d", feld[count_zeilen][count_spalten] ); } printf ("\n"); } } //Main-Funktion int main (void) { int zeilen = 2; spalten = 2; int feld [zeilen][spalten]; for ( int count_zeilen = 0; count_zeilen < zeilen; count_zeilen++ ) { for ( int count_spalten = 0; count_spalten < spalten; count_spalten++ ) { feld[count_zeilen][count_spalten] = count_zeilen + count_spalten; } } drucken (feld, zeilen, spalten); }
Der Onkel zeigt jetzt mal, wie man sowas macht:
- ohne globale Variablen
- ohne VLA
- ohne UB
- ohne Zeiger-Cast
- C99 konform (wegen Verwendung von Zeigern auf VLA)
- im Übrigen kommen in den meisten o.g. "Vorschlägen" überhaupt keine Arrays vor
- es gibt auch keine zweidimensionalen Arrays sondern nur Arrays von Arraysvoid setzen (void *speicher, int zeilen, int spalten) { int (*f)[spalten] = speicher; for ( int count_zeilen = 0; count_zeilen < zeilen; count_zeilen++ ) { for ( int count_spalten = 0; count_spalten < spalten; count_spalten++ ) { f[count_zeilen][count_spalten] = count_zeilen + count_spalten; } } } void drucken (void *speicher, int zeilen, int spalten) { int (*f)[spalten] = speicher; for ( int count_zeilen = 0; count_zeilen < zeilen; count_zeilen++ ) { for ( int count_spalten = 0; count_spalten < spalten; count_spalten++ ) { printf ( "%3d", f[count_zeilen][count_spalten] ); } printf ("\n"); } } int main (void) { int zeilen = 2; int spalten = 2; int *speicher = malloc( zeilen*spalten*sizeof*speicher ); setzen (speicher, zeilen, spalten); drucken (speicher, zeilen, spalten); free( speicher ); return 0; }
Das Ganze arbeitet mit Dimensionen, die erst zur Laufzeit bekannt sind auf einem Speicherbereich, d.h. es wird auch nur 1x malloc/free verwendet (was in der Regel ziemlich teuer ist).
Weiterhin kann die offensichtlich ja wohl gewünschte Doppelsubskription [zeile][spalte] verwendet werden, die bei den meisten o.g. Beispielen zu der irrigen Annahme führte, es handele sich um Arrays.