Assignment Chef icon Assignment Chef
All German tutorials

Programming lesson

C++ Datei-I/O und Exceptions: Ein Tutorial mit der Cowsay-Erweiterung

Lerne, wie du in C++ Dateien liest und Exceptions wirfst – am Beispiel einer erweiterten Cowsay-Version, die benutzerdefinierte Kuh-Grafiken aus Dateien lädt.

C++ Datei-I/O Tutorial C++ Exceptions werfen ifstream C++ FileCow Klasse Cowsay C++ Programm C++17 CMakeLists.txt C++ Fehlerbehandlung C++ Datei lesen std::ifstream::failure C++ Vererbung Beispiel C++ OOP Projekt C++ Lab 08 Lösung C++ Datei nicht gefunden Exception C++ Programmierung Studium C++ Game Entwicklung Exceptions C++ Kommandozeilenargumente

Einführung: Warum Datei-I/O und Exceptions? – Ein Trend-Vergleich

Stell dir vor, du entwickelst eine App wie ChatGPT oder einen KI-Assistenten, der aus Benutzereingaben lernt. Wenn die KI eine Datei mit Trainingsdaten nicht finden kann, darf sie nicht einfach abstürzen – sie muss einen Fehler melden und weiterarbeiten. Genau darum geht es in diesem Tutorial: Du lernst, wie du in C++ mit Datei-I/O (ifstream) arbeitest und mit Exceptions (Ausnahmen) kontrolliert auf Fehler reagierst.

Das Beispielprojekt ist eine erweiterte Version des beliebten Cowsay-Programms, das eine sprechende Kuh im Terminal anzeigt. In dieser Version („Return of the Cow“) werden Kuh-Grafiken aus Dateien geladen – und wenn eine Datei fehlt, wird eine Exception geworfen.

Dieses Tutorial richtet sich an Studierende, die bereits Grundkenntnisse in C++ haben (Klassen, Vererbung) und nun lernen möchten, wie man Dateien einliest und Fehlerbehandlung implementiert. Der Code ist auf C++17 ausgelegt – eine der aktuellsten Versionen, die auch in der Industrie und in Game-Engines wie Unreal Engine verwendet wird.

Grundlagen: Datei-I/O mit std::ifstream

In C++ liest du eine Datei mit der Klasse std::ifstream (Input File Stream). Du musst die Header <fstream> und <string> einbinden.

#include <fstream>
#include <string>

std::ifstream file("kuh.txt");
if (!file.is_open()) {
    // Fehler: Datei konnte nicht geöffnet werden
}

Die Methode is_open() prüft, ob die Datei erfolgreich geöffnet wurde. Wenn nicht, kannst du einen Fehler werfen (Exception). Das Einlesen des gesamten Inhalts einer Textdatei erfolgt oft mit einem stringstream:

#include <sstream>

std::stringstream buffer;
buffer << file.rdbuf();
std::string image = buffer.str();

In unserem Projekt laden wir das Bild einer Kuh aus einer Datei und speichern es in einem string.

Exceptions in C++: Grundlagen und Praxis

Exceptions sind ein Mechanismus, um Fehler zur Laufzeit zu melden, ohne dass das Programm sofort abstürzt. Du wirfst eine Exception mit throw und fängst sie mit try-catch.

Typische Exception-Klassen in C++ sind:

  • std::runtime_error – für Laufzeitfehler
  • std::ifstream::failure – für Datei-I/O-Fehler (seit C++11)

Beispiel:

#include <stdexcept>

void loadFile(const std::string& filename) {
    std::ifstream file(filename);
    if (!file.is_open()) {
        throw std::ifstream::failure("Datei nicht gefunden!");
    }
}

Im Hauptprogramm fängst du die Exception:

try {
    loadFile("kuh.txt");
} catch (const std::ifstream::failure& e) {
    std::cerr << "Fehler: " << e.what() << std::endl;
}

Das Projekt: FileCow – eine Kuh aus der Datei

In der Vorgabe gibt es bereits eine Basisklasse Cow und abgeleitete Klassen wie Dragon und IceDragon. Deine Aufgabe ist es, die Klasse FileCow zu implementieren, die von Cow erbt und das Bild aus einer Datei lädt.

