134 lines
6.0 KiB
Markdown
134 lines
6.0 KiB
Markdown
|
# Assignment: Vektor (stack-basiert)
|
||
|
|
||
|
📆 **Fällig: ----** 📆 [Musterlösung](solution/)
|
||
|
|
||
|
Es ist sechs Uhr morgens, Ihr Radiowecker weckt Sie mit dem Song "I Got You Babe" von Sonny and Cher. Irgendwie erinnert Sie das an einen [Film](https://www.imdb.com/title/tt0107048), den Sie vor längerer Zeit gesehen haben, mit Bill Murray...
|
||
|
|
||
|
![Quelle: Pixabay.com](kryptonier.jpg)
|
||
|
|
||
|
Es gibt einen lauten Knall. Sie schauen zum Himmel uns sehen dort ein Raumschiff der Kryptonier, die offensichtlich die Weltherrschaft an sich reißen wollen; woher Sie das wissen? Natürlich aus den vielen Filmen, die Sie gesehen haben: Aliens == böse. Zum Glück haben Sie noch eine kleine Rakete im Garten (woher auch immer die stammt), die Sie auf das Raumschiff abfeuern könnten. Aber wie bloß die Flugbahn berechnen? Dazu bietet sich doch die gute alte Vektorrechnung an...
|
||
|
|
||
|
Wie bitte? Die Geschichte kennen wir doch schon. Wieso schon wieder die Kryptonier? Wenn Ihnen das nicht klar ist, sollten Sie noch einmal den [Film](https://www.imdb.com/title/tt0107048) mit Bill Murray schauen.
|
||
|
|
||
|
**Ziel**: Ziel dieses Assignments ist es, Vektoren in C zu implementieren.
|
||
|
|
||
|
|
||
|
## Vector: Struktur und Funktionen
|
||
|
|
||
|
### Beschreibung des Programms
|
||
|
|
||
|
Implementieren Sie eine Struktur `Vector` und die dazugehörigen Funktionen in einer Datei `vector_stack.c` mit deren Hilfe man auf dreidimensionalen Vektoren die wichtigsten Operationen durchführen kann. Drei Dimensionen reichen, um die Flugbahn der Rakete zu berechnen -- also kein Grund für mehr Dimensionen!
|
||
|
|
||
|
Die Komponenten x, y und z sollen als `double` gespeichert werden.
|
||
|
|
||
|
Ihre Implementierung soll die folgenden Aktionen unterstützen:
|
||
|
|
||
|
* `vec_init` - Befüllen des Vektors mit Daten für die drei Komponenten
|
||
|
* `vec_null` - Setzen eines Vektors als Nullvektor (alle drei Komponenten [x,y,z] sind 0)
|
||
|
* `vec_add` - Addieren zweier Vektoren
|
||
|
* `vec_sub` - Subtrahieren zweier Vektoren
|
||
|
* `vec_mul_scalar` - Multiplikation des Vektors mit einem Skalar
|
||
|
* `vec_mul_dot` - Skalarmultiplikation zweier Vektoren
|
||
|
* `vec_mul_cross` - Kreuzprodukt zweier Vektoren
|
||
|
* `vec_norm` - Erzeugung des Einheitsvektors aus einem gegebenen Vektor (d.h. Vektor der Länge 1 mit derselben Richtung wie der ursprüngliche Vektor). Beachten Sie, dass vom Nullvektor kein Einheitsvektor erzeugt werden kann. In diesem Fall müssen Sie eine entsprechende Rückgabe machen, um den Fehler anzuzeigen.
|
||
|
* `vec_length` - Berechnung des Betrages (der Länge) eines Vektors
|
||
|
* `vec_collinear` - Test, ob zwei Vektoren kollinear (parallel oder antiparallel) sind
|
||
|
* `vec_equals` - Test, ob zwei Vektoren gleich sind
|
||
|
* `vec_print` - Ausgabe des Vektors auf der Console
|
||
|
* `vec_to_s` - Umwandlung des Vektors in einen String
|
||
|
|
||
|
Keine der Funktionen verändert die übergebenen Vektoren, sondern schreibt das Ergebnis in den ebenfalls übergebenen Vektor für das Ergebnis. Siehe hierzu das Beispiel unten.
|
||
|
|
||
|
Bei einer C-Bibliothek muss man sich entscheiden, wer für die Allokation des Speichers zuständig ist. Hier entscheiden wir uns dafür, dass der Verwender der Funktionen den Speicher beschaffen muss und den Funktionen als Pointer übergeben. Das folgende Beispiel zeigt, wie Ihre Vektor-Bibliothek zu benutzen ist:
|
||
|
|
||
|
```c
|
||
|
Vector v1, v2, v3;
|
||
|
char* result;
|
||
|
|
||
|
/* Vektoren initialisieren */
|
||
|
vec_init(&v1, 10.0, 20.0, 30.0);
|
||
|
vec_init(&v2, -20.0, 99.0, 38.0);
|
||
|
|
||
|
/* Kreuzprodukt berechnen. v1 und v2 bleiben unverändert,
|
||
|
Ergebnis wird in v3 gespeichert. */
|
||
|
vec_mul_cross(&v3, v1, v2);
|
||
|
|
||
|
/* Ergebnis ausgeben */
|
||
|
result = vec_to_str(v3);
|
||
|
printf("Das Ergebnis ist: %s\n", result);
|
||
|
free(result);
|
||
|
```
|
||
|
|
||
|
Einzig die `vec_to_str`-Funktion beschafft Speicher für den String per `malloc`, den der Verwender per `free` wieder freigeben muss. Alle anderen Funktionen führen keine Speicherallokation durch.
|
||
|
|
||
|
Schreiben Sie eine Header-Datei `vector_stack.h`, welche die exportierten Funktionen als Prototypen enthält. Diese werden wir für die Tests benötigen. Kommentieren Sie die Funktionen ausreichend.
|
||
|
|
||
|
## Tests
|
||
|
|
||
|
Überprüfen Sie die Funktionalität Ihrer Implementierung mit entsprechenden Unit-Tests (Datei `vektor_stack_test.c`) und weisen Sie mit diesen Tests nach, dass die implementierten Operationen richtig funktionieren.
|
||
|
|
||
|
Für die Unit-Tests steht Ihnen eine ganz einfache Testbibliothek über das Header-File `minitest.h` zur Verfügung. Die Datei `vektor_stack_test.c` enthält ein Beispiel für die Benutzung dieser Bibliothek. Verwenden Sie das dort benutzte Schema und fügen Sie Ihre Tests hinzu.
|
||
|
|
||
|
Verwenden Sie bitte __mindestens__ die folgenden Testdaten/Testfälle.
|
||
|
|
||
|
### Multiplikation mit einem Skalar
|
||
|
|
||
|
* `[1, -5, 3] * 6 = [ 6, -30, 18 ]`
|
||
|
* `[ 1, -5, 3 ] * -3 = [ -3, 15, -9 ]`
|
||
|
|
||
|
|
||
|
### Skalarprodukt zweier Vektoren
|
||
|
|
||
|
* `[ 1, 2, 3 ] * [ -7, 8, 9 ] = 36`
|
||
|
* `[ -5, 9, 7 ] * [ 10, 3, 8 ] = 33`
|
||
|
|
||
|
|
||
|
### Addition und Subtraktion
|
||
|
|
||
|
* `[ 4, 0, 8 ] + [ -1, 4, 7 ] = [ 3, 4, 15 ]`
|
||
|
* `[ 4, 0, 8 ] - [ -1, 4, 7 ] = [ 5, -4, 1 ]`
|
||
|
* `[ 4, 0, 8 ] + [ -1, 4, 7 ] = [ -1, 4, 7 ] + [ 4, 0, 8 ]`
|
||
|
|
||
|
|
||
|
### Kreuzprodukt
|
||
|
|
||
|
* `[ 1, 2, 3 ] x [ -7, 8, 9 ] = [ -6, -30, 22 ]`
|
||
|
* `[ 1, 2, 8 ] x [ 4, 3, 5 ] = [ -14, 27, -5 ]`
|
||
|
|
||
|
|
||
|
### Betrag
|
||
|
|
||
|
* `|[ 1, 1, 1 ]| = sqrt(3)`
|
||
|
* `|[ 5, 4, 3 ]| = sqrt(50)`
|
||
|
|
||
|
|
||
|
### Kollinearität
|
||
|
|
||
|
* `[ 4, 5, 7 ]` und `[ 16, 20, 28 ]` sind kollinear
|
||
|
* `[ 4, 5, 7 ]` und `[ 16, 20, 21 ]` sind nicht kollinear
|
||
|
|
||
|
|
||
|
### Komplexere Rechnung
|
||
|
|
||
|
* `([ -1, 5, -2 ] x [ 2, 1, 2 ]) * [ 2, 0, 5 ] = -31`
|
||
|
|
||
|
|
||
|
## Makefile
|
||
|
|
||
|
Automatisieren Sie das Kompilieren und Testen Ihrer Programme mit einem Makefile. Dieses sollte mindestens die folgenden Targets haben:
|
||
|
|
||
|
* `all` - baut alle Dateien
|
||
|
* `clean` - setzt das Projekt zurück und löscht alle Kompilationsergebnisse
|
||
|
* `test` - führt die oben beschriebenen Tests aus
|
||
|
|
||
|
Sie benötigen natürlich weitere Targets für die Objektdateien und fertigen Executables.
|
||
|
|
||
|
|
||
|
|
||
|
## Quellen
|
||
|
|
||
|
* [Skript](https://smits-net.de/files/pr3_c/html/) zur Vorlesung
|
||
|
* [C-Tutorial](https://www.learn-c.org/)
|
||
|
* [C von A bis Z](https://openbook.rheinwerk-verlag.de/c_von_a_bis_z/)
|
||
|
|
||
|
* Vektorrechnung: [Wikipedia: Vektor -- Rechenoperationen](https://de.wikipedia.org/wiki/Vektor#Rechenoperationen)
|