Alternativen
(mit einem Exkurs zur Logik)
Lass uns wandern
Wer sagt, dass man beim Programmierenlernen im stickigen Zimmer vor der Rechenkiste sitzen muss? Du wirst erstaunt sein, wie viel man draußen im Grünen über Informatik lernen kann. Und genau deswegen begeben wir uns jetzt auf einen kleinen Wanderausflug. Ja, richtig gehört. Jetzt gleich. Worauf wartest du? Los geht es!
Du gehst durch eine idyllische Berglandschaft spazieren, hörst die Vögel zwitschern und erfreust dich an den endlosen grünen Weiden. Doch plötzlich kommst du an einer Weggabelung an. Ein Schild weist dich darauf hin: Links geht es einen gemächlichen Hügel entlang, doch rechts erwarten dich steile Bergklippen. Und nein, du hast nicht deine besten Wanderschuhe dabei. Schade! Wenn du die doch nur hättest, wärst du sicher nach rechts gegangen. Bleibt wohl nur der Weg nach links.
Gratulation, du hast gerade eines der wichtigsten Programmierkonstrukte überhaupt kennengelernt!
Hä?
Berechtigte Frage. Okay, zurück ins stickige Zimmer.
Genauso wie du beim Wanderausflug nämlich entscheiden musstest, ob du aufgrund gewisser Bedingungen entweder da lang oder in die andere Richtung gehst, wird auch beim Programmieren häufig – was sagen wir da, immer! - mit solchen Weggabelungen gearbeitet. Oder in der Sprache der Informatiker: Verzweigungen. Wenn ich meine Wanderschuhe dabei habe, gehe ich nach rechts. Genau nach dem Muster sind auch Verzweigungen in C++ aufgebaut:
if (Bedingung) {
Anweisungen;
}
Verzweigungen werden also mit dem Schlüsselwort „if“ eingeleitet, dem englischen Begriff zum deutschen „wenn“. Als Programmierer musst du auf alles gefasst sein. Stelle dir ein Programm zur Berechnung des Flächeninhalts eines Kreises vor:
float radius;
float pi=3.14159;
cin >> radius;
float flaeche=pi*radius*radius;
cout << Der Flächeninhalt beträgt: " << flaeche;
Dieses Programm fragt den Anwender zunächst, einen Radius einzugeben. Nun kann ein Scherzkeks auf die Idee kommen, eine negative Zahl einzugeben und schon haben wir den Salat! Die Lösung: Wir fügen eine Verzweigung ein. Wenn der Radius größer als 0 ist, berechne den Flächeninhalt. Als Programm:
float radius;
float pi=3.14159;
cin >> radius;
if (radius > 0) {
float flaeche=pi*radius*radius;
cout << Der Flächeninhalt beträgt: " << flaeche;
};
Gibt nun jemand eine negative Zahl ein, wird die Berechnung gar nicht erst ausgeführt. Die nach dem Schlüsselwort „if“ stehende Bedingung wird nämlich geprüft. Wird als Wahrheitswert „true“ geliefert, kann die Abarbeitung des if-Blocks beginnen.
Eng verbunden mit der if-Anweisung ist der else-Block. Der Blick ins Wörterbuch verrät uns, dass „else“ am besten mit „sonst“ übersetzt werden kann. Die Syntax einer if-else-Anweisung sieht nun wie folgt aus:
if (Bedingung) {
Anweisungen;
}
else {
Anweisungen;
}
Falls also die Bedingung zur Abarbeitung des if-Blocks nicht erfüllt ist, wird in den else-Block gesprungen und eine alternative Anweisung ausgeführt. Als Beispiel nehmen wir wieder unser Flächeninhalts-Programm:
float radius;
float pi=3.14159;
cin >> radius;
if (radius > 0) {
float flaeche=pi*radius*radius;
cout << "Der Flächeninhalt beträgt: " << flaeche;
}
else {
cout << „Bitte gib eine positive Zahl ein!“ << endl;
}
Merke, dass ein else-Block nie alleine stehen kann!
Das lassen wir erst einmal sacken und gehen wieder wandern. An der altbekannten Weggabelung angekommen, merken wir jedoch, dass ein lokales Tourismusunternehmen einen dritten Pfad gebaut hat, der direkt zu einem bisher unerschlossenen Badesee führt. Und auch das Schild wurde um einen weiteren Wegweiser ergänzt: Links zum gemächlichen Hügel, rechts der steile Berg, geradeaus der See. Und genau wie man sich beim Wandern meist zwischen mehr als zwei Alternativen entscheiden muss, kann man auch beim Programmieren eine Vielzahl von Wegweisern einbauen:
if (Bedingung1) {
Anweisungen;
}
else if (Bedingung2) {
Anweisungen;
}
else if (Bedingung3) {
Anweisungen;
}
else {
Anweisungen;
}
Wenn ich meine Wanderschuhe dabei habe, gehe ich nach rechts, sonst, wenn ich meine Badesachen im Gepäck habe, gehe ich nach links, und sonst, wenn ich beides nicht mit habe, gehe ich geradeaus. So kannst du also mehrere if-Anweisungen verstehen. Als angehender Lehrer kannst du mit diesem Wissen auch eine automatische Notenvergabe programmieren:
int punkte;
cin >> punkte;
if (punkte >=18) {
cout << "Note: 1“;
}
else if (punkte >=15) {
cout << "Note: 2“;
}
else if (punkte >=10) {
cout << "Note: 3“;
}
else {
cout << "Nicht bestanden“;
}
Als Bedingung kannst du alles Erdenkliche abfragen, am häufigsten wirst du aber Vergleiche abprüfen. Dafür benötigst du die im obigen Programm schon verwendeten Vergleichsoperatoren. Hier findest du eine kleine Übersicht:
Vergleichsoperation
gleich
ungleich
kleiner
größer
kleiner gleich
größer gleich
Vergleichsoperator
==
!=
<
>
<=
>=
Was ist aber, wenn ich im Winter wandern gehe, erneut vor der Weggabelungen stehe und merke: Auf den Gipfeln stürmt und schneit es! Für den rechten Weg brauche ich ja nicht nur Wanderschuhe, sondern auch eine dickere Winterjacke! Anders gefragt: Was, wenn man kombinierte Bedingungen prüfen möchte?
Auch dies lässt sich leicht mittels so genannter logischer Operatoren realisieren. Von denen gibt es genau drei: not (nicht), and (und), or (oder), in der C++-Syntax mit den folgenden Symbolen realisiert: !, &&, ||. Wenn du Wanderschuhe UND eine dickere Winterjacke hast, gehe rechts. Wenn du eine dickere Winterjacke hast ODER dir Kälte nichts ausmacht, gehe rechts. Im Sommer: Wenn du NICHT Wanderschuhe hast, gehe links. Für UND gilt dabei: Beide Bedingungen müssen wahr sein, damit der Anweisungsblock ausgeführt wird. Für ODER lässt sich merken: Eine der beiden Bedingungen muss wahr sein (auch beide können wahr sein, dies ist kein ausschließendes ODER), damit in den if-Block gesprungen wird. Warum gerade diese Merkregeln gelten, lässt sich aus der so genannten Aussagenlogik herleiten. In diesem Gebiet der Mathematik betrachtet man Aussagen wie „Ein Schaf ist weiß“ oder „3<2“ und ordnet denen die Werte true (wahr) oder false (falsch) zu. Abstrahieren wir mal und betrachten zwei beliebige Aussagen A und B. Wann gilt nun die Aussage „A and B“ bzw. "A or B"? Dazu schaue man sich die vier möglichen Wahrheitsbelegungen von A und B in dieser Tabelle an:
Wie du siehst, ist axiomatisch festgelegt, dass „A and B“ nur wahr ist, wenn A wahr ist und B wahr ist. Im Fall von „A or B“ folgt, dass „A or B“ wahr ist, wenn mindestens eine der beiden Aussagen wahr ist.
Auch verschachtelten Aussagen wie „(A or (B and C))“ können nun mittels Wahrheitstabellen Wahrheitswerte zugeordnet werden. Fürs Erste belassen wir es jedoch bei diesem kleinen Exkurs und fragen uns nun, wie man kombinierte Aussagen konkret in C++ programmieren kann. Wie wär's, wenn wir ein Programm zur Berechnung des Umfangs eines Rechtecks schreiben?
float a;
float b;
float umfang;
cin >> a;
cin >> b;
if ((a >=0) && (b >= 0)) {
umfang= 2*(a+b);
}
else {
cout << "ERROR!“;
}
Kenner der Aussagenlogik wissen nun: Nur, wenn a und b größer als 0 sind, wird der Umfang berechnet. Ist auch nur einer der beiden Zahlen negativ, spuckt das Programm eine Fehlermeldung aus.
Nun soll die ODER-Verknüpfung an einem Beispiel demonstriert werden:
int klausurnote1;
int klausurnote2;
if ((klausurnote1<5) || (klausurnote2<5)) {
cout << "Zur Prüfung zugelassen“;
}
else {
cout << "Nicht zur Prüfung zugelassen“;
}
Wenn also mindestens eine Klausurnote über 5 liegt, ist man zur Prüfung zugelassen. Hat man beide Klausuren vergeigt, erhält man keine Prüfungszulassung.
Da siehst du mal, wie viel man auf einem Wanderausflug übers Programmieren lernen kann!
Schleifen
Im Kreisverkehr der Programmierung
Die Quadratzahlenfolge... wie ging die nochmal? 1, 4, 9 – das klappt. Aber was war nochmal die Quadratzahl von 16? Bevor wir uns den Kopf zerbrechen, können wir doch ein kleines C++-Programm schreiben, das uns die Quadratzahlen ausgibt. Gesagt, getan:
cout << 1*1;
cout << 2*2;
cout << 3*3;
cout << 4*4;
Okay, stop! Das einzutippen wird uns hier zu mühselig. Die Ausgabe von Quadratzahlen als eine ganze Sequenz, also eine Folge mehrfacher Befehle zu schreiben, ist nicht nur enormer Schreibaufwand (immer das Gleiche zu wiederholen ist teuer und typischerweise auch fehleranfällig), sondern auch eine sehr unelegante Art des Programmierens. Gibt es nicht irgendein Programmierkonstrukt, das uns Abhilfe schaffen kann?
Das gibt’s! Mit so genannten Schleifen lässt sich mit nur ein paar Programmzeilen eine Anweisung wiederholt ausführen lassen. In der Programmiersprache C++ hast du dabei drei Möglichkeiten, eine Schleife zu programmieren. Gehen wir diese mal Schritt für Schritt durch.
Als erstes schauen wir uns die while-Schleife an. Die Syntax ist leicht und einprägsam:
while (Bedingung) {
Anweisungen;
}
Wer der englischen Sprache mächtig ist, weiß, dass man „while“ am besten mit „solange“ übersetzen kann. Solange also eine bestimmte Bedingung erfüllt ist, werden die Anweisungen immer wieder im while-Block ausgeführt. Immer und immer und immer wieder. Aber größte Vorsicht ist geboten! Irgendwann willst du ja aus der Schleife hinaus. Schließlich möchtest du dir bestimmt nicht unendlich viele Quadratzahlen ausrechnen lassen – und dein Computer, glaub uns, hat auch keine Lust drauf. Wenn man also nicht achtsam ist, kann man sehr schnell eine Endlosschleife programmieren. Deshalb ist es wichtig, dass sich während des Schleifendurchlaufs deine Bedingung (das Zeug in den runden Klammern) irgendwann verändert. Denn dann ist sie ja nicht erfüllt – und die Schleife wird nicht mehr ausgeführt.
Alles so abstrakt. Lass es uns an einem Beispiel demonstrieren. Nehmen wir dazu wieder unsere Quadratzahlen.
int i=1;
while (i<=10) {
cout << i*i << endl;
i++;
}
Dieses Programm gibt dir die ersten zehn Quadratzahlen aus. Besonderes Augenmerk solltest du auf die Zeile „i++“ legen. Denn nachdem eine Quadratzahl berechnet und ausgegeben wurde, erhöht sich die anfangs deklarierte Integer-Variable jeweils um 1. Sprich, nach dem zehnten Schleifendurchlauf besitzt i den Wert 11. Die Bedingung sagt jedoch: Nur solange i kleiner gleich 10 ist, wird die Schleife ausgeführt. Da 11<=10 eine falsche Aussage ist, endet das Programm. An dieser Zeile siehst du, wie wichtig es ist, die Variable der Bedingung innerhalb der Schleife zu verändern. Ohne die Zeile „i++“ hätte i stets den Wert 1 gehabt, die Bedingung wäre also bis in alle Ewigkeit erfüllt, das Programm würde in diesem Fall nicht terminieren (also nicht aufhören, die Quadratzahl zur 1 zu berechnen und auszugeben).
Eng verwandt mit der while-Schleife ist die do-while-Schleife. Auch hier werfen wir erstmal einen Blick auf die Syntax:
do {
Anweisungen;
} while (Bedingung);
Und eigentlich könnten wir mit unseren Ausführungen über die do-while-Schleife schon aufhören. Denn groß unterscheidet sich die do-while-Schleife von der bereits gesehenen while-Schleife nicht. Alles, was wir für die while-Schleife vereinbart haben, ist auch für die do-while-Schleife gültig. Warum gibt’s die dann trotzdem? Worin liegt der entscheidende Unterschied?
Eine while-Schleife muss nicht ausgeführt werden. Betrachte dazu nochmal unser Quadratzahlen-Programm von oben. Hätten wir den Integer i gleich auf 11 gesetzt, wäre das Programm nie in die Schleife gesprungen – die Bedingung ist schließlich nicht erfüllt. Eine do-while-Schleife hingegen lässt sich davon nicht beirren – und wird immer mindestens ein Mal ausgeführt. While-Schleifen sind Pessimisten – die Katzen der Programmierung. Sie beäugen alles erst einmal kritisch. Die Variable „i“ ist nicht kleiner gleich 10? Dann springe ich gar nicht erst an! Do-While-Schleifen hingegen sind Optimisten, die Hunde unter den Programmierkonstrukten. Fröhlich und offen führen sie die Anweisungen aus, stürzen sich ins Getümmel und merken erst dann: Ach so, i ist ja nicht kleiner gleich 10. Was soll's, ich hatte meinen Spaß!
Von dieser Sache abgesehen, sind while- und do-while-Schleifen jedoch gleich. Die Eigenschaft, dass eine do-while-Schleife mindestens ein Mal durchlaufen wird, kann jedoch manchmal von Vorteil sein. Denn wie gesagt: Eine while-Schleife kann oft gar nicht erst anspringen, eine do-while-Schleife tut es immer. Dies ist zum Beispiel hilfreich, wenn du ein Programm schreibst, dass in einem Text nach einem bestimmten Wort sucht. Hier eignet sich die do-while-Schleife, weil sie garantiert einmal durch den Text laufen wird. Näheres dazu findest du jedoch im Kapitel über Strings.
Kenntnisse über while- und do-while-Schleifen bereichern deine Programme schon enorm. Wir wollen uns noch die so genannte for-Schleife ansehen, die mit Abstand beliebteste und am häufigsten verwendete Schleifenart. Schauen wir uns die Syntax einmal näher an:
for (Anweisung1; Bedingung; Anweisung2) {
Anweisungen;
}
Sieht auf den ersten Blick deutlich komplizierter und abstrakter aus als die vorherigen Schleifenarten. Aber lass dich davon nicht beirren – die for-Schleife ist unglaublich nützlich. Doch klären wir zunächst, was all die Ausdrücke in den Klammern zu bedeuten haben:
-Anweisung1: In dieser deklarierst du eine Zählvariable, einen so genannten Iterator. Dieser steht für die Schleifendurchläufe.
-Bedingung: Hier vereinbarst du, unter welchen Umständen die Schleife durchlaufen wird. Solange diese Bedingung erfüllt ist, wird die Schleife weiter ausgeführt. In gewisser Weise stellst du also ein Abbruchkriterium auf.
-Anweisung2: Mit dieser veränderst du die Zählvariable, erhöhst sie also beispielsweise um 1. Diese Anweisung wird nach jedem Schleifendurchlauf ausgeführt.
Vielleicht mag das für dich immer noch abstrakt anmuten, deshalb folgt sogleich ein kleines Beispiel:
for (int i=1; i<=10; i++) {
cout << i*i << endl;
}
Und schon haben wir ein kleines, effizientes Programm zur Ausgabe der ersten zehn Quadratzahlen. An diesem Beispiel merkt man, wie praktisch for-Schleifen sind: Alles, was man nämlich bei einer while-Schleife beachten musste, wird einfach zwischen die Klammern nach dem Schlüsselwort „for“ gepackt: Eine Zählvariable, eine Bedingung, für die die Schleife ausgeführt wird, und eine Veränderung der Variable aus der Bedingung. Mit diesen drei Ausdrücken ist für alles vorgesorgt, sodass man sich im for-Block selbst nur um die wiederholt auszuführenden Anweisungen bemühen muss. Das ist auch der Grund dafür, warum diese Schleifenart so häufig verwendet wird. Viele Berechnungen laufen von einem Start- bis zu einem Endewert, bei jedem Berechnungsschritt erfolgt eine inkrementelle Änderung. All ds lässt sich im Kopf einer for-Schleife (innerhalb der runden Klammern) angeben.
Da wir sowohl mit einer for-, als auch mit einer while-Schleife denselben Umstand programmieren konnten, liegt nahe, dass eine gewisse Analogie zwischen beiden vorherrscht. Und in der Tat lässt sich aus jeder for- eine while-Schleife basteln. Vergleiche dazu einfach das Quadratzahlenprogramm von oben mit unserer for-Schleife. Der Ausdruck1, also die Deklaration der Variablen i, wird an den Anfang gesetzt. Die Bedingung bleibt in den Klammern und die Veränderung der Zählvariablen steht im Schleifenkörper. Vergleiche dazu folgendes Abbildung:
for-Schleife
for (Anweisung1; Bedingung; Anweisung2) {
Anweisungen;
}
while-Schleife für das gleiche Beispiel
Anweisung1;
while (Bedingung) {
Anweisungen;
Anweisung2;
}
Vielleicht mag sich dir jedoch wieder die Frage stellen: Warum dann for-Schleifen benutzen, wenn alles mit einer while-Schleife geht? Soll ich die wirklich nur aus Gruppenzwang verwenden?
While-Schleifen kommen zum Einsatz, wenn man nicht genau weiß, wie oft man eine Anweisung ausführen muss. Wenn dir jedoch schon im Vornherein klar ist, du willst ganz zackig zehn Quadratzahlen auf dem Bildschirm haben, verwendest du am besten die for-Schleife. Du kannst es dir aber auch so verdeutlichen: Angenommen, du suchst ein Buch in der Bibliothek, in der sich unzählige Regale befinden. In einer Bibliothek verhältst du dich wie eine while-Schleife: Du suchst und suchst solange, bis das Buch gefunden wurde. Falls du jedoch bei dir zu Hause nach einem Buch suchst, wo sich nur genau drei große Regale befinden, wendest du die for-Schleifen-Methode an: Du suchst genau drei Mal, in jedem Regal. Dann findet sich das Buch schon.
Interessant wird es, wenn du for-Schleifen schachtelst, also ein Programm nach folgendem Muster schreibst:
for (int i=0; i<10; i++) {
for (int j=0; j<10; j++) {
…
}
}
Wie genau werden Anweisungen in einer verschachtelten Schleife ausgeführt? Die Antwort ist eigentlich ziemlich einleuchtend: Verschachtelte Schleifen sind nämlich wie Uhren. Die zweite Schleife in unserem Programm, nennen wir sie mal wegen der Zählvariablen „j-Schleife“, ist der Minuten-Zeiger, die „i-Schleife“ der Stundenzeiger. Der Stundenzeiger steht auf 0, es bewegt sich der Minutenzeiger: Solange, bis er einmal um die Uhr gewandert ist, also j=9 ist. Der Stundenzeiger springt auf 1, und wieder ist der Minutenzeiger am Zug: Erneut dreht er sich einmal um die Uhr, bis j=9 ist. Der Stundenzeiger springt auf 2 und so geht es fröhlich weiter.
Auf diese Weise kannst du beispielsweise ein Programm schreiben, das dir das Einmaleins ausgibt:
for (int i=1; i<=10; i++) {
for (int j=1; j<=10; j++) {
cout << i << "*" << j << "= " << i*j << endl;
}
}
Hierbei wird die äußere Schleife abgearbeitet und für JEDEN Durchlauf durch diese wird vollständig einmal die innere Schleife abgearbeitet. In dem oberen Beispiel werden also 100 Zeilen auf den Bildschirm ausgegeben.
Daher solltest du es mit den verschachtelten Schleifen nicht übertreiben. Schaue dir dazu nur mal dieses Programm an:
for (int i=1; i<=1000; i++) {
for (int j=1; j<=1000; j++) {
for (int k=1; k<=1000; k++) {
for (int l=1; l<=1000; l++) {
for (int m=1; m<=1000; m++) {
cout <<i << "*" <<j << "*" <<k << "*" <<l << "*" <<m << "=" <<i*j *k*l*m <<endl;
}
}
}
}
}
Hast du schon ausgerechnet, wie viele Berechnungen hier ausgeführt werden und wie viele Zeilen auf den Bildschirm ausgegeben werden würden?
Der Computer führt in dem ober gezeigten Programmausschnitt 1000*1000*1000*1000*1000 = 10^15 Berechnungen aus und gibt ebensoviele Zeilen auf den Bildschirm aus! Bis er die abgearbeitet hat, vergehen Monate!
Wie man eine Schleife vorzeitig verlässt
Was nehmen wir aus dem Kapitel über Schleifen mit? Zu allererst mal Folgendes: Endlosschleifen sind doof!
Oder doch nicht?
Nun ja, tatsächlich gibt es Situationen, in denen Endlosschleifen auch nützlich sein können. Natürlich nicht in ihrer Reinform – man muss sich immer ein Hintertürchen offen halten, eine andere Möglichkeit, aus einer Schleife auszusteigen, also eine Anweisung, durch die man vorzeitig eine Schleife verlassen kann. Wie man dieses „Hintertürchen“ im Programm realisieren kann, erfährst du in den folgenden Zeilen.
Betrachte zunächst folgendes Programm:
int zahl;
while (true){
cout << „Bitte geben Sie eine gerade Zahl ein.“ << endl;
cin >> zahl;
if (zahl%2==0){
break; // Ausstieg aus der Schleife
}
}
Dies ist eine Endlosschleife, erkennbar an dem Wörtchen „true“ in der Schleifenbedingung: Wahr ist immer wahr, also wird die Schleife bis in die Unendlichkeit ausgeführt. Eine Schleife wird nur beendet, wenn die Schleifenbedingung den Wert „false“ annimmt, was hier nie der Fall ist. Nun fordert uns das Programm auf, eine gerade Zahl einzutippen und wenn wir uns so neckisch anstellen und eine ungerade Zahl eingeben, werden wir erneut höflich dazu aufgefordert. Hier wird also auf praktische Weise das Prinzip der Endlosschleife ausgenutzt: Es geht erst wieder voran, wenn man auch wirklich eine gerade Zahl eintippt. Denn dann springt das Programm in die if-Bedingung und verlässt die Schleife durch eben jenes „Hintertürchen“. Wie genau sieht nun aber die Syntax dieses Hintertürchens aus? Ganz einfach: Schreibe das Wörtchen „break“. „break“ ist ein Befehl, der jede Schleife vorzeitig beendet. Mit „break“ machst du dem Compiler klar, dass die Abarbeitung der Schleife abgebrochen werden soll und man mit den nächsten Anweisungen fortsetzen soll. Beachte, dass dabei lediglich die Schleife verlassen wird, in der „break“ auftaucht. Sprich, bei geschachtelten Schleifen wird nicht das gesamte Schleifenkonstrukt, sondern nur eine Schleife verlassen, in der man sich bei der Bearbeitung gerade befindet.
Manchmal passieren während eines Schleifendurchlaufs blöde Dinge. Beispielsweise will man 100 gerade – die Betonung liegt auf „gerade“ - Werte einlesen. Dann passiert es: Der Finger rutscht auf der Tastatur aus und man gibt aus Versehen einen ungeraden Wert ein! Richtig blöd! Denn die Schleife vorzeitig abzubrechen ist nicht möglich, hinzu kommt, dass man die restlichen Werte weiter eingeben muss, damit die Schleife zum Ende kommt. Kann man sich da nicht Abhilfe schaffen? Es muss ja nicht gleich zum radikalen Abbruch der Schleife mit „break“ kommen. Wie wäre es mit einem Befehl, der dem Compiler sagt: „Hier habe ich einen Fehler gemacht, ignoriere ihn und mache ganz normal weiter.“
Den gibt’s. Passenderweise nennt sich der Befehl „continue“, bei diesem Befehl wird also mit dem nächsten Schleifendurchlauf fortgesetzt. Schauen wir uns unser Eingabeprogramm mal an:
int zaehler=1;
int wert;
while (zaehler<=100){
cin >> wert:
if (wert%2 != 0){
continue;
}
zaehler++;
}
Hier wirst du wie besprochen dazu aufgefordert, 100 gerade Werte einzugeben. Für den Fall, dass du mal versehentlich einen ungeraden Wert eintippst, befiehlst du dem Compiler, dies nicht zu beachten und unbeirrt weiterzumachen. „continue“ beendet nämlich im Gegensatz zu „break“ nur einen einzigen Schleifendurchlauf und nicht die ganze Schleife. Anschließend setzt das Programm mit dem nächsten Durchlauf fort.
Die Befehle „break“ und „continue“ können dabei in allen drei Schleifenarten verwendet werden.
Nun bist du mit dem nötigen Wissen über Schleifen und Alternativen versorgt. Und sollen wir dir etwas verraten? Mit diesen wenigen Programmierkonstrukten kannst du eigentlich schon so gut wie alles programmieren! Aus mehr besteht das Programmieren wirklich nicht. Gratulation! Doch wer eine wahre Programmierlegende werden will, sollte sich auch die anderen Kapitel mal ansehen. Denn jetzt beherrschst du das Einmaleins des Programmierens, aber wer stupide rechnen kann, ist ja noch lange kein Mathematiker. Das sollte Anreiz genug sein, gleich mit dem nächsten Kapitel zu starten!
Aufgaben: Alternativen und Schleifen
A1: Quiz dich schlau!
Nachfolgend sind einige Fragen aufgeführt, die du nach diesem Abschnitt beantworten können solltest:
(1) Wie sieht eine Verzweigung mit vier Bedingungen in C++ aus?
(2) Stelle die einzelnen Sätze mittels Vergleichsoperatoren und anschließend als Hierarchiekette dar:
Robert ist älter als Hans. Hans ist gleich alt wie Marie. Hans ist aber nicht so alt wie Paula. Denn Paula ist zwar jünger oder gleich alt wie Robert, aber immer noch älter als Marie.
(3) Welche Schleifenarten hast du kennengelernt?
(4) Was ist der Unterschied zwischen den Befehlen break und continue ?
(5) Was ist der Unterschied zwischen einer while- und einer do-while Schleife?
(6) Kann man eine for-Schleife durch eine while-Schleife ersetzen? Wenn ja, wie?
(7) Drei Schleifen werden ineinander verschachtelt, jede Schleife wird 100 mal ausgeführt, in dem Schleifenkörper der inneren Schleife steht eine Ausgabeanweisung:
for (i= 1; i<=100; i++) {
for (j= 1; j<=100; j++) {
for (k= 1; k<=100; k++) {
cout << "Ausgabe " << endl;
}
}
}
Wie viele Zeilen werden von diesem Programm auf dem Bildschirm ausgegeben?
A2: Getränkecrash
Marie wollte sich nur fix vor einer Vorlesung eine Limo aus dem Getränkeautomaten holen. Doch offenbar scheint da etwas mit deren Software nicht zu stimmen: Statt einer Zitronenlimo spuckte der Automat ein Schokoriegel aus!
Doch du kannst es besser! Daher schreibe bitte ein kleines Programm, welches folgendes interaktives Menü in Dauerschleife ausgibt (Preise können selbst festgelegt werden):
Was möchten Sie kaufen?
(1) Sprudelwasser (2) Zitronenlimo (3) Cola (4) Schokoriegel
Auswahl: 2
Preis: 1,10€
Was möchten Sie kaufen?
(1) Sprudelwasser (2) Zitronenlimo (3) Cola (4) Schokoriegel
Auswahl: 4
Preis: 0,80€
...
A3: Sonne ich komme!
Strahlende Sonne, eisgekühlter Cocktail und Meeresrauschen... Ja, Urlaub kann so schön sein. Doch bevor dieser so richtig genossen werden kann, muss noch ein entsprechendes Hotel gebucht werden. Eine Website preist ihre Unterkunft mit speziellen Angeboten an:
- Eine Übernachtung kostet 75€.
- Ab der 3. Übernachtung gibt es 10% Rabatt auf den Gesamtpreis.
- Ab der 7. Nacht gibt es 20% Rabatt auf den Gesamtpreis.
Schreibe bitte ein C++‐Programm, das den zu zahlenden Preis für die gemieteten Nächte ausgibt. Die Ausgabe soll so aussehen:
Gemietete Nächte: 10
1 Uebernachtung/en: 75 EUR
2 Uebernachtung/en: 150 EUR
3 Uebernachtung/en: 202 EUR
4 Uebernachtung/en: 270 EUR
5 Uebernachtung/en: 337 EUR
6 Uebernachtung/en: 360 EUR
7 Uebernachtung/en: 420 EUR
8 Uebernachtung/en: 480 EUR
9 Uebernachtung/en: 540 EUR
10 Uebernachtung/en: 600 EUR
A4: Zurück zu den Tannenbäumen!
Wir hatten uns bereits ein erstes Programm zur grafischen Ausgabe von Tannenbäumen angesehen, jetzt (nach dem Kennenlernen von Schleifen) kannst du dieses doch bestimmt bereits etwas besser lösen.
*
***
*****
*******
***
Lies bitte zuerst für die maximale Breite des Baumes eine ungerade Zahl ein und gib dementsprechend den Baum aus. (Bitte eine Schleife dafür verwenden.)
Musterlösungen
L1: Quiz dich schlau!
(1) if (Bedingung1) {
Anweisungen;
}
else if (Bedingung2) {
Anweisungen;
}
else if (Bedingung3) {
Anweisungen;
}
else {
Anweisungen;
}
(2) (Robert > Hans) &&
(Hans == Marie) &&
(Hans != Paula) &&
(Paula <= Robert) &&
( Paula > Marie )
-> Robert >= Paula > Hans == Marie
(3) for, while und do-while Schleifen
(4) break: beendet die Schleife und setzt mit dem Programmcode nach der Schleife fort.
continue: beendet einem Schleifendurchlauf und setzt am Beginn der Schleife mit dem nächsten Durchlauf dieser fort
(7) Die do-while Schleife wird mindestens einmal durchlaufen, bevor die Bedingung überprüft wird, die am Ende steht. Bei der while-Schleife wird die Gültigkeit der Bedingung bereits vor dem ersten Schleifendurchlauf überprüft.
(8) for (i= 1; i<=100; i++) { wird zu i = 1;
Anweisungen; while (i<= 100){
} Anweisungen;
i++;
}
(9) Drei verschachtelte Schleifen mit je 100 Durchläufen ergeben eine 100*100*100 = 1 000 000 malige Ausgabe des Wortes "Ausgabe".
L2: Getränkecrash
#include <iostream>
using namespace std;
int main() {
int auswahl;
while(true) { // oder while(1)
cout << "Was möchten Sie kaufen?" << endl;
cout << "(1) Sprudelwasser (2) Zitronenlimo (3) Cola (4) Schokoriegel" << endl << endl;
cout << "Auswahl: ";
cin >> auswahl;
cout << "Preis: ";
if (auswahl == 1) {
cout << "1,00€";
}
else if (auswahl == 2) {
cout << "1,10€";
}
else if (auswahl == 3) {
cout << "1,90€";
}
else if (auswahl == 4){
cout << "0,80€";
}
else { //weist den Kunden auf Tippfehler hin
cout << "Fehlerhafte Eingabe.";
}
cout << endl << endl;
}
return(0);
}
L3: Sonne ich komme!
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
int preis;
int einzelpreis = 75;
for (int tage = 1; tage <= 10; tage++) {
preis = einzelpreis*tage;
if (tage >= 6) {
preis = preis*0.8;
}
else if (tage >= 3) {
preis = preis*0.9;
}
cout << setw(2) <<tage << ". Uebernachtung/en: " << setw(4) << preis << " EUR" <<endl;
}
return 0;
}
L4: Noch mehr Tannenbäume!
Nicht jeder Baum gelingt sofort, aber bei dieser Aufgabe sieht man sofort ein Ergebnis.
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
int maxBreite, breiteZeile, anzLeerzeichen;
int anfangswert = 20;
cout << "Wie gross soll der Tannenbaum werden, bitte ein ungerade Zahl eingeben: ";
do {
cin >> maxBreite;
if (maxBreite % 2 == 0) {
cout << "Bitte eine gerade Zahl eingeben: ";
}
} while (maxBreite % 2 != 1);
// Ausgabe des Baumes, zeilenweise
anzLeerzeichen = anfangswert;
breiteZeile = 1;
while (breiteZeile <= maxBreite) {
// Ausgabe einer Zeile
cout << setw(anzLeerzeichen) << " "; // Ausgabe von führenden Leerzeichen
for (int i = 1; i <= breiteZeile; i++) {
cout << "*"; // Ausgabe der Sterne einer Zeile
}
cout << endl; // Ausgabe eines Zeilenumbruches
breiteZeile = breiteZeile + 2; // Verändern der Werte für die nächste Zeile
anzLeerzeichen = anzLeerzeichen - 1;
}
// Ausgabe des "Baumstammes"
cout << setw(anfangswert - 1) << " " << "***" << endl;
return(0);
}
Fragen, Anregungen?
Ist etwas unverständlich oder du hast Fragen zu einem Thema, Aufgabe oder einfach zur C++-Welt?
Dann schreibe uns einfach eine Mail!