15-roman-number-gcd-MarcUs7i created by GitHub Classroom
Find a file
2025-02-13 16:52:14 +01:00
general.h Of course 2025-02-13 16:52:14 +01:00
main_driver.c Of course 2025-02-13 16:52:14 +01:00
makefile Of course 2025-02-13 16:52:14 +01:00
README.md Of course 2025-02-13 16:52:14 +01:00
README_de.md Of course 2025-02-13 16:52:14 +01:00
README_en.md Of course 2025-02-13 16:52:14 +01:00
roman_number.c Of course 2025-02-13 16:52:14 +01:00
roman_number.h Of course 2025-02-13 16:52:14 +01:00
shortcut.c Of course 2025-02-13 16:52:14 +01:00
shortcut.h Of course 2025-02-13 16:52:14 +01:00
test_driver.c Of course 2025-02-13 16:52:14 +01:00
test_roman_number.c Of course 2025-02-13 16:52:14 +01:00
test_roman_number.h Of course 2025-02-13 16:52:14 +01:00

if.03.22 Procedural Programming

Roman numbers

This assignment targets on string analysis and validation, pointer handling as well as a simple recursive calculation.

Introduction

Roman numbers are used since ancient ages. They are expressed via letters which have the following values:

  • I: 1
  • V: 5
  • X: 10
  • L: 50
  • C: 100
  • D: 500
  • M: 1000
  • some more higher value signs

The numerical value is calculated by simply adding the value of each letter:

MMCLXXXVII => 1000 + 1000 + 100 + 50 + 10 + 10 + 10 + 5 + 1 + 1 = 2187

In addition, values are subtracted, if one I, X, or C is placed before the next larger value.

IV => -1 + 5 = 4
IX => -1 + 10 = 9
XL => -10 + 50 = 40
CD => -100 + 500 = 400

An extension of this rule allows subtraction of the letters above if they are placed in front of even larger values

IC => -1 + 100 = 99 instead of XCIX => -10 + 100 - 1 + 10

which simplifies the usage of the numbers. The letters V, L, D are never used as subtractive values.

Roman number letters are written in descending order of their nominal value, except for the special case of subtraction.

MCMLXVII (1967) must not be written in different order, e.g. IIVXLMCM is not allowed

Assignment

Your task is to implement an abstract data type calls RomanNumber, which encapsulates the numerical representation of a string that expresses a valid roman number.

The following functions for the ADT RomanNumber shall be implemented:

  • rn_is_valid_number_str
    A private function which determines whether a given string represents a valid roman number. If the string contains any other characters but the above defined ones, it DOES NOT represent a valid number!
    The validity can easily be done by iterating through all characters of the string and testing if the current letter is a defined one and its numerical value is equal or less the numerical letter of the previous letter. The only exception to this rule are valid subtraction patterns (e.g. IX). If the current and next letter form a valid subtraction pattern can be tested with the already implemented private function rn_is_valid_subtraction. If such a valid pattern was detected, the string remains valid for the current letter and the check stated above can be skipped. Nevertheless, the 'next' letter (which was used to test the subtraction pattern) still need regularly be checked.
  • rn_get_value_for_letter:
    A private function that provides the numerical value of a single letter. Note that switch / case instructions work for characters as well.
  • rn_create:
    Allocates a new RomanNumber out of a statically allocated pool of data structs for the ADT. The pool of RomanNumber data is allocated on the global scope with a size of MAX_ROMAN_NUMBER_COUNT as defined in roman_number.c.
    It MAY be trusted, that the pool is sufficiently large to provide instances for all unit tests without the need of returning instances to the pool.
    It MAY be trusted that a valid string is provided, although not necessarily a valid roman number string. If the string does not represent a valid roman number, an invalid (non-null)RomanNumber shall be provided. The given string need therefore be checked using the private function rn_is_valid_number_str, whether the string represents a valid roman number.
    If the given string is a valid roman number, its numerical value shall be calculated upon creation and stored within the ADTs data. The roman number is converted by simply adding the values of its letters, except a subtraction pattern is detected. In this case the value of the letter has to be subtracted. Use the function rn_is_valid_subtraction to check for subtractions.
    Note that an empty string is valid and results in the value zero (0), while a null-string is invalid.
  • rn_is_valid:
    Determines whether or not the given RomanNumber is valid. It is, if it is neither 0 nor was created from an invalid roman number.
  • rn_get_value:
    Provides the numerical value of the given RomanNumber as stored in the ADTs data or a value less than zero, if the RomanNumber is not valid.
  • rn_gcd:
    Calculates the greatest common divisor of two RomanNumbers and returns the result again as RomanNumber.
    Important note: This function DOES NOT actually calculate the GCD but uses the function int_gcd for this purpose. It only 'converts' the roman number back and forth.
  • int_gcd: Actually calculates the greatest common divisor (GCD) of two positive integer values using recursion. It MAY be trusted, that the given integers are always positive.
    The GCD is defined as:
    • gcd(x, 0) = x;
    • gcd(x, y) = gcd(y, x % y);
      where % is the modulo operator.
      Note the this function is independently tested and can be implemented even if the ADT is not working.

Tasks

  • Create a skeleton implmentation of the ADT to make the unit tests compilable.
  • Implement all required functions to make the unit tests pass.
  • A main application is not required.

Good Luck!