Programm zum multiplizieren 2er Matrizen mit Arrays und Funktionen



  • Hallo Forum,

    ich habe die Aufgabe, ein Programm zu schreiben, welches Matrizenmultiplikation macht und möchte daher 3 Matrizen definieren, ich dachte mir ich definiere sie 2-dimensional mit matrix[][], da gibt mir der Compiler jedoch einen fehler anscheinend akzeptiert er nur 1-dimensionale arrays?

    Das nächste Problem ist, dass wir alles mit Funktionen machen müssen und hier habe ich die Frage, wie übergebe ich sinnvollerweise ein 2-d array an eine funktion und wie kann ich dieses array innerhalb der Funktion dann manipulieren (damit rechnen)?

    also wenn ich zb definiere:

    #define Zeilenzahl 3
    #define Spaltenzahl 4
    int matrix1[Zeilenzahl][Spaltenzahl[];
    int *zeigermatrix1=&matrix1[0][0];

    void funktion(int *zeigermatrix1)
    for(int i=0;i<Zeilenzahl;i++)
    for(int u=0;u<Spaltenzahl;u++)
    scanf("%i", zeigermatrix1+i+u);

    int main()
    {
    funktion(zeigermatrix1);
    }

    würde das stimmen, um per Funktion eine 2-d matrix einzulesen? so, dass ich mit dieser dann auch rechnen kann? Also wird der Wert dann in die Originalmatrix geschrieben?

    Vielen Dank im voraus!


  • Mod

    Prüf doch noch mal, ob alle Klammern einen öffnenden und einen schließenden Partner haben.

    Du benutzt derzeit recht sinnlos globale Variablen. Damit wirst du später Schwierigkeiten bekommen.

    Du nennst eine Funktion "funktion". Wirklich?

    Wäre es nicht schöner, wenn diese Funktion nicht von globalen defines abhängen würde? Dann würdest du auch besser lernen, mit 2D-Arrays umzugehen.

    würde das stimmen, um per Funktion eine 2-d matrix einzulesen?

    Nein. Probier's doch aus!

    so, dass ich mit dieser dann auch rechnen kann?

    Probier's doch aus! Es wäre schon ein komischer Vorgang, wenn das Einlesen spätere Berechnungen verhindert.

    Also wird der Wert dann in die Originalmatrix geschrieben?

    Ja. Probier's doch aus!



  • mein eigentlicher code ist der hier (nur zum teil kopiert bis zur ersten funktion:)

    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define ZEILENZAHL1 4
    #define SPALTENZAHL1 3
    #define ZEILENZAHL2 3
    #define SPALTENZAHL2 4
    #define ZEILENZAHL3 4
    #define SPALTENZAHL3 4
    
    void funktioneingabematrix1(int);    //drei integer werte, ein pointer für die array übergabe, 2 weitere int werte für ide größe der matrix
    void funktioneingabematrix2(int*,int,int);    //drei integer werte, ein pointer für die array übergabe, 2 weitere int werte für ide größe der matrix
    void funktionberechnungergebnismatrix(int*,int,int,int*,int,int,int*,int,int); //übergabe der 3 arrays jeweils mit den pointer und die 2 laufvariablen
    void funktionausgabeergebnismatrix(int*,int,int); //ein Zeiger und die 2 laufvariablen
    
    int main()
    {       //zum test auf 3x2 geändert, ursprünglich 4x3
      int matrix1[ZEILENZAHL1][SPALTENZAHL1], matrix2 [ZEILENZAHL2][SPALTENZAHL2], ergebnismatrix[ZEILENZAHL3][SPALTENZAHL3]; //matrizen 2 dimensional deklariert
      int *zeigermatrix1=&matrix1[0][0],*zeigermatrix2=&matrix2[0][0],*zeigerergebnismatrix=&ergebnismatrix[0][0];   //zeiger auf die matrizen, enthalten die adresse des ersten elements der jeweiligen matrix
    
      //Eingabe Matrix 1
      funktioneingabematrix1(matrix1[0][0]); //WICHTIGER KOMMENTAR: Anleitung zum Übergeben von Arrays an Funktion
      //Eingabe Matrix1 ENDE
    
      //Eingabe Matirx 2
      funktioneingabematrix2(zeigermatrix2,ZEILENZAHL2,SPALTENZAHL2);  //wichtig: das matrix mit der adresse auf das erste Element übergeben
      //Eingabe Matrix 2 ENDE
    
      //Berechnung ergebnismatrix
      funktionberechnungergebnismatrix(zeigerergebnismatrix,ZEILENZAHL3,SPALTENZAHL3, zeigermatrix1,ZEILENZAHL1,ZEILENZAHL2, zeigermatrix2,ZEILENZAHL2,SPALTENZAHL2);
      //Berechnung ergebnismatrix ENDE
    
      //Ausgabe ergebnismatrix
      funktionausgabeergebnismatrix(zeigerergebnismatrix,ZEILENZAHL3,SPALTENZAHL3);
      //Ausgabe ergebnismatrix ENDE
    
      getch();
      return 0;
    } 
    
                                                                                                                //WICHTIGER KOMMENTAR: Anleitung zum übergeben von arrays an funktion
    void funktioneingabematrix1(int matrix1) //pointer als übergabewert (enthält adresse der matrix entsprechend des aufrufes in der main funktion)
    {
      int zaehl1,zaehl2, counter=0;
      printf("Bitte geben Sie die erste Matrix ein\n");
      for(zaehl1=0;zaehl1<ZEILENZAHL1;zaehl1++)
          for(zaehl2=0;zaehl2<SPALTENZAHL1;zaehl2++)
             { 
               scanf("%i",&matrix1[zaehl1][zaehl2]);             //WICHTIGER KOMMENTAR: Anleitung zum übergeben von arrays an funktion
               counter++;
               if(counter==SPALTENZAHL1)
                  {
                      printf("\n");
                      counter=0;}
                  }
    
        counter=0;
    

    bei scanf schreibt man ja mit & an die adresse,

    ich wüsste nur gerne wie man das halt machen soll, nur ganz grob


  • Mod

    Ist das ein Witz? ~Wenn man fragen muss, ist er nicht besonders lustig.~



  • Lass mal die Texte "funktion" und "ZAHL" in deinem Code weg.
    Der Unterstrich _ gehört auch zu den gültigen Zeichen für Bezeichner.

    Die zeiger... Variablen in main sind sowas von überflüssig.

    Der Kommentar in funktioneingabematrix1 (mit dem Pointer) passt nicht zur Definition.

    Wenn dann matrix1 in funktioneingabematrix1 ein Pointer ist, kannst du damit eine Dimension ansprechen.
    Die zweite ist verloren.



  • Also ich bin jetzt (vielleicht 😕 ) etwas weitergekommen und es funktioniert insofern, dass ich schon die beiden matrizen eingeben kann und er berechnet dann auch was und gibt etwas aus, allerdings mit rechenfehler, der vollständige Code ist:

    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define ZEILENZAHL1 4
    #define SPALTENZAHL1 3
    #define ZEILENZAHL2 3
    #define SPALTENZAHL2 4
    #define ZEILENZAHL3 4
    #define SPALTENZAHL3 4
    
    void funktioneingabematrix1(int[][SPALTENZAHL1],int );   //hier wird das 2-d Array übergeben und der zweite int wert ist die zeilenzahl
    void funktioneingabematrix2(int[][SPALTENZAHL2],int);    //hier wird das 2-d Array übergeben und der zweite int wert ist die zeilenzahl
    void funktionberechnungergebnismatrix(int[][SPALTENZAHL3],int[][SPALTENZAHL1],int[][SPALTENZAHL2]); //übergabe der 3 arrays jeweils mit den pointer und die 2 laufvariablen
    void funktionausgabeergebnismatrix(int[][SPALTENZAHL3]); //ergebnismatrix wird übergeben
    
    int main()
    {       //zum test auf 3x2 geändert, ursprünglich 4x3
      int matrix1[ZEILENZAHL1][SPALTENZAHL1], matrix2 [ZEILENZAHL2][SPALTENZAHL2], ergebnismatrix[ZEILENZAHL3][SPALTENZAHL3]; //matrizen 2 dimensional deklariert
      //int *zeigermatrix1=&matrix1[0][0],*zeigermatrix2=&matrix2[0][0],*zeigerergebnismatrix=&ergebnismatrix[0][0];   //zeiger auf die matrizen, enthalten die adresse des ersten elements der jeweiligen matrix
    
      //Eingabe Matrix 1
      funktioneingabematrix1(matrix1,ZEILENZAHL1); //man muss der Funktion das array selbst und die Zeilenzahl (als laufparameter) übergeben
      //Eingabe Matrix1 ENDE
    
      //Eingabe Matirx 2
      funktioneingabematrix2(matrix2,ZEILENZAHL2);  //man muss der Funktion das array selbst und die Zeilenzahl (als laufparameter) übergeben
      //Eingabe Matrix 2 ENDE
    
      //Berechnung ergebnismatrix
      funktionberechnungergebnismatrix(ergebnismatrix, matrix1, matrix2);
      //Berechnung ergebnismatrix ENDE
    
      //Ausgabe ergebnismatrix
      funktionausgabeergebnismatrix(ergebnismatrix);
      //Ausgabe ergebnismatrix ENDE
    
      getch();
      return 0;
    } 
    
                                                                                                                //WICHTIGER KOMMENTAR: Anleitung zum übergeben von arrays an funktion
    void funktioneingabematrix1(int matrix1[][SPALTENZAHL1],int) //pointer als übergabewert (enthält adresse der matrix entsprechend des aufrufes in der main funktion)
    {
      int zaehl1,zaehl2, counter=0;
      printf("Bitte geben Sie die erste Matrix ein\n");
      for(zaehl1=0;zaehl1<ZEILENZAHL1;zaehl1++)
          for(zaehl2=0;zaehl2<SPALTENZAHL1;zaehl2++)
             { 
               scanf("%i",&matrix1[zaehl1][zaehl2]);             //WICHTIGER KOMMENTAR: Anleitung zum übergeben von arrays an funktion
               counter++;
               if(counter==SPALTENZAHL1)
                  {
                      printf("\n");
                      counter=0;
    		      }
             }
    
    }
    
    void funktioneingabematrix2(int matrix2[][SPALTENZAHL2],int) //pointer als übergabewert für das array und zeilen und spaltenzahl als 2 extra werte
    {
     int zaehl1,zaehl2, counter=0;
     printf("Bitte geben Sie die zweite Matrix ein\n");
      for(zaehl1=0;zaehl1<ZEILENZAHL2;zaehl1++)
          for(zaehl2=0;zaehl2<SPALTENZAHL2;zaehl2++)
          {
              scanf("%i",&matrix2[zaehl1][zaehl2]);  //m ist adresse der matrix, das element an zaehl1+zaehl2 -ter stelle wird angesprochen, da der Speicher alles nebeneinander (hintereinander) unabhängig von zeilen speichert
              counter++;
              if(counter==SPALTENZAHL2)
              {
                  printf("\n");
                  counter=0;
              }
          }
       counter=0;
    }
    
    void funktionberechnungergebnismatrix(int ergebnismatrix[][SPALTENZAHL3],int matrix1[][SPALTENZAHL1],int matrix2[][SPALTENZAHL2])
    {
    	int zaehl1,zaehl2, counter=0;
        for(zaehl1=0;zaehl1<ZEILENZAHL3;zaehl1++)
          for(zaehl2=0;zaehl2<SPALTENZAHL3;zaehl2++)																	  //an dieser stelle ändern für 4x3 matrix=
              ergebnismatrix[zaehl1][zaehl2]=matrix1[zaehl1][0]*matrix2[0][zaehl2]+matrix1[zaehl1][1]*matrix2[1][zaehl2]+matrix1[zaehl1][2]*matrix2[2][zaehl2];//+matrix1[zaehl1][2]*matrix2[2][zaehl2];   //statt
    		  //ergebnismatrix[zaehl1][zaehl2]=((*zeigermatrix1)+zaehl1)*((*zeigermatrix2)+zaehl2)+((*zeigermatrix1)+zaehl1+1)*((*zeigermatrix2)+1+zaehl2);
    }
    
    void funktionausgabeergebnismatrix(int ergebnismatrix[][SPALTENZAHL3])
    {
        int zaehl1,zaehl2, counter=0;
        printf("Die resultierende Matrix aus Matrix1 * Matrix 2 lautet: \n");
        for(zaehl1=0;zaehl1<ZEILENZAHL3;zaehl1++)
          for(zaehl2=0;zaehl2<SPALTENZAHL3;zaehl2++)
              {
                  printf("%i ", ergebnismatrix[zaehl1][zaehl2]);
                  counter++;
                  if(counter==SPALTENZAHL3)
                  {
                      printf("\n");
                      counter=0;}
              }
    
    }
    

    wenn ich die matrizen
    2 2 2
    2 2 2
    2 2 2
    2 2 2
    und
    4 4 4 4
    4 4 4 4
    4 4 4 4
    eingebe, kommt
    16 16 16 16
    16 16 16 16
    16 16 16 16
    16 16 16 16
    heraus, richtig wäre jedoch
    24 24 24 24
    24 24 24 24
    24 24 24 24
    24 24 24 24

    jetzt wollte ich nur fragen, ob das einfach ein rechenfehler ist, oder ob es was mit den schreiben/lesen/verwenden der arrays zu tun hat?

    beziehungsweise habe ich nun die arrays richtig definiert, übergeben und beschrieben?

    ** Die Kommentare sind nun alle falsch, bitte ignorieren **

    Liebe Grüße!


  • Mod

    Problem ist nicht nachvollziehbar.

    Übrigens nutzt du einen C++-Compiler für deinen C-Code. Tu das nicht!



  • Pures Fett schrieb:

    jetzt wollte ich nur fragen, ob das einfach ein rechenfehler ist, oder ob es was mit den schreiben/lesen/verwenden der arrays zu tun hat?

    Rechenfehler im Sinn von falscher Algorithmus.
    Rundungsfehler treten da nicht auf.

    Du rechnest 16 aus. möchtest aber 24 haben. Das ist eine Differenz von 8 (oder 2*4).
    Da hast du bei der Multiplikation wohl einen Summand vergessen.

    I.A. nimmt man drei verschachtelte Schleifen. Und da darfst du ruhig i,j,k als Zählvariablen nehmen, da das in der Mathematik üblich ist.
    https://de.wikipedia.org/wiki/Matrizenmultiplikation#Standardalgorithmus

    Pures Fett schrieb:

    ** Die Kommentare sind nun alle falsch, bitte ignorieren **

    Dann mach die mal richtig. Die falschen Kommentare lenken nur vom Wesentlichem ab.

    Zudem sind deine Bezeichner zu lang, um den Code flüssig lesen zu können.
    Statt funktioneingabematrix1 und funktioneingabematrix2
    etwa matrix_eingabe_1 und matrix_eingabe_2 bzw. später matrix_eingabe

    Und lass überflüsige Kommentare weg (Zeile 26 und 27)
    Du musst jede Zeile vom Programm nachvollziehen können.
    Dann findest du auch den Fehler.

    Wozu ist eigentlich der zweite Paramter in funktioneingabematrix1 da?
    Wenn der keinen Bezeichner hat, kannst du ihn nicht benutzen. Und somit ist er überflüssig.



  • Deine Berechnung war falsch, unsinnige Kommentare lösche lieber gleich, deine Variablennamen sind zu lang.

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define ZEILENZAHL1 4
    #define SPALTENZAHL1 3
    #define ZEILENZAHL2 3
    #define SPALTENZAHL2 4
    #define ZEILENZAHL3 4
    #define SPALTENZAHL3 4
    
    void funktioneingabematrix1(int[][SPALTENZAHL1],int);
    void funktioneingabematrix2(int[][SPALTENZAHL2],int);
    void funktionberechnungergebnismatrix(int[][SPALTENZAHL3],int[][SPALTENZAHL1],int[][SPALTENZAHL2]);
    void funktionausgabeergebnismatrix(int[][SPALTENZAHL3]);
    
    int main()
    {
      int matrix1[ZEILENZAHL1][SPALTENZAHL1],
      		matrix2 [ZEILENZAHL2][SPALTENZAHL2],
      		ergebnismatrix[ZEILENZAHL3][SPALTENZAHL3];
    
      funktioneingabematrix1(matrix1,ZEILENZAHL1);
    
      funktioneingabematrix2(matrix2,ZEILENZAHL2);
    
      funktionberechnungergebnismatrix(ergebnismatrix, matrix1, matrix2);
    
      funktionausgabeergebnismatrix(ergebnismatrix);
    
      return 0;
    }
    
    void funktioneingabematrix1(int matrix1[][SPALTENZAHL1],int z1)
    {
      int zaehl1,zaehl2, counter=0;
      printf("Bitte geben Sie die erste Matrix ein\n");
      for(zaehl1=0;zaehl1<z1;zaehl1++)
          for(zaehl2=0;zaehl2<SPALTENZAHL1;zaehl2++)
             {
               scanf("%i",&matrix1[zaehl1][zaehl2]);
               counter++;
               if(counter==SPALTENZAHL1)
                  {
                      printf("\n");
                      counter=0;
                  }
             }
    
    }
    
    void funktioneingabematrix2(int matrix2[][SPALTENZAHL2],int z2)
    {
     int zaehl1,zaehl2, counter=0;
     printf("Bitte geben Sie die zweite Matrix ein\n");
      for(zaehl1=0;zaehl1<z2;zaehl1++)
          for(zaehl2=0;zaehl2<SPALTENZAHL2;zaehl2++)
          {
              scanf("%i",&matrix2[zaehl1][zaehl2]);
              counter++;
              if(counter==SPALTENZAHL2)
              {
                  printf("\n");
                  counter=0;
              }
          }
       counter=0;
    }
    
    void funktionberechnungergebnismatrix(int e[][SPALTENZAHL3],int m1[][SPALTENZAHL1],int m2[][SPALTENZAHL2])
    {
        int zaehl1,zaehl2,x=0;
        for(zaehl1=0;zaehl1<ZEILENZAHL3;zaehl1++)
          for(zaehl2=0;zaehl2<SPALTENZAHL3;zaehl2++)
             for(e[zaehl1][zaehl2]=x=0;x<SPALTENZAHL1;++x)
                e[zaehl1][zaehl2]+=m1[zaehl1][x]*m2[x][zaehl2];
    }
    
    void funktionausgabeergebnismatrix(int ergebnismatrix[][SPALTENZAHL3])
    {
        int zaehl1,zaehl2, counter=0;
        printf("Die resultierende Matrix aus Matrix1 * Matrix 2 lautet: \n");
        for(zaehl1=0;zaehl1<ZEILENZAHL3;zaehl1++)
          for(zaehl2=0;zaehl2<SPALTENZAHL3;zaehl2++)
              {
                  printf("%i ", ergebnismatrix[zaehl1][zaehl2]);
                  counter++;
                  if(counter==SPALTENZAHL3)
                  {
                      printf("\n");
                      counter=0;}
              }
    
    }
    

    http://ideone.com/AH6tHu



  • Danke dir Wutz, das ist sehr hilfreich! 👍

    Um es nochmal in Worte zu fassen: man übergibt einfach die Adresse des ersten Elementes der Matrix an die Funktion, bei mehr als 1-D noch die Laufparameter und kann dann die Originalmatrix innerhalb der Funktion direkt ansteuern und muss das nicht über den Umweg mit Zeigern machen.

    Also mit funktion(int matrix[][spaltenzahl],int zeilenzahl)
    wird der funktion die Adresse des Ersten Elementes übergeben? wieso kann man eigentlich den laufparameter (zeilenzahl) nicht auch direkt übergeben:
    funktion(int matrix [zeilenzahl][spaltenzahl])?

    Man muss also die Matrix innerhalb der Funktion immer durchzählen, da nur die Adresse des ersten Elementes übergeben wird aber man kann die einzelnen Elemente dann direkt ansteuern und nicht über Zeiger, das hat mich verwirrt.

    Vielen Dank euch allen und insbesondere dir Wutz, ich werde nun noch weitere Programme mit Funktionen und Arrays schreiben ich denke ich bekomm es nun alleine hin 😉



  • Ein Array (egal welche Dimension) ist in C immer ein zusammenhängender Speicherplatz.
    Die Daten werden hintereinander im Speicher abgelegt, wobei der höchste Index am schnellsten wechselt.

    int a[12]     = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    
    int b1[2][6]  = { { 0, 1, 2, 3, 4, 5 }, // 2 Zeilen, 6 Spalten
                      { 6, 7, 8, 9, 10, 11 }};
    int b2[3][4]  = { { 0, 1, 2, 3 }, 
                      { 4, 5, 6, 7 }, 
                      { 8, 9, 10, 11 }};
    int b3[6][2]  = { { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }, { 8, 9 }, { 10, 11 }};
    
    int c[2][3][2]  = { {{ 0, 1 }, { 2, 3 },  { 4, 5 }}, 
                        {{ 6, 7 }, { 8, 9 },  { 10, 11}} };
    

    ergibt für jedes Array dasselbe Speicherbild.

    Deine Funktion bekommt jetzt die Adresse vom ersten Element geliefert.

    Wenn du bei der Definition der Funktion aber die Dimensionen mit angibst, ist deine Funktion sehr eingeschränkt, da sie nur für diese Art Arrays geht.

    Aber du kannst den Index bei Mehrdimensionalen Arrays auch selber berechnen, wenn du die Anzahl der Zeilen und Spalten kennst.

    Index = Zeile*Spalten + Spalte;

    Wie du siehst, spielt die Anzahl der Zeilen für die Berechnung keine Rolle.
    Darum kannst du den ersten Index bei der Definiton auch weglassen.

    Das gibt dann z.B für eine universelle 2D-Ausgabe:

    void matrix_print(int *matrix, int zeilen, int spalten)
    {
        int zeile, spalte;
    
        for(zeile=0;zeile<zeilen;zeile++)
          for(spalte=0;spalte<spalten;spalte++)
          {
            printf(" %3d", matrix[zeile*spalten + spalte]);
          }
          putchar('\n');          
    }
    

    Aufruf mit:

    matrix_print(&matrix1[0][0]       , ZEILENZAHL1, SPALTENZAHL1);
    matrix_print(&ergebnismatrix[0][0], ZEILENZAHL3, SPALTENZAHL3);
    

Log in to reply