Skip to content

Commit 5e739ba

Browse files
committed
Add solution for example in L01
1 parent 57b8011 commit 5e739ba

5 files changed

Lines changed: 166 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ output/
99
bin/
1010
obj/
1111
.vscode/
12+
13+
code/01_Software/improved
14+
code/01_Software/withBugs

01_Software.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@ Das Programm schließt zwei Bugs ein:
494494
1. Der Vergleich schließt die Werte mit dem Index 0 aus da die Bedingung `i=2` lautet, aber die Indizes von 0 bis 9 gehen. Das führt zu einem unvollständigen Sortieren.
495495
2. `l++` in Zeile 14 bewirkt das `l` hinter das Ende des Arrays zeigt. Damit sind Zugriffe auf `a[j]` wegen `j=l` in Zeile 25 undefiniert und können zu einem Absturz führen.
496496

497+
Eine überarbeitete studentische Lösung (Nico Seidler, SoSe 2026) findet sich unter [code/01_Software/](https://github.com/TUBAF-IfI-LiaScript/VL_Softwareentwicklung/tree/master/code/01_Software) — inklusive einer [README](https://github.com/TUBAF-IfI-LiaScript/VL_Softwareentwicklung/blob/master/code/01_Software/README.md), die Stärken und offene Diskussionspunkte gegenüberstellt.
498+
497499
*******************************************************************************
498500

499501
## Herausforderungen

code/01_Software/README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Codebeispiel "AllesFalsch" – Bugs und überarbeitete Lösung
2+
3+
Dieser Ordner begleitet den Abschnitt *Qualitätsmängel erkennen* aus [01_Software.md](../../01_Software.md).
4+
5+
Die Lösung hat Nico Seidler (SoSe 2026) beigesteuert. Die überarbeitete Version korrigiert die beiden echten Bugs der Ursprungsfassung, beseitigt einige Qualitätsmängel (z. B. fehlende Fehlerprüfungen, ungenutzte Header) und verbessert die Wartbarkeit durch bessere Strukturierung und sprechende Bezeichner. Dennoch bleiben einige Schwächen (z. B. algorithmische Komplexität, Endlosschleife bei Fehleingaben) bestehen, um Diskussionsanlässe zu bieten.
6+
7+
| Datei | Inhalt |
8+
| ---------------------------- | ---------------------------------------------------------------------- |
9+
| [withBugs.c](withBugs.c) | Ursprungsfassung mit zahlreichen Qualitätsmängeln und zwei echten Bugs |
10+
| [improved.c](improved.c) | Überarbeitete Lösung (studentischer Beitrag, SoSe 2026) |
11+
| [numbers.txt](numbers.txt) | Beispiel-Eingabedatei |
12+
13+
## Übersetzen und Ausführen
14+
15+
```bash
16+
gcc -Wall -Wextra -O2 improved.c -o improved
17+
./improved
18+
# Eingabe des Pfads, z. B.: numbers.txt
19+
```
20+
21+
## Stärken der überarbeiteten Lösung
22+
23+
Die Lösung adressiert systematisch die in der ISO-25010-Tabelle aufgelisteten Qualitätsmerkmale:
24+
25+
- **Funktionale Eignung** — Beide Bugs des Originals sind korrigiert:
26+
- äußere Sortierschleife startet bei `i = 0` (vorher fälschlich `i = 2` → Element 0 und 1 wurden nicht einbezogen),
27+
- innere Schleife läuft bis `j < n - i - 1` (vorher `j = l` → Zugriff hinter das Array-Ende).
28+
- **Zuverlässigkeit**`fopen` wird auf `NULL` geprüft, `fclose` und `free` werden konsequent aufgerufen, auch auf den Fehlerpfaden (z. B. `realloc`-Fail).
29+
- **Leistungseffizienz (partiell)** — Sortierung *in-place* über Zeigerübergabe, keine Array-Kopie.
30+
- **Wartbarkeit** — BubbleSort ist in eine eigene Funktion mit Doxygen-Kopf ausgelagert; sprechende Bezeichner (`pfad`, `daten`, `kapazitaet`, `anzahl`).
31+
- **Sicherheit**`scanf("%255s", …)` mit expliziter Längenbegrenzung → kein Buffer Overflow beim Einlesen des Pfads.
32+
- **Flexibilität** — Dateipfad wird zur Laufzeit abgefragt, Datenarray wächst dynamisch über `realloc`.
33+
- **Robuster `realloc`-Umgang** — Rückgabewert wird in einem Zwischenpointer (`optimiert`) aufgefangen, damit `daten` bei Allokationsfehler nicht verloren geht.
34+
35+
## Offene Punkte / Diskussionsanlässe
36+
37+
Nicht alle Schwächen des Originals sind vollständig behoben. Die folgenden Punkte eignen sich gut für die Plenumsdiskussion:
38+
39+
1. **Endlosschleife bei wiederholter Fehleingabe**
40+
Die `while (datei == NULL)`-Schleife besitzt kein Abbruchkriterium. Bei permanent falschen Eingaben läuft das Programm unbegrenzt.
41+
*Verbesserung:* Maximale Anzahl Versuche oder Abbruch bei `EOF`.
42+
43+
2. **Algorithmische Komplexität weiterhin O(n²)**
44+
Der Mangel "quadratischer Aufwand der Sortierung" aus der Qualitätstabelle wird nicht behoben.
45+
*Verbesserung:* `swapped`-Flag für Early-Exit bei sortierten Eingaben, oder Verwendung von `qsort` aus `<stdlib.h>`.
46+
47+
3. **Magic Numbers**
48+
Die Werte `256` (Pfadlänge) und `10` (Startkapazität) stehen im Code ohne Benennung.
49+
*Verbesserung:* `#define` bzw. `PATH_MAX` aus `<limits.h>`.
50+
51+
4. **Keine Validierung der Datei-Inhalte**
52+
`fscanf` bricht beim ersten Nicht-Integer still ab; nachfolgende gültige Zahlen werden ignoriert, ohne Warnung.
53+
*Verbesserung:* Ursache des Abbruchs prüfen (`feof` vs. Parse-Fehler) und melden.
54+
55+
5. **Sonderfall leere Datei**
56+
Bei `anzahl == 0` wird trotzdem "Sortierte Ergebnisse:" ausgegeben.
57+
*Verbesserung:* explizite Meldung "Keine Daten eingelesen".
58+
59+
6. **Pfade mit Leerzeichen**
60+
`scanf("%255s", …)` liest nur bis zum ersten Whitespace.
61+
*Verbesserung:* `fgets` + Newline-Trimming.
62+
63+
## Bezug zur Vorlesung
64+
65+
Die Lösung zeigt exemplarisch, dass *Bug-Fix* und *Qualitätsverbesserung* zwei unterschiedliche Dimensionen sind: Die funktionalen Fehler sind behoben, einige nicht-funktionale Mängel (insbesondere Leistungseffizienz und vollständige Eingabevalidierung) bleiben jedoch bestehen. Genau diese Trennung ist ein zentrales Motiv des Abschnitts.

code/01_Software/improved.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
4+
/**
5+
* @brief BubbleSort-Algorithmus als eigene Funktion (Prozedur) -> Wartbarkeit
6+
* Ausnutzen von Seiteneffekten (Zeigeruebergabe -> Call by Reference) zum Sortieren des originalen Arrays,
7+
* kein Anfertigen einer Array-Kopie notwendig -> Effizienz
8+
* @param arr zu sortierendes Integer-Array
9+
* @param n Laenge des Arrays (Anz. Elemente im Array)
10+
*/
11+
void bubbleSort(int arr[], int n) {
12+
int i, j, temp;
13+
14+
// auessere Schleife -> bestimmt, wie oft das Array durchlaufen wird
15+
for (i = 0; i < n - 1; i++) {
16+
// innere Schleife zum Vergleich benachbarter Elemente (j und j + 1)
17+
/* 'n - i - 1' sorgt dafuer, dass bereits sortierte Elemente
18+
am Ende des Arrays nicht erneut geprueft werden. -> Effizienz */
19+
for (j = 0; j < n - i - 1; j++) {
20+
21+
if (arr[j] > arr[j + 1]) {
22+
// Tauschvorgang mit temp-Variable
23+
temp = arr[j];
24+
arr[j] = arr[j + 1];
25+
arr[j + 1] = temp;
26+
}
27+
}
28+
}
29+
}
30+
31+
int main() {
32+
char pfad[256];
33+
int *daten = NULL;
34+
int kapazitaet = 10;
35+
int anzahl = 0;
36+
int wert;
37+
FILE *datei = NULL;
38+
39+
// flexibler Pfad statt hart gecodeter Standardpfad zur Standard-Datei
40+
// Fehlerbehandlung bei falscher Eingabe
41+
while (datei == NULL) {
42+
printf("Bitte den Pfad zur Datei eingeben (ohne Leerzeichen): ");
43+
if (scanf("%255s", pfad) != 1) return 1;
44+
45+
// Oeffnen der Datei inkl. Fehlerbehandlung
46+
datei = fopen(pfad, "r");
47+
if (datei == NULL) {
48+
printf("Datei nicht gefunden! Bitte erneut versuchen.\n");
49+
}
50+
}
51+
52+
// Allokieren dynamischen Speichers, damit Arraygroesse erst zur Laufzeit festgelegt wird
53+
daten = malloc(kapazitaet * sizeof(int));
54+
if (daten == NULL) {
55+
fclose(datei);
56+
return 1;
57+
}
58+
59+
// Einlesen der Daten
60+
while (fscanf(datei, "%d", &wert) == 1) {
61+
if (anzahl >= kapazitaet) {
62+
kapazitaet *= 2;
63+
// realloc fuer dynamische Speicherallokierung zur Laufzeit, ebenso Behandlung
64+
// von Platzmangel an zusammenhaengendem Speicherbereich auf dem Heap
65+
int *optimiert = realloc(daten, kapazitaet * sizeof(int));
66+
67+
if (optimiert == NULL) {
68+
free(daten);
69+
fclose(datei);
70+
return 1;
71+
}
72+
daten = optimiert;
73+
}
74+
daten[anzahl++] = wert;
75+
}
76+
77+
// Datei am Ende schliessen
78+
fclose(datei);
79+
80+
// Aufruf der Bubblesort-Funktion
81+
if (anzahl > 1) {
82+
bubbleSort(daten, anzahl);
83+
}
84+
85+
// Ausgabe der sortierten Liste
86+
printf("\nSortierte Ergebnisse:\n");
87+
for (int i = 0; i < anzahl; i++) {
88+
printf("%d ", daten[i]);
89+
}
90+
printf("\nFertig! (%d Eintraege verarbeitet)\n", anzahl);
91+
92+
// Freigeben des vorher genutzten Heapspeichers
93+
free(daten);
94+
// Programm erfolgreich beendet
95+
return 0;
96+
}

0 commit comments

Comments
 (0)