IT-Academy Logo
Sign Up Login Help
Home - Programmieren - C++ - Schleifen in C/C++



Schleifen in C/C++

Generell besteht ein Programm aus einer Reihe von Befehlen die nach einander ausgeführt werden. Wenn nach einander ein gleicher Befehl wiederholt ausgeführt werden soll oder nachfolgende Befehlen sich ähneln, bieten sich Schleifen an.


Autor: Patrick Faes (dreamer)
Datum: 14-09-2007, 13:05:49
Referenzen: keine
Schwierigkeit: Anfänger
Ansichten: 12908x
Rating: Bisher keine Bewertung.

Hinweis:

Für den hier dargestellte Inhalt ist nicht der Betreiber der Plattform, sondern der jeweilige Autor verantwortlich.
Falls Sie Missbrauch vermuten, bitten wir Sie, uns unter missbrauch@it-academy.cc zu kontaktieren.

[Druckansicht] [Als E-Mail senden] [Kommentar verfassen]



Ein Computerprogramm ist eigentlich nicht mehr als eine Reihe von Befehlen die nach einander ausgeführt werden und ein Ergebnis bieten das dem Programmierer ein Problem löst. Dabei werden die Befehle jeweils von oben nach unten abgearbeitet. Manchmal kann es aber vorkommen dass ein Befehl mehrere Male ausgeführt werden soll oder nach einander ein sehr ähnlicher Befehl ausgeführt werden soll. Als klassiches Beispiel gibt es da die Auflistung einer Reihe von Werte, z.B. alle Zahlen von 1 bis 10.

Man könnte dazu jede Zahl einzeln mit einem Befehl ausgeben und die Befehle dann alle nach einander im Programmcode schreiben.

#include <iostream>
using namespace std;

int main()
{
	cout << 1 << endl;
	cout << 2 << endl;
	cout << 3 << endl;
	cout << 4 << endl;
	cout << 5 << endl;
	cout << 6 << endl;
	cout << 7 << endl;
	cout << 8 << endl;
	cout << 9 << endl;
	cout << 10 << endl;
	
	return 0;
}

Dieses Programm können Sie kompilieren und dann auf der Kommandozeile ausführen. Es wird alle Zahlen von 1 bis 10 jeweils auf einer Zeile ausgeben. Da der Befehl sich jedesmal stark ähnelt, ist es eine harte Arbeit den Befehl jedesmal neu schreiben zu müssen, und es ist noch eine schwerere Arbeit diese nachher zu ändern. Zudem wurde hier ausgegangen von einem festgelegten Programmablauf. In Wirklichkeit ist es nicht immer sicher dass ein Befehl z.B. 10 mal ausgeführt werden soll. Wenn z.B. eine Liste aller Vereinsmitglieder ausgegeben werden soll, dann soll der zutreffende Befehl genau so oft ausgeführt werden wie es Mitglieder gibt, und zudem sind die Daten variabel.

Zur Lösung gibt es in C/C++ (wie in jeder anderen Programmiersprache auch) so genannte Schleifen. Diese wiederholen ein Stück Programmcode immer wieder. Ob und wie oft die Schleife wiederholt wird, hängt von die angegebenen Bedingungen ab (die so genannte "Abbruchbedingung").


Die While-Schleife

Die While-Schleife ist die einfachste Form einer Schleife. Der Code wird ausgeführt solange wie die angegebene Bedingung erfüllt ist.

In folgendem Beispiel wird immer erneut der Text "Schleifendurchgang" ausgegeben, bis die Variable erneut nicht mehr den Wert true hat. Im Codeblock innerhalb der Schleife wird ein Zähler jeweils um eins erhöht. Wenn dieser Zähler einen Wert hat der größer ist als 8, wird die Variable erneut auf false geschaltet. Die Schleife wird danach nicht erneut durchlaufen.

#include <iostream>
using namespace std;

