hpi-artificial-intelligence-teaching-pt2-2026-ex1-cplusplusintro-26-pt2-ex1 created by GitHub Classroom
  • C++ 89.1%
  • Makefile 10.9%
Find a file
2026-04-29 18:27:07 +02:00
.github GitHub Classroom Feedback 2026-04-21 09:04:17 +00:00
.vscode update make and launch file 2026-02-08 18:46:43 +01:00
data Initial commit 2026-02-06 22:52:05 +00:00
doctest@1da23a3e81 Initial commit 2026-02-06 22:52:05 +00:00
src Merge branch 'main' of github.com:HPI-Artificial-Intelligence-Teaching/ex1-cplusplusintro-asbestos-1 2026-04-29 18:27:07 +02:00
tests Initial commit 2026-02-06 22:52:05 +00:00
.gitignore Initial commit 2026-02-06 22:52:05 +00:00
.gitmodules Initial commit 2026-02-06 22:52:05 +00:00
Makefile update make and launch file 2026-02-08 18:46:43 +01:00
readme.md add online IDE url; add deadline 2026-04-21 09:04:22 +00:00

Review Assignment Due Date Open in Codespaces

Programmiertechnik II SS26, Übung 1

Pro Übung gibt es 20 Punkte. Für die Zulassung zur Prüfung müssen in allen Übungen insgesamt mindestens 50 % der Punkte sowie in jeder einzelnen Übung mindestens 25 % erzielt werden.

Der Code für diese Aufgabe kann als Repository geklont und lokal kompiliert werden. Dafür ist es nötig, die Git-Submodule zu initialisieren und zu aktualisieren (wichtig‼️):

git submodule update --init

Anschließend kann

make tests

im Projektordner ausgeführt werden, um die Tests zu kompilieren. (Der Code kann auch unabhängig von den Tests mit make main kompiliert und z. B. mit ./out/main a data/grading_results.db manuell gestartet werden.)

Dev Environment (siehe PT1 im letzten Semester, Übung 1)

Debugging in VS Code/Codespaces

Im .vscode-Ordner finden Sie zwei Launchfiles/Setups, um den Debugger je nach Programmierumgebung zu starten:

  • Visual Studio Code auf macOS
    • .vscode/launch.json muss entfernt oder umbenannt werden
    • .vscode/launch_macos.json muss zu .vscode/launch.json umbenannt werden
    • Installieren Sie die CodeLLDB Extension in Visual Studio Code
  • GitHub Codespaces
    • (lokales Linux/WSL2 sollte mit diesem Setup auch funktionieren, wurde aber nicht getestet)
    • Installieren Sie die C/C++ Extension

Aufgabenstellung

In dieser Übung implementieren Sie eine kleine Auswertungs-Pipeline für Übungsergebnisse:

  1. GradingTable liest eine Binärdatei ein und speichert alle Einträge in einer einfach verketteten Liste.
  2. TaskAgents iterieren/reduzieren über diese Liste und geben Ergebnisse aus.

Projektstruktur:

  • src/grading_table.h/.cpp – Einlesen der Datenbank
  • src/grading_tasks.h/.cpp – Basisklassen & konkrete Tasks (A–E)
  • src/main.cpp – Vorgegeben (CLI-Auswahl des Tasks)
  • data/grading_results.db - Testdaten
  • tests/tests.cpp – Tests

Datenformat: data/grading_results.db

Binärdatei mit einer unbekannten Anzahl an Einträgen ohne Trennzeichen. Jeder Eintrag besteht exakt aus drei Werten (insgesamt 64 Bit):

  • mat_no (Matrikelnummer) als std::uint32_t
  • series (Veranstaltungs-/Übungsnummer) als std::uint16_t
  • points (Punkte) als std::uint16_t

Aufgabe 1 - GradingTable (10 Punkte)

Zu modifizierende Dateien: src/grading_table.h, src/grading_table.cpp

A1.1 Einlesen & Liste aufbauen

Implementieren Sie den Konstruktor GradingTable::GradingTable(std::ifstream& fp) so, dass:

  • nur gelesen wird, wenn die Datei geöffnet ist (fp.is_open()).
  • Einträge vollständig gelesen werden (alle drei Felder); ansonsten wird sauber abgebrochen.
  • für jeden Eintrag ein neues GradingTableEntry erzeugt und in eine einfach verkettete Liste eingehängt wird.
  • GradingTable sowohl Kopf als auch Ende der Liste speichert (g_head, g_tail).

Hinweis 1: Eine Spezifikation des ifstream-Interfaces (C++-Filestream) ist verfügbar unter: cplusplus.com/reference/fstream/ifstream/

