====== Mehrdimensionale Felder ======
===== Grundlagen =====
Ein Element eines mehrdimensionalen Feldes wird über mehr als einen Index angesprochen.
**Beispiel Sitzplan:** 6 nebeneinander liegende Plätze bilden eine Reihe. 5 Reihen bilden die Klasse k.
#define plmax 6
#define reimax 5
#typedef int Reihe[plmax];
#typedef Reihe Klasse[reimax];
Klasse k;
Die Definition von Klasse kann auch als
typedef int Klasse[reimax][plmax];
geschrieben werden. Schließlich könnte ''k'' auch als
int k[reimax][plmax];
vereinbart werden.
Beim Zugriff auf ein Element eines zweidimensionalen Feldes müssen beide Indizes angegeben werden, wobei die Reihenfolge wesentlich ist.
In C%%++%% lautet die Angabe beispielsweise ''k[4][2]''.
{{:inf:cpp:arrays_mehrdim-1.png?direct|}}
Der Index des Platzes geht von 0 bis 5, der Index der Reihe von 0 bis 4. Wenn aber der Sitzplan einer Klasse bearbeitet wird, wird der linke vordere Platz als 1. Platz in der 1. Reihe bezeichnet (und nicht als 0. Platz in der 0. Reihe). In den folgenden Beispielen wird der Index des Feldes im C%%++%%-Programm immer auf diese 'übliche' Nummerierung umgerechnet.
**Beispiel:** Ein Programm soll geschrieben werden, das jedem Schüler (repräsentiert durch die Katalognummer) einen Platz in der Klasse zuordnet. Außerdem soll es möglich sein, dass zwei Schüler ihre Sitzplätze tauschen und anschließend der neue Sitzplan ausgegeben wird.
{{:inf:cpp:arrays_mehrdim-2a.png|}}
{{:inf:cpp:arrays_mehrdim-2b.png|}}
{{:inf:cpp:arrays_mehrdim-2c.png|}}
++++ gesamtes Programm|
/* Eingabe, Ausgabe und Änderung von Klassensitzplänen */
#include
#include
#include
using namespace std;
const int plmax=3, reimax=2;
typedef int Reihe[plmax];
typedef Reihe Klasse[reimax];
void platzschreiben
(int reihe,int platz,int nr)
{ gotoxy(platz*4+2,14-reihe*2);
cout.width(2);
cout << nr;
}
void platztausch(int &platz1,int &platz2)
{ int zwsp;
zwsp=platz1;
platz1=platz2;
platz2=zwsp;
}
void ausgabe(Klasse k)
{ int i,j;
clrscr(); gotoxy(0,0);
cout << "Ausgabe des Sitzplanes:\n";
for(i=0;i> k[i][j];
platzschreiben(i,j,k[i][j]);
}
}
/* Alternative Variante (reines Zeigerkonzept)
void platztausch(int *platz1,int *platz2)
{ int zwsp;
zwsp=*platz1;
*platz1=*platz2;
*platz2=zwsp;
}
void ausgabe(int *k)
{ int i,j;
clrscr(); gotoxy(0,0);
cout << "Ausgabe des Sitzplanes:\n";
for(i=0;i> *(k+i*plmax+j);
platzschreiben(i,j,*(k+i*plmax+j));
}
}
*/
// ******************************************************
int main()
{ int i,m,j,n;
Klasse k;
eingabe(k);
// eingabe(*k); // alternative Variante (reines Zeigerkonzept)
gotoxy(0,0); clreol();
cout << "Platztausch";
gotoxy(0,2); clreol();
cout << "Reihe des ersten Schuelers: "; cin >> i;
cout << "Platz des ersten Schuelers: "; cin >> j;
cout << "Reihe des zweiten Schuelers: "; cin >> m;
cout << "Platz des zweiten Schuelers: "; cin >> n;
platztausch(k[i-1][j-1],k[m-1][n-1]);
// platztausch(&k[i-1][j-1],&k[m-1][n-1]); // alternative Variante (reines Zeigerkonzept)
ausgabe(k);
// ausgabe(*k); // alternative Variante (reines Zeigerkonzept)
gotoxy(0,20);
system("PAUSE");
return 0;
}
Hinweis: Die Includedatei {{:inf:cpp:console.h|}} ermöglicht Befehle wie ''gotoxy(), clrscr(), clreol(), ...'' und muss ins Verzeichnis ''\Dev-Cpp\include'' kopiert werden.
++++
===== Übergabe von zweidimensionalen Feldern an Unterprogramme =====
Das Beispiel zeigt, dass zweidimensionale Felder genauso an Unterprogramme übergeben werden wie eindimensionale. Statt der Zeile
void eingabe(Klasse k)
kann auch
void eingabe(Klasse &k)
oder
void eingabe(int &k[reimax][plmax])
oder
void eingabe(int *k)
vereinbart werden.
In C%%++%% können sehr komplexe Datenstrukturen gebildet werden, ein- oder zweidimensionale Felder sind im Vergleich dazu sehr einfach. Wird die ''typedef''-Anweisung konsequent angewendet, bleiben die Programme trotzdem übersichtlich. Die erste Form des Beispiels ist daher am ehesten zu empfehlen.
**Beispiel Sitzplan mit Reihen- und Spaltentausch:**
Das Beispiel "Sitzplan" soll um zwei Prozeduren erweitert werden, sodass die Schüler zweier Reihen bzw. zweier Spalten des Sitzplans ihre Plätze tauschen können.
{{:inf:cpp:arrays_mehrdim-3a.png|}}
void reihentausch(Reihe reihe1,Reihe reihe2)
{ int j;
for (j=0;j
{{:inf:cpp:arrays_mehrdim-3b.png|}}
void spaltentausch(Klasse k,int spalte1, int spalte2)
{ int i;
for (i=0;i
Aufrufe:
int main()
{ int i,m,j,n;
Klasse k;
eingabe(k);
gotoxy(0,0); clreol(); cout << "Reihentausch";
gotoxy(0,2); clreol();
cout << "Erste Reihe fuer den Tausch: "; cin >> i;
cout << "Zweite Reihe fuer den Tausch: "; cin >> m;
reihentausch(k[i-1],k[m-1]);
ausgabe(k);
gotoxy(0,0); clreol(); cout << "Spaltentausch";
gotoxy(0,2); clreol();
cout << "Erste Spalte fuer den Tausch: "; cin >> j;
cout << "Zweite Spalte fuer den Tausch: "; cin >> n;
spaltentausch(k,j-1,n-1);
ausgabe(k);
gotoxy(0,20);
system("PAUSE");
return 0;
}
++++ gesamtes Programm|
/* Eingabe, Ausgabe und Änderung von Klassensitzplänen
mit Reihen- und Spaltentausch */
#include
#include
#include
using namespace std;
const int plmax=3, reimax=2;
typedef int Reihe[plmax];
typedef Reihe Klasse[reimax];
void platzschreiben
(int reihe,int platz,int nr)
{ gotoxy(platz*4+2,14-reihe*2);
cout.width(2);
cout << nr;
}
void platztausch(int &platz1,int &platz2)
{ int zwsp;
zwsp=platz1;
platz1=platz2;
platz2=zwsp;
}
void ausgabe(Klasse k)
{ int i,j;
clrscr(); gotoxy(0,0);
cout << "Ausgabe des Sitzplanes:\n";
for(i=0;i> k[i][j];
platzschreiben(i,j,k[i][j]);
}
}
void reihentausch(Reihe reihe1,Reihe reihe2)
{ int j;
for (j=0;j> i;
cout << "Zweite Reihe fuer den Tausch: "; cin >> m;
reihentausch(k[i-1],k[m-1]);
ausgabe(k);
gotoxy(0,0); clreol(); cout << "Spaltentausch";
gotoxy(0,2); clreol();
cout << "Erste Spalte fuer den Tausch: "; cin >> j;
cout << "Zweite Spalte fuer den Tausch: "; cin >> n;
spaltentausch(k,j-1,n-1);
ausgabe(k);
gotoxy(0,20);
system("PAUSE");
return 0;
}
++++
===== Felder von Feldern =====
Es ist auch möglich, nicht nur den Sitzplan einer Klasse, sondern den Sitzplan aller Klassen einer Schule in einer Variablen abzuspeichern:
Beispiel (die Schule hat 4 Klassen):
#define klmax 4
typedef Klasse Schule[klinax];
Schule s;
Wenn es die Daten erfordern, können auch noch mehr als drei Dimensionen bei Feldern definiert werden. Von C%%%++%% her gibt es da keine Einschränkung, aber es ist zu überlegen, wie viel Speicherplatz von einem Feld belegt wird.
Größe des Feldes ''s'': eine ''int''-Variable verlangt 2 Byte, daher insgesamt 240 (=''klmax*reimax*plmax*2'') Byte.
{{:inf:cpp:arrays_mehrdim-5.png|}}
Auf die einzelnen Komponenten eines zwei- oder mehrdimensionalen Feldes wird durch die Angabe des Feldnamens und aller Indizes zugegriffen.
Zugriffe (es werden die 'üblichen' Platzbezeichnungen in Indizes umgerechnet):
s[0][0][0] -> 1. KLASSE, 1. REIHE, 1. PLATZ\\
s[2][4][0] -> 3. KLASSE, 5. REIHE, 1. PLATZ\\
s[3][0][5] -> 4. KLASSE, 1. REIHE, 6. PLATZ\\
**Beispiel Minischulverwaltung:** Ein Programm soll geschrieben werden, das die Sitzpläne einer ganzen Schule einliest und feststellt, wie viele Plätze der Schule nicht besetzt sind.
{{:inf:cpp:arrays_mehrdim-4c.png|}} {{:inf:cpp:arrays_mehrdim-4d.png|}}
int unbesetzt(Schule s)
{ int leer=0,i,j,k;
for (i=0;i
Aufruf:
int main()
{ Schule s;
for (int c=0;c
++++ gesamtes Programm|
/* Minischulverwaltung */
#include
#include
#include
using namespace std;
const int plmax=3, reimax=2, klmax=2;
typedef int Reihe[plmax];
typedef Reihe Klasse[reimax];
typedef Klasse Schule[klmax];
void platzschreiben
(int reihe,int platz,int nr)
{ gotoxy(platz*4+2,14-reihe*2);
cout.width(2);
cout << nr;
}
void platztausch(int &platz1,int &platz2)
{ int zwsp;
zwsp=platz1;
platz1=platz2;
platz2=zwsp;
}
void ausgabe(Klasse k)
{ int i,j;
clrscr(); gotoxy(0,0);
cout << "Ausgabe des Sitzplanes:\n";
for(i=0;i> k[i][j];
platzschreiben(i,j,k[i][j]);
}
}
void reihentausch(Reihe reihe1,Reihe reihe2)
{ int j;
for (j=0;j
++++
===== Übungsaufgaben =====
Schreibe ein Programm,...
Ex 1>
... das eine 2*2-Matrix einliest, zeilenweise ausgibt und die Determinante berechnet.
Hinweis: {{:inf:cpp:tm-angewandtemathematik-matrizen.pdf|Hier}} kannst du dich über Matrizen informieren. Die Berechnung von Determinanten findest du auf Seite 13.
Ex 2>
... das eine 3*3-Matrix einliest, zeilenweise ausgibt und die Determinante berechnet.
Hinweis: {{:inf:cpp:tm-angewandtemathematik-matrizen.pdf|Hier}} kannst du dich über Matrizen informieren.
Ex 3>
... das ein lineares Gleichungssystem mit zwei Unbekannten mit Hilfe von Matrizen löst.
Hinweis: {{:inf:cpp:tm-angewandtemathematik-matrizen.pdf|Hier}} kannst du dich über Matrizen informieren. Wie du Gleichungssysteme mit Matrizen lösen kannst, ist auf Seite 14 beschrieben.
Ex 4>
... das eine n*n-Matrix transponiert, das heißt entlang der Hauptdiagonale spiegelt.
Hinweis: {{:inf:cpp:tm-angewandtemathematik-matrizen.pdf|Hier}} kannst du dich über Matrizen informieren.
Ex 5>
... das einen Kalender aufstellt. Dazu sind folgende Angaben notwendig:
* Nummer a des Tages, auf den der Monatserste fällt (a=0..Mo, usw.)
* Anzahl t der Tage des Monats
Aus diesen Angaben lassen sich die Elemente einer 7*6-Monatskalender-Matrix p (nichtbesetzte Tage gleich 0) berechnen. Das Programm soll den Kalender eines Monats aufstellen und in übersichtlicher Form ausgeben.
Ex 6>
... das für jedes beliebige Jahr einen vollständigen Kalender erstellt. /*Die dazu benötigten Formeln sind in den Beispielen 4.21 und 4.2J angegeben.*/
Anleitung:
* ''j''=Jahreszahl des Datums
* ''m''=Monat
* ''t''=Tag
Wenn ''m'' größer als 2 ist, ist ''m'' um 3 zu verringern; andernfalls ist ''m'' um 9 zu erhöhen und ''j'' um 1 zu verringern
* ''h''=ganzzahlige Division von ''j'' durch 100
* ''k''=Divisionsrest von ''j'' durch 100
* ''a''=ganzzahlige Division von ''146097 h'' durch 4
* ''b''=ganzzahlige Division von 1461
* ''k'' durch 4
* ''c''=ganzzahlige Division von ''153 m+2'' durch 5 ''n=a+b+c+t+1721119''
Aus der Tagesnummer ''n'' kann der Wochentag bestimmt werden: Divisionsrest von ''n'' durch 7 gleich 0...Montag usw.
Ex 7>
... das die Anzahl der Zeilen und Spalten einer Matrix (maximal 10*10), sowie die Matrix selbst einliest. Danach sollen die Zeilen der Matrix nach der Anzahl ihrer Nullen sortiert werden (Die Zeile mit den meisten Nullen an erster Stelle.) Danach ist die Matrix auszugeben.
Ex 8>
... das das Produkt zweier Matrizen berechnet. Voraussetzung ist, dass die Anzahl der Spalten der Matrix A gleich der Anzahl der Zeilen der Matrix B ist.
Ex 9>
... das die monatlichen Niederschlagsmengen auswertet. Für den Zeitraum von 4 Wochen wird täglich der gefallene Niederschlag gemessen. Die so erhaltenen Messergebnisse sollen folgendermaßen ausgewertet werden:
* der Tag mit dem meisten Niederschlag,
* die Gesamtniederschlagsmenge pro Woche,
* die Woche mit dem meisten Niederschlag,
* die längste Trockenperiode in dem betrachteten Zeitraum (Niederschlagt),
* die durchschnittliche Niederschlagsmenge pro Woche und Tag.
Ex 10>
... das die Rangliste von Vereinen nach Austragung einer Fußballmeisterschaft (jeder Verein gegen jeden) erstellt:
Jeder Verein erhält für einen Sieg 2 Punkte, für ein Unentschieden erhalten beide Vereine je einen Punkt. Auf Grund der Punktesumme wird eine Reihung der Vereine vorgenommen.
* Bei Punktegleichheit mehrerer Mannschaften entscheidet die Tordifferenz (Differenz zwischen geschossenen und erhaltenen Toren einer Mannschaft).
* Ist auch diese gleich, so wird die Mannschaft mit der größeren Anzahl von erzielten Toren vorgereiht.
* Sonst wird derselbe Platz mehrmals vergeben.
Das Programm soll eine n*n-Matrix T der geschossenen Tore einlesen (T[i][j] ist die Anzahl der Tore, die der Verein j im Spiel gegen den Verein i erzielt hat) und daraus für jeden der n Vereine die Platzierung in der Rangliste, die Nummer (eventuell auch den Namen) des Vereins, die Summe der insgesamt geschossenen und erhaltenen Tore, sowie die Anzahl der Punkte berechnen und in der Reihenfolge der Platzierung ausgeben.
Ex 11>
...das n*n Zahlen liest (n%%<=%%5) und feststellt, ob diese Zahlen ein magisches Quadrat bilden. Bei einem magischen Quadrat ist die Summe der Zahlen in jeder Zeile und in jeder Spalte gleich.
Beispiel:
|2|4|9|
|7|3|5|
|6|8|1|