int main()
{
	bool erneut = true;
	int zaehler = 0;
	
	while (erneut == true)
	{
		cout << "Schleifendurchgang" << endl;
		zaehler = zaehler + 1;
		if (zaehler > 8) {erneut = false;}
	}
	
	return 0;
}

So können wir auch alle Zahlen von 1 bis 10 ausgeben.

#include <iostream>
using namespace std;

int main()
{
	int zahl = 1;
	
	while (zahl <= 10)
	{
		cout << zahl << endl;
		zahl = zahl + 1;
	}
	
	return 0;
}

Wir speichern dazu eine Variable zahl. Solange diese Zahl nicht größer ist als 10 (also kleiner oder gleich groß als 10) wird diese Zahl erneut ausgegeben. Beachten Sie dabei dass Sie die Variable zahl auch bei jedem Schleifendurchgang erhöhen müssen. Wenn Sie dies nicht tun, würden Sie eine Endlosschleife bekommen, da zahl dann immer kleiner oder gleich groß als 10 sein wird und somit die Schleife endlos lange wiederholt wird.


Die Do-While-Schleife

Die Do-While-Schleife ist eine Variante der gerade eben besprochenen While-Schleife. Der Unterschied liegt darin dass der Code in einer Do-While-Schleife mindestens einmal ausgeführt wird. Ein Beispiel könnte dies verdeutlichen.

Wir wiederholen unser letztes Beispiel. Die Variable zahl wird solange erneut ausgegeben wie sie kleiner oder gleich groß ist als 10.

#include <iostream>
using namespace std;

int main()
{
	int zahl = 1;
	
	while (zahl <= 10)
	{
		cout << zahl << endl;
		zahl = zahl + 1;
	}
	
	return 0;
}

Nun könnte es aber sein dass die Variable zahl schon vorher einen Wert besitzt der größer ist als 10. Die Schleife würde dann kein einziges Mal durchlaufen werden.

#include <iostream>
using namespace std;

int main()
{
	int zahl = 30;
	
	while (zahl <= 10)
	{
		cout << zahl << endl;
		zahl = zahl + 1;
	}
	
	return 0;
}

Jedoch könnte es sein dass Sie dennoch möchten dass die Schleife mindestens einmal durchlaufen wird, z.B. um den aktuellen Wert der Variable zahl auszugeben. Dafür eignet sich die Do-While-Schleife.

Der Unterschied liegt darin dass nicht vor der Schleife geprüft wird ob sie (noch einmal) durchlaufen werden sollen, sondern erst nachher. Im Klartext bedeutet dies dass die Schleife durchlaufen wird und danach überprüft wird ob sie erneut durchlaufen werden soll. Damit wird erzielt dass sie mindestens einmal durchlaufen wird.

#include <iostream>
using namespace std;

int main()
{
	int zahl = 30;
	
	do
	{
		cout << "Zahl ist jetzt: " << zahl << endl;
		zahl = zahl + 1;
	}
	while (zahl <= 10);
	
	return 0;
}

Beachten Sie das Semikolon am Ende der Schleifendefinition.
Do-While-Schleifen werden auch verwendet wenn z.B. innerhalb der Schleife Variablen initializiert werden sollen die weiter verwendet werden sollen.


Die For-Schleife

Die While- und Do-While-Schleifen eignen sich für unterschiedliche Zwecke, wenn jedoch vorher schon feststeht dass eine Schleife z.B. 10 oder 20 mal durchlaufen werden soll, ist eine For-Schleife zu befürworten. Eine For-Schleife definiert selbst einen Zähler und ein Zählmechanismus. So kann festgelegt werden dass eine Schleife z.B. 10, 20, 100, oder 3000 mal durchlaufen werden soll.

Die Anweisung einer For-Schleife braucht dabei drei Daten:
- eine Zählervariable
- eine Abbruchbedingung
- eine Bearbeitetung dieses Zählers beim jedem Schleifendurchgang

