Hilfe bei Matrixmultiplikation in C als Funktion



  • Allerdings kennt die main Funktion ja die Variablen h1.. etc nicht, was die Eingabe in dieser Form, also mit den bisherigen for-Schleifen, nicht möglich macht.
    Dasselbe mit den a1 a2 etc in der Nebenfunktion.
    Deine Kritik ist natürlich super sinnvoll, mich ärgert nur gerade dass ich ziemlichen Mist fabriziert hab.
    Aber dann bräuchte ich doch quasi die doppelte Anzahl von Variablen, oder?



  • Broetchen93 schrieb:

    Allerdings kennt die main Funktion ja die Variablen h1.. etc nicht, was die Eingabe in dieser Form, also mit den bisherigen for-Schleifen, nicht möglich macht.
    Dasselbe mit den a1 a2 etc in der Nebenfunktion.
    Deine Kritik ist natürlich super sinnvoll, mich ärgert nur gerade dass ich ziemlichen Mist fabriziert hab.
    Aber dann bräuchte ich doch quasi die doppelte Anzahl von Variablen, oder?

    Du kannst der Funktion einfach noch weitere Parameter übergeben.
    Statt h1, h2, h3, a1, a2, b1, b2 wäre es einfacher h[3], a[2] und b[2] zu übergeben.



  • Da du wieder ein Array aus der Funktion zurück haben willst und dies in C so nicht möglich ist, übergibt man das Array mit an die Funktion.
    Zudem muss di Funktion noch die Dimensionen der Matrizen wissen.

    int multiplikation(int ergebnis[10][10], int matrix1[10][10],int matrix2[10][10], int b1, int h1, int b2, int h2){
    ....
    

    Dann gehören auch

    int h1,h2,h3,b.....;
    int ergebnis[10][10];
    

    noch mit in main .

    Genauso kannst du eine Funktion

    int matrix_eingabe(int matrix[10][10], int b, int h, char text[]){
      printf("Elemente der %s Matrix eingeben(v.l.n.r.)", text);
    ....
    

    für die Eingabe machen

    Aufruf ist einfach:

    matrix_eingabe(matrix1, b1, h1, "1.");
    matrix_eingabe(matrix2, b2, h2, "2.");
    


  • DirkB schrieb:

    Da du wieder ein Array aus der Funktion zurück haben willst und dies in C so nicht möglich ist

    Oder man definiert es in der Funktion als static und gibt die Adresse zurück.


  • Mod

    Bitmapper schrieb:

    DirkB schrieb:

    Da du wieder ein Array aus der Funktion zurück haben willst und dies in C so nicht möglich ist

    Oder man definiert es in der Funktion als static und gibt die Adresse zurück.

    😮

    Bloß nicht Zuhause nachmachen!



  • So, ich habe teil a jetzt fertig!
    Jetzt hab ich heute keine Lust mehr auf Teil B, wo ich Zugriff und durchführung der Rechnung mit Pointerarithmetik umsetzen muss.
    Das kommt dann frühestens morgen.

    Ich bedanke mich vielmals für eure Hilfe, auf jeden Fall habe ich die Geschichte mit den Funktionen verstanden.
    Programmieren ist halt echt wie ne eigene Sprache



  • Hallo nochmal, bin gerade bei Aufgabenteil b, bei dem ich nun Zuweisung und Multiplikation per Pointerarithmetik umsetzen soll.
    Hier erstmal mein fertiges Programm aus Teilaufgabe a:

    #include <stdio.h>
    #include <stdlib.h>
    
    int multiplikation(int matrix1[10][10],int matrix2[10][10],int a1, int b1, int b2){
    	int h1,h2,h3,Summe=0;
    	int ergebnis[10][10];
    	for (h1 = 0; h1 < a1; h1++){
    				for (h2 = 0; h2 < b2; h2++){
    					for (h3 = 0; h3 < b1; h3++){
    						Summe = Summe + matrix1[h1][h3]*matrix2[h3][h2];
    					}
    				ergebnis[h1][h2] = Summe;
    				Summe = 0;
    				}
    			}
    			for (h1 = 0; h1 < a1; h1++) {
    				for (h2 = 0; h2 < b2; h2++){
    					printf("%i\t", ergebnis[h1][h2]);
    				      }
    				printf("\n");
    				}
    	return 0;
    }
    
    int main(void){
    	int a1,a2,b1,b2;
    	int h1,h2;
    	int matrix1[10][10], matrix2[10][10];
    	printf("Zeilen der ersten Matrix angeben:");
    	scanf("%i",&a1);
    	printf("Spalten der ersten Matrix angeben:");
    	scanf("%i",&a2);
    	printf("Zeilen der zweiten Matrix angeben:");
    	scanf("%i",&b1);
    	printf("Spalten der zweiten Matrix angeben:");
    	scanf("%i",&b2);
    	if (a2!=b1){
    		printf("Die Matrizen k�nnen nicht multipliziert werden!\n");
    	}
    	printf("Elemente der ersten Matrix eingeben(v.l.n.r.)");
    				for (h1 = 0; h1 < a1; h1++){
    				    for (h2 = 0; h2 < a2; h2++){
    				    	scanf("%i", &matrix1[h1][h2]);
    				    }
    				}
    				printf("Elemente der zweiten Matrix eingeben(v.l.n.r.)");
    				for (h1 = 0; h1 < b1; h1++){
    					for (h2 = 0; h2 < b2; h2++){
    						scanf("%i", &matrix2[h1][h2]);
    					}
    				}
    	multiplikation(matrix1, matrix2,a1,b1,b2);
    return 0;
    }
    

    Nun das, was ich bereits für Teilaufgabe b abgeändert habe:

    #include <stdio.h>
    #include <stdlib.h>
    
    int *multiplikation(int *matrix1,int *matrix2,int *a1, int *b1, int *b2){
    	int *h1,*h2,*h3,*Summe;
    	int *ergebnis;
    	for (h1 = 0; h1 < a1; h1++){
    				for (h2 = 0; h2 < b2; h2++){
    					for (h3 = 0; h3 < b1; h3++){
    						*Summe = *Summe + *matrix1**matrix2;
    					}
    				*ergebnis = *Summe;
    				Summe = 0;
    				}
    			}
    			for (h1 = 0; h1 < a1; h1++) {
    				for (h2 = 0; h2 < b2; h2++){
    					printf("%i\t", *ergebnis);
    				      }
    				printf("\n");
    				}
    	return 0;
    }
    
    int main(void){
    	int a1,a2,b1,b2;
    	int h1,h2;
    	int matrix1[10][10], matrix2[10][10];
    	printf("Zeilen der ersten Matrix angeben:");
    	scanf("%i",&a1);
    	printf("Spalten der ersten Matrix angeben:");
    	scanf("%i",&a2);
    	printf("Zeilen der zweiten Matrix angeben:");
    	scanf("%i",&b1);
    	printf("Spalten der zweiten Matrix angeben:");
    	scanf("%i",&b2);
    	if (a2!=b1){
    		printf("Die Matrizen k�nnen nicht multipliziert werden!\n");
    	}
    	printf("Elemente der ersten Matrix eingeben(v.l.n.r.)");
    				for (h1 = 0; h1 < a1; h1++){
    				    for (h2 = 0; h2 < a2; h2++){
    				    	scanf("%i", &matrix1[h1][h2]);
    				    }
    				}
    				printf("Elemente der zweiten Matrix eingeben(v.l.n.r.)");
    				for (h1 = 0; h1 < b1; h1++){
    					for (h2 = 0; h2 < b2; h2++){
    						scanf("%i", &matrix2[h1][h2]);
    					}
    				}
    	multiplikation(*matrix1, *matrix2,*a1,*b1,*b2);
    return 0;
    }
    

    In Zeile 54 kommt nun die Fehlermeldung: "Ungültiger Argumenttyp in unärem >*<(haben int)

    Aber ich habe doch nur Pointer, die auf eine Variable mit dem Typ int zeigen.



  • Nein hast du nicht. a1 etc sind doch ints.



  • Das heisst, ich muss quasi für jede Variable noch zusätzlich Pointervariablen festlegen?



  • Broetchen93 schrieb:

    Das heisst, ich muss quasi für jede Variable noch zusätzlich Pointervariablen festlegen?

    Für Die Dimension nicht, die kannst du auch weiter als int benutzen.

    Zudem ist die Multiplikation ziemlich sinnfrei, wenn du das Ergebnis nicht aus der Funktion raus bekommst.

    Mit matrix1[h1][h3] greifst du auf die verschiedenen Elemente der Arrays zu.

    Wie machst du das in deiner Pointerversion?
    (Füge ruhig mal ein paar printf in die Schleife ein, und gib ein paar Variablen aus.



  • Zudem ist die Multiplikation ziemlich sinnfrei, wenn du das Ergebnis nicht aus der Funktion raus bekommst.

    Hast du recht, aber ich schaffe es anders nicht. Funktionieren tut es ja.
    Also für die Matrizen muss ich dann Pointer festlegen, die auf die Adresse der Matrize zeigen? z.b. sowas wie int *pM1[10] [10] ?
    Aber dann muss man den Pointer doch auch noch zusätzlich irgendwie hochzählen, oder? Und woher weiss der Pointer, dass er auf Matrix1 zeigen soll und nicht auf Matrix2?



  • Win 2D-Array ist ein zusammenhängender Speicherbereich, bei dem der ganze rechte Index am schnellsten wechselt.

    Wenn du ein 2D-Array hast (int matrix[ZEILEN][SPALTEN]), dann kannst du auf die Elemente über einen Zeiger (*int zeigeraufint) zugreifen, der auf den Anfang vom Speicher zeigt.
    Dazu musst du wissen, wieviel Spalten das Array hat:

    matrix[z][s] ist dabei äquvalent zu *(zeigeraufint + z * SPALTEN + s)



  • Okay, vielen Dank für eure Hilfestellungen, aber ich checks gerade gar nicht.
    Das, was ich davor gemacht habe, war auch nur Stückwerk, weil ich einfach überall nen Pointersymbol vorgeschrieben habe.
    Ich versuchs jetzt mal ganz von vorne, vielleicht kommt ja was dabei heraus.



  • Ich bin schon wieder einen Schritt vorwärts gekommen.
    Jetzt habe ich die Funktion Zeiger auf Matrix1 und Matrix2 anfordern lassen.

    int multiplikation(int (*m1)[10],int (*m2)[10],int *a1, int *b1, int *b2){
    	int h1,h2,h3,Summe=0;
    	int ergebnis[10][10];
    	for (h1 = 0; h1 < *a1; h1++){
    				for (h2 = 0; h2 < *b2; h2++){
    					for (h3 = 0; h3 < *b1; h3++){
    						Summe = Summe + (*m1)[10]*(*m2)[10];
    					}
    				ergebnis[h1][h2] = Summe;
    				Summe = 0;
    				}
    			}
    			for (h1 = 0; h1 < *a1; h1++) {
    				for (h2 = 0; h2 < *b2; h2++){
    					printf("%i\t", ergebnis[h1][h2]);
    				      }
    				printf("\n");
    				}
    	return 0;
    }
    
    int main(void){
    	int a1,a2,b1,b2;
    	int h1,h2;
    	int matrix1[10][10], matrix2[10][10];
    	printf("Zeilen der ersten Matrix angeben:");
    	scanf("%i",&a1);
    	printf("Spalten der ersten Matrix angeben:");
    	scanf("%i",&a2);
    	printf("Zeilen der zweiten Matrix angeben:");
    	scanf("%i",&b1);
    	printf("Spalten der zweiten Matrix angeben:");
    	scanf("%i",&b2);
    	if (a2!=b1){
    		printf("Die Matrizen k�nnen nicht multipliziert werden!\n");
    	}
    	printf("Elemente der ersten Matrix eingeben(v.l.n.r.)");
    				for (h1 = 0; h1 < a1; h1++){
    				    for (h2 = 0; h2 < a2; h2++){
    				    	scanf("%i", &matrix1[h1][h2]);
    				    }
    				}
    				printf("Elemente der zweiten Matrix eingeben(v.l.n.r.)");
    				for (h1 = 0; h1 < b1; h1++){
    					for (h2 = 0; h2 < b2; h2++){
    						scanf("%i", &matrix2[h1][h2]);
    					}
    				}
    	multiplikation(matrix1, matrix2,*a1,*b1,*b2);
    return 0;
    }
    

    Jetzt scheint wider was bei der Übergabe falsch zu sein. Es erscheint dieselbe Fehlermeldung wie vorhin.



  • Broetchen93 schrieb:

    ..., weil ich einfach überall nen Pointersymbol vorgeschrieben habe.

    So geht es nicht.
    Du musst schon wissen, was da passiert.

    Warum sind a1, b1, b2 in multiplikation Pointer?

    Warum dereferenzierst du a1, b1, b2 in main beim Aufruf von multiplikation, obwohl es einfach int sind?

    Wie bist du auf (*m1)[10] gekommen (das ist richtig) , wenn der Rest so verkehrt ist?



  • Broetchen93 schrieb:

    Zudem ist die Multiplikation ziemlich sinnfrei, wenn du das Ergebnis nicht aus der Funktion raus bekommst.

    Hast du recht, aber ich schaffe es anders nicht. Funktionieren tut es ja.

    Was heißt "anders"?
    Da funktioniert überhaupt nichts.
    Du kannst das Ergebnis nicht verwenden und das sollte selbst dir als Anfänger klar sein, dass das Schrott ist; Note 6, setzen.
    Höre auf rumzufrickeln und übernehme die konkreten gegebenen Hinweise;
    was fragst du überhaupt hier im Forum wenn du die Hinweise nicht übernimmst?
    Hinweis:

    int multiplikation(int ergebnis[10][10], int matrix1[10][10],int matrix2[10][10], int b1, int h1, int b2, int h2){
    ....
    


  • Was heißt "anders"? 
    Da funktioniert überhaupt nichts. 
    Du kannst das Ergebnis nicht verwenden und das sollte selbst dir als Anfänger klar sein, dass das Schrott ist; Note 6, setzen. 
    Höre auf rumzufrickeln und übernehme die konkreten gegebenen Hinweise; 
    was fragst du überhaupt hier im Forum wenn du die Hinweise nicht übernimmst?
    

    Du hast natürlich recht, ich habe viele Hilfestellungen einfach übergangen.
    Deswegen springe ich jetzt auch noch einen Schritt zurück.
    Den Programmcode der Teilaufgabe a habe ich nun abgeändert.

    int multiplikation(int matrix1[10][10],int matrix2[10][10],int ergebnis[10][10],int a1,int b1, int b2,int h1, int h2, int Summe){
    	int h3;
    	for (h1 = 0; h1 < a1; h1++){
    				for (h2 = 0; h2 < b2; h2++){
    					for (h3 = 0; h3 < b1; h3++){
    						Summe = Summe + matrix1[h1][h3]*matrix2[h3][h2];
    					}
    				ergebnis[h1][h2] = Summe;
    				Summe = 0;
    				}
    			}
    	return ergebnis[10][10];
    }
    

    Das ist nur die Funktion, in der ich allerdings immernoch die Variable h3 deklariert habe, da ich diese in der Hauptfunktion ja gar nicht brauche.
    Der Rest wird aus dem main übergeben. Die Ausgabefunktion findet auch dort statt.

    int main(void){
    	int a1,a2,b1,b2;
    	int h1,h2,Summe=0;
    	int matrix1[10][10], matrix2[10][10],ergebnis[10][10];
    	printf("Zeilen der ersten Matrix angeben:");
    	scanf("%i",&a1);
    	printf("Spalten der ersten Matrix angeben:");
    	scanf("%i",&a2);
    	printf("Zeilen der zweiten Matrix angeben:");
    	scanf("%i",&b1);
    	printf("Spalten der zweiten Matrix angeben:");
    	scanf("%i",&b2);
    	if (a2!=b1){
    		printf("Die Matrizen k�nnen nicht multipliziert werden!\n");
    	}
    	printf("Elemente der ersten Matrix eingeben(v.l.n.r.)");
    				for (h1 = 0; h1 < a1; h1++){
    				    for (h2 = 0; h2 < a2; h2++){
    				    	scanf("%i", &matrix1[h1][h2]);
    				    }
    				}
    				printf("Elemente der zweiten Matrix eingeben(v.l.n.r.)");
    				for (h1 = 0; h1 < b1; h1++){
    					for (h2 = 0; h2 < b2; h2++){
    						scanf("%i", &matrix2[h1][h2]);
    					}
    				}
    	multiplikation(matrix1,matrix2,ergebnis,a1,b1,b2,h1,h2,Summe);
    	for (h1 = 0; h1 < a1; h1++) {
    					for (h2 = 0; h2 < b2; h2++){
    						printf("%i\t", ergebnis[h1][h2]);
    					      }
    					printf("\n");
    					}
    return 0;
    }
    

    So, zur nächsten Teilaufgabe:

    ..., weil ich einfach überall nen Pointersymbol vorgeschrieben habe.

    So geht es nicht.
    Du musst schon wissen, was da passiert.

    Absolut, das war bloß ein Versuch.

    Wie bist du auf (*m1)[10] gekommen (das ist richtig) , wenn der Rest so verkehrt ist?

    Das übernahm ich aus dem Skript, wo ein ähnliches Beispiel behandelt wurde.
    So. Die Übergabe und die Berechnung sollen also per Pointerarithmetik umgesetzt werden.
    So wie ich das verstanden habe, zeigt int (*m1)[10] auf den Anfang einer Matrix der Dimension 10 mit Datentyp int. Das gleiche eben für die anderen beiden int (*m2)[10] und int (*e)[10].
    Ich übergebe immernoch matrix1,matrix2 und ergebnis. Also auf deren [0][0] "Koordinate" wird quasi gezeigt.



  • Wofür ist denn Summe als Paramter von multiplikation?.
    Wenn der Wert ungleich 0 ist, kommt Müll raus.

    Laut http://cdecl.org ist *int (m2)[10] "declare m2 as pointer to array 10 of int"
    Also ein Zeiger auf ein Array aus 10 int.

    Die Benutzung ist innerhalb der Funktion auch nich anders als mit Arrayschreibweise.
    m2[0] ist die erste Zeile
    m2[3] ist die vierte Zeile
    m2[0][3] ist das 4. Element in der 1. Zeile

    Warum hatte ich ergebnis als ersten Paramter stehen?
    Nun, in der C-Standardlibrary ist das so üblich, dass das Ziel zuerst kommt. (strcpy, memcpy, fgets, )
    Es soll etwas die Reihenfolge der Gleichung nachbilden. Da steht ergebnis auch links ( ergebnis = m1 * m2 )
    😉



  • also auf die einzelnen Elemente einer Matrix greifst du z.B. so zu:

    *(matrix+zeile*anzahl_spalten+spalte)=wert;
    

    das 1. Element in der 1. Spalte ist also *(matrix+0), das zweite *(matrix+1).
    das 1. Element in der 2. spalte *(matrix+1*anzahlspalten+0), also bei einer Matrix mit 10 Spalten *(matrix+10) usw.

    vereinfacht gesagt zeigt *matrix auf das 1. Element und *(matrix+x) auf das x-te Element, den Rest machen dann die Kenntnisse der Mathematik.



  • HansKlaus schrieb:

    also auf die einzelnen Elemente einer Matrix greifst du z.B. so zu:

    *(matrix+zeile*anzahl_spalten+spalte)=wert;
    

    das 1. Element in der 1. Spalte ist also *(matrix+0), das zweite *(matrix+1).
    das 1. Element in der 2. spalte *(matrix+1*anzahlspalten+0), also bei einer Matrix mit 10 Spalten *(matrix+10) usw.

    vereinfacht gesagt zeigt *matrix auf das 1. Element und *(matrix+x) auf das x-te Element, den Rest machen dann die Kenntnisse der Mathematik.

    Dann soltest du auch dazu schreiben, wie matrix definiert ist.
    Nur so viel: *int (matrix)[10] ist es nicht.

    ^(Im Übrigen hatte ich das auch schon geschrieben.)^


Anmelden zum Antworten