Lösungen zu den Aufgaben des C/C++ Kurses
Transcription
Lösungen zu den Aufgaben des C/C++ Kurses
Universität Regensburg Fakultät Physik IT-Ausbildung Lösungen zu den Aufgaben des C/C++ Kurses Die hier aufgeführten Lösungen zu den Aufgaben sind als Vorschläge gedacht, wobei auf eine kurze und knappe Problemlösung Wert gelegt wurde. Oft gibt es Alternativlösungen zu den Aufgaben, sowohl in C als auch in C++. Bei den angegebenen Lösungen wird C++ und CCode bewußt gemischt, um die Transparenz zwischen den beiden Sprachen zu demonstrieren (Ausnahme: Aufgaben 1, 43). Aufgabe 1 Schreiben Sie ein Programm, das den Namen des Benutzers einliest und ihn dann mit seinem Namen begrüßt. Verwenden Sie sowohl printf bzw. scanf als auch cout und cin. Erweitern Sie dazu das in Kapitel 1 abgedruckte Hello world‘-Programm. ’ I Lösung: (ANSI-C) 1 # include < stdio .h > 2 3 4 5 int main ( void ) { char name [30]; 6 printf (" Name eingeben : "); scanf ("% s " , name ); printf (" Hallo % s !\ n " , name ); 7 8 9 10 } I Lösung: (C++) 1 # include < iostream > 2 3 using namespace std ; 4 5 6 7 int main ( void ) { char name [30]; 8 cout << " Name eingeben : "; cin >> name ; cout << " Hallo " << name << "!" << endl ; 9 10 11 12 } Aufgabe 2 Lesen Sie mit scanf und cin ein Wort, ein Zeichen und eine Fließkommazahl ein und geben Sie die Inhalte mit printf und cout wieder aus. I Lösung: 1 2 # include < stdio .h > # include < iostream > 3 4 using namespace std ; 5 6 7 8 9 10 int main ( void ) { char wort [30]; char c ; float x ; 11 printf (" Wort , Zeichen und Zahl eingeben : "); scanf ("% s % c % f " , wort , &c , & x ); printf (" Eingegeben wurde : %s , %c , % f \ n " , wort , c , x ); 12 13 14 15 cout << " Wort , Zeichen und Zahl eingeben : "; cin >> wort >> c >> x ; cout < <" Eingegeben wurde : " < < wort < <" , " < <c < <" , " < <x < < endl ; 16 17 18 19 } Aufgabe 3 Lesen Sie zwei ganze Zahlen ein und geben Sie deren Summe, Produkt, Differenz und Quotienten aus. Achten Sie beim Teilen auf die Richtigkeit des Ergebnisses! I Lösung: 1 # include < stdio .h > 2 3 4 5 int main ( void ) { int n , m ; 6 printf ("2 Zahlen eingeben : "); scanf ("% d % d " , &n , & m ); printf ("% d + % d = % d \ n " , n , m , printf ("% d - % d = % d \ n " , n , m , printf ("% d * % d = % d \ n " , n , m , printf ("% d / % d = % f \ n " , n , m , 7 8 9 10 11 12 13 } n + m ); n - m ); n * m ); ( float ) n / m ); Aufgabe 4 Geben Sie mithilfe des Modulo-Operators % die letzte Ziffer einer vom Benutzer eingegebenen Ganzzahl (int) aus. I Lösung: 1 # include < stdio .h > 2 3 4 5 int main ( void ) { int zahl ; 6 printf (" Zahl eingeben : "); scanf ("% d " , & zahl ); printf (" Die letzte Ziffer von % d ist % d \ n " , zahl , zahl %10); 7 8 9 10 } Aufgabe 5 Ein Zeichen soll eingelesen und dann wieder ausgegeben werden. Dabei soll die Ausgabe sowohl als Zeichen als auch als Dezimal- bzw. Hexadezimalwert erfolgen (z.B.: z → z 122 0x7A). Verwenden Sie sowohl scanf als auch cin für die Eingabe, bei der Ausgabe probieren Sie cout und printf aus. I Lösung: 1 2 # include < stdio .h > # include < iostream > 3 4 using namespace std ; 5 6 7 8 9 10 11 12 13 14 int main ( void ) { char z ; cout << "\ nEin Zeichen eingeben : "; cin >> z ; cout < <" Das Zeichen war : " < <z < <" , dezimal : " < < int ( z ) < <" , hex : 0 x " < < hex < < int ( z ); printf ("\ nDas Zeichen war : %c , dezimal : %d , hex : 0 x % x \ n " ,z ,z , z ); } Aufgabe 6 Erstellen Sie ein Programm, das mithilfe einer for-Schleife alle durch 7 teilbaren Zahlen zwischen zwei zuvor eingegebenen Grenzen ausgibt. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 6 7 int main ( void ) { int a , b ; 8 cout << " Untergrenze : cout << " Obergrenze : 9 10 "; cin >> a ; "; cin >> b ; 11 for ( int i = a ; i <= b ; i = i +1) if ( i %7==0) cout << i << " 12 13 14 "; } Aufgabe 7 Schreiben Sie ein Programm, das zu einem gegebenen Anfangskapital bei einem vorgegebenem jährlichen Zinssatz berechnet, wie viele Jahre benötigt werden, damit das Kapital eine bestimmte Zielsumme überschreitet. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 6 7 8 int main ( void ) { int jahre =0; double kapital , zins , endkapital ; 9 cout << " Anfangskapital : "; cin >> kapital ; cout << " Zinssatz in %: "; cin >> zins ; cout << " Angestrebtes Endkapital : cin >> endkapital ; 10 11 12 13 14 15 "; 16 17 while ( kapital < endkapital ) { jahre ++; kapital += kapital *( zins /100); } 18 19 20 21 22 23 cout << " Es dauert " << jahre << " Jahre !" << endl ; 24 25 } Aufgabe 8 Erweitern Sie das in Kapitel 3.3 abgedruckte Programm so, dass ein Schachbrettmuster auf dem Bildschirm erscheint. I Lösung: 1 # include < stdio .h > 2 3 4 5 int main ( void ) { int zeile , n , m ; 6 for ( zeile =1; zeile <=4; zeile = zeile +1) { for ( m =1; m <=2; m = m +1) { for ( n =1; n <=4; n = n +1) printf ("*** "); printf ("\ n "); } 7 8 9 10 11 12 13 14 15 for ( m =1; m <=2; m = m +1) { for ( n =1; n <=4; n = n +1) printf (" ***"); printf ("\ n "); } 16 17 18 19 20 21 } 22 23 } Aufgabe 9 Schreiben Sie ein Programm, das das kleine Einmaleins berechnet und in Tabellenform auf dem Bildschirm ausgibt. I Lösung: 1 # include < stdio .h > 2 3 4 5 int main ( void ) { int i , j ; 6 printf (" 7 | 1 2 3 4 5 6 7 8 9 10\ n "); 8 printf (" - - -+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\ n "); 9 10 for ( i =1; i <=10; i ++) { printf ("%2 d | " , i ); for ( j =1; j <=10; j ++) printf ("%3 d " , i * j ); printf ("\ n "); } 11 12 13 14 15 16 17 } Aufgabe 10 Geben Sie alle Primzahlen zwischen 2 und einer vom Benutzer einzugebenen Obergrenze aus. Bestimmen Sie die Primzahlen mittels Ganzzahldivision. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 6 7 int main ( void ) { int zahl , teiler , limit ; 8 cout << " Obergrenze eingeben : "; cin >> limit ; cout << "\ nPrimzahlen bis " << limit << ":\ n "; 9 10 11 12 for ( zahl =2; zahl < limit ; zahl ++) { teiler = 2; while ( zahl % teiler != 0) teiler ++; if ( teiler == zahl ) cout << zahl << " "; } 13 14 15 16 17 18 19 } Aufgabe 11 Geben Sie einen Christbaum‘ durch Ausdruck entsprechend vieler Leerzeichen und Sterne auf ’ dem Bildschirm aus. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 6 7 int main ( void ) { int blzahl =20 , sternzahl =1 , i , zeile ; 8 for ( zeile =0; zeile <10; zeile ++) { for ( i =0; i < blzahl ; i ++) cout << ’ ’; for ( i =0; i < sternzahl ; i ++) cout << ’* ’; blzahl - -; sternzahl +=2; cout << ’\n ’; } 9 10 11 12 13 14 15 16 } Aufgabe 12 In unserem Kalender sind zum Ausgleich der astronomischen und kalendarischen Jahreslänge in regelmäßigen Abständen Schaltjahre eingebaut. Zur exakten Festlegung der Schaltjahre dienen die folgenden Regeln: ◦ Ist die Jahreszahl durch 4 teilbar, so ist das Jahr ein Schaltjahr. Diese Regel hat allerdings eine Ausnahme: ◦ Ist die Jahreszahl durch 100 teilbar, so ist das Jahr kein Schaltjahr. Diese Ausnahme hat wiederum eine Ausnahme: ◦ Ist die Jahreszahl durch 400 teilbar, so ist das Jahr doch ein Schaltjahr. Erstellen Sie ein Programm, das berechnet, ob eine vom Benutzer eingegebene Jahreszahl ein Schaltjahr bezeichnet oder nicht. I Lösung: 1 # include < stdio .h > 2 3 4 5 int main () { int jahr ; 6 printf (" Geben Sie ein Jahr ein : "); scanf ("% d " ,& jahr ); 7 8 9 if ( jahr %4==0) if ( jahr %100==0) if ( jahr %400==0) printf (" Schaltjahr !\ n "); else printf (" Kein Schaltjahr !\ n "); else printf (" Schaltjahr !\ n "); else printf (" Kein Schaltjahr !\ n "); 10 11 12 13 14 15 16 17 18 19 20 } Aufgabe 13 Programmieren Sie das Spiel Zahlenraten‘: Der Computer generiert eine Zufallszahl zwischen ’ 1 und 100, die der Spieler erraten muß. Es wird bei jedem Durchgang mitgeteilt, ob die eingegebene Zahl zu groß oder zu klein war. Tipp: Zufallszahlen werden wie folgt generiert: Ein einmaliger Aufruf srand(time(NULL)) initialisiert den Zufallszahlengenerator. Anschließend liefert jeder Aufruf von rand()%100 eine Zufallszahl zwischen 0 und 99. Die Funktionen sind in stdlib.h bzw. time.h deklariert. I Lösung: 1 2 3 # include < stdio .h > # include < time .h > # include < stdlib .h > 4 5 6 7 int main ( void ) { int zahl , rat , versuche =0; 8 srand ( time ( NULL )); zahl = rand ()%100 + 1; 9 10 11 do 12 { 13 printf (" Zahl eingeben : "); scanf ("% d " , & rat ); if ( rat > zahl ) printf (" Zu gross !\ n "); if ( rat < zahl ) printf (" Zu klein !\ n "); versuche ++; 14 15 16 17 18 } while ( rat != zahl && versuche <6); 19 20 21 if ( rat == zahl ) printf (" Erraten !\ n "); else printf (" Verloren ! Die gesuchte Zahl war % d \ n " , zahl ); 22 23 24 } Aufgabe 14 (fakultativ) Lösen Sie die quadratische Gleichung ax2 + bx + c = 0 für vom Benutzer eingegebene Parameter a, b und c. Falls Ihnen komplexe Zahlen geläufig sind, sollen auch komplexe Lösungen ausgegeben werden. √ b2 − 4ac . 2a Die Funktion float sqrt(float) zur Berechnung der Wurzel einer positiven Zahl ist in math.h deklariert. Zum Testen des Programms können Sie folgende Parametersätze verwenden: 4, -36, 81 → 4.5; 2, 2, -12 → 2, 3; 1, -2, 2 → 1+ −i. Tipp: Die Lösungsformel für die quadratische Gleichung lautet: x1/2 = −b ± I Lösung: 1 2 # include < iostream > # include < math .h > 3 4 using namespace std ; 5 6 7 8 int main ( void ) { float a ,b ,c , D ; // a * x * x + b * x + c = 0 9 cout << "\ nKoeffizienten a b c : "; cin >> a >> b >> c ; 10 11 12 D = b *b -4* a * c ; if ( D ==0) cout << " x = " << -b /(2* a ) << endl ; if (D >0) cout << " x = " << ( - b + sqrt ( D ))/(2* a ) << " und x = " << ( -b - sqrt ( D ))/(2* a ) << endl ; if (D <0) cout << " x = " << -b /(2* a ) << "+ -" << sqrt ( - D )/(2* a ) << "* i " << endl ; 13 14 15 16 17 18 19 } Aufgabe 15 Programmieren Sie mithilfe der switch-case Anweisung einen Mini-Taschenrechner, der zwei Zahlen und einen Operator (+, -, *, /) einliest und das Ergebnis ausgibt. Eine eventuelle Division durch 0 soll abgefangen werden. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 int main ( void ) { float z1 , z2 ; char op ; cout << "2 Zahlen mit Operator dazwischen [+ -*/]: "; cin >> z1 >> op >> z2 ; cout << z1 << op << z2 << "="; switch ( op ) { case ’+ ’: cout << z1 + z2 << ’\n ’; break ; case ’ - ’: cout << z1 - z2 << ’\n ’; break ; case ’* ’: cout << z1 * z2 << ’\n ’; break ; case ’/ ’: if ( z2 ==0) cout << " Div durch 0 geht nicht \ n "; else cout << z1 / z2 << ’\n ’; break ; default : cout << " Den Operator kenne ich nicht \ n "; } } Aufgabe 16 Primzahlberechnung nach dem Sieb-Verfahren: Schreiben Sie alle Zahlen (z.B. von 2 bis 100) in ein Array. Beginnend mit der kleinsten Zahl wird die Zahl als Primzahl auf dem Bildschirm ausgegeben und gleichzeitig alle Vielfachen dieser Zahl im Array auf 0 gesetzt d.h. aus der Liste gestrichen. Anschliessend wird die nächste Zahl 6= 0 im Array bearbeitet. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 6 7 int main ( void ) { int a [100] , i , j ; 8 for ( i =0; i <100; i ++) a [ i ]= i ; cout << "\ nDie Ersten Primzahlen ...\ n "; for ( i =2; i <100; i ++) { if ( a [ i ] >0) { cout << a [ i ] << ’ ’; for ( j =2* i ; j <100; j += i ) a [ j ]=0; } } 9 10 11 12 13 14 15 16 17 18 19 } Aufgabe 17 Lesen Sie eine Integerzahl ein und geben Sie deren Bitmuster aus (z.B.: 23 → 00010111). I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 6 7 8 int main ( void ) { short int n ; unsigned short int maske =0 x80 ; 9 cout << "8 - Bit - Integer eingeben : "; cin >> n ; cout << " dezimal : " << n << " binaer : "; while ( maske ) { if (( n & maske ) > 0) cout << ’1 ’; else cout << ’0 ’; maske > >=1; } 10 11 12 13 14 15 16 17 18 19 20 21 } Aufgabe 18 Bestimmen Sie die Primfaktorzerlegung einer eingegebenen Zahl (z.B.: 200 = 2*2*2*5*5). I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 6 7 int main ( void ) { int zahl , i , anz =0; 8 cout << " Gib Integerzahl ein : "; cin >> zahl ; cout << " Zerlegung : "; for ( i =2; i <= zahl ; i ++) while ( zahl % i == 0) { if ( anz ==0) cout << i ; else cout << ’* ’ << i ; anz ++; zahl /= i ; } 9 10 11 12 13 14 15 16 17 18 19 20 21 22 } Aufgabe 19 Sortieren Sie ein mit Zufallszahlen belegtes Array beliebiger Größe mit dem Bubble-SortVerfahren: jeweils zwei benachbarte Feldelemente werden vertauscht, wenn sie in der falschen Reihenfolge sind. I Lösung: 1 2 # include < iostream > # include < stdlib .h > 3 4 using namespace std ; 5 6 7 8 int main ( void ) { int a [10] , i , zw , change ; 9 cout << " unsortiert : for ( i =0; i <10; i ++) { a [ i ]= rand ()%100; cout << a [ i ] << ’ ’; } 10 11 12 13 14 15 "; 16 // sortieren ( und dabei ausgeben ...) do { cout << "\ nZwischenschritt : "; change =0; // keine Vertauschung noetig for ( i =0; i <9; i ++) if ( a [ i ] > a [ i +1]) { zw = a [ i ]; a [ i ]= a [ i +1]; a [ i +1]= zw ; change =1; // Vertauschung } for ( i =0; i <10; i ++) cout << a [ i ] << ’ ’; } while ( change ); 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 } Aufgabe 20 Schreiben Sie ein Sortierprogramm, das nach dem Selection-Sort Algorithmus arbeitet: 1. suche das kleinste/größte Element des Arrays, 2. vertausche dieses mit dem ersten Element des Arrays, 3. gehe wieder zu Schritt 1, jetzt aber mit dem verkürzten Array. Wieso ist dieses Verfahren effizienter als Bubble-Sort? I Lösung: 1 2 # include < iostream > # include < stdlib .h > 3 4 using namespace std ; 5 6 7 8 int main ( void ) { int a [10] , i , k , zw , min , stelle ; 9 cout << " unsortiert : for ( i =0; i <10; i ++) { a [ i ]= rand ()%100; cout << a [ i ] << ’ ’; } 10 11 12 13 14 15 "; 16 for ( k =0; k <10; k ++) { cout << "\ nZwischenschritt : "; min = a [ k ]; stelle = k ; for ( i = k ; i <10; i ++) /* suche kleinstes Element */ if ( a [ i ] < min ) { min = a [ i ]; stelle = i ; } zw = a [ stelle ]; a [ stelle ]= a [ k ]; a [ k ]= zw ; for ( i =0; i <10; i ++) cout << a [ i ] << ’ ’; } 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 } Aufgabe 21 (fakultativ) Familie Müller ist zu einer Geburtstagsfeier eingeladen. Leider können sich die Familienmitglieder (Anton, Berta, Claus und Doris) nicht einigen, wer hingeht und wer nicht. In einer gemeinsamen Diskussion kann man sich jedoch auf die folgenden Grundsätze verständigen: ◦ ◦ ◦ ◦ ◦ Mindestens ein Familienmitglied geht zu der Feier. Anton geht auf keinen Fall zusammen mit Doris. Wenn Berta geht, dann geht Claus mit. Wenn Anton und Claus gehen, dann bleibt Berta zu Hause. Wenn Anton zu Hause bleibt, dann geht entweder(!) Doris oder Claus. Helfen Sie Familie Müller, indem Sie ein Programm erstellen, das alle Gruppierungen ermittelt, in denen Familie Müller zur Feier gehen könnte. Tipp: Erstellen Sie alle denkbaren Kombinationen und prüfen Sie jede darauf, ob sie alle obigen Grundsätze erfüllt. I Lösung: 1 2 # include < stdio .h > # include < stdlib .h > 3 4 5 6 7 8 int main ( void ) { unsigned char a , b , c , d ; unsigned char gehen ; unsigned char z =0; 9 printf (" Folgende Personen koennen zusammen gehen : \ n \ n "); 10 11 /* Dabei heisst z . B . a == 1 , dass Anton mitgehen moechte ,*/ for ( a = 0; a <= 1; a = a + 1) for ( b = 0; b <= 1; b = b + 1) for ( c = 0; c <= 1; c = c + 1) for ( d = 0; d <= 1; d = d + 1) { // EINE Moeglichkeit der Implementierung gehen = ( ( a || b || c || d ) && ( ! d || ! a ) && ( ! b || c ) && ((!( a && c )) || ! b ) && ( a || ( d || c ))); 12 13 14 15 16 17 18 19 20 21 22 23 24 if ( gehen == 1) { printf (" % d . " , z = z +1); if ( a ) printf (" Anton "); if ( b ) printf (" Berta "); if ( c ) printf (" Claus "); if ( d ) printf (" Doris "); printf ("\ n "); } 25 26 27 28 29 30 31 32 33 } 34 35 } Aufgabe 22 (fakultativ) Man berechne die Nullstellen einer Funktion mithilfe des sogenannten Bisektionsverfahrens: eine linke und rechte Intervallgrenze wird eingelesen, die Funktionswerte hier und in der Mitte des Intervalls werden bestimmt. Dann wird das Intervall immer wieder halbiert, bis genügend Genauigkeit erreicht ist. Verwenden Sie als Beispiel die Funktion f (x) = x3 − x2 − x + 0.04. Diese hat Nullstellen in den Intervallen [0,1], [-1,0] und [1,2]. I Lösung: 1 2 # include < iostream > # include < math .h > 3 4 using namespace std ; 5 6 7 8 9 10 int main ( void ) { int i =1; float a ,b , c ; float fa , fc ; /* Zahl der Iterationen */ /* linker und rechter x - Wert , Mitte */ /* Funktionswerte */ 11 cout << " Linke und rechte Grenze : "; cin >> a >> b ; 12 13 14 do { 15 16 c =( a + b )/2.0; fa = a * a *a - a *a - a +0.04; fc = c * c *c - c *c - c +0.04; cout << " Iteriere : Nr =" < <i < <" x =" < <c < <" , f ( x )=" < < fc < < ’\n ’; if ( fc * fa > 0) a=c; else b=c; i ++; 17 18 19 20 21 22 23 24 25 } while ( ( fabs (b - a ) > 1e -7) && (i <10) ); 26 27 28 29 } Aufgabe 23 Freunden Sie sich zunächst einmal mit Unterprogrammen an. Im Skript sind folgende Programmfragmente zu finden: ◦ ◦ ◦ ◦ Berechnung von nm : Funktion mypow Näherung für exp(x): Funktion myexp Einfache Rekursion: Funktion fak Türme von Hanoi: Funktion hanoi Machen Sie daraus jeweils ein lauffähiges Programm. I Lösung: (Potenz und Exponentialfunktion) 1 # include < stdio .h > 2 3 4 long int mypow ( int n , int m ); double myexp ( double x , int k ); 5 6 7 8 9 int main ( void ) { int n =2 , m =10; double x =3.0; 10 printf ("% d hoch % d ist % ld \ n " , n , m , mypow (n , m )); printf (" exp (% lf ) ist etwa % lf \ n " , x , myexp (x , 1000)); 11 12 13 } 14 15 16 17 18 long int mypow ( int n , int m ) { int i ; long int erg =1; 19 for ( i =1; i <= m ; i ++) erg *= n ; return erg ; 20 21 22 23 } 24 25 26 27 28 double myexp ( double x , int k ) { int n ; double summand =1.0 , sum =1.0; 29 for ( n =1; n <= k ; n ++) { summand *= x / n ; sum += summand ; } return sum ; 30 31 32 33 34 35 36 } I Lösung: (Fakultät, rekursiv) 1 # include < stdio .h > 2 3 long fak ( int wert ); 4 5 6 7 int main ( void ) { int m =10; 8 printf ("% d ! = % ld \ n " , m , fak ( m )); 9 10 } 11 12 13 14 15 16 long fak ( int wert ) { if ( wert ==1) return 1; else return ( wert * fak ( wert -1)); } I Lösung: (Türme von Hanoi, rekursiv) 1 # include < stdio .h > 2 3 void hanoi ( int , int , int ); 4 5 6 7 8 int main ( void ) { hanoi (5 ,1 ,2); } 9 10 11 12 void hanoi ( int n , int p1 , int p2 ) { int parkplatz ; 13 if (n >1) { parkplatz = 6 - p1 - p2 ; hanoi (n -1 , p1 , parkplatz ); } 14 15 16 17 18 19 printf ("1 Scheibe von % d nach % d \ n " , p1 , p2 ); 20 21 if (n >1) hanoi (n -1 , parkplatz , p2 ); 22 23 } Aufgabe 24 Schreiben Sie das Programm zur Primzahlzerlegung (Aufgabe 18) so um, dass das Einlesen der Zahl von einer Funktion eingabe erledigt wird und die Berechnung und Ausgabe der Primfaktoren von einer anderen Funktion zerlegung. Überlegen Sie zuerst, welche Variablentypen die Funktionen erhalten und zurückliefern sollen! I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 6 int eingabe ( void ); void zerlegung ( int zahl ); 7 8 9 10 11 int main ( void ) { zerlegung ( eingabe ()); } 12 13 14 15 int eingabe ( void ) { int z ; 16 do 17 { 18 cout << " Gib Integerzahl ein : "; cin >> z ; 19 20 } while (z <2); 21 22 23 return z ; 24 25 } 26 27 28 29 void zerlegung ( int zahl ) { int i , anz =0; 30 cout << zahl << " = "; for ( i =2; i <= zahl ; i ++) { while ( zahl % i == 0) { if (! anz ) cout << i ; else cout << ’* ’ << i ; anz ++; zahl /= i ; } } 31 32 33 34 35 36 37 38 39 40 41 42 } Aufgabe 25 Erstellen Sie ein Programm zur numerischen Integration einer Funktion mit der RechtecksMethode. Das Programm soll eine Funktion double f(double x) enthalten, die zu jedem x einen Funktionswert liefert, sowie eine Funktion double integral(double a, double b, int n). Darin soll das Intervall [a, b] in n kleine Intervalle aufgeteilt werden, die Fläche der Rechtecke unter dem Funktionsgraphen berechnet werden und die Gesamtfläche zurückgeliefert werden. Z 1 exp(−x2 )dx ≈ 0.746824 benutzen. Tipp: Zum Testen Ihres Programms können Sie 0 I Lösung: 1 2 # include < iostream > # include < math .h > 3 4 using namespace std ; 5 6 7 double f ( double x ); double integral ( double a , double b , int n ); 8 9 10 11 12 13 14 15 16 int main ( void ) { double a , b ; int n ; cout << " Grenze links , rechts und Intervallzahl : "; cin >> a >> b >> n ; cout << " Ergebnis : " << integral (a ,b , n ) << ’\n ’ ; return 0; } 17 18 19 20 21 double f ( double x ) { return exp ( - x * x ); } 22 23 24 25 26 double integral ( double a , double b , int n ) { double flaeche =0 , h ; int i ; 27 h =( b - a )/ n ; for ( i =0; i < n ; i ++) flaeche = flaeche + h * f ( a + i * h ); return flaeche ; 28 29 30 31 32 } Aufgabe 26 Schreiben Sie eine Funktion int palin(char *c, int erstes, int letztes), die rekursiv prüfen soll, ob ein gegebenes Wort oder ein Satz ein Palindromi ist. Ihr wird das Wort oder der Satz in einem char-Array c sowie die Stelle des ersten und letzten Zeichens als int übergeben. Stimmen beide Zeichen überein, so kann man mit dem Prüfen des verkürzten Wortes oder Satzes fortfahren. Tipp: Die Funktion strlen(text) liefert die Länge des Textes char text[]. Sie ist in string.h deklariert. Überlegen Sie sich auch, wie Sie Leerzeichen behandeln (siehe Bsp. in der Fussnote). Beachten Sie bitte die Schreibweise . . .palin(char *c. . . zur Übergabe des char-Arrays. I Lösung: 1 2 # include < stdio .h > # include < string .h > 3 4 int palin ( char * , int , int ); 5 6 7 8 9 10 int main ( void ) { char wort []=" derfreibierfred "; char unwort []=" derfreibiersepp "; char satz []=" Ein Schwarzer mit Gazelle zagt im Regen nie "; 11 if ( palin ( wort , 0 , strlen ( wort ) -1) == 1) printf ("\"% s \" ist ein Palindrom \ n " , wort ); else printf ("\"% s \" ist kein Palindrom \ n " , wort ); 12 13 14 15 if ( palin ( unwort , 0 , strlen ( unwort ) -1) == 1) printf ("\"% s \" ist ein Palindrom \ n " , unwort ); else printf ("\"% s \" ist kein Palindrom \ n " , unwort ); 16 17 18 19 if ( palin ( satz , 0 , strlen ( satz ) -1) == 1) printf ("\"% s \" ist ein Palindrom \ n " , satz ); else printf ("\"% s \" ist kein Palindrom \ n " , satz ); 20 21 22 23 } 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 int palin ( char *c , int erstes , int letztes ) { while ( c [ erstes ] == ’ ’ && letztes - erstes > 2) erstes ++; while ( c [ letztes ] == ’ ’ && letztes - erstes > 2) letztes - -; if (!( c [ erstes ]== c [ letztes ] || c [ erstes ]== c [ letztes ]+32 || c [ erstes ]== c [ letztes ] -32)) return 0; else { if ( letztes - erstes <= 2) return 1; return palin (c , erstes +1 , letztes -1); } } i vorwärts ! rückwärts z.B.: an Hr. De Muirier von der DLR, heutzutage rassistisch und stark ” anna‘, otto‘, ein schwarzer mit gazelle zagt im regen nie‘. Danke an dieser Stelle ’der mich’ darauf ’ hingewiesen hat, dass das im Original-Palindrom verwendete Wort pejorativ ist“. (Zitat) Aufgabe 27 Das Treppenproblem: Sie können bei einer Treppe entweder genau eine Stufe pro Schritt nehmen, oder, falls sie sportlich und durchtrainiert sind, 2 Stufen auf einmal. Damit haben sie mehrere Möglichkeiten eine mehrstufige Treppe zu überwinden (z.B.: 1 Stufe → 1 Möglichkeit, 2 Stufen → 2 Möglichkeiten, 3 Stufen → 3 Möglichkeiten, 4 Stufen → 5 Möglichkeiten, . . .). Schreiben Sie ein Programm, welches Ihnen rekursiv die Anzahl der Möglichkeiten berechnet, eine Treppe T mit n Stufen zu erklimmen: n für n < 3 Tn = T(n−1) + T(n−2) für n ≥ 3 Berechnen Sie dann die Anzahl der Möglichkeiten für n=25. Wieso und wie müssen Sie ihr Programm modifizieren, damit dieses auch die Anzahl der Möglichkeiten für n=768 (Ulmer Münster) und n=1860 (Empire State Building) berechnen kann? Tipp: Bei der Treppe zur Physik-Bibliothek (n=25) haben Sie 121.393 Möglichkeiten, beim Ulmer Münster etwa 23 x 10159 Möglichkeiten und beim Empire State Building immerhin etwa 37 x 10387 Möglichkeiten. I Lösung: (rekursiv) 1 # include < stdio .h > 2 3 int treppe ( int ); 4 5 6 7 int main ( void ) { int stufen ; 8 printf ("\ n \ nAnzahl der Stufen ?: "); scanf ("% d " , & stufen ); printf (" Bei % d Stufen haben Sie % d Moeglichkeiten \ n " , stufen , treppe ( stufen )); 9 10 11 12 13 } 14 15 16 17 18 19 20 21 int treppe ( int stufen ) { if ( stufen <= 2) return stufen ; else return treppe ( stufen -1) + treppe ( stufen -2); } I Lösung: (additiv) 1 # include < stdio .h > 2 3 void treppe ( int ); 4 5 6 7 int main ( void ) { int stufen ; 8 printf ("\ n \ nAnzahl der Stufen ?: "); scanf ("% d " , & stufen ); printf (" Bei % d Stufen haben Sie " , stufen ); treppe ( stufen ); printf (" Moeglichkeiten "); 9 10 11 12 13 14 } 15 16 17 void treppe ( int stufen ) { int letztes [1000] , vletztes [1000] , ergebnis [1000]; int result =0 , carry =0; int z , index , lastindex =999 , treffer =0; 18 19 20 21 for ( z =0; z <1000; z ++) vletztes [ z ]= letztes [ z ]= ergebnis [ z ]=0; 22 23 24 letztes [0]=2; vletztes [0]=1; 25 26 27 if ( stufen < 3) ergebnis [0] = stufen ; 28 29 30 while ( stufen - - > 2) { for ( z =0; z <1000; z ++) { result = vletztes [ z ] + letztes [ z ] + carry ; if ( result >= 10) { ergebnis [ z ] = result - 10; carry = 1; } else { ergebnis [ z ] = result ; carry = 0; } } 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 for ( z =0; z <1000; z ++) { vletztes [ z ] = letztes [ z ]; letztes [ z ] = ergebnis [ z ]; } 48 49 50 51 52 } 53 54 while ( treffer != 1) if ( ergebnis [ lastindex ] == 0) lastindex - -; else treffer = 1; index = lastindex ; while ( index >= 0) { if ( index != 0 && index % 3 == 0) printf ("% d ." , ergebnis [ index - -]); else printf ("% d " , ergebnis [ index - -]); } if ( lastindex >= 9) printf (" (=% d ,% de % d )" , ergebnis [ lastindex ] , ergebnis [ lastindex - 1] , lastindex ); 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 } Aufgabe 28 (fakultativ) Zur Berechnung der Wurzel einer Zahl gibt es ein rekursives Verfahren. Die Rekursionsformel lautet: ( h i x 1 w(n − 1, x) + für n ≥ 1 2 w(n−1,x) w(n, x) = 1 für n = 0 Schreiben Sie eine Funktion double wurzel(int n, double x), die rekursiv die Wurzel einer eingegebenen Zahl x berechnet. Die Zahl n gibt die Rekursionstiefe an. Vergleichen Sie das Ergebnis mit dem exakten Wert. I Lösung: 1 2 # include < stdio .h > # include < math .h > 3 4 5 6 7 8 double wurzel ( int n , double x ) { if ( n ==0) return 1; else return 0.5*( wurzel (n -1 , x )+ x / wurzel (n -1 , x )); } 9 10 11 12 13 int main ( void ) { double x ; int n ; 14 printf (" Zahl eingeben : "); scanf ("% lf " , & x ); printf (" Anzahl der Rekursionen : "); scanf ("% d " , & n ); printf (" Die Wurzel von % f ist etwa %1.12 f , exakt %1.12 f \ n " , x , wurzel (n , x ) , sqrt ( x )); 15 16 17 18 19 20 21 } Aufgabe 29 Man berechne für kleine ganze Zahlen m, n (m ≤ 3, n ≤ 8) die Ackermann-Funktion a(m, n): falls m = 0 n+1 a(m − 1, 1) falls n = 0 a(m, n) := a(m − 1, a(m, n − 1)) sonst Tipp: Zum Testen Ihres Programms können Sie a(1, 1) = 3, a(3, 3) = 61, a(3, 8) = 2045 benutzen. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 int acker ( int m , int n ); 6 7 8 9 int main ( void ) { int a , b ; 10 cout << "2 Zahlen : "; cin >> a >> b ; cout << " a (" << a << " , " << b << ") = " << acker (a , b ) << endl ; 11 12 13 14 15 } 16 17 18 19 20 21 22 23 24 25 int acker ( int m , int n ) { if ( m ==0) return n +1; else { if ( n ==0) return acker (m -1 ,1); else return acker (m -1 , acker (m ,n -1)); } } Aufgabe 30 Erstellen Sie ein Programm mit einer Struktur namens person, die einige Daten (Name, Vorname, Alter, Schuhgröße,. . .) einer Person speichert. Eine Funktion eingabe soll einen Datensatz einlesen und zurückliefern. Das Programm soll dann mithilfe von eingabe die Daten zweier Personen aufnehmen und den Namen des Älteren ausgeben. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 6 7 8 9 typedef struct { char name [20] , vname [20]; int alter , schuhgroesse ; } person ; 10 11 person einlesen ( void ); 12 13 14 15 int main ( void ) { person p1 , p2 ; 16 p1 = einlesen (); cout << endl ; p2 = einlesen (); 17 18 19 20 if ( p1 . alter > p2 . alter ) cout << p1 . vname << " " << p1 . name << " ist der aeltere ." << endl ; else cout << p2 . vname << " " << p2 . name << " koennte der aeltere sein ." << endl ; 21 22 23 24 25 26 27 } 28 29 30 31 person einlesen ( void ) { person p ; 32 cout << " Vorname : "; cin >> p . vname ; cout << " Name : "; cin >> p . name ; cout << " Alter : "; cin >> p . alter ; cout << " Schuhgroesse : "; cin >> p . schuhgroesse ; 33 34 35 36 37 38 39 40 41 return p ; 42 43 } Aufgabe 31 Im Sript finden Sie ein Beispielprogramm zur Dateibearbeitung. Versuchen Sie, es zu verstehen, und experimentieren Sie damit. I Lösung: Hier hilft nun wirklich nur noch lesen, verstehen und abtippen! Für die Lösungen der Aufgaben 32–34 werden die folgenden Textdateien im jeweils aktuellen Verzeichnis vorausgesetzt: demo.txt 1 2 3 Hallo , das ist eine Testdatei ! Hier steht die zweite Zeile . Und schon ist ’ s wieder zu Ende ... text.txt 1 2 3 4 In diesem Text sind viel zu viele Leerzeichen vorhanden , die entfernt werden muessen . Aufgabe 32 Erstellen Sie ein Programm, das einen Text aus einer Datei einliest und auf dem Bildschirm ausgibt, wobei Groß- in Kleinbuchstaben verwandelt werden sollen und umgekehrt. I Lösung: 1 2 # include < iostream > # include < fstream > 3 4 using namespace std ; 5 6 7 8 9 int main ( void ) { char c ; ifstream datei ; 10 datei . open (" demo . txt " , ios :: in ); if (! datei ) { cout << " Datei nicht gefunden !\ n "; return 1; } 11 12 13 14 15 16 17 while ( datei . get ( c )) { if (c >= ’a ’ && c <= ’z ’) c = c +( ’A ’ - ’a ’); else if (c >= ’A ’ && c <= ’Z ’) c =c -( ’A ’ - ’a ’); cout << c ; } datei . close (); 18 19 20 21 22 23 24 25 } Aufgabe 33 Schreiben Sie ein Programm, das einen Text aus einer Datei und einen Buchstaben einliest und ermittelt, wie oft der Buchstabe in dem Text vorkommt. I Lösung: 1 2 # include < iostream > # include < fstream > 3 4 using namespace std ; 5 6 7 8 9 10 int main ( void ) { char c , buchst ; int anzahl =0; ifstream datei ; 11 cout << " Zeichen eingeben : cin >> buchst ; 12 13 "; 14 cout << " Der Text \ n "; 15 16 datei . open (" demo . txt " , ios :: in ); while ( datei . get ( c )) { if ( c == buchst ) anzahl ++; cout << c ; } datei . close (); cout << "\ nenthaelt " << anzahl << " mal das Zeichen " << buchst << endl ; 17 18 19 20 21 22 23 24 25 26 } Aufgabe 34 Schreiben Sie ein Programm, das aus einem Text in einer Datei alle mehrfach vorkommenden Leerzeichen entfernt und den Text auf dem Bildschirm ausgibt. I Lösung: 1 2 # include < iostream > # include < fstream > 3 4 using namespace std ; 5 6 7 8 9 int main ( void ) { char c , voriges = ’a ’; ifstream datei ; 10 datei . open (" text . txt " , ios :: in ); 11 12 while ( datei . get ( c )) { if (!( voriges == ’ ’ && c == ’ ’)) cout << c ; voriges = c ; } datei . close (); 13 14 15 16 17 18 19 20 } Aufgabe 35 Es ist feld ein int-Array und p ein int-Zeiger. Welche der folgenden Zuweisungen sind zulässig, welche nicht? (Ggf. ausprobieren!) ◦ ◦ ◦ ◦ p = feld; feld = p; p = &feld[3]; feld[2] = p[5]; I Lösung: Alle Zuweisungen sind zulässig ausser der Zweiten da feld eine Zeigerkonstante ist und die Adresse der Elemente enthält, welche durch die Definition von feld reserviert wurden. Diese Adresse kann nicht geändert werden. Der Zeigervariablen p dürfen beliebige Adressen zugewiesen werden. Die erste und dritte Zuweisung sind daher korrekt, weil auch die Ausdrücke zur Berechnung dieser Adressen korrekt sind. In der letzten Zuweisung wird ein einzelner int-Wert (evtl. unbekannter Herkunft, je nach Vorgeschichte) in ein Element von feld gespeichert, was formal richtig ist. Aufgabe 36 Es seien p1 und p2 zwei int-Zeiger und i eine int-Variable. Welche Zuweisungen wird der Compiler akzeptieren, welche nicht? (Ggf. ausprobieren!) ◦ ◦ ◦ ◦ ◦ p1 = p2 + i; p1 = i + p2; i = p1 * p2; i = p1 - p2; i = p1 + p2; I Lösung: Die erste Zuweisung wird vom Compiler akzeptiert. Hier wird zu einer Adresse eine ganze Zahl addiert. Das Resultat ist ein um einen konstanten Wert (i*sizeof(int)) verschobener Zeiger. Die meisten Compiler akzeptieren auch die zweite Zuweisung, da das Vertauschen der Operanden bei +‘durchaus erlaubt ist. Die dritte Zuweisung ist völliger Blödsinn. Bei der ’ vierten Zuweisung wird die Entfernung der Elemente (in sizeof(int)) ermittelt, auf die die Zeigervariablen p1 und p2 zeigen. Die letzte Zuweisung ist wiederum keine sinnvolle Operation. Aufgabe 37 Schreiben Sie ein bestehendes Programm (z.B. Lösung der quadratischen Gleichung) so um, dass die Benutzereingabe von einer Funktion eingabe erledigt wird, der man die Variablen übergeben muss (Pointer!). I Lösung: 1 2 # include < iostream > # include < math .h > 3 4 using namespace std ; 5 6 void eingabe ( double * , double * , double *); 7 8 9 10 int main ( void ) { double a ,b ,c , D ; 11 eingabe (& a , &b , & c ); D = b *b -4* a * c ; if ( D ==0) cout << " x = " << -b /(2* a ) << endl ; if (D >0) cout << " x = " << ( - b + sqrt ( D ))/(2* a ) << " und x = " << ( -b - sqrt ( D ))/(2* a ) << endl ; if (D <0) cout << " x = " << -b /(2* a ) << "+ -" << sqrt ( - D )/(2* a ) << "* i " << endl ; 12 13 14 15 16 17 18 19 } 20 21 22 23 24 25 void eingabe ( double *a , double *b , double * c ) { cout << " Die Parameter a , b und c eingeben : cin >> * a >> * b >> * c ; } "; Aufgabe 38 Schreiben Sie eine Funktion stringlength, an die ein char-Array übergeben wird, und die die Länge dieser Zeichenkette zurückliefert. Tipp: Das Ende einer Zeichenkette ist durch ’\0’ (ASCII: 0) gekennzeichnet. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 int stringlength ( char * w ); 6 7 8 9 int main ( void ) { char wort [50]; 10 cout << " Wort eingeben : "; cin >> wort ; cout << " Das Wort " << wort < <" hat " << stringlength ( wort ) << " Zeichen ." << endl ; 11 12 13 14 15 } 16 17 18 19 int stringlength ( char * w ) { int i =0; 20 while ( w [ i ]!= ’\0 ’) i ++; return i ; 21 22 23 } Aufgabe 39 Der Benutzer soll ein Wort und ein Zeichen eingeben. Es soll das Wort, das um dieses Zeichen verlängert worden ist, ausgegeben werden (z.B.: Hall + o → Hallo). Verwenden Sie dazu die vorher (Aufgabe 38) definierte Funktion stringlength, um die Stelle des letzten Zeichens zu ermitteln. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 int strlen ( char * w ); 6 7 8 9 10 int main ( void ) { char wort [50] , c ; int j , l ; 11 cout << " Wort eingeben : "; cin >> wort ; cout << " Buchstaben eingeben : "; cin >> c ; 12 13 14 15 16 l = stringlength ( wort ); wort [ l ]= c ; wort [ l +1]= ’\0 ’; cout << wort << endl ; 17 18 19 20 21 } 22 23 24 25 int stringlength ( char * w ) { int i =0; 26 while ( w [ i ]!= ’\0 ’) i ++; return i ; 27 28 29 } Aufgabe 40 Schreiben Sie das Bubble-Sort-Programm (Aufgabe 19) so um, dass das Sortieren in einer Funktion geschieht, der man den Zeiger auf das Array übergibt. I Lösung: 1 2 # include < iostream > # include < stdlib .h > 3 4 using namespace std ; 5 6 void sortiere ( int *); 7 8 9 10 int main ( void ) { int a [10] , i ; 11 cout << "\ nUnsortiertes Array : \ n "; for ( i =0; i <10; i ++) { a [ i ]= rand ()%100; cout << a [ i ] << " "; } sortiere ( a ); cout << "\ nSortiertes Array : \ n "; for ( i =0; i <10; i ++) cout << a [ i ] << " "; cout << endl ; 12 13 14 15 16 17 18 19 20 21 22 23 } 24 25 26 27 void sortiere ( int * x ) { int i , ablage , change ; 28 do { 29 30 change = 0; for ( i =0; i <9; i ++) if ( x [ i ] > x [ i +1]) { ablage = x [ i ]; x [ i ]= x [ i +1]; x [ i +1]= ablage ; change = 1; } 31 32 33 34 35 36 37 38 39 } while ( change ); 40 41 42 } Aufgabe 41 Schreiben Sie ein Programm, das eine Funktion prosumo enthält. Dieser Funktion wird ein Vektor übergeben; sie liefert die Summe und das Produkt der Vektorelemente zurück. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 void prosumo ( int , float * , float * , float *); 6 7 8 9 int main ( void ) { float f []={1.0 ,2.0 ,3.0 ,7.0} , ergp , ergs ; 10 prosumo (4 ,f ,& ergp ,& ergs ); cout << " Produkt : " << ergp << " , Summe : " << ergs << ’\n ’ ; 11 12 13 14 } 15 16 17 18 19 20 21 22 23 24 void prosumo ( int n , float *F , float *x , float * y ) { int i ; * x =1.0; * y =0.0; for ( i =0; i < n ; i ++) { * x *= F [ i ]; * y += F [ i ]; } } Aufgabe 42 Schreiben Sie das Integrations-Programm (Aufgabe 25) so um, dass die zu integrierende Funktion f(x) der Funktion integral als Pointer übergeben wird. I Lösung: 1 2 # include < iostream > # include < math .h > 3 4 using namespace std ; 5 6 7 8 double gauss ( double x ); double parabel ( double x ); double integral ( double (*)( double ) , double , double , int ); 9 10 11 12 13 int main ( void ) { double a , b ; int n ; 14 cout << " Grenze oben , unten und Intervallzahl : "; cin >> a >> b >> n ; cout << " Ergebnis ( Gauss ): " << integral ( gauss ,a ,b , n ) << ’\n ’; cout << " Ergebnis ( Parabel ): " << integral ( parabel ,a ,b , n ) << ’\n ’; 15 16 17 18 19 20 21 return 0; 22 23 } 24 25 26 27 28 double gauss ( double x ) { return exp ( - x * x ); } 29 30 31 32 33 double parabel ( double x ) { return x * x ; } 34 35 36 37 38 double integral ( double (* f )( double x ) , double a , double b , int n ) { double flaeche =0 , h ; int i ; 39 h =( b - a )/ n ; for ( i =0; i < n ; i ++) flaeche = flaeche + h * f ( a + i * h + h /2); return flaeche ; 40 41 42 43 44 } Aufgabe 43 Erzeugen Sie dynamisch Speicherplatz für n double-Zahlen, lesen Sie sie ein und bestimmen Sie das Maximum und die Summe. Wie sieht die Speicheralloziierung in reinem C und in C++ aus? I Lösung: (ANSI-C) 1 2 # include < stdio .h > # include < stdlib .h > 3 4 5 6 7 8 int main ( void ) { int SIZE , i ; float *v , sum , * max ; 9 printf (" Laenge des Vekors eingeben : "); scanf ("% d " ,& SIZE ); 10 11 12 v = ( float *) malloc ( SIZE * sizeof ( float )); 13 14 if ( v == NULL ) return 1; 15 16 printf ("% d Float - Zahlen eingeben : " , SIZE ); for ( i =0; i < SIZE ; i ++) scanf ("% f " , v + i ); 17 18 19 20 max = v ; sum = 0.0; 21 22 23 for ( i =0; i < SIZE ; i ++) { sum += v [ i ]; if ( v [ i ] > * max ) max = v + i ; } 24 25 26 27 28 29 printf ("\ nSumme : %f , Maximum : % f \ n " , sum , * max ); 30 31 free ( v ); 32 33 } I Lösung: (C++) 1 # include < iostream > 2 3 using namespace std ; 4 5 6 7 8 int main ( void ) { int SIZE , i ; float *v , sum , * max ; 9 10 11 cout << " Laenge des Vekors eingeben : "; cin >> SIZE ; 12 13 v = new float [ SIZE ]; 14 15 if ( v == NULL ) return 1; 16 17 18 19 20 cout << SIZE << " Float - Zahlen eingeben : "; for ( i =0; i < SIZE ; i ++) cin >> v [ i ]; max = v ; sum = 0.0; 21 22 23 for ( i =0; i < SIZE ; i ++) { sum += v [ i ]; if ( v [ i ] > * max ) max = v + i ; } 24 25 26 27 28 29 cout << " Summe : " << sum << " , Maximum : " << * max << endl ; 30 31 32 delete v ; 33 34 } Aufgabe 44 Erstellen Sie eine Funktion zur Sortierung eines Arrays von int-Zahlen. Übergeben Sie der Sortierfunktion als Parameter eine Funktion zum Vergleich zweier Zahlen. Erzeugen Sie unterschiedliche Sortierungen (aufsteigend, absteigend, nach letzter Ziffer, nach der Quersumme,. . .), indem Sie unterschiedliche Vergleichsfunktionen an die Sortierfunktion übergeben. I Lösung: 1 # include < iostream > 2 3 using namespace std ; 4 5 void Ausgabe ( int *); 6 7 8 9 10 11 int int int int int auf ( const int , const int ); ab ( const int , const int ); lziffer ( const int , const int ); rueckw ( const int , const int ); qsumme ( const int , const int ); 12 13 void sort ( int * , int , int (*)( const int , const int )); 14 15 16 17 int main ( void ) { int Zahlen []={10 ,5 ,78 ,3 ,34 ,76 ,33 ,1352 ,56 ,85}; 18 cout << " Unsortiertes Array :\ n "; Ausgabe ( Zahlen ); sort ( Zahlen , 10 , auf ); cout << " aufsteigend sortiert :\ n "; Ausgabe ( Zahlen ); sort ( Zahlen , 10 , ab ); cout << " absteigend sortiert :\ n "; Ausgabe ( Zahlen ); sort ( Zahlen , 10 , lziffer ); cout << " nach letzter Ziffer sortiert :\ n "; Ausgabe ( Zahlen ); sort ( Zahlen , 10 , qsumme ); cout << " nach der Quersumme sortiert :\ n "; Ausgabe ( Zahlen ); 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 } 34 35 36 37 38 39 void Ausgabe ( int * z ) { for ( int i =0; i <10; i ++) cout << z [ i ] << " cout << endl << endl ; } "; 40 41 42 43 void sort ( int *z , int size , int (* comp )( const int , const int )) { int ablage ; 44 45 46 47 48 49 50 51 52 53 54 for ( int i =0; i < size -1; i ++) for ( int j = i +1; j < size ; j ++) { if ( comp ( z [ i ] , z [ j ])==0) { ablage = z [ i ]; z [ i ]= z [ j ]; z [ j ]= ablage ; } } 55 } 56 57 58 59 60 61 62 int auf ( const int a , const int b ) { if (a < b ) return 1; else return 0; } 63 64 65 66 67 68 int ab ( const int a , const int b ) { if (a > b ) return 1; else return 0; } 69 70 71 72 73 74 int lziffer ( const int a , const int b ) { if ( a %10 < b %10) return 1; else return 0; } 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 int qsumme ( const int a , const int b ) { int x =0 , y =0 , z ; z=a; while ( z !=0) { x += z %10; z = z /10; } z=b; while ( z !=0) { y += z %10; z = z /10; } if (x < y ) return 1; else return 0; } Aufgabe 45 Schreiben Sie ein Programm zur Verwaltung einer verketteten Liste. Als Nutzinhalt‘der Liste ’ wählen Sie eine char-Variable, in der Sie genau ein Zeichen speichern können. Füllen Sie die Kette in einer Funktion fangan mit den Kleinbuchstaben des Alphabets. Mit einer Funktion gibaus können Sie jeweils den Inhalt der gesamten Liste ausgeben. Experimentieren sie dann, indem sie ihr Programm mit einer Funktion fuegein erweitern, die an beliebiger Stelle n-mal den Buchstaben ’X’ einfügt. Vergessen Sie nicht eine Funktion loesche zu implementieren, mit der Teile der Liste gelöscht werden können. Eine weitere Ausbaumöglichkeit ist eine Funktion ersetze, die nach Wunsch beliebige Kleinbuchstaben durch Grossbuchstaben ersetzt. Tipp: Lassen Sie sich durch verkettete Listen nicht abschrecken! Setzen Sie sich in aller Ruhe mit Bleistift, Papier und einer guten Tasse Tee bzw. Capuccinoii hin und dröseln Sie Element für Element und Pointer für Pointer auf. Vergessen Sie dabei nicht, dass auch Pointervariablen ganz einfache, lokale Variablen sein können. . . I Lösung: 1 2 3 # include < iostream > # include < stdlib .h > # include < string .h > 4 5 using namespace std ; 6 7 8 9 10 11 typedef struct slink { char zeichen ; struct slink * next ; } link ; 12 13 14 15 16 17 link * fangan ( void ); void gibaus ( link *); void fuegein ( link * , int , int , char ); void loesche ( link * , int , int ); void ersetze ( link * , char *); 18 19 20 21 int main ( void ) { link * anfang ; 22 cout < <" Unser Alphabet als verkettete Liste ...\ n "; gibaus ( anfang = fangan ()); cout < <"\ n \ nFuege 5 ’X ’ nach der 8. Stelle ein \ n "; fuegein ( anfang , 8 , 5 , ’X ’); gibaus ( anfang ); cout < <"\ n \ nLoesche 10 Zeichen nach der 7. Stelle \ n "; loesche ( anfang , 7 , 10); gibaus ( anfang ); cout < <"\ n \ nErsetze a ,e ,u ,v ,w , z durch Grossbuchstaben \ n "; ersetze ( anfang , " aeuvwz "); gibaus ( anfang ); 23 24 25 26 27 28 29 30 31 32 33 34 delete ( anfang ); 35 36 } 37 38 39 40 41 ii link * fangan ( void ) { link * anfang , * kette , * hilf ; oder Espresso, je nach Tageszeit 42 if (!( anfang = kette = new link )) exit (1); anfang - > zeichen = ’a ’; anfang - > next = NULL ; 43 44 45 46 47 for ( int i =1; i <=25; i ++) { if (!( hilf = new link )) exit (1); hilf - > zeichen = ’a ’+ i ; hilf - > next = NULL ; kette - > next = hilf ; kette = hilf ; } 48 49 50 51 52 53 54 55 56 57 return anfang ; 58 59 } 60 61 62 63 64 65 66 67 68 69 void gibaus ( link * kette ) { cout << " Inhalt der Kette : "; while ( kette != NULL ) { cout << kette - > zeichen ; kette = kette - > next ; } } 70 71 72 73 void fuegein ( link * kette , int stelle , int anzahl , char zeichen ) { link * hilf , * next ; 74 for ( int i =1; i < stelle ; i ++) { if ( kette - > next == NULL ) break ; kette = kette - > next ; } next = kette - > next ; 75 76 77 78 79 80 81 82 for ( int j =1; j <= anzahl ; j ++) { if (!( hilf = new link )) exit (1); hilf - > zeichen = zeichen ; hilf - > next = next ; kette - > next = hilf ; kette = hilf ; } 83 84 85 86 87 88 89 90 91 92 } 93 94 95 96 97 98 void loesche ( link * kette , int stelle , int anzahl ) { link * hilf ; if ( stelle < 2) return ; 99 100 101 102 103 104 for ( int i =1; i < stelle ; i ++) { if ( kette - > next == NULL ) break ; kette = kette - > next ; } 105 106 for ( int j =1; j <= anzahl ; j ++) { hilf = kette - > next ; if ( hilf == NULL ) break ; kette - > next = kette - > next - > next ; delete ( hilf ); } 107 108 109 110 111 112 113 114 115 } 116 117 118 119 120 121 122 123 124 125 126 void ersetze ( link * kette , char * zeichen ) { while ( kette != NULL ) { for ( int i =0; i < strlen ( zeichen ); i ++) if ( kette - > zeichen == zeichen [ i ]) kette - > zeichen -=32; kette = kette - > next ; } } D. Schuh et al. August 2015