Ein Beispiel könnte so aussehen:

#include <iostream>
using namespace std;

int main()
{
	for (int x = 0; x < 30; x = x + 1)
	{
		
	}
	
	return 0;
}

In der For-Schleife wird eine Zählervariable x definiert die den Wert 0 bekommt. Danach wird definiert dass der Schleifendurchgang wiederholt werden soll solange x kleiner ist als 30. Zuletzt wird noch eine Bearbeitung dieser Zählervariable definiert, nämlich eine Erhöhung dieser Variable um eins bei jedem Schleifendurchgang. Somit wird erreicht dass der Code innerhalb der Schleife genau 30 mal ausgeführt wird.

Mit einer For-Schleife kann man leicht alle Elemente eines Arrays durchlaufen.

#include <iostream>
using namespace std;

int main()
{
	string[] zahlen = {0, 1, 2, 3, 4, 5};

	for (int i = 0; i < 6; i = i + 1)
	{
		cout << zahlen[i] << endl;
	}
	
	return 0;
}


Schleifendurchgänge abbrechen

Nehmen wir mal an Sie möchten den Code innerhalb einer Schleife in zwei Teilen aufteilen: ein Teil der immer ausgeführt werden soll, und einer dessen Ausführung vom Resultat im ersten Codeteil abhängig ist. Dies könnte mit einer bedingten Ausführung erreicht werden.

#include <iostream>
using namespace std;

int main()
{
	for (int x = 0; x < 30; x = x + 1)
	{
		cout << x << endl;
		
		if (x < 20) cout << "Kleiner als 20" << endl;
	}
	
	return 0;
}

Im obigen Beispiel wird zuerst der aktuelle Wert der Zählervariable x ausgegeben. Danach wird geprüft ob dieser aktuelle Wert kleiner ist als 20. Wenn dies zutrifft, wird noch der Text "Kleiner als 20" ausgegeben.

Dieses simple Beispiel könnte jedoch weitaus effektiver realisiert werden. Stellen Sie sich mal vor, Sie möchten mehrere Codeteile von mehreren, unterschiedlichen Bedingungen abhängig machen, dann würde der Code schon schnell unübersichtlich und fehleranfällig werden. Deshalb kann man einen Schleifendurchgang auch frühzeitig ganz abbrechen.

Die Schlüsselwörter continue und break können jeden Schleifentyp abbrechen. An der Stelle wo eines dieser Schlüsselworter vorkommt, wird der aktuelle Schleifendurchgang sofort abgebrochen. Dazu soll nur das Schlüsselwort vorkommen, keine zusätzlichen Parameter. Der Unterschied zwischen continue und break ist der dass bei continue der aktuelle Schleifendurchgang abgebrochen und beim Nächsten angefangen wird, während break die Schleife ganz abbricht und das Programm beim Code nach der Schleife vortfährt. Ein Beispiel könnte dies verdeutlichen.

Wir wiederholen unser Beispiel, jedoch ersetzen wir die bedingte Ausführung mit der Anweisung continue.

#include <iostream>
using namespace std;

int main()
{
	for (int x = 0; x < 30; x = x + 1)
	{
		cout << x << endl;
		
		if (x >= 20) continue;
		
		cout << "Kleiner als 20" << endl;
	}
	
	return 0;
}

Wenn unsere Zählervariable x größer oder gleich 20 ist, wird der Schleifendurchgang abgebrochen. Das Resultat wäre dass alle Zahlen von 0 bis einschließlich 19 ausgegeben werden, jeweils gefolgt von dem Text "Kleiner als 20". Danach werden nur noch alle Zahlen von 20 bis 30 ausgegeben.

Ersetzen wir die Anweisung durch break, dann wird die gesamte Ausführung der Schleife abgebrochen.

#include <iostream>
using namespace std;

int main()
{
	for (int x = 0; x < 30; x = x + 1)
	{
		cout << x << endl;
		
		if (x >= 20) break;
		
		cout << "Kleiner als 20" << endl;
	}
	
	return 0;
}

