Matrix zurückgeben
-
Normalerweise programmiere ich mit Java, weshalb mir C mit seinen Zeigern sehr ungewohnt ist.
Ich will ein Programm schreiben, das zwei Matizen addiert. Die Addition soll in einer seperaten Funktion sein und hier fangen die Probleme an.
Ich glaube, dass ich inzwischen herausgefunden habe wie ich eine Matrix übergebe (durch dieses **-Bla), aber nicht wie ich eine zurück bekomme.#include <stdio.h> int** mAddierer(int** matrix1, int** matrix2, int breite, int hoehe) { int matrixE[breite][hoehe]; int i, j; for(i=0; i<breite; i++) { for(j=0; j<hoehe; j++) { matrixE[i][j] = (matrix1[i][j] + matrix2[i][j]); } } return(matrixE); } int main(void) { /* Variablen */ int matrix1[4][4] = {{0,2,1,0},{2,0,0,-1},{4,1,2,0},{1,1,-3,4}}; int matrix2[4][4] = {{-2,1,4,0},{1,1,-1,0},{1,2,0,0},{1,-3,3,2}}; int matrixE[4][4]; int i, j,result=1; /* Berechnung */ matrixE = mAddierer(matrix1,matrix2,4,4); //Hier gibt es eine Fehlermeldung /* Ausgabe */ for(i=0; i<4; i++) { for(j=0; j<4; j++) { printf("%3d; ",matrixE[i][j]); } printf("\n"); } return(0); }
Ich habe schon etwas rumprobiert, aber ich glaube, dass ich irgendwas Wichtiges nicht beachte.
Danke schonmal für die Hilfe.
-
LRinser schrieb:
Ich habe schon etwas rumprobiert, aber ich glaube, dass ich irgendwas Wichtiges nicht beachte.
Recht hast du.
-
Nunja, der Typ von
int matrix1[4][4]
ist leider nichtint **
.
Eine genauere Erklärung findest du hier: http://www.cplusplus.com/doc/tutorial/arrays/Konkret heisst das, du musst von den mehrdimensionalen Arrays auf einfache Pointer umsteigen.
Wenn ich mich nicht irre, sieht das dann etwa so aus:
int* mAddierer(int* matrix1, int* matrix2, int breite, int hoehe) { int *matrixE = malloc(breite*hoehe); int i, j; for(i=0; i<breite; i++) { for(j=0; j<hoehe; j++) { matrixE[i*breite+j] = (matrix1[i*breite + j] + matrix2[i*breite + j]); } } return matrixE; } int main() { /* Variablen */ int matrix1[4][4] = {{0,2,1,0},{2,0,0,-1},{4,1,2,0},{1,1,-3,4}}; int matrix2[4][4] = {{-2,1,4,0},{1,1,-1,0},{1,2,0,0},{1,-3,3,2}}; int *matrixE; int i, j,result=1; /* Berechnung */ matrixE = mAddierer(&matrix1[0][0], &matrix2[0][0],4,4); //Hier gibt es keine Fehlermeldung mehr /* Ausgabe */ for(i=0; i<4; i++) { for(j=0; j<4; j++) { printf("%3d; ",matrixE[i*4+j]); } printf("\n"); } return 0; }
-
Dein Hauptproblem ist wohl, daß das Ergebnis-Array lokal in der Funktion existiert und bei deren Rückkehr wieder beseitigt wird. Außerdem ist dieses "**-Bla", wie du es nennst, schon nicht richtig - die implizite Umwandlung von Arrays nach Zeigern funktioniert nur in einer Dimension.
Du mußt dich schon selber um die Bereitstellung und Freigabe der Speicherbereiche kümmern, die du verwenden willst - dazu gibt es bei C die Funktionen malloc() und free(). Und zum Thema Matrix-Rechnungen solltest du lieber eine vorgefertigte Bibliothek verwenden anstatt etwas selber zu basteln.
PS: Wenn du einen Fehler hast, kannst du auch dazuschreiben, welchen
-
LRinser schrieb:
matrixE = mAddierer(matrix1,matrix2,4,4); //Hier gibt es eine Fehlermeldung
Die Fehlermeldung ist korrekt. In C kann man keine Zuweisung an ein Array machen.
Hier eine ANSI C Lösungsvariante, deine ist bloß C99.
int** mAddierer(int (* matrix1)[4], int (* matrix2)[4], int breite, int hoehe, int (*matrixE)[4]) { int i, j; for(i=0; i<breite; i++) { for(j=0; j<hoehe; j++) { matrixE[i][j] = (matrix1[i][j] + matrix2[i][j]); } } return(matrixE); } int main(void) { /* Variablen */ int matrix1[4][4] = {{0,2,1,0},{2,0,0,-1},{4,1,2,0},{1,1,-3,4}}; int matrix2[4][4] = {{-2,1,4,0},{1,1,-1,0},{1,2,0,0},{1,-3,3,2}}; int ergebnis[4][4], (*matrixE)[4] = mAddierer(matrix1,matrix2,4,4,ergebnis); int i, j,result=1; /* Ausgabe */ for(i=0; i<4; i++) { for(j=0; j<4; j++) { printf("%3d; ",matrixE[i][j]); } printf("\n"); } return(0); }
-
C macht es einem echt nicht leicht.
Ich werd mich damit noch weiter auseinandersetzen, aber ich danke euch für die Hinweise und Ratschläge.
-
Moin,
hier noch eine ungetestete Lösung für die Addition einer 4x4 Matrix, vielleicht ist die etwas leichter zu lesen:
void mat_add(int a[][4], int b[][4], int c[][4]) { int i, j; for(i=0; i<4; ++i) { for(j=0; j<4; ++j) { c[i][j] = a[i][j] + b[i][j]; } } }
Gruß Chris
-
Wutz schrieb:
Hier eine ANSI C Lösungsvariante, deine ist bloß C99.
C99 ist ein ISO-Standard, der 2000 auch von der ANSI übernommen wurde. C99 ist ANSI-C. Das Problem ist nur, dass Microsoft sich bis heute nicht bequemt hat, selbigen zu implementieren.
Wie dem auch sei, aufgrund der Garantien, die der C-Standard (auch schon C90) über das Speicherlayout von Arrays macht, kann man in diesem Fall Arrays sämtlicher Layouts über einen Kamm scheren. Etwa
#include <stdio.h> #include <stddef.h> void array_add(int *dest, int *lhs, int *rhs, size_t len) { size_t i; for(i = 0; i < len; ++i) { dest[i] = lhs[i] + rhs[i]; } } int main(void) { int matrix1[4][4] = { { 0, 2, 1, 0 }, { 2, 0, 0, -1 }, { 4, 1, 2, 0 }, { 1, 1, -3, 4 } }; int matrix2[4][4] = { { -2, 1, 4, 0 }, { 1, 1, -1, 0 }, { 1, 2, 0, 0 }, { 1, -3, 3, 2 } }; int matrixE[4][4]; size_t i, j; array_add((int*) matrixE, (int*) matrix1, (int*) matrix2, 4 * 4); for(i = 0; i < 4; ++i) { for(j = 0; j < 4; ++j) { printf("%3d; ", matrixE[i][j]); } putchar('\n'); } return 0; }
Der Cast bei der Parameterübergabe ist nicht besonders hübsch, aber es ist besser, als für jede Matrizengröße die gewollten Funktionen wieder neu schreiben zu müssen. Wenn dein Compiler C99 beherrscht (d.h. ein anderer ist als MSVC), kannst du auch Folgendes machen:
#include <stdio.h> #include <stddef.h> void matrix_add(size_t breite, size_t hoehe, int (*dest)[breite], int(*lhs)[breite], int(*rhs)[breite]) { size_t i, j; for(i = 0; i < hoehe; ++i) { for(j = 0; j < breite; ++j) { dest[i][j] = lhs[i][j] + rhs[i][j]; } } } int main(void) { int matrix1[4][4] = { { 0, 2, 1, 0 }, { 2, 0, 0, -1 }, { 4, 1, 2, 0 }, { 1, 1, -3, 4 } }; int matrix2[4][4] = { { -2, 1, 4, 0 }, { 1, 1, -1, 0 }, { 1, 2, 0, 0 }, { 1, -3, 3, 2 } }; int matrixE[4][4]; size_t i, j; matrix_add(4, 4, matrixE, matrix1, matrix2); for(i = 0; i < 4; ++i) { for(j = 0; j < 4; ++j) { printf("%3d; ", matrixE[i][j]); } putchar('\n'); } return 0; }
Aber wie gesagt, MSVC kann das bislang nicht, und MS hat auch keine Pläne, das nachzuholen. Inwieweit dich das tangiert, musst du selbst entscheiden.
-
Deine Funktion zur Matrixaddition könnte man in C99 auch so schreiben, oder?
void matrix_add(size_t breite, size_t hoehe, int dest[][breite], int lhs[][breite], int rhs[][breite]) { size_t i, j; for(i = 0; i < hoehe; ++i) { for(j = 0; j < breite; ++j) { dest[i][j] = lhs[i][j] + rhs[i][j]; } } }
-
Ja, kann man. Sieht eigentlich auch hübscher aus.
Womöglich wäre es sogar hilfreich,
void array_add(size_t breite, size_t hoehe, int dest[hoehe][breite], int lhs [hoehe][breite], int rhs [hoehe][breite]) { size_t i, j; for(i = 0; i < hoehe; ++i) { for(j = 0; j < breite; ++j) { dest[i][j] = lhs[i][j] + rhs[i][j]; } } }
zu schreiben. Ich weiß nicht, ob es Compiler gibt, die dadurch bessere Warnungen auswerfen, wenn man etwa zu kleine Arrays in die Funktion wirft oder Grenzen in zur Compilezeit feststellbarer Weise überschreitet (gcc tut das bislang nicht), aber so was kann ja durchaus noch kommen.