Zum Inhalt springen
C++ Anfรคnger 25 min

if, switch & Schleifen

Kontrollstrukturen in C++: klassisches if, moderne Init-Statements, switch, Schleifen und range-for. Plus break, continue und das neue if constexpr.

Aktualisiert:
Inhaltsverzeichnis

Kontrollstrukturen in C++

C-aehnlich, aber mit einigen modernen Erweiterungen, die den Alltag angenehmer machen.

if / else

int alter = 18;

if (alter >= 18) {
    std::cout << "Volljaehrig\n";
} else if (alter >= 16) {
    std::cout << "Fast volljaehrig\n";
} else {
    std::cout << "Zu jung\n";
}

Regeln:

  • Klammern () um die Bedingung sind Pflicht
  • Geschweifte Klammern {} technisch optional, aber immer empfohlen
  • Bedingung wird zu bool konvertiert (0 = false, alles andere = true)

if mit Init-Statement (C++17)

Du kannst eine Variable direkt in der if-Bedingung deklarieren - sie lebt nur im if/else-Block:

if (auto ergebnis = berechne(); ergebnis > 0) {
    std::cout << "Positiv: " << ergebnis << "\n";
} else {
    std::cout << "Nicht positiv: " << ergebnis << "\n";
}
// ergebnis existiert hier nicht mehr

Praktisch fuer temporaere Werte, die nur fuer den Check gebraucht werden.

Ternaerer Operator

auto text = (alter >= 18) ? "volljaehrig" : "minderjaehrig";

Standard-C-Syntax.

switch

int tag = 3;

switch (tag) {
    case 1:
        std::cout << "Montag\n";
        break;
    case 2:
    case 3:
    case 4:
        std::cout << "Mitte der Woche\n";
        break;
    case 5:
        std::cout << "Freitag\n";
        break;
    default:
        std::cout << "Wochenende\n";
}

Wichtig: break; am Ende jedes Case, sonst Fall-Through zum naechsten.

Fall-Through explizit markieren (C++17)

switch (n) {
    case 1:
        std::cout << "Eins\n";
        [[fallthrough]];
    case 2:
        std::cout << "Zwei oder eins\n";
        break;
    default:
        break;
}

Das [[fallthrough]]-Attribut macht klar: โ€œDer Fall-Through ist gewollt, nicht vergessen.โ€

switch mit Init-Statement

switch (auto wert = berechne(); wert) {
    case 0: /* ... */ break;
    case 1: /* ... */ break;
}

while und do-while

int n = 10;
while (n > 0) {
    std::cout << n << "\n";
    n--;
}

// mindestens einmal ausfuehren
int eingabe;
do {
    std::cin >> eingabe;
} while (eingabe != 0);

Klassische for-Schleife

for (int i = 0; i < 5; i++) {
    std::cout << i << "\n";
}

Range-for (C++11, bevorzugt)

Der moderne Weg, ueber Sammlungen zu iterieren:

#include <vector>
#include <string>

std::vector<std::string> namen = {"Max", "Anna", "Leo"};

for (const auto& name : namen) {
    std::cout << name << "\n";
}
  • const auto& - lesen, keine Kopie
  • auto& - lesen und aendern, keine Kopie
  • auto - Kopie

Mit Initialisierung

for (auto name : std::vector{"a", "b", "c"}) {
    std::cout << name << "\n";
}

Index bekommen

C++ hat kein eingebautes โ€œenumerateโ€ - aber du kannst Zaehler nutzen:

int i = 0;
for (const auto& name : namen) {
    std::cout << i++ << ": " << name << "\n";
}

Oder mit std::ranges::views::enumerate (C++23):

#include <ranges>

for (auto [i, name] : std::views::enumerate(namen)) {
    std::cout << i << ": " << name << "\n";
}

break und continue

for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) continue;  // gerade ueberspringen
    if (i > 7) break;           // abbrechen bei > 7
    std::cout << i << "\n";     // 1, 3, 5, 7
}

Labels (C++ hat keine)

Wenn du aus verschachtelten Schleifen ausbrechen willst:

bool abbruch = false;
for (int x = 0; x < 10 && !abbruch; x++) {
    for (int y = 0; y < 10; y++) {
        if (finde(x, y)) {
            abbruch = true;
            break;
        }
    }
}

Oder die Schleife in eine Funktion auslagern und return nutzen - oft sauberer.

if constexpr (C++17)

Das ist ein Compile-Zeit-if fuer Templates:

template <typename T>
void print(const T& wert) {
    if constexpr (std::is_integral_v<T>) {
        std::cout << "Int: " << wert << "\n";
    } else if constexpr (std::is_floating_point_v<T>) {
        std::cout << "Float: " << wert << "\n";
    } else {
        std::cout << "Anderer Typ\n";
    }
}

Der Zweig, der nicht passt, wird nicht einmal kompiliert - das ist maechtig fuer generische Programmierung. Fuer Anfaenger erst mal nicht wichtig, aber gut zu wissen, dass es das gibt.

Structured Bindings

Destrukturierung fuer Tuples, Paare, Structs:

#include <map>
#include <string>

std::map<std::string, int> alter = {{"Anna", 28}, {"Max", 34}};

for (const auto& [name, jahre] : alter) {
    std::cout << name << ": " << jahre << "\n";
}

Und bei std::pair:

auto [min, max] = std::minmax({3, 1, 4, 1, 5, 9, 2});

Sehr praktisch bei Map-Iteration oder Funktionen, die mehrere Werte zurueckgeben.

Praktisches Beispiel

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

int main() {
    std::vector<int> zahlen = {3, 1, 4, 1, 5, 9, 2, 6};

    // Maximum finden (klassisch)
    int max = zahlen[0];
    for (const auto& z : zahlen) {
        if (z > max) max = z;
    }
    std::cout << "Max: " << max << "\n";

    // Einfacher mit <algorithm>
    auto maxIt = std::max_element(zahlen.begin(), zahlen.end());
    std::cout << "Max: " << *maxIt << "\n";

    // Alle geraden Zahlen
    for (const auto& z : zahlen) {
        if (z % 2 != 0) continue;
        std::cout << z << " ";
    }
    std::cout << "\n";
}

Zusammenfassung

  • if / else mit optionalem Init-Statement (C++17)
  • switch mit explizitem [[fallthrough]]
  • Range-for ist der idiomatische Weg fuer Schleifen
  • auto&, const auto&, auto - bewusst waehlen
  • Structured Bindings fuer elegante Destrukturierung
  • std::max_element, std::sort, etc. sparen Handarbeit

Im naechsten Kapitel: Funktionen und References.

Zurรผck zum C++ Kurs