Hinweis 2: fp.read(...) erwartet char* → benutzen Sie reinterpret_cast<char*>(&feld)

A1.2 Speicher freigeben (Destruktor)

Implementieren Sie GradingTable::~GradingTable() so, dass alle Listenelemente mit delete freigegeben werden.

A1.3 Iterator-Interface (Range-based for)

Ergänzen Sie GradingTable::Iterator und die Methoden begin()/end(), sodass GradingTable das Iterator-Interface implementiert und folgender Code funktioniert:

for (auto& el : table) {
    // ...
}

Dafür erforderlich sind:

  • operator* liefert Referenz auf aktuelles GradingTableEntry
  • operator-> liefert Pointer auf aktuelles GradingTableEntry
  • operator++ Prefix, geht zum nächsten Element und liefert Iterator&
  • operator++(int) Postfix, liefert alten Iterator-Zustand und geht dann zum nächsten Element
  • operator==, operator!= geben an, ob zwei Iteratoren auf dasselbe Element zeigen
  • begin() gibt Iterator auf g_head
  • end() gibt Iterator, der das Listenende markiert (typisch: nullptr)

Aufgabe 2 - TaskAgents (10 Punkte)

Zu modifizierende Dateien: src/grading_tasks.h, src/grading_tasks.cpp

Sie implementieren eine kleine Klassenhierarchie aus Agents, die alle über performTask() gestartet werden:

  • IteratingTaskAgent: besucht jedes Element einzeln (visit)
  • ReducingTaskAgent: aggregiert einen Integer-Wert über alle Elemente (reduce)

A2.1 Vererbung & virtuelle Methoden

In src/grading_tasks.h fehlen an mehreren Stellen Schlüsselwörter, damit Polymorphie korrekt funktioniert:

  • TaskAgent ist die Basisklasse und besitzt performTask() als "pure virtual function".
  • IteratingTaskAgent und ReducingTaskAgent sind abstrakt:
    • visit(...) ist pure virtual
    • reduce(...) ist pure virtual
  • Setzen Sie override überall dort, wo eine Methode eine Basismethode überschreibt.

A2.2 IteratingTaskAgent: performTask() und visitAll()

Implementieren Sie:

  • int* IteratingTaskAgent::visitAll()

    • Initialisiert ein Array der Länge CONST_MAX_EXPECTED_RESULTS mit Nullen.
    • Iteriert über *table (Range-based for).
    • Ruft für jedes Element visit(&el) auf.
    • Nur wenn visit(...) != 0, wird der Wert in das Array geschrieben (fortlaufend).
    • Gibt den Pointer auf das Array zurück.
  • void IteratingTaskAgent::performTask()

    • Ruft visitAll() auf. Die Ergebnisse für jeden Eintrag im Array müssen jeweils in einer separaten Zeile auf std::cout ausgegeben werden.

A2.3 ReducingTaskAgent: performTask() und reduceAll()

  • int ReducingTaskAgent::reduceAll()

    • Legt eine Integer-Variable als Akkumulator an (Startwert 0).
    • Iteriert über *table (Range-based for).
    • Aktualisiert den Akkumulator mit acc = reduce(&el, acc).
    • Gibt den finalen Akkumulator zurück.
  • void ReducingTaskAgent::performTask()

    • Ruft reduceAll() auf und gibt das Ergebnis auf std::cout aus.

A2.4 Konkrete Tasks (A–E)

Es müssen folgende 5 Agents existieren (CLI-Auswahl über main.cpp):

Task A (a) - alle Einträge ausgeben
  • visit(...) gibt points zurück
Task B (b) - alle Einträge, die < 10 Punkte haben, ausgeben
  • visit(...) gibt mat_no zurück oder 0, damit visitAll() ignorieren kann
Task C (c) – Anzahl der Elemente
  • Ergebnis: Anzahl der Einträge in der Tabelle
Task D (d) – Maximum der Punkte
  • Ergebnis: höchste Punktzahl in allen Einträgen
Task E (e) – Summe der Punkte in Series 3
  • Ergebnis: Summe aller points in series 3

Abgabehinweise

  • Bearbeiten Sie die mit // TODO markierten Stellen im Code.
  • Die verkettete Liste mit dem Iterator-Interface soll selbst implementiert werden. Davon abgesehen darf die STL verwendet werden.
  • Korrekte Speicherverwaltung (new/delete, new[]/delete[] oder ggf. Initialisierung im Stack) gehört zur Aufgabenstellung :)
  • Die Tests sollen alle grün sein (make tests), sind aber in erster Linie eine Hilfestellung, keine Garantie für volle Punktzahl - dafür gibt es die Testatgespräche.