Sie sind auf Seite 1von 34

TU Ilmenau, Institut für Mathematik

FG Numerische Mathematik und Informationsverarbeitung


PD Dr. rer. nat. habil. W.Neundorf
Datei: LINUX C.TEX

Hinweise zur Programmierung sowie zur Erstellung von Program-


men und Projekten in C und C++ unter Linux

1 Programm und Projekt in Dev-C++


Die Programmieroberfläche Dev-C++ (Version Dev-C++ 4.9.6.0) mit den GNU-Compilern
g++ und gcc lässt ein bequemes Arbeiten mit der Entwicklungsumgebung (Windows IDE)
zu. Alle Einstellungen können von dort aus erfolgen. Im Skript DEV CPP.TEX(PS) sind die
Grundlagen dazu beschrieben. Die Arbeit soll an einem einfachen Beispiel erläutert werden.
Da in den Programmen die Eingabe von Daten über Tastatur mit der <Enter>-Taste been-
det wird, haben wir das <Enter>-Zeichen extra einer Variablen zugeordnet, z. B.
printf("Kontrollausgabe A (j/n)? ");
scanf("%c%c",&kont,&ret);
Damit sichert man, dass der Tastaturpuffer geleert wird. Man kann dies unter Windows
auch mit dem Aufruf der Methoden flush() bzw. fflush(stdin) mit dem Standardbe-
zeichner stdin aus den Header-Files stdio.h oder conio.h tun. Aber unter Linux ist der
Befehl fflush(stdin) ohne Wirkung, so dass von vornherein die scanf-Version implemen-
tiert wird.
Außerdem verwenden wir die Anweisung
scanf("%c",&ret);
um den Rechenablauf sowie nach Fehlermeldungen anzuhalten. Wir verzichten auf den ein-
facheren Befehl getch(). Weiterhin ist zu beachten, dass unter Windows der Ergebnisbild-
schirm automatisch schließt, wenn er nicht angehalten wird.

Matrixoperationen A + B, A − B, A ∗ B
(1) Implementation als ein einziges C-Programm mit allen Komponenten
// matrix_prog.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef double **laMatrix;

// Prototypen
laMatrix laMatrixNeu(int n, int m);
void laVernichte(laMatrix A);
void laDim(laMatrix A, int *n, int *m);
void laMatEinlesen(laMatrix *A);
void laMatAusgeben(laMatrix A);
void laAdd(laMatrix A, laMatrix B, laMatrix *C);
void laMult(laMatrix A, laMatrix B, laMatrix *C);
void laSub(laMatrix A, laMatrix B, laMatrix *C);

int main()
{
int n,m;
laMatrix A,B,C,S,D,P;
char kont,ret;

1
printf("Programm\n");
printf("Matrixoperationen\n");
printf("-----------------\n\n");

printf("Matrix A\n");
laMatEinlesen(&A);
//scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe A (j/n)? ");
scanf("%c%c",&kont,&ret);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension A(n,m): n=%i, m=%i\n",n,m);
printf("\nA\n");
laMatAusgeben(A);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}

printf("Matrix B\n");
laMatEinlesen(&B);
//scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe B (j/n)? ");
scanf("%c%c",&kont,&ret); // fflush(stdin);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension B(n,m): n=%i, m=%i\n",n,m);
printf("\nB\n");
laMatAusgeben(B);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}

printf("Matrix C\n");
laMatEinlesen(&C);
//scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe C (j/n)? ");
scanf("%c%c",&kont,&ret);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension C(n,m): n=%i, m=%i\n",n,m);
printf("\nC\n");
laMatAusgeben(C);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}

printf("\nErgebnisse");
laAdd(A,B,&S);
printf("\nS=A+B\n");
laMatAusgeben(S);
laSub(A,B,&D);
printf("\nD=A-B\n");
laMatAusgeben(D);
laMult(A,C,&P);
printf("\nP=A*C\n");
laMatAusgeben(P);
scanf("%c",&ret);

laVernichte(A);
laVernichte(B);
laVernichte(C);
laVernichte(D);
laVernichte(S);
laVernichte(P);

return 0;
}

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