Die Klasse FileCow hat:

  • Einen Konstruktor FileCow(const string& name, const string& filename), der die Datei lädt und bei Fehler eine std::ifstream::failure-Exception mit der Nachricht „MOOOOO!!!!!!“ wirft.
  • Eine Methode setImage(), die immer eine std::runtime_error-Exception mit der Nachricht „Cannot reset FileCow Image“ wirft (weil das Bild aus der Datei nicht überschrieben werden darf).

Hier ein möglicher Code (du musst ihn natürlich selbst schreiben):

// FileCow.h
#ifndef FILECOW_H
#define FILECOW_H

#include "Cow.h"
#include <string>

class FileCow : public Cow {
public:
    FileCow(const std::string& name, const std::string& filename);
    void setImage() override; // wirft immer Exception
};

#endif

Die Implementierung des Konstruktors öffnet die Datei, liest den Inhalt und setzt das Bild. Wenn die Datei nicht geöffnet werden kann, wird eine Exception geworfen.

Häufige Fehler und wie du sie vermeidest

Hier sind typische Stolperfallen bei diesem Lab:

  1. Vergessen, die Datei zu schließen – das macht der Destruktor von ifstream automatisch, aber es ist guter Stil, file.close() aufzurufen.
  2. Falscher Exception-Typ – die Aufgabenstellung verlangt std::ifstream::failure, nicht std::runtime_error (außer bei setImage).
  3. CMakeLists.txt nicht auf C++17 gesetzt – sonst gibt es Compiler-Fehler. Füge set(CMAKE_CXX_STANDARD 17) hinzu.
  4. Dateipfade – die Dateien liegen im Unterordner „cows“. Du musst den Pfad relativ zum Arbeitsverzeichnis angeben: "cows/meineKuh.txt".

Vollständiges Beispiel: Cowsay mit Datei-Kuh

Das Hauptprogramm (Cowsay.cpp) verarbeitet Kommandozeilenargumente und ruft die entsprechenden Cow-Objekte auf. Der HeiferGenerator erzeugt automatisch FileCow-Objekte aus Dateien im „cows“-Verzeichnis. Wenn der Benutzer cowsay -f tux "Hallo" eingibt, wird die Datei „cows/tux.txt“ geladen und angezeigt.

Beispiel für die Ausgabe (wie in der Aufgabenstellung):

> cowsay -f tux "Hast du einen Hering?"
  ______________________
< Hast du einen Hering? >
  ----------------------
         .--.
        |o_o |
        |:_/ |
       //   \\
      (|     | )
     /'\_   _/`\
     \___)=(___/

Wenn die Datei nicht existiert, erscheint eine Fehlermeldung (Exception wird abgefangen).

Trend-Tipp: Exceptions in der Spieleentwicklung

In der Spieleentwicklung (z.B. mit Unreal Engine oder Unity) werden Exceptions verwendet, um Ressourcen-Fehler zu melden: Eine Textur kann nicht geladen werden, eine Sounddatei fehlt, oder ein Netzwerk-Timeout tritt auf. Statt das Spiel abstürzen zu lassen, wird eine Exception geworfen, die an einer zentralen Stelle gefangen wird – ähnlich wie in deinem Cowsay-Programm. Ein populäres Beispiel: In Minecraft (in Java, aber das Prinzip ist ähnlich) wird beim Laden einer defekten Welt eine Exception geworfen und der Spieler erhält eine Fehlermeldung, anstatt dass die Welt korrupt wird.

Indem du dieses Lab löst, lernst du eine grundlegende Technik der Softwareentwicklung, die in KI-Anwendungen, Finanz-Apps und sogar in der Robotik verwendet wird.

Zusammenfassung

In diesem Tutorial hast du gelernt:

  • Wie man mit std::ifstream Dateien in C++ liest
  • Wie man Exceptions wirft und fängt (std::ifstream::failure und std::runtime_error)
  • Wie man eine abgeleitete Klasse FileCow schreibt, die eine Datei lädt und bei Fehlern Exceptions wirft
  • Wie man das Ganze in einem kommandozeilenbasierten Cowsay-Programm einsetzt

Mit diesem Wissen kannst du nun die Lab-Aufgabe „Return of the Cow“ erfolgreich lösen. Viel Erfolg!