Download as pdf or txt
Download as pdf or txt
You are on page 1of 3

RomanNumeral Assignment for C Programming

M. Beeson March 27, 2010

The Assignment

This assignment involves practice with elementary string manipulation in C. It involves converting decimal numbers to and from Roman numerals. For this assignment you have to implement two functions: int DecimalToRoman(int N, char *ans) /* If N is between 1 and 3999, inclusive, translate the number N into Roman numerals and write the result (as a null-terminated string) into ans, assuming ans has enough space to hold the result. Return 0 for success. Rules for Roman numerals are given in the assignment. If N is not between 1 and 3999, return 1 if N is too large, 2 if N is zero, and 3 if N is negative. In those cases, the space pointed to by ans must not be modified. */ int RomanToDecimal(const char *x, int *ans) /* x will be a null-terminated string. Determine if x is a valid Roman numeral for a number between 1 and 3999 inclusive. See the assignment for the rules for validity. If so write the translation into modern decimal (ordinary base 10) notation into *ans, and return 0. If x is not a valid Roman numeral, return 1 if x contains a character other than I, V, X, L, C, D, and M; return 2 if x contains only those characters but in some illegal combination, such as IL or VIIII. You are not allowed to modify the characters of x. Note that MMMM is also considered an illegal combination. */ The required lename is RomanNumeral.c. You should, as usual, prepare a header le RomanNumeral.h and a le main.c for your own use, but submit only RomanNumeral.c

The detailed specication of Roman numerals

The Wikipedia article on Roman numerals is interesting, but you do not have to read it. It contains the following very useful information:

The basic multiples of Roman numerals follow a pattern: 1 I X C M 2 II XX CC MM 3 III XXX CCC MMM 4 IV XL CD 5 V L D 6 VI LX DC 7 VII LXX DCC 8 VIII LXXX DCCC 9 IX XC CM

Ones Tens Hundreds Thousands

[continuing the quotation from Wikipedia] A practical way to write a Roman number is to consider the modern Arabic numeral system, and separately convert the thousands, hundreds, tens, and ones as given in the chart above. So, for instance, 1234 may be thought of as one thousand and two hundreds and three tens and four, obtaining M (one thousand) + CC (two hundreds) + XXX (thirty) + IV (four), for MCCXXXIV. Thus eleven is XI (ten and one), 32 is XXXII (thirty and two) and 2009 is MMIX (two thousand and nine). Note that the subtractive principle is not extended beyond the chart: for example, IL is not used for 49, rather this should be written as forty (XL) and nine (IX), or XLIX. [end of the quotation from Wikipedia] This will serve as the reference, for this assignment, as to what is the correct Roman numeral for any decimal number up to 3999. Beyond that you will not go in this assignment. I note that the subtractive principle is never use to subtract V. For example, 45 cannot be written as VL, and 95 cannot be written as VC. You can never have a V immediately preceding a larger character. Note that a string can fail to be a valid Roman numeral by containing an illegal character, or by containing legal characters in illegal combinations.

Programming Hints

1. Start by writing a main() program to test your DecimalToRoman. You should do this before writing any other code (except, of course, skeleton code for the two required functions that does nothing, but does at least compile, and your header le.) For starters, have main print out the values of the roman numerals for a lot of numbers. 2. Then write DecimalToRoman. This function should implement the algorithm described in the quotation from Wikipedia above. To review, the steps are (i) First check if N is a valid input. If not, return the appropriate error value, and thats that. (ii) Find the units, tens, hundreds, and thousands digits of N . There are two (dierent) good ways to do this. Either use sprintf, or just repeatedly take the number mod 10 and then divide it by 10. You have already had practice in converting between digits (as numbers) and the Ascii codes of the characters for them. (iii) Starting from thousands (or the hundreds if there are no thousands, etc.), look up the Roman numeral in the table and incorporate what you nd into your answer appropriately. That means that the rst thing written will be copied into ans and the rest will be concatenated onto what is already there. When nished, return 0. Look up the Roman numeral in the table can be conveniently implemented by making each row of the table into an array of strings. Possibly you can even cut and paste the table from the pdf le of the assignment and then insert commas, quotation marks, braces and equal signs; Im not sure if this will actually work, but it illustrates the idea. 2

3. Use the main you wrote in step 1 to test and debug DecimalToRoman. Dont go on until you are satised that DecimalToRoman is working perfectly on valid inputs. 4. Now extend main to test RomanToDecimal. Comment out the code that tests DecimalToRoman, and write a loop that converts all the possible valid inputs to Roman numeral form, and then converts the Roman numeral form back to decimal form, and compares with the original decimal form, printing out any wrong answers (but not the right answers). 5. Then write RomanToDecimal, at least the part dealing with valid inputs. Note that subtraction is never applied to more than one character at a time. Thus you have IX for 9, but you dont have IIX for 8. You can have XCIX (which is 99) but the two digits that are subtracted are not consecutive. Only one digit at a time is subtracted. As another example, note that LXC is illegal, so the question of whether the X is added or subtracted does not arise. You can only have a larger Roman digit (character) following a smaller one in the cases when the smaller one will be subtracted. Hence, you can go through the input string examining two digits at a time, and determine whether the numerical value of the rst of the two digits is to be added or subtracted. For example, in XCIX, the rst X gives 10 since it is followed by C, which has a larger value than X (larger in the sense of Roman numerals, not in the sense of ascii codes). Then, the C gives 100, so the total so far is 90. The C gives 100, not 100, since it is followed by the smaller I. Then the I gives 1, since it is followed by the larger X, making 89 so far. Then the nal X gives 10, making 99 for the answer. The last digit can never be subtracted, so dont bother examining the non-existent character after it. Its easy to check whether the input has illegal character and return the required 1 in that case. You can get a C without doing further checking for validity of a Roman numeral. The algorithm described here works on valid inputs, but is not easily extended to check for valid input. 6. Use the main you wrote in step 4 to test and debug RomanToDecimal on valid inputs. 7. After everything is working on valid inputs, add code to main to check the error conditions and corresponding return values specied in the assignment. There are a lot of possible invalid inputs, so make sure that you test all the dierent possible return values at least. 8. Then write code (which you might want to put into a separate function) to check whether a string is a valid Roman numeral or not. To plan how to write this code, make the following observation about the table above. Except for the last column, the Ones involve only I and V; the Tens involve only X and C; the Hundreds involve only C and D; and the Thousands involve only M. So a legal Roman numeral has to fall into several (at most four) groups, the Thousands, Hundreds, Tens, and Ones, which can be recognized by the digits they contain. You can test for legality by seeing if x can be broken into these four strings and then if the four strings are listed in the corresponding row of the table. This will be a guaranteed correct method. Trying to check pairs and triples of adjacent characters might be made to work too, but that isnt how the reference solution works. This code is more complicated than RomanToDecimal as described above, and by the time you have nished checking that x is valid input, you could have easily computed the decimal value of x too. As a test, you can write that code and verify that it gives the same results as your rst pass at RomanToDecimal. After testing everything (and only after all the tests mentioned are passed locally) submit your code.

You might also like