C/C++ Programmierung

Aufgabe 11

Deklarieren Sie den Datentyp MATRIX als eine Struktur mit den Komponenten nRows und nCols als Anzahl der Zeilen und Spalten sowie pElmts als Zeiger auf ein (eindimensionales) Array von double-Werten. In diesem sollen die Elemente der Matrix zeilenweise (Elemente einer Zeile stehen direkt aufeinanderfolgend im Speicher) abgelegt werden.

Schreiben Sie darüberhinaus jeweils eine Funktion zum

Jede dieser Funktionen soll als ersten Parameter die Adresse einer Variablen vom Typ MATRIX bekommen.

Die Dimension soll jeweils vom Typ unsigned int sein.

Schreiben Sie dazu folgendes Hauptprogramm (die Parameter der einzelnen Funktionen gehen hieraus hervor):

#include <stdio.h>
/* ... */
int main(void)
{
  unsigned int rows, cols;
  MATRIX m1, m2, m3;
  printf("Zeilen, Spalten: "); scanf("%u,%u", &rows, &cols );
  mInit( &m1, rows, cols ); mInit( &m2, rows, cols ); mInit( &m3, rows, cols );
  mRand( &m1 ); mRead( &m2, stdin );
  mMul( &m3, &m1, &m2 ); /* m3 = m1 * m2 */
  mAdd( &m3, &m3, &m2 ); /* m3 = m3 + m2 */
  mWrite( &m3, stdout ); mFree( &m3 ); mFree( &m2 ); mFree( &m1 );
  return 0;
}

Lösung für die Aufgabe

#include <stdio.h>

/* Die Struktur der MATRIX */
struct MATRIX
{
  unsigned int nRows;
  unsigned int nCols;
  double *pElmts;
};

/*--------------------------------------------------------------------------*/

void mInit(struct MATRIX *matrix, unsigned int rows, unsigned int cols)
{
  if (!matrix) /* Ist der übergebene MATRIX-Pointer gleich NULL, */
    return;    /* dann die Funktion mInit() beenden.             */

  /* Speicher fuer die Elemente reservieren */
  matrix->pElmts = (double *)malloc(rows * cols * sizeof(double));
  if (!matrix->pElmts) /* wurde Speicher reserviert? */
  {
    printf("Es konnte nicht genug Speicher reserviert werden!\n");
    exit(1); /* Programm abbrechen */
  }
  matrix->nRows = rows; /* Rows in die Matrix-Struktur schreiben */
  matrix->nCols = cols; /* Cols in die Matrix-Struktur schreiben */
}

/*--------------------------------------------------------------------------*/

void mFree(struct MATRIX *matrix)
{
  if (matrix && matrix->pElmts) /* Ist die Matrix und der Elmts-Pointer der Matrix ungleich NULL? */
  {
    free(matrix->pElmts); /* Speicher freigeben */
    matrix->pElmts = NULL;
  }
}

/*--------------------------------------------------------------------------*/

void mResize(struct MATRIX *matrix, unsigned int rows, unsigned int cols)
{
  mFree(matrix); /* Funktion mFree() aufrufen */
  mInit(matrix, rows, cols); /* Funktion mInit() aufrufen */
}

/*--------------------------------------------------------------------------*/

void mRand(struct MATRIX *matrix)
{
  unsigned int rows,cols;

  if (!matrix && !matrix->pElmts) /* Ist die Matrix und der Elmts-Pointer der Matrix ungleich NULL? */
    return;                       /* sonst die Funktion mRand() beenden */

  for (rows = 0; rows < matrix->nRows; rows++) /* alle Zeilen durchgehen */
  {
    for (cols = 0; cols < matrix->nCols; cols++) /* Spalten der aktuellen Zeile durchgehen */
    {
      matrix->pElmts[(rows * matrix->nCols) + cols] = rand(); /* Random-Zahl ins aktuelle Element schreiben */
    }
  }
}

/*--------------------------------------------------------------------------*/

void mRead(struct MATRIX *matrix, FILE *file)
{
  unsigned int rows,cols;
  double dummy;

  if (!matrix) /* Ist der übergebene MATRIX-Pointer gleich NULL, */
    return;    /* dann die Funktion mRead() beenden.             */

  for (rows = 0; rows < matrix->nRows; rows++) /* alle Zeilen durchgehen */
  {
    for (cols = 0; cols < matrix->nCols; cols++) /* Spalten der aktuellen Zeile durchgehen */
    {
      printf("Zeile: %u, Spalte: %u = ", rows + 1, cols + 1);
      fscanf(file, "%lf", &dummy);                           /* Zahl in einen Dummy schreiben */
      matrix->pElmts[(rows * matrix->nCols) + cols] = dummy; /* dummy jetzt in das aktuelle Element schreiben */
    }
  }
}

/*--------------------------------------------------------------------------*/

