// Converts Roman numerals to decimal integers. // This code is very resilient to non-standard or variant forms, but does not handle // exotic forms such as fractions (S etc.), the overstrike x1000 operator or unicode numerals. // Andrew Fountain, released under GPL 3.0 or higher #define ID "$Id: roman_num.cpp 46 2012-08-03 18:24:25Z andrewfn $" #include <iostream> #include <string.h> using namespace std; /* Helper function for romChars() * return the value of a Roman character, or zero if not a valid character */ int romCharVal(char ch) {// C D E F G H I J K L M N O P Q R S T U V W X static int romval[] = { 100, 500, 0,0,0,0, 1, 0,0, 50, 1000, 0,0,0,0,0,0,0,0, 5, 0, 10 }; int i = ch - 'C'; if ((i >= 0) && (i <= ('X'-'C'))) return romval[i]; else return 0; } /* Takes a pair of Roman numerals and modifies *dec by the value of the first one * comparing it to the second to see if it is to be added or subtracted. * A value of FALSE is returned if ch is a character that is not a valid Roman numeral. * An invalid alphanumeric character will cause the dec to be set to zero. * Note that this will successfully convert even variant forms, e.g. IIII (4) or IM (999). */ bool romChars(int * dec, char ch, char ch2) { if (!isalnum(ch)) return false; // Roman numeral has been terminated int romval = romCharVal(ch); if (romval == 0) { // illegal character, so return zero value *dec = 0; return false; } if (romval >= romCharVal(ch2)) *dec += romval; // if character larger than the next one: add else *dec -= romval; // if character less than the following one, then subtract return true; } /* Example conversion function: returns the integer value of a Roman numeral character string. * The string is terminated by a space or non-alphanumeric characters * If there are any invalid alphanumeric characters, the function returns 0 */ int rom2int(const char * roman) { int dec = 0; for (const char *r = roman; *r; r++) { if (!romChars(&dec, *r, *(r+1))) break; } return dec; } /* test code */ int main (int argc, char *argv[]) { const char *roman[] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", //1-15 "XXXVIII", "XXXIX", "XL", "XLI", "XLII", "XLIII", "XLIV", "XLV", //38-45 "MCMLXXXVIII", "MCMLXXXIX", "MCMXC", "MCMXCI", "MCMXCII", "MCMXCIII", "MCMXCIV", //1988-1994 "MCMXCV", "MCMXCVI", "MCMXCVII", "MCMXCVIII", "MCMXCIX", "MM ", //1995-2000 "IIII", "VIIII.", "IC", "MIM", "XJ", "KII", "I1", ""}; // Non-standard 4, 9, 99, 1999, + 3 errors for (size_t i=0; strlen(roman[i]); i++) { cout << rom2int(roman[i]) << " = " << roman[i] << endl; } }