Dieses Beispiel wurde resultieren in der Auflistung aller Zahlen von 0 bis 19, gefolgt von dem Text "Kleiner als 20". Danach kommt nichts mehr.


Endlosschleifen

Bei Schleifen ist Vorsicht geboten: ist die Abbrechbedingung falsch definiert, bzw. wird nie erreicht, dann wird die Schleife endlos wiederholt. Dies führt zu einem Programmabsturz.

Ein Beispiel einer Endlosschleife ist die, wobei eine Zählervariable verwendet wird, diese aber nicht erhöht wird.

#include <iostream>
using namespace std;

int main()
{
	int zaehler = 0;
	
	while (zaehler < 10)
	{
		cout << zaehler << endl;
	}
	
	return 0;
}

Hier wurde vergessen die Variable zaehler bei jedem Durchgang zu erhöhen. Deshalb wird sie immer kleiner als 10 sein und wird die Schleife als endlos lange wiederholt ausgeführt.

Eine andere Gefahr besteht darin dass die Zaehlervariable einer For-Schleife innerhalb der Schleife verändert wird, wodurch die Abbruchbedingung nie erfült wird.

#include <iostream>
using namespace std;

int main()
{
	for (int x = 0; x == 10; x = x + 1)
	{
		x = x - 1;
	}
	
	return 0;
}

Hier wurde noch eine zusätzliche potentielle Gefahr eingabaut: die Abbruchbedingung ist nur erfüllt wenn die Zählervariable exact den Wert 10 hat. Wenn Sie also den Wert 12 hat, würde die Bedingung nicht erfüllt sein, obwohl dies vom Programmierer warscheinlich beabsichtigt wurde.

Manchmal könnte eine Endlosschleife jedoch beabsichtigt sein. Es könnte z.B. sein dass eine Schleife immer erneut ausgeführt werden soll, bis der Anwender eine bestimmte Antwort gegeben hat, z.B. bei einem Quiz.

#include <iostream>
using namespace std;

int main()
{
	string antwort;

	while (true)
	{
		cout << "Zu welchem Kontinent gehört Deutschland?: ";
		cin >> antwort;
		
		if (antwort == "Europa") break;
	}
	
	return 0;
}

Das Programm wird immer (beachte dass die Abbruchbedingung der While-Schleife immer wahr, bzw. true ist) erneut ausführen, bis der Anwender auf die Frage "Zu welchem Kontinent gehört Deutschland?" mit "Europa" antwortet. Wenn der Anwender richtig geantwortet hat, wird die Schleife verlassen mit der Anweisung break.

Ein anderer Grund für die Verwendung einer Endlosschleife ist eine zu komplexe Abbruchbedingung, sprich eine Bedingung (oder dessen Überprüfung) die sich aus mehreren Zeilen Code zusammensetzt.


Inkrementierung und Dekrementierung

Bisher hatten wir den Wert unserer Zählervariable immer um eins erhöht mit dem Code "x = x + 1". Jedoch kann dies kurzer geschrieben werden, nl. einfach "x++". Hierdurch wird die Variable um eins erhöht. Analag dazu kann man den Wert jeweils um eins substraktiert. Damit wird also eine schrittweise Veränderung der Zählervariable erzielt. Dieses Verfahren nennt man "Inkrementierung", bzw. "Dekrementierung".

Dabei werden Inkrementierungen (und Dekrementierungen) als Postfix und als Präfix unterscheiden. Als Postfix bewirkt dies, dass der Wert um eins erhöht wird nachdem der Schleifendurchgang beendet wurde. Im Gegensatz dazu wird beim Präfix die Zählervariable sofort erhöht und beim Schleifendurchgang verwendet. Ein Beispiel könnte dies sicherlich verdeutlichen.