void mWrite(struct MATRIX *matrix, FILE *file)
{
  unsigned int rows,cols;

  if (!matrix) /* Ist der übergebene MATRIX-Pointer gleich NULL, */
    return;    /* dann die Funktion mWrite() beenden.            */

  for (rows = 0; rows < matrix->nRows; rows++) /* alle Zeilen durchgehen */
  {
    for (cols = 0; cols < matrix->nCols; cols++) /* Spalten der aktuellen Zeile durchgehen */
    {
      if (matrix->nCols < 6)
        fprintf(file, "%12e  ", matrix->pElmts[(rows * matrix->nCols) + cols]); /* ausgeben vom aktuellen Element */
      else
        fprintf(file, "Zeile: %u, Spalte: %u = %12e\n", rows, cols, matrix->pElmts[(rows * matrix->nCols) + cols]); /* ausgeben vom aktuellen Element */
    }
    fprintf(file,"\n");
  }
}

/*--------------------------------------------------------------------------*/

void mAdd(struct MATRIX *dest, struct MATRIX *source1, struct MATRIX *source2)
{
  unsigned int rows,cols;

  if (!source1 || !source2 || !dest) /* Ist einer der übergebenen MATRIX-Pointer gleich NULL? */
    return;                          /* dann Funktion mAdd() beenden                          */

  for (rows = 0; rows < source1->nRows; rows++) /* alle Zeilen durchgehen */
  {
    for (cols = 0; cols < source1->nCols; cols++) /* Spalten der aktuellen Zeile durchgehen */
    {
      dest->pElmts[(rows * source1->nCols) + cols] = source1->pElmts[(rows * source1->nCols) + cols] + source2->pElmts[(rows * source1->nCols) + cols];
    }
  }

  dest->nRows = source1->nRows; /* nRows bei der Ziel-Matrix setzen */
  dest->nCols = source1->nCols; /* nCols bei ber Ziel-Matrix setzen */
}

/*--------------------------------------------------------------------------*/

void mMul(struct MATRIX *dest, struct MATRIX *source1, struct MATRIX *source2)
{
  unsigned int i,j,k;

  if (!source1 || !source2 || !dest) /* Ist einer der übergebenen MATRIX-Pointer gleich NULL? */
    return;                          /* dann Funktion mMul() beenden                          */

  mResize(dest, source1->nRows, source2->nCols); /* neue Größe der Ziel-Matrix festlegen */

  /* eigentliche Routine zur Berechnung des Matrizenprodukts */
  for (k = 0; k < source1->nCols; k++)
  {
    for (i = 0; i < source1->nRows; i++)
    {
      for (j = 0; j < source2->nCols; j++)
      {
        if (k == 0)
          dest->pElmts[(i * dest->nCols) + j] = source1->pElmts[(i * source1->nCols) + k] * source2->pElmts[(k * source2->nCols) + j];
        else
          dest->pElmts[(i * dest->nCols) + j] += source1->pElmts[(i * source1->nCols) + k] * source2->pElmts[(k * source2->nCols) + j];
      }
    }
  }
}

/*--------------------------------------------------------------------------*/

int main(void)
{
  unsigned int rows,cols;
  struct MATRIX m1,m2,m3;

  printf("\nMatrix-Berechnungen\ncopyright 2000 Olaf Gramkow\n\n");

  printf("Bitte eine quadratische Matrix eingeben.\n");
  printf("Zeilen, Spalten: ");
  scanf("%u, %u", &rows, &cols); /* Anzahl der Zeilen und Spalten einlesen */

  if ((rows < 1) || (cols < 1)) /* min. Zeilen, Spalten gleich 1 ? */
  {
    printf("Es müssen min. eine Zeile und eine Spalte vorhanden sein!\n");
    exit(1); /* Programm beenden */
  }

  if (rows != cols) /* ist es eine quadratische Matrix? */
  {
    printf("Die Anzahl der Zeilen und Spalten ist unterschiedlich!\n");
    exit(1); /* Programm beenden */
  }

  mInit(&m1, rows, cols); /* Allokieren der Matrix m1 */
  mInit(&m2, rows, cols); /* Allokieren der Matrix m2 */
  mInit(&m3, rows, cols); /* Allokieren der Matrix m3 */

  mRand(&m1); /* Random-Zahlen in Matrix m1 schreiben */

  mRead(&m2, stdin); /* Matrix m2 einlesen */

  mMul(&m3, &m1, &m2); /* m3 = m1 * m2 */
  mAdd(&m3, &m3, &m2); /* m3 = m3 + m2 */

  printf("\nErgebnis:\n");
  mWrite(&m3, stdout); /* Matrix m3 schreiben (ausgeben) */

  mFree(&m3); /* Freigeben der Matrix m3 */
  mFree(&m2); /* Freigeben der Matrix m2 */
  mFree(&m1); /* Freigeben der Matrix m1 */

  return(0); /* Das Hauptprogramm gibt am Ende 0 zurück, da kein Fehler aufgetreten ist. */
}


Zurück zur Übersicht