2
laMatrix laMatrixNeu(int n, int m)
{
unsigned i;
char ret;
laMatrix A;

if((A = malloc(sizeof(double*)*n+2*sizeof(int)))==NULL)
{
fprintf(stderr,"\nzu wenig Speicher\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
*((int*)A) = n;
*(((int*)A)+1) = m;
A = (double**)(((int*)A)+2);
for(i=0;i<n;i++)
if((*(A+i) = malloc(sizeof(double)*m))==NULL)
{
fprintf(stderr,"\nzu wenig Speicher\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
return(A);
}
/*----------------------------------------------------------------------------*/

void laVernichte(laMatrix A)
{
unsigned i,n;

n = *(((int*)A)-2);
for(i=0;i<n;i++)
free(*(A+i));
free(((int*)A)-2);
}
/*----------------------------------------------------------------------------*/

void laDim(laMatrix A, int *n, int *m)


{
*n = *(((int*)A)-2);
*m = *(((int*)A)-1);
}
/*----------------------------------------------------------------------------*/

void laMatEinlesen(laMatrix *A)


{
FILE *matIn;
int i,j,n,m;
char ret;
char s[80]="Matrix.in"; // Initialisierung

printf("Dateiname fuer Daten zur Matrix : ");


scanf("%s%c",&s,&ret); // auch scanf("%s%c",s,&ret);
matIn = fopen(s,"r"); // matIn = fopen("Matrix.in","r");
if(matIn == NULL)
{
printf("\nFehler: Datei nicht gefunden\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
fscanf(matIn,"%u %u",&n,&m);
*A = laMatrixNeu(n,m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
fscanf(matIn,"%lf",&(*A)[i][j]);
fclose(matIn);
}
/*----------------------------------------------------------------------------*/

void laMatAusgeben(laMatrix A)
{
int i,j,n,m;

laDim(A,&n,&m);

3
for(i=0;i<n;i++)
{
for(j=0;j<m;j++) printf(" %10.6lf ",A[i][j]);
printf("\n");
}
}
/*----------------------------------------------------------------------------*/

void laAdd(laMatrix A, laMatrix B, laMatrix *C)


{
int n,m,i,j,r,s;
char ret;

laDim(A,&n,&m);
laDim(B,&r,&s);
if((n!=r)||(m!=s))
{
printf("\nFehler: Matrizen sind nicht von gleicher Dimension\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
else
{
*C = laMatrixNeu(n,m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
(*C)[i][j] = A[i][j]+B[i][j];
}
}
/*----------------------------------------------------------------------------*/

void laSub(laMatrix A, laMatrix B, laMatrix *C)


{
int n,m,k,l,i,j;
char ret;

laDim(A,&n,&m);
laDim(B,&k,&l);
if ((n!=k)||(m!=l))
{
printf("\nFehler: Matrixdimension(en) nicht gleich\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
*C = laMatrixNeu(n,m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
(*C)[i][j] = A[i][j]-B[i][j];
}
/*----------------------------------------------------------------------------*/

void laMult(laMatrix A, laMatrix B, laMatrix *C)


{
int i,j,k,n,m,r,s;
double h;
char ret;

laDim(A,&n,&m);
laDim(B,&r,&s);
if(m!=r)
{
printf ("\nFehler: innere Dimensionen unzulaessig\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
*C = laMatrixNeu(n,s);
for(i=0;i<n;i++)
for(j=0;j<s;j++)
{
h = 0;
for(k=0;k<m;k++) h += A[i][k]*B[k][j];
(*C)[i][j] = h;
}
}

4
Man klickt nun auf das Programm matrix_prog.c und kommt zum Menüpunkt Ausführen
⇒ Kompilieren u. Ausführen
Es folgen Informationen zum Übersetzen und im Kompilier Log steht
Fuehrt gcc.exe... aus

gcc.exe "C:\d\Neundorf\nwptexte\tech_phy\05\dev_cpp\projekt0\matrix_prog.c" -o
"C:\d\Neundorf\nwptexte\tech_phy\05\dev_cpp\projekt0\matrix_prog.exe" -s
-I"C:\Dev-Cpp\include"
-I"c:\d\neundorf\nwptexte\tech_phy\05\dev_cpp\projekt0"
-L"C:\Dev-Cpp\lib"

Ausfuehrung beendet
Kompilierung erfolgreich

Die Beispiele werden als ASCII-Dateien in der Datenreihenfolge n, m, A(1..n, 1..m), b(1..n), ...
bereitgestellt. Der Dateiname für die Daten zur Matrix usw. wird eingelesen.
Zum Test nehmen wir die (3×3)- Matrizen aus den Dateien matrix23, matrix57, matrix58

matrix23 matrix57 matrix58


-------- ------------ --------
3 3 3 3 3 3
1 -2 2 1 -2 2 2 2 2
-1 1 -1 -1 2 -1 1 3 0
-2 -2 1 -2 4 1 2 4 1
1 1 5
-1 0 4
-3 3 7
Loesung: Loesung: Loesung:
1 1 keine
1 1
1 1
EW: EW: EW:
1,1,1 0,2+-i*2.646 0,1,5

sowie die (2×2)- Matrix aus der Datei matrix3

matrix3
------------------
2 2
1.441969 1.040807
1.040807 0.751250
0.401162
0.289557
Loesung:
1
-1
EW:
2.193218999999544
4.5595081932092e-13

5
Eingabe- und Ergebnisfenster
2 C:\d\Neundorf\nwptexte\tech phy\05\dev cpp\projekt0\matrix prog.exe
Programm
Matrixperationen
————————–
Matrix A
Dateiname fuer Daten zur Matrix : matrix23
Kontrollausgabe A (j/n)? j
Dimension A(n,m): n=3, m=3
A
1.000000 -2.000000 2.000000
-1.000000 1.000000 -1.000000
-2.000000 -2.000000 1.000000
——————————————————————————————————–
Matrix B
Dateiname fuer Daten zur Matrix : matrix57
Kontrollausgabe B (j/n)? j
Dimension B(n,m): n=3, m=3
B
1.000000 -2.000000 2.000000
-1.000000 2.000000 -1.000000
-2.000000 4.000000 1.000000
——————————————————————————————————–
Matrix C
Dateiname fuer Daten zur Matrix : matrix58
Kontrollausgabe C (j/n)? j
Dimension C(n,m): n=3, m=3
C
2.000000 2.000000 2.000000
1.000000 3.000000 0.000000
2.000000 4.000000 1.000000
——————————————————————————————————–

Ergebnisse
S=A+B
2.000000 -4.000000 4.000000
-2.000000 3.000000 -2.000000
-4.000000 2.000000 2.000000
D=A-B
0.000000 0.000000 0.000000
0.000000 -1.000000 0.000000
0.000000 -6.000000 0.000000
P=A*C
4.000000 4.000000 4.000000
-3.000000 -3.000000 -3.000000
-4.000000 -6.000000 -3.000000

6
(2) Implementation als ein einziges C++-Programm mit allen Komponenten
Im Vergleich zum Programm matrix_prog.c sind an zwei Stellen der dynamischen Reser-
vierung von Speicherplatz in der Funktion laMatrixNeu Veränderungen vorzunehmen. Alles
andere kann übernommen werden.
// matrix_prog.cpp
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef double **laMatrix;

// Prototypen
laMatrix laMatrixNeu(int n, int m);
void laVernichte(laMatrix A);
void laDim(laMatrix A, int *n, int *m);
void laMatEinlesen(laMatrix *A);
void laMatAusgeben(laMatrix A);
void laAdd(laMatrix A, laMatrix B, laMatrix *C);
void laMult(laMatrix A, laMatrix B, laMatrix *C);
void laSub(laMatrix A, laMatrix B, laMatrix *C);

int main()
{
int n,m;
laMatrix A,B,C,S,D,P;
char kont,ret;

...
}

/*----------------------------------------------------------------------------*/
laMatrix laMatrixNeu(int n, int m)
{
unsigned i;
char ret;
laMatrix A;

// if((A = malloc(sizeof(double*)*n+2*sizeof(int)))==NULL) // C
if(((void*)A = malloc(sizeof(double*)*n+2*sizeof(int)))==NULL) // C++
{
fprintf(stderr,"\nzu wenig Speicher\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}

*((int*)A) = n;
*(((int*)A)+1) = m;
A = (double**)(((int*)A)+2);

for(i=0;i<n;i++)
// if((*(A+i) = malloc(sizeof(double)*m))==NULL) // C
if(((void*)(*(A+i)) = malloc(sizeof(double)*m))==NULL) // C++
{
fprintf(stderr,"zu wenig Speicher\n\r");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
return(A);
}
/*----------------------------------------------------------------------------*/
...

7
(3) Implementation als ein Projekt in C
Alle Vorwärtsdeklarationen und eine Sammlung von Prototypen befinden sich im Header-
File la.h und sind im Wesentlichen selbstkommentierend.
Gebraucht werden davon nur die Funktionen laMatrixNeu, laVernichte, laDim,
laMatEinlesen, laMatAusgeben, laAdd, laMult, laSub.
// la.h, Header-File fuer eine Bibliothek fuer lineare Algebra
#include <stdio.h>
#include <stdlib.h>

typedef double **laMatrix;

void laGlSysEinlesen(laMatrix *A, laMatrix *b);


/* Liest die Matrix A und den Vektor b der rechten Seite
aus der Datei "Matrix.in" bzw. Eingabedatei ... ein.
Vektor = Spaltenvektor = n*1-Matrix */

void laGlSysAusgeben(laMatrix A, laMatrix b);


/* Gibt die Matrix A und den Vektor b auf dem Bildschirm aus. */

void laMatAusgeben(laMatrix A);


/* Gibt die Matrix A auf dem Bildschirm aus. */

void laMatEinlesen(laMatrix *A);


/* Liest die Matrix A aus der Datei "Matrix.in" bzw. Eingabedatei ... ein. */

void laVektAusgeben(laMatrix x);


/* Gibt den reellen Vektor x (n*1-Matrix) auf dem Bildschirm aus. */

void laVektAusgebenI(laMatrix x);


/* Gibt den reellen Vektor x mit ganzzahligen Werten
der Komponenten auf dem Bildschirm aus. */

laMatrix laMatrixNeu(int n, int m);


/* Erzeugt eine n*m-Matrix und speichert die Dimensionen in ihr ab. */

void laVernichte(laMatrix A);


/* Gibt den Speicher der Matrix A wieder frei. */

void laDim(laMatrix A, int *n, int *m);


/* Gibt die Dimensionen der Matrix A in n (Zeilen) und m (Sp\"{u}alten) zurueck. */

laMatrix laNull(int n, int m);


/* Erzeugt eine n*m-Nullmatrix. */

laMatrix laEins(int n, int m);


/* Erzeugt eine n*m-Einheitsmatrix mit 1 auf der Diagonale. */

void laAdd(laMatrix A, laMatrix B, laMatrix *C);


/* Addiert die Matrix A mit der Matrix B und speichert
das Ergebnis in einer von der Funktion erzeugten Matrix ab.
Auf dies Matrix zeigt nach dem Aufruf C.
Fehlermeldung und Programmabbruch, falls die Dimensionen
von A und B nicht vertraeglich sind.*/

void laMult(laMatrix A, laMatrix B, laMatrix *C);


/* Multipliziert die Matrix A mit der Matrix B algebraisch
und speichert das Ergebnis in einer von der Funktion erzeugten Matrix ab.
Auf diese Matrix zeigt nach dem Aufruf C.
Fehlermeldung und Programmabbruch, falls die inneren Dimensionen
von A und B nicht vertraeglich sind. */

void laSub(laMatrix A, laMatrix B, laMatrix *C);


/* Subtrahiert die Matrix B von Matrix A und speichert
das Ergebnis in einer von der Funktion erzeugten Matrix ab.
Auf dies Matrix zeigt nach dem Aufruf C.
Fehlermeldung und Programmabbruch, falls die Dimensionen
von A und B nicht vertraeglich sind.*/

void laSkMult(double z, laMatrix A);


/* Multipliziert die reelle Zahl z mit der Matrix A. */

8
laMatrix laTransponiere(laMatrix A);
/* Transponiert die Matrix A. Da die Matrix i. Allg. nicht quadratisch
ist, muss auch der Speicher umorganisiert werden.
A zeigt also nach dem Aufruf auf einen anderen Speicherbreich,
der urspruengliche Speicherbereich wird freigegeben. */

void laVertauscheZe(laMatrix A, int r, int s);


/* Vertauscht in der Matrix A die Zeile r mit Zeile s.
Fehlermeldung und Programmabbruch, falls r, s unzulaessig sind. */

void laVertauscheSp(laMatrix A, int r, int s);


/* Vertauscht in der Matrix A die Spalte r mit Spalte s.
Fehlermeldung und Programmabbruch, falls r, s unzulaessig sind. */

void laKopiere(laMatrix A, laMatrix B);


/* Kopiert die Matrix A in eine vor der Funktion erzeugte
Matrix. Auf diese Matrix zeigt nach dem Aufruf B.
Dimensionskontrolle mit Fehlermeldung */

void laElemMult(laMatrix A, laMatrix B, laMatrix *C);


/* Multiplikation der Matrizen A und B elementweise und Speichern des Ergebnisses
in eine von der Funktion erzeugte Matrix. Auf diese Matrix zeigt nach dem Aufruf C.
Fehlermeldung und Programmabbruch, falls die Dimensionen von A und B
nicht vertraeglich sind. */

void laKreuzProd(laMatrix A, laMatrix B, laMatrix *C);


/* Berechnet das Kreuzprodukt der 3*1-Matrizen (Vektoren)
A und B und speichert das Ergebnis in einer von der Funktion
erzeugte 3*1-Matrix. Auf diese Matrix zeigt nach dem Aufruf C.
Bei unzulaessigen Dimensionen von A, B Abbruch mit einer Fehlermeldung. */

double laSkalProd(laMatrix A, laMatrix B);


/* Berechnet das Skalarprodukt der n*1-Matrizen
(Vektoren) A und B und gibt den Wert zurueck.
Bei unzulaessigen Dimensionen Abbruch mit Fehlermeldung. */

Die Definitionen sind in verschiedenen Quelltexten untergebracht.


Zunächst ist es das wichtige Modul la.c mit vier Grundfunktionen, wobei hier nur die
Funktionen laMatrixNeu, laVernichte, laDim Anwendung finden.
// la.c, Bibliothek fuer lineare Algebra
#include <stdlib.h>
#include <stdio.h>
#include "la.h"

/*----------------------------------------------------------------------------*/
laMatrix laMatrixNeu(int n, int m)
{
unsigned i;
char ret;
laMatrix A;

if((A = malloc(sizeof(double*)*n+2*sizeof(int)))==NULL)
{
fprintf(stderr,"\nzu wenig Speicher\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
*((int*)A) = n;
*(((int*)A)+1) = m;
A = (double**)(((int*)A)+2);
for(i=0;i<n;i++)
if((*(A+i) = malloc(sizeof(double)*m))==NULL)
{
fprintf(stderr,"\nzu wenig Speicher\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
return(A);
}
/*----------------------------------------------------------------------------*/

9
void laVernichte(laMatrix A)
{
unsigned i,n;

n = *(((int*)A)-2);
for(i=0;i<n;i++) free(*(A+i));
free(((int*)A)-2);
}
/*----------------------------------------------------------------------------*/
void laDim(laMatrix A, int *n, int *m)
{
*n = *(((int*)A)-2);
*m = *(((int*)A)-1);
}
/*----------------------------------------------------------------------------*/
laMatrix laTransponiere(laMatrix A)
{
int n,m,i,j;
laMatrix B;

laDim(A,&n,&m);
B = laMatrixNeu(m,n);
for(i=0;i<=n;++i)
for(j=0;j<=m;++j)
B[j][i] = A[i][j];
laVernichte(A);
return(B);
}

Die beiden Funktionen für die Ein- und Ausgabe sind problemangepasst und extra Quell-
texte. Darin aufgerufen werden auch die Funktionen laMatrixNeu, laDim.
// laMatEinlesen.c
#include <stdlib.h>
#include "la.h"

void laMatEinlesen(laMatrix *A)


{
FILE *matIn;
int i,j,n,m;
char ret;
char s[80]="Matrix.in"; // Initialisierung

printf("Dateiname fuer Daten zur Matrix : ");


scanf("%s%c",&s,&ret); // auch scanf("%s%c",s,&ret);
matIn = fopen(s,"r"); // matIn = fopen("Matrix.in","r");
if(matIn == NULL)
{
printf("Fehler: Datei nicht gefunden\n");
scanf("%c",&ret);
exit(EXIT_FAILURE);
}
fscanf(matIn,"%u %u",&n,&m);
*A = laMatrixNeu(n,m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
fscanf(matIn,"%lf",&(*A)[i][j]);
fclose(matIn);
}
/*----------------------------------------------------------------------------*/
// laMatAusgeben.c
#include "la.h"

void laMatAusgeben(laMatrix A)
{
int i,j,n,m;

laDim(A,&n,&m);
for(i=0;i<n;i++)
{
for(j=0;j<m;j++) printf(" %10.6lf ",A[i][j]);
printf("\n");
}
}

10
Dazu kommen noch die Quellen der eigentlichen Matrixoperationen laAdd, laMult, laSub.
// laAdd.c, C = A+B
#include <stdlib.h>
#include "la.h"

void laAdd(laMatrix A, laMatrix B, laMatrix *C)


{
int n,m,i,j,r,s;
char ret;

laDim(A,&n,&m);
laDim(B,&r,&s);
if((n!=r)||(m!=s))
{
printf("\nFehler: Matrizen sind nicht von gleicher Dimension\n");
scanf("%c",&ret); exit(EXIT_FAILURE);
}
else
{
*C = laMatrixNeu(n,m);
for(i=0;i<n;i++)
for(j=0;j<m;j++) (*C)[i][j] = A[i][j]+B[i][j];
}
}
/*----------------------------------------------------------------------------*/
// laMult.c, C = AB algebraisch
#include <stdlib.h>
#include "la.h"

void laMult(laMatrix A, laMatrix B, laMatrix *C)


{
int i,j,k,n,m,r,s;
double h;
char ret;

laDim(A,&n,&m);
laDim(B,&r,&s);
if(m!=r)
{
printf ("\nFehler: innere Dimensionen unzulaessig\n");
scanf("%c",&ret); exit(EXIT_FAILURE);
}
*C = laMatrixNeu(n,s);
for(i=0;i<n;i++)
for(j=0;j<s;j++)
{
h = 0;
for(k=0;k<m;k++) h += A[i][k]*B[k][j];
(*C)[i][j] = h;
}
}
/*----------------------------------------------------------------------------*/
// laSub.c, C = A-B
#include <stdlib.h>
#include "la.h"

void laSub(laMatrix A, laMatrix B, laMatrix *C)


{
int n,m,k,l,i,j;
char ret;

laDim(A,&n,&m);
laDim(B,&k,&l);
if((n!=k)||(m!=l))
{
printf("\nFehler: Matrixdimension(en) nicht gleich\n");
scanf("%c",&ret); exit(EXIT_FAILURE);
}
*C = laMatrixNeu(n,m);
for(i=0;i<n;i++)
for(j=0;j<m;j++) (*C)[i][j] = A[i][j]-B[i][j];
}

11
Nun fehlt nur noch der Quelltext (Rahmenprogramm) matrix_main.c mit der main-Funktion.
In ihm befinden sich die notwendigen include-Anweisungen, die Eingaben, Berechnungen
und Ausgaben.
// matrix_main.c
// Projekt: main-Funktion
// sonstige Komponenten: la.c, laMatEinlesen.c, laMatAusgeben.c, laAdd.c, laSub.c, laMult.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "la.h"

int main()
{
int n,m;
laMatrix A,B,C,S,D,P;
char kont,ret;

printf("Projekt\n");
printf("Matrixoperationen\n");
printf("-----------------\n\n");

printf("Matrix A\n");
laMatEinlesen(&A);
// scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe A (j/n)? ");
scanf("%c%c",&kont,&ret);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension A(n,m): n=%i, m=%i\n",n,m);
printf("\nA\n");
laMatAusgeben(A);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}

printf("Matrix B\n");
laMatEinlesen(&B);
// scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe B (j/n)? ");
scanf("%c%c",&kont,&ret); // fflush(stdin);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension B(n,m): n=%i, m=%i\n",n,m);
printf("\nB\n");
laMatAusgeben(B);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}

printf("Matrix C\n");
laMatEinlesen(&C);
// scanf("%c",&ret); // fflush(stdin);
printf("Kontrollausgabe C (j/n)? ");
scanf("%c%c",&kont,&ret);
if(kont==’j’)
{
laDim(A,&n,&m);
printf("\nDimension C(n,m): n=%i, m=%i\n",n,m);
printf("\nC\n");
laMatAusgeben(C);
printf("-----------------------------------------------------------------------------\n");
scanf("%c",&ret);
}

printf("\nErgebnisse");
laAdd(A,B,&S);
printf("\nS=A+B\n");
laMatAusgeben(S);
laSub(A,B,&D);
printf("\nD=A-B\n");

12
laMatAusgeben(D);
laMult(A,C,&P);
printf("\nP=A*C\n");
laMatAusgeben(P);
scanf("%c",&ret);

laVernichte(A);
laVernichte(B);
laVernichte(C);
laVernichte(D);
laVernichte(S);
laVernichte(P);

return 0;
}

Zusammenstellung des C-Projekts matrix0 im Arbeitsverzeichnis


C:\d\Neundorf\nwptexte\tech phy\05\dev cpp\projekt0
Im Projektfenster steht der Baum des Projekts.
S
2- –ℵ≡ matrix0
||− la.c
|
|− laAdd.c
|
|− laMatAusgeben.c
|
|− laMatEinlesen.c
|
|− laMult.c
|
|− laSub.c
|
− matrix_main.c

Klickt man den Schalter Klassen an, so erscheint im Projektfenster eine umfangreiche Liste
von Klassen und Funktionen zum Projekt.
Man klickt nun auf das Projekt matrix0 und kommt zum Menüpunkt Ausführen
⇒ Kompilieren u. Ausführen
Es folgen Informationen zum Übersetzen und im Kompilier Log steht
Building Makefile: "C:\d\Neundorf\nwptexte\tech_phy\05\dev_cpp\projekt0\Makefile.win"
Fuehrt make... aus

make.exe -f "C:\d\Neundorf\nwptexte\tech_phy\05\dev_cpp\projekt0\Makefile.win" all

gcc.exe -c la.c -o la.o -I"C:/Dev-Cpp/include"


-I"c:/d/neundorf/nwptexte/tech_phy/05/dev_cpp/projekt0" -s
gcc.exe -c laAdd.c -o laAdd.o -I"C:/Dev-Cpp/include"
-I"c:/d/neundorf/nwptexte/tech_phy/05/dev_cpp/projekt0" -s
gcc.exe -c laMatAusgeben.c -o laMatAusgeben.o -I"C:/Dev-Cpp/include"
-I"c:/d/neundorf/nwptexte/tech_phy/05/dev_cpp/projekt0" -s
gcc.exe -c laMatEinlesen.c -o laMatEinlesen.o -I"C:/Dev-Cpp/include"
-I"c:/d/neundorf/nwptexte/tech_phy/05/dev_cpp/projekt0" -s
gcc.exe -c laMult.c -o laMult.o -I"C:/Dev-Cpp/include"
-I"c:/d/neundorf/nwptexte/tech_phy/05/dev_cpp/projekt0" -s
gcc.exe -c laSub.c -o laSub.o -I"C:/Dev-Cpp/include"
-I"c:/d/neundorf/nwptexte/tech_phy/05/dev_cpp/projekt0" -s
gcc.exe -c matrix_main.c -o matrix_main.o -I"C:/Dev-Cpp/include"
-I"c:/d/neundorf/nwptexte/tech_phy/05/dev_cpp/projekt0" -s
gcc.exe la.o laAdd.o laMatAusgeben.o laMatEinlesen.o laMult.o laSub.o matrix_main.o -o "matrix0.exe"
-L"C:/Dev-Cpp/lib"
-I"C:/Dev-Cpp/include"
-I"c:/d/neundorf/nwptexte/tech_phy/05/dev_cpp/projekt0" -s

Ausfuehrung beendet
Kompilierung erfolgreich

13
Im Verzeichnis stehen dann die Projektdatei matrix0.dev
[Project]
FileName=matrix0.dev
Name=matrix0
UnitCount=7
Type=1
Ver=1
ObjFiles=
Includes=
Libs=
PrivateResource=
ResourceIncludes=
MakeIncludes=
Resources=
Compiler=
Linker=
IsCpp=0
Icon=
ExeOutput=
ObjectOutput=
OverrideOutput=0
OverrideOutputName=
Folders=
CommandLine=
Focused=6
Order=0,1,2,3,5,4,-1,6

[Unit2]
FileName=laAdd.c
Open=1
Folder=
Top=0
CursorCol=2
CursorRow=2
TopLine=1
LeftChar=1

[Unit3]
FileName=laMatAusgeben.c
Open=1
Folder=
Top=0
CursorCol=1
CursorRow=2
TopLine=1
LeftChar=1

[Unit4]
FileName=laMatEinlesen.c
Open=1
Folder=
Top=0
CursorCol=1
CursorRow=2
TopLine=1
LeftChar=1

[Unit5]
FileName=laMult.c
Open=1
Folder=
Top=0
CursorCol=3
CursorRow=26
TopLine=6
LeftChar=1

[Unit6]
FileName=laSub.c
Open=1
Folder=
Top=0
CursorCol=3
CursorRow=20

14
TopLine=1
LeftChar=1

[Unit7]
FileName=matrix_main.c
Open=0
Folder=
Top=0
CursorCol=3
CursorRow=23
TopLine=4
LeftChar=1

[Views]
ProjectView=1

[Unit1]
FileName=la.c
Open=1
Folder=
Top=0
CursorCol=1
CursorRow=2
TopLine=1
LeftChar=1

Im Verzeichnis stehen dann die ausführbare Datei matrix0.exe sowie alle Objektdateien
*.o der Projektquellen.
Dazu kommt zum Projekt noch das sogenannte Makefile Makefile.win.
# Project: matrix0
# Makefile created by Dev-C++ 4.9.6.0

CC = gcc.exe
WINDRES = windres.exe
RES =
OBJ = la.o laAdd.o laMatAusgeben.o laMatEinlesen.o laMult.o laSub.o matrix_main.o $(RES)
LIBS = -L"C:/Dev-Cpp/lib"
INCS = -I"C:/Dev-Cpp/include" -I"c:/d/neundorf/nwptexte/tech_phy/05/dev_cpp/projekt0"
BIN = matrix0.exe
CFLAGS = $(INCS) -s

.PHONY: all all-before all-after clean clean-custom


all: all-before matrix0.exe all-after
clean: clean-custom
rm -f $(OBJ) $(BIN)

$(BIN): $(OBJ)
$(CC) $(OBJ) -o "matrix0.exe" $(LIBS) $(CFLAGS)

la.o: la.c
$(CC) -c la.c -o la.o $(CFLAGS)
laAdd.o: laAdd.c
$(CC) -c laAdd.c -o laAdd.o $(CFLAGS)
laMatAusgeben.o: laMatAusgeben.c
$(CC) -c laMatAusgeben.c -o laMatAusgeben.o $(CFLAGS)
laMatEinlesen.o: laMatEinlesen.c
$(CC) -c laMatEinlesen.c -o laMatEinlesen.o $(CFLAGS)
laMult.o: laMult.c
$(CC) -c laMult.c -o laMult.o $(CFLAGS)
laSub.o: laSub.c
$(CC) -c laSub.c -o laSub.o $(CFLAGS)
matrix_main.o: matrix_main.c
$(CC) -c matrix_main.c -o matrix_main.o $(CFLAGS)

Eingaben und Ergebnisse sind nun als Projekt wie im Teil (1).

15
2 C und C++ unter Linux 9.0
Auf der Oberfläche stehen die Compiler cc und c++ sowie gcc und g++ (GNU-Compiler)
zur Verfügung. Zwischen den beiden C-Compilern lässt sich kein Unterschied feststellen, ge-
nauso bei den Compilern für C++.
Die Entwicklungsumgebung basiert auf einer Kommandosprache und die Einstellungen können
dort erfolgen. Im Vergleich mit der Entwicklungsumgebung von Dev-C++ ist der Umgang
nicht ganz so bequem. Außerdem gibt es zur Windows-Umgebung kleine Unterschiede bez.
der Benutzung bestimmter Anweisungen und Header-Files.
Die Arbeit soll an einfachen Beispielen erläutert werden. Die Numerik dazu sowie die Pro-
grammstruktur befinden sich im Skript DEV CPP.TEX(PS). Nach diesem Muster können
andere Programme gleichfalls erstellt und abgearbeitet werden.

2.1 Compileraufrufe für einfache Programme


Die Kommandos für den Aufruf des jeweiligen Compilers für ein einzelnes Programm in C
bzw. C++ haben analoge Struktur.
<comp> <option1> <dateiname> <quelltext/datei> <objektdateien> <option2>
Dabei stehen die Bezeichner für folgende Varianten:
<comp> <option1> <dateiname> <quelltext/datei> <objektdateien> <option2>
--------------------------------------------------------------------------------
gcc -c ausfuehrbare Programm Objektdatei(en) -lm
cc -o Datei in C bzw. C++
g++
c++
Die Option -lm bedeutet das Verlinken mit der Mathematik-Bibliothek und ist gegebenenfalls
hinzuzufügen, auf jeden Fall bei Verwendung von zusätzlichen Standardfunktionen (vergl.
#include<math.h>).
Der Compiler erzeugt bei der Option -c eine Objektdatei, die zumeist Teil eines größeren
Programms ist, bei -o eine ausführbare Datei, die noch aufzurufen ist.
Sei <quelltext/datei>: programm.c bzw. programm.cpp.
Dann gibt es die folgenden hauptsächlichen Anwendungen. Dabei verwenden wir den GNU-
Compiler gcc.
gcc programm.c --> ausfuehrbare Datei ist standardmaessig a.out
gcc programm.c -lm Aufruf: a.out
------------------------------------------------------------------------------------------------------------
gcc -c programm.c --> Erzeugung der Objektdatei programm.o
gcc -c programm.c -lm --> Message: linker input file unused because linking not done
gcc -c objekt.c --> Erzeugung der Objektdatei objekt.o
(i. Allg. kein selbstaendiger Aufruf)
gcc -c obj1 objekt1.c --> keine Erzeugung der Objektdatei obj1.o
------------------------------------------------------------------------------------------------------------
gcc -o mein programm.c -lm --> Erzeugung zum Programm programm.c
als ausfuehrbare Datei mein
Aufruf: mein
------------------------------------------------------------------------------------------------------------
gcc programm.c objekt.o -lm --> Erzeugung zum Programm programm.c unter Einbeziehung
des Objekts (Link) die ausfuehrbare Datei a.out
Aufruf: a.out
gcc programm.c obj1.o obj2.0 ... -lm --> Erzeugung zum Programm programm.c unter Einbeziehung
von Objekten die ausfuehrbare Datei a.out
Aufruf: a.out
gcc -o mein programm.c obj1.o obj2.o ... -lm --> Erzeugung zum Programm programm.c unter Einbeziehung
von Objekten die ausfuehrbare Datei mein
Aufruf: mein

16
2.2 Erzeugung einer Bibliothek
Zu jedem Quelltext kann man seine Objektdatei erzeugen.
Manchmal ist es jedoch sinnvoller und überschaubarer, zunächst einige Quelltexte (z. B.
Funktionen) in einem Verbund als Bibliothek zusammen zu stellen. Dabei kann es jedoch
passieren, dass die einzelnen Quellen dieselben Include-Anweisungen verwenden. Da die
Bibliothek nur eine davon braucht, sind die sich wiederholenden Includes zu entfernen bzw.
heraus zu kommentieren.
Danach kann aus der Bibliothek wiederum eine Objektdatei erzeugt werden.
Zum Erzeugen einer Bibliothek und Anhängen von weiteren Dateien an diese gibt es das
Kommando cat.
cat quelle1.c > laLib.c --> Erzeugen einer Bibliothek mit dem Namen laLib.c
cat quelle2.c >> laLib.c --> Anhaengen an diese
cat quelle3.c >> laLib.c
...
gcc -c laLib.c --> Erzeugung der Objektdatei laLib.o (i. Allg. kein selbstaendiger Aufruf)

2.3 Beispiele für die Einprogrammversion


Wir verwenden die beiden Programme (Quelltexte) matrix_prog.c und matrix_prog.cpp
und arbeiten mit den 4 genannten Compilern, später jedoch i. Allg. mit gcc.
Die Dateien sollen sich im Verzeichnis 05/make0 befinden, in welches aus Gründen des ein-
facheren Zugriffs gewechselt wird.
Das Verlinken mit der Bibliothek der mathematischen Funktionen führt nur zu einer geringen
Vergrößerung der Ergebnisdatei, falls keine Funktionen einzubinden sind.
Groesse
cc matrix_prog.c --> a.out (12865 Byte)
gcc matrix_prog.c --> a.out (12865 Byte)
gcc matrix_prog.c -lm --> a.out (12937 Byte)
----------------------------------------------------------------------------------------
c++ matrix_prog.cpp --> a.out (13873 Byte)
g++ matrix_prog.cpp --> a.out (13873 Byte)
g++ matrix_prog.cpp -lm --> a.out (13873 Byte)
----------------------------------------------------------------------------------------
gcc -c matrix_prog.c --> matrix_prog.o ( 5888 Byte)

gcc -o mein_prog1 matrix_prog.c --> mein_prog1 (12865 Byte)


gcc -o mein_prog1 matrix_prog.c -lm --> mein_prog1 (12937 Byte)
----------------------------------------------------------------------------------------
gcc -c la.c --> la.o ( 1644 Byte)
gcc -c laAdd.c --> laAdd.o ( 1228 Byte)
gcc -c laMult.c --> laMult.o ( 1284 Byte)
gcc -c laSub.c --> laSub.o ( 1220 Byte)
gcc -c laMatEinlesen.c --> laMatEinlesen.o ( 1576 Byte)
gcc -c laMatAusgeben.c --> laMatAusgeben.o ( 952 Byte)

2.4 Modulares Programmkonzept


Die einfachste Version der Verknüpfung mehrerer Programmbausteine basiert auf dem Ver-
linken der gerade erzeugten Objekte
la.o, laAdd.o, laMult.o, laSub.o, laMatEinlesen.o, laMatAusgeben.o
mit dem Rahmenprogramm matrix_main.c.
gcc matrix_main.c la.o laAdd.o laMult.o laSub.o laMatEinlesen.o laMatAusgeben.o --> a.out (13422 Byte)
gcc matrix_main.c la.o laAdd.o laMult.o laSub.o laMatEinlesen.o laMatAusgeben.o -lm --> a.out (13494 Byte)
----------------------------------------------------------------------------------------------------------------
gcc -o mein_prog2 matrix_main.c la.o laAdd.o laMult.o laSub.o laMatEinlesen.o laMatAusgeben.o --> mein_prog2
gcc -o mein_prog2 matrix_main.c la.o laAdd.o laMult.o laSub.o laMatEinlesen.o laMatAusgeben.o -lm --> mein_prog2
(13494 Byte)

17
Um das abzukürzen, kann man die Module vorher zusammenfassen zu einer Bibliothek.
cat la.c > laLib1.c --> Erzeugen einer Bibliothek mit dem Namen laLib1.c
cat laAdd.c >> laLib1.c --> Anhaengen an diese
cat laMult.c >> laLib1.c
cat laSub.c >> laLib1.c
cat laMatEinlesen.c >> laLib1.c
cat laMatAusgeben.c >> laLib1.c --> laLib1.c "saeubern"
---------------------------------------------------------------------------------------------------
gcc -c laLib1.c --> Erzeugung der Objektdatei laLib1.o

gcc -o mein_prog3 matrix_main.c laLib1.o -lm --> mein_prog3 (13201 byte)

Würde man in laLib1.c nicht die sich wiederholenden include-Anweisungen löschen, ergäbe
sich bei gcc -c laLib1.c folgende Fehlermeldung.
05/make0> gcc -c laLib1.c
In file included from laLib1.c:67:
la.h:5: error: redefinition of ‘laMatrix’
la.h:5: error: ‘laMatrix’ previously declared here
In file included from laLib1.c:93:
la.h:5: error: redefinition of ‘laMatrix’
la.h:5: error: ‘laMatrix’ previously declared here
In file included from laLib1.c:121:
la.h:5: error: redefinition of ‘laMatrix’
la.h:5: error: ‘laMatrix’ previously declared here
In file included from laLib1.c:145:
la.h:5: error: redefinition of ‘laMatrix’
la.h:5: error: ‘laMatrix’ previously declared here
In file included from laLib1.c:171:
la.h:5: error: redefinition of ‘laMatrix’
la.h:5: error: ‘laMatrix’ previously declared here

Die elegante Version verwendet jedoch ein Makefile, dass alle Schritte und Dateien zusam-
menfasst und mittels make aufgerufen wird. Heißt das Makefile standardmäßig makefile
oder Makefile, so erfolgt sein Aufruf einfach mit make. Hat es einen anderen Namen, so
notieren wir make -f makefile_name.
Hier ist die Erstellung eines Makefiles notwendig. In Dev-C++ wurde dies beim Kompilieren
automatisch erzeugt.
Wir demonstrieren die stufenweise Entwicklung der Version.
Stufe 1
Dabei kann es jedoch wie oben passieren, dass ursprünglich die einzelnen Quellen dieselben
include-Anweisungen verwenden. Folgende Version ist also fehlerhaft.
# makefile0

# fuer Physik ("roadrunner")


#Dir = /home/Studenten/neundorf/make0/
#Dir = /home/Studenten/Austausch/

# fuer Mathematik ("gauss")


Dir = /export/home/neundorf/tech_phy/05/make0/

Alles:
cat $(Dir)la.c > laLib.c
cat $(Dir)laAdd.c >> laLib.c
cat $(Dir)laMult.c >> laLib.c
cat $(Dir)laSub.c >> laLib.c
cat $(Dir)laMatEinlesen.c >> laLib.c
cat $(Dir)laMatAusgeben.c >> laLib.c

gcc -c laLib.c
gcc -c matrix_main.c
gcc -o mein_prog4 matrix_main.o laLib.o

18
Da die Bibliothek zu jedem Header-File nur eine include-Anweisung braucht, sind die sich
wiederholenden Includes zu entfernen bzw. heraus zu kommentieren.
Deshalb werden in den beiden ersten Stufen diese include-Anweisungen aus den Quel-
len laAdd.c, laMult.c, laSub.c, laMatEinlesen.c, laMatAusgeben.c herausgenom-
men. Die veränderten Quellen sind laAdd_.c, laMult_.c, laSub_.c, laMatEinlesen_.c,
laMatAusgeben_.c.
# makefile0_

# fuer Physik ("roadrunner")


#Dir = /home/Studenten/neundorf/make0/
#Dir = /home/Studenten/Austausch/

# fuer Mathematik ("gauss")


Dir = /export/home/neundorf/tech_phy/05/make0/

Alles:
cat $(Dir)la.c > laLib.c
cat $(Dir)laAdd_.c >> laLib.c
cat $(Dir)laMult_.c >> laLib.c
cat $(Dir)laSub_.c >> laLib.c
cat $(Dir)laMatEinlesen_.c >> laLib.c
cat $(Dir)laMatAusgeben_.c >> laLib.c

gcc -c laLib.c
gcc -c matrix_main.c
gcc -o mein_prog4 matrix_main.o laLib.o

Stufe 2
Ähnlich zu Stufe 1 mit Weglassen der Kommentarzeilen und Verzeichniseinstellung
(mein_prog4 hat 13128 Byte).
# makefile0_kurz_

Alles:
cat la.c > laLib.c
cat laAdd_.c >> laLib.c
cat laMult_.c >> laLib.c
cat laSub_.c >> laLib.c
cat laMatEinlesen_.c >> laLib.c
cat laMatAusgeben_.c >> laLib.c

gcc -c laLib.c
gcc -c matrix_main.c
gcc -o mein_prog4 matrix_main.o laLib.o

Stufe 3
Diese Langform soll angegeben werden, um die Arbeit in einem aktuellen Verzeichnis zu-
sammen mit der Kopie von Dateien aus einem fernen Verzeichnis zu zeigen. Da hier alles im
aktuellen Verzeichnis stattfindet, vereinfacht sich die Situation. So muss die Datei la.h im
aktuellen Verzeichnis nicht kopiert werden. Der Kopierbefehl cp $(Dir)$(la).h . wird
als Kommentar notiert oder gelöscht.
Macht man es nicht, erfolgt wegen der nicht möglichen Kopie einer Datei auf sich selbst die
Fehlermeldung und Warnung
cp /export/home/neundorf/tech_phy/05/make0/la.h .
cp: /export/home/neundorf/tech_phy/05/make0/la.h und ./la.h sind die gleiche Datei
make: *** [libla.a] Fehler 1

Die Quelltexte müssen also nicht wie in den Stufen 1 und 2 bezüglich der Kopfzeilen
(include-Anweisungen) verändert werden.

19
# makefile
#
CC = gcc

CFlags = -g -c
#DFlags = -O -c
#
# fuer Physik ("roadrunner")
#Dir = /home/Studenten/neundorf/make0/
#Dir = /home/Studenten/Austausch/

# fuer Mathematik ("gauss")


Dir = /export/home/neundorf/tech_phy/05/make0/

#
la = la
Add = laAdd
Mult = laMult
Sub = laSub
Ein = laMatEinlesen
Aus = laMatAusgeben
#
mein_prog5: matrix_main.o libla.a
$(CC) -g -o mein_prog5 matrix_main.o -lm -lla -L./
#
matrix_main.o: matrix_main.c
$(CC) $(CFlags) matrix_main.c

#
libla.a: $(la).o $(Add).o $(Mult).o $(Sub).o $(Ein).o $(Aus).o

# Quellen aus dem Verzeichnis Dir holen.


# Anders, falls diese im aktuellen Verzeichnis sind.
# cp $(Dir)$(la).h .

ar r libla.a $(la).o $(Add).o $(Mult).o $(Sub).o $(Ein).o $(Aus).o


ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
$(la).c: $(Dir)$(la).c
cp $(Dir)$(la).h .
cp $(Dir)$(la).c .
#
$(Add).o: $(Add).c
$(CC) $(CFlags) $(Add).c
$(Add).c: $(Dir)$(Add).c
cp $(Dir)$(la).h .
cp $(Dir)$(Add).c .
#
$(Mult).o: $(Mult).c
$(CC) $(CFlags) $(Mult).c
$(Mult).c: $(Dir)$(Mult).c
cp $(Dir)$(la).h .
cp $(Dir)$(Mult).c .
#
$(Sub).o: $(Sub).c
$(CC) $(CFlags) $(Sub).c
$(Sub).c: $(Dir)$(Sub).c
cp $(Dir)$(la).h .
cp $(Dir)$(Sub).c .
#
$(Ein).o: $(Ein).c
$(CC) $(CFlags) $(Ein).c
$(Ein).c: $(Dir)$(Ein).c
cp $(Dir)$(la).h .
cp $(Dir)$(Ein).c .
#
$(Aus).o: $(Aus).c
$(CC) $(CFlags) $(Aus).c
$(Aus).c: $(Dir)$(Aus).c
cp $(Dir)$(la).h .
cp $(Dir)$(Aus).c .

20
Stufe 4
Genauso kann man auf die anderen Kommandozeilen verzichten wie
$(la).c: $(Dir)$(la).c
cp $(Dir)$(la).h .
cp $(Dir)$(la).c .

Alle Quellen befinden sich im aktuellen Verzeichnis, so dass man diese nicht erst von woan-
ders dahin kopieren muss. Kommentarzeilen sind dabei meistens weggelassen worden. Das
verkürzte Makefile ist damit makefile_kurz (mein_prog5 hat 20198 Byte).
# makefile_kurz
#
CC = gcc

CFlags = -g -c

#
la = la
Add = laAdd
Mult = laMult
Sub = laSub
Ein = laMatEinlesen
Aus = laMatAusgeben

#
mein_prog5: matrix_main.o libla.a
$(CC) -g -o mein_prog5 matrix_main.o -lm -lla -L./
#
matrix_main.o: matrix_main.c
$(CC) $(CFlags) matrix_main.c

#
libla.a: $(la).o $(Add).o $(Mult).o $(Sub).o $(Ein).o $(Aus).o
ar r libla.a $(la).o $(Add).o $(Mult).o $(Sub).o $(Ein).o $(Aus).o
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
#
$(Add).o: $(Add).c
$(CC) $(CFlags) $(Add).c
#
$(Mult).o: $(Mult).c
$(CC) $(CFlags) $(Mult).c
#
$(Sub).o: $(Sub).c
$(CC) $(CFlags) $(Sub).c
#
$(Ein).o: $(Ein).c
$(CC) $(CFlags) $(Ein).c
#
$(Aus).o: $(Aus).c
$(CC) $(CFlags) $(Aus).c

21
2.5 Implementation von Algorithmen in C und Makefiles
Wir demonstrieren den Umgang mit Makefiles anhand von weiteren Beispielen und werden
dabei schrittweise vorgehen.
In den Demoprogrammen werden der Gauß-Algorithmus, das Newton-Verfahren und die
Vektoriteration in verschiedenen Versionen und Ausbaustufen implementiert.

Beispiel 1
Einzelnes Demoprogramm gauss1.c zum Gauß-Algorithmus.
Unter der Linux-Oberfläche ist im Programm das Header-File conio.h nicht vorhanden,
also die include-Anweisung #include <conio.h> nicht möglich und zu entfernen sowie
der getch()-Befehl durch char ret ... scanf("%c",&ret) zu ersetzen.
Dann genügt es, den Compiler aufzurufen und danach das Programm auszuführen.
gcc gauss1.c --> ausfuehrbare Datei ist standardmaessig a.out
gcc gauss1.c -lm Aufruf: a.out
gcc -o gauss1 gauss1.c -lm --> Aufruf: gauss1

Beispiel 2
Demoprogramm tgauss.c zum Gauß-Algorithmus mit zusätzlichen Quellen und Berechnun-
gen. In den Quellen ist die include-Anweisung #include <conio.h> zu entfernen, die pri-
vaten Header-File wie basis.h, vmblock.h, u_proto.h mittels #include "name" an-
stelle von #include <name> einzubinden und der getch-Befehl durch scanf("%c",&ret)
zu ersetzen.
Da wir im Verzeichnis arbeiten, wo alle Dateien zur Verfügung stehen, erstellt man folgendes
Makefile (Langform).
# makefile
#
CC = gcc
CFlags = -g -c
#
Dir = export/home/neundorf/tech_phy/05/make2/
# Dir = /home/Studenten/neundorf/make2/
# Dir = /home/Studenten/Austausch/
#
basis = basis
fgauss = fgauss
vmblock = vmblock
#
tgauss: tgauss.o libla.a
$(CC) -g -o tgauss tgauss.o -lm -lla -L./
#
tgauss.o: tgauss.c
$(CC) $(CFlags) tgauss.c
#
libla.a: $(basis).o $(fgauss).o $(vmblock).o
# Quellen aus dem Verzeichnis Dir holen.
# Anders, falls diese im aktuellen Verzeichnis sind.
# cp $(Dir)$(basis.h) .
# cp $(Dir)$(u_proto.h) .
# cp $(Dir)$(vmblock.h) .
ar r libla.a $(basis).o $(fgauss).o $(vmblock).o
ar s libla.a
#
$(basis).o: $(basis).c
$(CC) $(CFlags) $(basis).c
#
$(fgauss).o: $(fgauss).c
$(CC) $(CFlags) $(fgauss).c
#
$(vmblock).o: $(vmblock).c
$(CC) $(CFlags) $(vmblock).c
#

22
Seine Kurzform ohne Aliasnamen und Verzeichnisbezug ist
# makefile_kurz
#
CC = gcc
CFlags = -g -c
#
#Dir = export/home/neundorf/tech_phy/05/make2/
#
tgauss: tgauss.o libla.a
$(CC) -g -o tgauss tgauss.o -lm -lla -L./
#
tgauss.o: tgauss.c
$(CC) $(CFlags) tgauss.c
#
libla.a: basis.o fgauss.o vmblock.o
ar r libla.a basis.o fgauss.o vmblock.o
ar s libla.a
#
basis.o: basis.c
$(CC) $(CFlags) basis.c
#
fgauss.o: fgauss.c
$(CC) $(CFlags) fgauss.c
#
vmblock.o: vmblock.c
$(CC) $(CFlags) vmblock.c
#

Aber es geht auch mit der Befehlsfolge


gcc -c basis.c
gcc -c fgauss.c
gcc -c vmblock.c
gcc -o tgauss tgauss1.c basis.o fgauss.o vmblock.o -lm
tgauss

Beispiel 3
Unter analogen Gesichtspunkten wie in Beispiel 2 verfährt man beim Programm tnewton.c
zum Newton-Verfahren. Wir notieren wieder die beiden Formen des Makefiles.
# makefile
#
CC = gcc

CFlags = -g -c
#
Dir = export/home/neundorf/tech_phy/05/make3/
# Dir = /home/Studenten/neundorf/make2/
# Dir = /home/Studenten/Austausch/
#
basis = basis
fnewton = fnewton
tfunc1 = tfunc1
#
tnewton: tnewton.o libla.a
$(CC) -g -o tnewton tnewton.o -lm -lla -L./
#
tnewton.o: tnewton.c
$(CC) $(CFlags) tnewton.c
#
libla.a: $(basis).o $(fnewton).o $(tfunc1).o
# Quellen aus dem Verzeichnis Dir holen.
# Anders, falls diese im aktuellen Verzeichnis sind.
# cp $(Dir)$(basis.h) .
# cp $(Dir)$(u_proto.h) .
# cp $(Dir)$(tfunc1.h) .
ar r libla.a $(basis).o $(fnewton).o $(tfunc1).o
ar s libla.a
#
$(basis).o: $(basis).c

23
$(CC) $(CFlags) $(basis).c
#
$(fnewton).o: $(fnewton).c
$(CC) $(CFlags) $(fnewton).c
#
$(tfunc1).o: $(tfunc1).c
$(CC) $(CFlags) $(tfunc1).c
#
------------------------------------------------------------------

# makefile_kurz
#
CC = gcc
CFlags = -g -c
#
#Dir = export/home/neundorf/tech_phy/05/make3/
#
tnewton: tnewton.o libla.a
$(CC) -g -o tnewton tnewton.o -lm -lla -L./
#
tnewton.o: tnewton.c
$(CC) $(CFlags) tnewton.c
#
libla.a: basis.o fnewton.o tfunc1.o
ar r libla.a basis.o fnewton.o tfunc1.o
ar s libla.a
#
basis.o: basis.c
$(CC) $(CFlags) basis.c
#
fnewton.o: fnewton.c
$(CC) $(CFlags) fnewton.c
#
tfunc1.o: tfunc1.c
$(CC) $(CFlags) tfunc1.c
#

Beispiel 4
Für das Demoprogramm meinprog.c mit der Funktion gauss4c.c zum Gauß-Algorithmus
und zahlreichen Quelltexten hat man folgendes ursprüngliche Makefile.
Version 1
# makefile
#
CC = gcc
CFlags = -g -c
#DFlags = -O -c
#
# fuer Physik ("roadrunner")
#Austausch = /home/Studenten/neundorf/austausch/
#Austausch = /home/Studenten/Austausch/

# fuer Mathematik ("gauss")


Austausch = /export/home/neundorf/tech_phy/05/austausch/
#
la = la
IO = laInOut
Add = laAdd
Eins = laEins
Null = laNull
Mult = laMult
ElMu = laElemMult
KrPr = laKreuzProd
SkPr = laSkalProd
SkMu = laSkMult
VerSp = laVertauscheSp
VerZe = laVertauscheZe
#
meinprog: meinprog.o libla.a
$(CC) -g -o meinprog meinprog.o -lm -lla -L./
#

24
meinprog.o: meinprog.c
$(CC) $(CFlags) meinprog.c

#
libla.a: $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o
# Quellen aus dem Verzeichnis Austausch holen.
# Anders, falls diese im aktuellen Verzeichnis sind
cp $(Austausch)$(la).h .
ar r libla.a $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
$(la).c: $(Austausch)$(la).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(la).c .
#
$(IO).o: $(IO).c
$(CC) $(CFlags) $(IO).c
$(IO).c: $(Austausch)$(IO).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(IO).c .
#
$(Add).o: $(Add).c
$(CC) $(CFlags) $(Add).c
$(Add).c: $(Austausch)$(Add).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Add).c .
#
$(Eins).o: $(Eins).c
$(CC) $(CFlags) $(Eins).c
$(Eins).c: $(Austausch)$(Eins).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Eins).c .
#
$(Null).o: $(Null).c
$(CC) $(CFlags) $(Null).c
$(Null).c: $(Austausch)$(Null).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Null).c .
#
$(Mult).o: $(Mult).c
$(CC) $(CFlags) $(Mult).c
$(Mult).c: $(Austausch)$(Mult).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Mult).c .
#
$(ElMu).o: $(ElMu).c
$(CC) $(CFlags) $(ElMu).c
$(ElMu).c: $(Austausch)$(ElMu).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(ElMu).c .
#
$(KrPr).o: $(KrPr).c
$(CC) $(CFlags) $(KrPr).c
$(KrPr).c: $(Austausch)$(KrPr).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(KrPr).c .
#
$(SkPr).o: $(SkPr).c
$(CC) $(CFlags) $(SkPr).c
$(SkPr).c: $(Austausch)$(SkPr).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(SkPr).c .
#
$(SkMu).o: $(SkMu).c
$(CC) $(CFlags) $(SkMu).c
$(SkMu).c: $(Austausch)$(SkMu).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(SkMu).c .

25
#
$(VerSp).o: $(VerSp).c
$(CC) $(CFlags) $(VerSp).c
$(VerSp).c: $(Austausch)$(VerSp).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(VerSp).c .
#
$(VerZe).o: $(VerZe).c
$(CC) $(CFlags) $(VerZe).c
$(VerZe).c: $(Austausch)$(VerZe).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(VerZe).c .

Der Aufruf der Makefiles erfolgt mittels Kommando make.


05/austausch> make
gcc -g -c meinprog.c
gcc -g -c la.c
gcc -g -c laInOut.c
gcc -g -c laAdd.c
gcc -g -c laEins.c
gcc -g -c laNull.c
gcc -g -c laMult.c
gcc -g -c laElemMult.c
gcc -g -c laKopiere.c
gcc -g -c laKreuzProd.c
gcc -g -c laSkalProd.c
gcc -g -c laSkMult.c
gcc -g -c laVertauscheSp.c
gcc -g -c laVertauscheZe.c
ar r libla.a la.o laInOut.o laAdd.o laEins.o laNull.o laMult.o \
laElemMult.o laKopiere.o laKreuzProd.o laSkalProd.o laSkMult.o laVertauscheSp.o \
laVertauscheZe.o
ar s libla.a
gcc -g -o meinprog meinprog.o -lm -lla -L./
05/austausch>

Das verkürzte Makefile dazu ist makefile_kurz.


# makefile_kurz
#
CC = gcc

CFlags = -g -c

#
la = la
IO = laInOut
Add = laAdd
Eins = laEins
Null = laNull
Mult = laMult
ElMu = laElemMult
Kop = laKopiere
KrPr = laKreuzProd
SkPr = laSkalProd
SkMu = laSkMult
VerSp = laVertauscheSp
VerZe = laVertauscheZe
#
meinprog: meinprog.o libla.a
$(CC) -g -o meinprog meinprog.o -lm -lla -L./
#
meinprog.o: meinprog.c
$(CC) $(CFlags) meinprog.c
#
libla.a: $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(Kop).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o
ar r libla.a $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(Kop).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o

26
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
#
$(IO).o: $(IO).c
$(CC) $(CFlags) $(IO).c
#
$(Add).o: $(Add).c
$(CC) $(CFlags) $(Add).c
#
$(Eins).o: $(Eins).c
$(CC) $(CFlags) $(Eins).c
#
$(Null).o: $(Null).c
$(CC) $(CFlags) $(Null).c
#
$(Mult).o: $(Mult).c
$(CC) $(CFlags) $(Mult).c
#
$(ElMu).o: $(ElMu).c
$(CC) $(CFlags) $(ElMu).c
#
$(Kop).o: $(Kop).c
$(CC) $(CFlags) $(Kop).c
#
$(KrPr).o: $(KrPr).c
$(CC) $(CFlags) $(KrPr).c
#
$(SkPr).o: $(SkPr).c
$(CC) $(CFlags) $(SkPr).c
#
$(SkMu).o: $(SkMu).c
$(CC) $(CFlags) $(SkMu).c
#
$(VerSp).o: $(VerSp).c
$(CC) $(CFlags) $(VerSp).c
#
$(VerZe).o: $(VerZe).c
$(CC) $(CFlags) $(VerZe).c

Der Aufruf dieses Makefiles erfolgt mittels Kommando make -f makefile_kurz.


Der Aufruf der Programms erfolgt mittels Kommando meinprog bzw. unter Linux (Physik)
./meinprog, wobei als Datei zum LGS matrix23 genommen wird.

05/austausch> meinprog

Resttableau-Gauss-Algorithmus mit Spaltenpivotisierung und Zeilenvertauschung


Tausch mit betragsgroessten NNE in der Spalte
Ax=b, A => L\U, P, PA=LU
Ux=c Loesung mit Rueckwaertseinsetzen
-----------------------------------------------------------------------------

Dimension: n=3 m=3


Kontrollausgabe A,b (j/n)? j

Dimension A(n,m): n=3, m=3

A | b
1.000000 -2.000000 2.000000 1.000000
-1.000000 1.000000 -1.000000 -1.000000
-2.000000 -2.000000 1.000000 -3.000000
-----------------------------------------------------------------------------

27
Loesungsvektor x
1.000000 1.000000 1.000000
-----------------------------------------------------------------------------

Ergebnisprotokoll (j/n)? j
-----------------------------------------------------------------------------
Dimension A(n,m): n=3, m=3

A | b
1.000000 -2.000000 2.000000 1.000000
-1.000000 1.000000 -1.000000 -1.000000
-2.000000 -2.000000 1.000000 -3.000000

Loesungsvektor x
1.000000 1.000000 1.000000

Permutationsvektor perm
3 1 2

Zerlegung PA=L\U
-2.000000 -2.000000 1.000000
-0.500000 -3.000000 2.500000
0.500000 -0.666667 0.166667
-----------------------------------------------------------------------------

Version 2
Im Vergleich zu Version 1 gibt es zusätzlich die Quellen
laKopiere_, laKopiere1_, laNorm_.
# makefile
#
CC = gcc

CFlags = -g -c
#
Austausch = export/home/neundorf/tech_phy/05/make4b/
# Austausch = /home/Studenten/neundorf/make4a/
# Austausch = /home/Studenten/Austausch/
#
la = la_
IO = laInOut_
Add = laAdd_
Eins = laEins_
Null = laNull_
Mult = laMult_
ElMu = laElemMult_
KrPr = laKreuzProd_
SkPr = laSkalProd_
SkMu = laSkMult_
VerSp = laVertauscheSp_
VerZe = laVertauscheZe_
Kop = laKopiere_
Kop1 = laKopiere1_
Norm = laNorm_
#
meinprog: meinprog_.o libla.a
$(CC) -g -o meinprog_ meinprog_.o -lm -lla -L./
#
meinprog_.o: meinprog_.c
$(CC) $(CFlags) meinprog_.c

28
libla.a: $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
# Quellen aus dem Verzeichnis Austausch holen.
# Anders, falls diese im aktuellen Verzeichnis sind.
# cp $(Austausch)la.h .
ar r libla.a $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
$(la).c: $(Austausch)$(la).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(la).c .
#
$(IO).o: $(IO).c
$(CC) $(CFlags) $(IO).c
$(IO).c: $(Austausch)$(IO).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(IO).c .
#
$(Add).o: $(Add).c
$(CC) $(CFlags) $(Add).c
$(Add).c: $(Austausch)$(Add).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Add).c .
#
$(Eins).o: $(Eins).c
...
#
$(Null).o: $(Null).c
...
#
$(Mult).o: $(Mult).c
...
#
$(ElMu).o: $(ElMu).c
...
#
$(KrPr).o: $(KrPr).c
...
#
$(SkPr).o: $(SkPr).c
...
#
$(SkMu).o: $(SkMu).c
...
#
$(VerSp).o: $(VerSp).c
...
#
$(VerZe).o: $(VerZe).c
...
#
$(Kop).o: $(Kop).c
$(CC) $(CFlags) $(Kop).c
$(Kop).c: $(Austausch)$(Kop).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Kop).c .
#
$(Kop1).o: $(Kop1).c
$(CC) $(CFlags) $(Kop1).c
$(Kop1).c: $(Austausch)$(Kop1).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Kop1).c .
#
$(Norm).o: $(Norm).c
$(CC) $(CFlags) $(Norm).c
$(Norm).c: $(Austausch)$(Norm).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Norm).c .

29
Im Vergleich zu meinprog sind hier die Dateiarbeit flexibel gehandhabt, die Ausgabeformate
besser angepasst sowie Kontrollrechnungen ergänzt worden.

05/make4b> meinprog_

Resttableau-Gauss-Algorithmus mit Spaltenpivotisierung und Zeilenvertauschung


Tausch mit betragsgroessten NNE in der Spalte
Ax=b, A => L\U, P, PA=LU
Ux=c Loesung mit Rueckwaertseinsetzen
-----------------------------------------------------------------------------

Dateiname fuer Daten A,b zum LGS Ax=b : matrix23


Kontrollausgabe A,b (j/n)? j

Dimension A(n,m): n=3, m=3

A | b
1.000000 -2.000000 2.000000 | 1.000000
-1.000000 1.000000 -1.000000 | -1.000000
-2.000000 -2.000000 1.000000 | -3.000000
-----------------------------------------------------------------------------

Loesungsvektor x
1.000000 1.000000 1.000000
-----------------------------------------------------------------------------

Ergebnisprotokoll (j/n)? j
-----------------------------------------------------------------------------
Dimension A(n,m): n=3, m=3

A | b
1.000000 -2.000000 2.000000 | 1.000000
-1.000000 1.000000 -1.000000 | -1.000000
-2.000000 -2.000000 1.000000 | -3.000000

Loesungsvektor x
1.000000 1.000000 1.000000

Permutationsvektor perm
3 1 2

Zerlegung PA=L\U
-2.000000 -2.000000 1.000000
-0.500000 -3.000000 2.500000
0.500000 -0.666667 0.166667
-----------------------------------------------------------------------------

Kontrollrechnungen (j/n)? j
C1 = LU mittels laKopiere_
-2.000000 -2.000000 1.000000
-0.500000 -3.000000 2.500000
0.500000 -0.666667 0.166667

30
C2 = LU mittels laKopiere1_
-2.000000 -2.000000 1.000000
-0.500000 -3.000000 2.500000
0.500000 -0.666667 0.166667

C3 = A+C2
-1.000000 -4.000000 3.000000
-1.500000 -2.000000 1.500000
-1.500000 -2.666667 1.166667

Normen von b
1.000000 -1.000000 -3.000000
||b||_u= 3.000000, ||b||_1= 5.000000, ||b||_2= 3.316625

Normen von A
1.000000 -2.000000 2.000000
-1.000000 1.000000 -1.000000
-2.000000 -2.000000 1.000000
||A||_u= 5.000000, ||A||_1= 5.000000, ||A||_F= 4.582576

Auf den Test von Versionen in C++ verzichten wir an dieser Stelle.

Beispiel 5
Wir betrachten nun das Demoprogramm meinprog .c zum Algorithmus der Vektoriteration
und inversen Vektoriteration.
Die neuen Funktionen des Projekts sind im Rahmenprogramm enthalten, während die an-
deren Projektkomponenten vom Gauß-Algorithmus stammen.
Die Lang- und Kurzversionen des Makefiles sind wie folgt.
# makefile
#
CC = gcc

CFlags = -g -c
#
Austausch = /export/home/neundorf/tech_phy/05/make5/
#Austausch = /home/Studenten/neundorf/make5/
#Austausch = /home/Studenten/Austausch/
#
la = la_
IO = laInOut_
Add = laAdd_
Eins = laEins_
Null = laNull_
Mult = laMult_
ElMu = laElemMult_
KrPr = laKreuzProd_
SkPr = laSkalProd_
SkMu = laSkMult_
VerSp = laVertauscheSp_
VerZe = laVertauscheZe_
Kop = laKopiere_
Kop1 = laKopiere1_
Norm = laNorm_
#
meinprog_: meinprog_.o libla.a
$(CC) -g -o meinprog_ meinprog_.o -lm -lla -L./
#
meinprog_.o: meinprog_.c
$(CC) $(CFlags) meinprog_.c

31
#
libla.a: $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
# Quellen aus dem Verzeichnis Austausch holen.
# Anders, falls diese im aktuellen Verzeichnis sind.
# cp $(Austausch)$(la).h .
ar r libla.a $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
$(la).c: $(Austausch)$(la).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(la).c .
#
$(IO).o: $(IO).c
$(CC) $(CFlags) $(IO).c
$(IO).c: $(Austausch)$(IO).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(IO).c .
#
$(Add).o: $(Add).c
...
#
$(Eins).o: $(Eins).c
...
#
$(Null).o: $(Null).c
...
#
$(Mult).o: $(Mult).c
...
#
$(ElMu).o: $(ElMu).c
...
#
$(KrPr).o: $(KrPr).c
...
#
$(SkPr).o: $(SkPr).c
...
#
$(SkMu).o: $(SkMu).c
...
#
$(VerSp).o: $(VerSp).c
...
#
$(VerZe).o: $(VerZe).c
...
#
$(Kop).o: $(Kop).c
...
#
$(Kop1).o: $(Kop1).c
...
#
$(Norm).o: $(Norm).c
$(CC) $(CFlags) $(Norm).c
$(Norm).c: $(Austausch)$(Norm).c
cp $(Austausch)$(la).h .
cp $(Austausch)$(Norm).c .

---------------------------------------------------------------------------------------

# makefile_kurz
#
CC = gcc
CFlags = -g -c
#

32
la = la_
IO = laInOut_
Add = laAdd_
Eins = laEins_
Null = laNull_
Mult = laMult_
ElMu = laElemMult_
KrPr = laKreuzProd_
SkPr = laSkalProd_
SkMu = laSkMult_
VerSp = laVertauscheSp_
VerZe = laVertauscheZe_
Kop = laKopiere_
Kop1 = laKopiere1_
Norm = laNorm_
#
meinprog_: meinprog_.o libla.a
$(CC) -g -o meinprog_ meinprog_.o -lm -lla -L./
#
meinprog_.o: meinprog_.c
$(CC) $(CFlags) meinprog_.c
#
libla.a: $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
ar r libla.a $(la).o $(IO).o $(Add).o $(Eins).o $(Null).o $(Mult).o \
$(ElMu).o $(KrPr).o $(SkPr).o $(SkMu).o $(VerSp).o \
$(VerZe).o $(Kop).o $(Kop1).o $(Norm).o
ar s libla.a
#
$(la).o: $(la).c
$(CC) $(CFlags) $(la).c
#
$(IO).o: $(IO).c
$(CC) $(CFlags) $(IO).c
#
$(Add).o: $(Add).c
$(CC) $(CFlags) $(Add).c
#
$(Eins).o: $(Eins).c
$(CC) $(CFlags) $(Eins).c
#
$(Null).o: $(Null).c
$(CC) $(CFlags) $(Null).c
#
$(Mult).o: $(Mult).c
$(CC) $(CFlags) $(Mult).c
#
$(ElMu).o: $(ElMu).c
$(CC) $(CFlags) $(ElMu).c
#
$(KrPr).o: $(KrPr).c
$(CC) $(CFlags) $(KrPr).c
#
$(SkPr).o: $(SkPr).c
$(CC) $(CFlags) $(SkPr).c
#
$(SkMu).o: $(SkMu).c
$(CC) $(CFlags) $(SkMu).c
#
$(VerSp).o: $(VerSp).c
$(CC) $(CFlags) $(VerSp).c
#
$(VerZe).o: $(VerZe).c
$(CC) $(CFlags) $(VerZe).c
#
$(Kop).o: $(Kop).c
$(CC) $(CFlags) $(Kop).c
#
$(Kop1).o: $(Kop1).c
$(CC) $(CFlags) $(Kop1).c
#
$(Norm).o: $(Norm).c
$(CC) $(CFlags) $(Norm).c

33
In meinprog_ sind hier die Dateiarbeit flexibel gehandhabt und sowohl Vektoriteration als
auch inverse Vektoriteration ausgeführt.

05/make5> meinprog_

Vektoriteration und inverse Vektoriteration fuer Eigenwerte einer Matrix


VI: y(m+1)=Ay(m), |la(A)|_max ~ ||y(m+1)||/||y(m)||
Inv. VI: Ay(m+1)=y(m), |la(A)|_min = 1/|la(A^-1)|_max
Loesung des LGS mittels LU-Faktorisierung und gestaffelter Systeme
-------------------------------------------------------------------------------

Dateiname fuer Daten zur Matrix A : matrix23


Kontrollausgabe A (j/n)? Eingabe/Belegung des Startvektors
Definition/Einsvektor/1.Einheitsvektor (d/e/i): d
x0[0] = 1
x0[1] = 2
x0[2] = 3
Eingabe Toleranz eps>0: 1e-12
Eingabe maximale Iterationsanzahl maxiter>0: 10000

Vektoriteration
Betragsgroesster Eigenwert la = 1.0002000600739880e+00
Zugehoeriger skalierter Eigenvektor x
-0.577408 0.577350 0.577293
Iterationsanzahl iter = 10000
-------------------------------------------------------------------------------

Inverse Vektoriteration
Betragskleinster Eigenwert la = 9.9980003788891614e-01
Zugehoeriger skalierter Eigenvektor x
-0.577293 0.577350 0.577408
Iterationsanzahl iter = 10000
-------------------------------------------------------------------------------

Der einzige Eigenwert λ = 1 zur Matrix


 
1 −2 2
A =  −1 1 −1 
−2 −2 1

ist betragsgrößter und betragskleinster sowie dreifach.


Zugehöriger einziger Eigenvektor ist x = (−1, 1, 1)T , denn der Rang der Matrix A − λI ist 2.
Die Vektoriteration konvergiert, aber wegen der Vielfachheit sehr langsam, so dass zur Errei-
chung der Toleranz ε = 10−12 in der Abbruchbedingung | |λ|neu − |λ|alt | < ε die vorgegebene
maximale Iterationsanzahl wesentlich größer sein muss.

34

Das könnte Ihnen auch gefallen