Wir möchten jetzt alle Zahlen von 1 bis 10 ausgeben. Im ersten Beispiel verwenden wir einen Postfix, im zweiten einen Präfix.

#include <iostream>
using namespace std;

int main()
{
	for (int x = 0; x < 10; x++)
	{
		cout << x << endl;
	}
	
	return 0;
}

//========================================

#include <iostream>
using namespace std;

int main()
{
	for (int x = 0; x < 10; ++x)
	{
		cout << x << endl;
	}
	
	return 0;
}

Im ersten Beispiel werden alle Zahlen von 0 bis 9 ausgegeben, im zweiten Beispiel sind das alle Zahlen von 1 bis 10.

Bei einem Postfix verläuft die Schleife wie folgt:
  1. überprüfe ob x kleiner ist als 10
  2. gib den Wert von x aus
  3. erhöhe x um eins
  4. überprüfe erneut ob x kleiner ist als 10
Bei einem Präfix wird die Reihenfolge leicht geändert:
  1. überprüfe ob x kleiner ist als 10
  2. erhöhe x um eins
  3. gib den Wert von x aus
  4. überprüfe erneut ob x kleiner ist als 10


Sprünge mit Zählervariablen

Statt den Wert einer Zählervariable immer um eins zu erhöhen, können wir diese auch z.B. jeweils um 3 erhöhen.

#include <iostream>
using namespace std;

int main()
{
	for (int x = 0; x < 30; x += 3) cout << x << endl;
	
	return 0;
}

Ich habe hier einfachkeitshalber die geschweifte Klammern weggelassen, da Sie bei nur einem Befehl in einer Schleife nicht notwendig sind.


Code-Parameter und Null-Parameter

In einer For-Schleife kann als dritter Parameter auch den Ausgabe-Code geschrieben werden und im eigentlichen Code-Block ein so genannter "Null-Parameter".

#include <iostream>
using namespace std;

int main()
{
	for (int x = 0; x < 10; cout << x++ << endl) ;
	
	return 0;
}

Diese Methode ist aber unübersichtlich und fehleranfällig. Ich rate von der Verwendung ab.


Verschachtelte Schleifen

Es ist auch möglich um mehrere Schleifen in einander zu verschachteln. Im folgenden Beispiel wird eine While-Schleife fünfmal wiederholt. Innerhalb dieser Schleife wird eine For-Schleife alle Zahlen von 1 bis 10 ausgeben. Diese verschachtelte Schleife wird komplett ausgeführt bevor mit dem nächsten Durchlauf der überliegenden Schleife fortgefahren wird.

#include <iostream>
using namespace std;

int main()
{
	int zaehler = 0;
	
	while (zaehler < 5)
	{
		for (int x = 0; x < 10; ++x) cout << x << endl;		
		
		zaehler++;
	}
	
	return 0;
}

Jede weitere Schleife könnte theoretisch noch eine weitere Schleife beinhalten, jedoch wird der Compiler ab einem bestimmten Zeitpunkt die Schleifenkonstruktion als zu komplex bezeichnen und es nicht mehr kompilieren können.

Zudem ist Vorsicht geboten bei Schleifenabbrüche mittels continue und break. Da in C/C++ keine Namen an Schleifen vergeben werden können, kann der Compiler eventuell nicht richtig entscheiden welche von mehreren verschachtelten Schleifen abgebrochen werden soll.


[back to top]



Userdaten
User nicht eingeloggt

Gesamtranking
Werbung
Datenbankstand
Autoren:04511
Artikel:00815
Glossar:04116
News:13565
Userbeiträge:16552
Queueeinträge:06248
News Umfrage
Ihre Anforderungen an ein Online-Zeiterfassungs-Produkt?
Mobile Nutzung möglich (Ipone, Android)
Externe API Schnittstelle/Plugins dritter
Zeiterfassung meiner Mitarbeiter
Exportieren in CSV/XLS
Siehe Kommentar



[Results] | [Archiv] Votes: 1158
Comments: 0