Lösungen Übung 5 1. Aufgabe #include <stdarg.h> int max(int anzarg, int a, int b,...) // Hilfsvariable für variable Parameter va_list argumente; va_start(argumente,b); // "b" letzter Parameter der Funktion, mit dessen // Hilfe der Makro die Anfangsadresse der variablen Para- // meterliste ermittelt int m = a; if (b > m) m = b; for (int i = 3; i <= anzarg; i++) int par = va_arg(argumente, int); // sukzessive Anwendung des Makro va_arg // Der Datentyp der Argumente ist int if (par > m) m = par; va_end(argumente); // Schliessen der Bearbeitung "Parameterliste" return m; double max(int anzarg, double a, double b,...) // Hilfsvariable für variable Parameter va_list argumente; va_start(argumente,b); // "b" letzter Parameter der Funktion, mit dessen // Hilfe der Makro die Anfangsadresse der variablen Para- // meterliste ermittelt double m = a; if (b > m) m = b; for (int i = 3; i <= anzarg; i++) double par = va_arg(argumente, double); // sukzessive Anwendung des Makro va_arg // Der Datentyp der Argumente ist int if (par > m) m = par; va_end(argumente); // Schliessen der Bearbeitung "Parameterliste" return m; void main() // cout << max(4,20,30,40,50) << endl; cout << "a) " << max(3, 17, 20, 15) << endl; cout << "b) " << max(2, 8.4, 13.7) << endl; cout << "c) " << max(4, 4.5, 12.2, 8.4,13.0) << endl; cout << "d) " << max(4, 4.5, 12.2, 8.4,13) << endl; 1) Die Ausgabe d) ist falsch, weil vom Compiler an Hand des 2. und 3. Parameters double max() ausgewählt wurde, der letzte Parameter jedoch vom Typ int ist. Da dieser sich allerdings im variablen Teil der formalen Parameterliste befindet, konnte der Compiler weder eine Fehlermeldung noch eine passende Datenkonversion (Ausweitung auf double) erzeugen. So wurde ein int-parameter übergeben, dessen Bitmuster von der Funktion max() als double-wert interpretiert wird. 2) Der Compiler ruft jetzt in den Zeilen b) bis d) die int-version auf. Die notwendigen Typ-Konversionen (Abschneiden der Nachkommastellen) werden automatisch durchgeführt, allerdings nur dort, wo der Übersetzer 1
weiß, welcher Datentyp erwartet wird (2. und 3. Parameter). Daher ist a) und b) halbwegs richtig. In den Fällen c) und d) werden unkonvertierte double-werte übermittelt, die, als int-werte interpretiert, keinen Sinn geben. 2. Aufgabe 1 /* Die Tuerme von Hanoi ------------------- In einer Tempelstadt sollen sich 3 Podeste aus Kupfer, Gold und Siber befunden haben. der Sage nach soll das Ende der Welt gekommen sein, falls es jemand gelingt: - 100 Scheiben, die auf dem Kunpferpodest liegen, abzutragen und in derselben Reihenfolge auf dem Golpodest aufzuschichten. - Scheiben duerfen auch auf dem Silberpodest abgelegt werden - Es ist nicht erlaubt, dass eine kleinere Scheibe auf einer groesseren abgelegt wird // Beschreibung der Klasse hanoi class hanoi private: char quellplatz, hilfsplatz, zielplatz; short n; short anzaufrufe; public: hanoi(); void bewegeturm(short,char,char,char); ; // Beschreibung der in der Klasse deklarierten Schnittstellen // (Methoden) hanoi :: hanoi() anzaufrufe = 0; void hanoi :: bewegeturm(short n, char quellplatz, char zielplatz, char hilfsplatz) if(n > 0) bewegeturm(n-1, quellplatz, hilfsplatz, zielplatz); cout << "\n\taufruf Nr. " << ++anzaufrufe << " Bewege Scheibe " << n << " von Turm " << quellplatz << " nach Turm " << zielplatz; bewegeturm(n-1, hilfsplatz, zielplatz, quellplatz); // Klient (client) int main() const short MAXSCHEIBEN = 16; // Mehr dauert ewig. 1 Vgl. PR17311.CPP 2
short anzahl; hanoi turm; // Instanz, Objekt bzw. Server /* Wie bei einer Variablendefinition wird für ein Objekt Speicherplatz bereitgestellt. Zu diesem Zweck wird eine besondere Klassendefinition aufgerufen, die Konstruktor genannt wird. Der Konstruktor wird vom System automatisch bereitgestellt, kann aber auch selbst definiert werden. cout << "\n\n\t\t\tdie Tuerme von Hanoi"; cout << "\n\t\t\t-------------------\n\n"; do cout << "\twieviele Scheiben sollen bewegt werden (max. " << MAXSCHEIBEN << "): "; cin >> anzahl; while ((anzahl < 1) (anzahl > MAXSCHEIBEN)); /* Der Server "turm" erbringt fuer den Klient "main" eine Dienstleistung turm.bewegeturm(anzahl, 'K', 'S', 'G'); // Rekursionsanfang cout << endl; // Ende von main() 3. Aufgabe /* Das Problem der acht Damen -------------------------- Kurzbeschreibung: Durch Backtracking werden alle Moeglichkeiten gefunden, acht Damen so auf einem Schachbrett zu positionieren, daá keine Dame eine andere bedroht. class damen private: unsigned short pos[8]; bool Zeile[8]; bool HD[15]; // Hauptdiagonale "/" bool ND[15]; // Nebendiagonale "\" public: damen(); // Konstruktor void versuche(int); friend ostream& operator <<(ostream &, damen &); // Ausgabe ; // ------ Schnittstellendefinition (Methoden) ------------------- damen :: damen() int i; // Im Konstruktor werden die einzelnen Felder initialisiert. for(i = 0; i < 8; i++) Zeile[i] = true; for(i = 0; i < 15; i++) HD[i] = ND[i] = true; 3
void damen :: versuche(int j) for(int i = 0; i < 8; i++) if(zeile[i] && HD[j+i] && ND[7+i-j]) // Position ist moeglich, also wird Dame gesetzt: pos[i] = j; // Dadurch werden alle oben ueberprueften Zeilen und // Diagonalen bedroht: Zeile[i] = HD[j+i] = ND[7+i-j] = false; /* Falls noch nicht alle Damen gesetzt wurden, erfolgt ein weiterer, rekursiver Aufruf, der die naechste Spalte ueberprueft. if(j < 8) versuche(j+1); else // Sonst wurde moegliche Loesung gefunden cout << (*this); // Die Belegung der Damen wird ausgegeben /* Nun muss der Versuch noch zurueckgenommen werden, da er am nach Verlassen dieser Spalte wieder moeglich wird Zeile[i] = HD[j+i] = ND[7+i-j] = true; // Ende von if(... // Ende von for(... // Ende von Versuche() // --------- non-member-funktionen --------------------- ostream& operator<<(ostream &s, damen &d) const char pluszeichen = '+'; const char minuszeichen = '-'; const char leerzeichen = ' '; const char strichzeichen = ' '; for (short k = 0; k < 8; k++) for (short m = 0; m < 3; m++) s << minuszeichen; for (short i = 0; i < 8; i++) s << strichzeichen; for (short j = 0; j < 8; j++) s << leerzeichen; if (d.pos[i] == j + 1) s << 'X'; else s << leerzeichen; s << leerzeichen << strichzeichen; for (short k = 0; k < 8; k++) for (short m = 0; m < 3; m++) s << minuszeichen; return s; // --------Klient: main-program ------------------------ 4
int main() damen queens; queens.versuche(1); // Ende von main() // Instanz, Server // Rekursionsanfang 4. Aufgabe #include <iomanip.h> class springer private: int x0, y0; // Anfangsposition des Springer int add_x[8]; int add_y[8]; int brett[5][5]; public: springer(int,int); void finde_weg(int,int,int,bool&); friend ostream& operator<<(ostream&, springer&); ; springer :: springer(int x, int y) x0 = x; y0 = y; for (int i = 0; i < 5; i++) for (int j = 0; j < 5; j++) brett[i][j] = 0; add_x[0] = -1; add_y[0] = +2; add_x[1] = -2; add_y[1] = +1; add_x[2] = -2; add_y[2] = -1; add_x[3] = -1; add_y[3] = -2; add_x[4] = +1; add_y[4] = -2; add_x[5] = +2; add_y[5] = -1; add_x[6] = +2; add_y[6] = +1; add_x[7] = +1; add_y[7] = +2; brett[x0][y0] = 1; void springer :: finde_weg(int zug, int x, int y, bool& erfolg) int versuch = 0; int x_neu, y_neu; bool erfolgreich; // cout << (*this); do erfolgreich = false; versuch++; x_neu = x + add_x[versuch-1]; y_neu = y + add_y[versuch-1]; if (((x_neu >= 0) && (x_neu < 5)) && ((y_neu >= 0) && (y_neu < 5))) // Zug zulaessig if (brett[x_neu][y_neu] == 0) brett[x_neu][y_neu] = zug; // Feld als belegt markieren if (zug < 25) 5
// Alle Felder sind noch nicht besprungen finde_weg(++zug,x_neu,y_neu,erfolgreich); if (!erfolgreich) brett[x_neu][y_neu] = 0; zug--; else erfolgreich = true; while ((!erfolgreich) && (versuch!= 8)); erfolg = erfolgreich; ostream& operator<<(ostream& s, springer& w) s << "\n"; for (int i = 0; i < 5; i++) for (int j = 0; j < 5; j++) s << setw(3) << w.brett[i][j] << " "; return(s); int main() bool gefunden; int x, y; // Anfangsposition des Springer cout << "\nanfangsposition des Springer a) x-koordinate: "; cin >> x; cout << "Anfangsposition des Springer b) y-koordinate: "; cin >> y; springer springer_weg(x,y); springer_weg.finde_weg(2,x,y,gefunden); if (gefunden) cout << springer_weg; else cout << "Kein Loesungsweg gefunden"; // cout << springer_weg; // Ende von main() 6