5.8 KiB
Executable file
if.03.22 Procedural Programming
Römische Zahlen
Diese Aufgabe zielt auf die Analyse und Validierung von Zeichenketten, die Bearbeitung von Zeigern sowie eine einfache rekursive Berechnung ab.
Einführung
Römische Zahlen werden seit der Antike verwendet. Sie werden durch Buchstaben ausgedrückt, die folgende Werte haben:
- I: 1
- V: 5
- X: 10
- L: 50
- C: 100
- D: 500
- M: 1000
- einige weitere Zeichen mit höheren Werten
Der numerische Wert wird einfach durch Addition des Werts jedes Buchstabens berechnet:
MMCLXXXVII => 1000 + 1000 + 100 + 50 + 10 + 10 + 10 + 5 + 1 + 1 = 2187
Zusätzlich werden Werte abgezogen, wenn ein I, X oder C vor dem nächsten größeren Wert steht.
IV => -1 + 5 = 4
IX => -1 + 10 = 9
XL => -10 + 50 = 40
CD => -100 + 500 = 400
Eine Erweiterung dieser Regel erlaubt das Subtrahieren der darüber liegenden Buchstaben, wenn sie vor noch größeren Werten stehen.
IC => -1 + 100 = 99 anstelle von XCIX => -10 + 100 - 1 + 10
was die Verwendung der Zahlen vereinfacht. Die Buchstaben V, L, D werden niemals als subtraktive Werte verwendet.
Römische Zahlen werden in absteigender Reihenfolge ihres Nennwerts geschrieben, mit Ausnahme des speziellen Falls der Subtraktion.
MCMLXVII (1967) darf nicht in anderer Reihenfolge geschrieben werden, z.B. IIVXLMCM ist nicht erlaubt
Aufgabe
Ihre Aufgabe besteht darin, einen abstrakten Datentyp namens RomanNumber zu implementieren, der die numerische Darstellung einer Zeichenkette kapselt, die eine gültige römische Zahl darstellt.
Die folgenden Funktionen für den ADT RomanNumber sollen implementiert werden:
-
rn_is_valid_number_str
Eine private Funktion, die feststellt, ob eine gegebene Zeichenkette eine gültige römische Zahl darstellt. Wenn die Zeichenkette andere Zeichen als die oben definierten enthält, stellt sie KEINE gültige Zahl dar!
Die Gültigkeit kann leicht überprüft werden, indem alle Zeichen der Zeichenkette durchlaufen und getestet wird, ob der aktuelle Buchstabe einer definierten entspricht und sein numerischer Wert gleich oder kleiner ist als der numerische Wert des vorherigen Buchstabens. Die einzige Ausnahme von dieser Regel sind gültige Subtraktionsmuster (z.B. IX). Wenn das aktuelle und das nächste Zeichen ein gültiges Subtraktionsmuster bilden, kann mit der bereits implementierten privaten Funktionrn_is_valid_subtractiongetestet werden. Wenn ein solches gültiges Muster erkannt wurde, bleibt die Zeichenkette für den aktuellen Buchstaben gültig, und die oben genannte Überprüfung kann übersprungen werden. Trotzdem muss der 'nächste' Buchstabe (der zum Testen des Subtraktionsmusters verwendet wurde) weiterhin regelmäßig überprüft werden. -
rn_get_value_for_letter:
Eine private Funktion, die den numerischen Wert eines einzelnen Buchstabens liefert. Beachten Sie, dassswitch / case-Anweisungen auch für Zeichen funktionieren. -
rn_create:
Alloziert eine neueRomanNumberaus einem statisch allokierten Pool von Datenstrukturen für den ADT. Der Pool vonRomanNumber-Daten wird im globalen Bereich mit einer Größe vonMAX_ROMAN_NUMBER_COUNTwie inroman_number.cdefiniert, allokiert.
Es kann darauf vertraut werden, dass der Pool ausreichend groß ist, um Instanzen für alle Unittests bereitzustellen, ohne dass Instanzen an den Pool zurückgegeben werden müssen.
Es kann darauf vertraut werden, dass eine gültige Zeichenkette bereitgestellt wird, jedoch nicht unbedingt eine gültige römische Zahl. Wenn die Zeichenkette keine gültige römische Zahl darstellt, soll eine ungültige (nicht-null)RomanNumberbereitgestellt werden. Die gegebene Zeichenkette muss daher mit der privaten Funktionrn_is_valid_number_strüberprüft werden, ob die Zeichenkette eine gültige römische Zahl darstellt.
Wenn die gegebene Zeichenkette eine gültige römische Zahl ist, soll ihr numerischer Wert bei der Erstellung berechnet und in den Daten des ADTs gespeichert werden. Die römische Zahl wird einfach durch Addition der Werte ihrer Buchstaben umgewandelt, es sei denn, ein Subtraktionsmuster wird erkannt. In diesem Fall muss der Wert des Buchstabens subtrahiert werden. Verwenden Sie die Funktionrn_is_valid_subtraction, um nach Subtraktionen zu suchen.
Beachten Sie, dass eine leere Zeichenkette gültig ist und zu einem Wert von null (0) führt, während eine null-Zeichenkette ungültig ist. -
rn_is_valid:
Bestimmt, ob die gegebeneRomanNumbergültig ist. Sie ist gültig, wenn sie weder 0 ist noch aus einer ungültigen römischen Zahl erstellt wurde. -
rn_get_value:
Liefert den numerischen Wert der gegebenenRomanNumber, wie er in den Daten des ADTs gespeichert ist, oder einen Wert kleiner als null, wenn dieRomanNumbernicht gültig ist. -
rn_gcd:
Berechnet den größten gemeinsamen Teiler (GGT / GCD) von zweiRomanNumbers und gibt das Ergebnis erneut alsRomanNumberzurück.
Wichtiger Hinweis: Diese Funktion berechnet DEN GGT NICHT tatsächlich, sondern verwendet die Funktionint_gcdzu diesem Zweck. Sie wandelt die römische Zahl nur hin und her. -
int_gcd: Berechnet tatsächlich den größten gemeinsamen Teiler (GGT / GCD) von zwei positiven Ganzzahlen mit Rekursion. Es kann darauf vertraut werden, dass die gegebenen Ganzzahlen immer positiv sind.
Der GGT ist definiert als:ggd(x, 0) = x;ggd(x, y) = ggd(y, x % y);
wobei%der Modulo-Operator ist.
Beachten Sie, dass diese Funktion unabhängig getestet wird und implementiert werden kann, auch wenn der ADT nicht funktioniert.
Aufgaben
- Erstellen Sie eine Skelettimplementierung des ADTs, um die Unittests kompilierbar zu machen.
- Implementieren Sie alle erforderlichen Funktionen, um die Unittests zu bestehen.
- Eine Hauptanwendung ist nicht erforderlich.