// Source: "Software Design ...", John A Robinson, Newnes, 2004, page 98. // Simple Roman number convertor: Doesn't handle subtraction prefices #include #include #include // Needed for isdigit() using namespace std; struct convertor // A convertor stores an arabic integer and its equivalent // Roman character. E.g. 10, 'X' { int value; char roman_symbol; }; // The array of convertors is declared globally and initialized to contain all relevant // arabic/roman number pairs. const convertor conv[7] = { 1, 'I', 5, 'V', 10, 'X', 50, 'L', 100, 'C', 500, 'D', 1000, 'M' }; void arabic_to_roman(const char *in, char *out); void roman_to_arabic(const char *in, long *value); int main(int argc, char *argv[]) { char outroman[20]; long outarabic; if (argc != 2) { cerr << "Usage: romanize number (where number is in Arabic or Roman numerals)\n"; return -1; } // Read the first character to see whether input is Arabic or Roman if (isdigit(argv[1][0])) // First character is a digit, i.e. an arabic numeral { arabic_to_roman(argv[1], outroman); cout << outroman << '\n'; } else { roman_to_arabic(argv[1], &outarabic); cout << outarabic << '\n'; } return 0; } void arabic_to_roman(const char *in, char *out) { long value; value = atoi(in); // Convert input to an integer value int i = 6; // Start at largest numbers // (i indexes the convertor array from large values to small) while(value >0) { if ((value - conv[i].value) >= 0) // Keep outputting current symbol so long as // its value can be subtracted from the residue // of the input value { *out++ = conv[i].roman_symbol; // Output symbol value -= conv[i].value; // Reduce "input" value appropriately } else i--; // Move to next convertor down (next lowest value) } *out = '\0'; // Terminating null } void roman_to_arabic(const char *in, long *value) { *value = 0; char c; int i = 6; // Assume Roman number is correctly formed: Starts with highest // value symbol and moves down values monotonically through string c = *in++; while ((c != '\0')&&(i >= 0)) { // Find character if (c == conv[i].roman_symbol) // Matches current symbol { *value += conv[i].value; // Add symbol value to output value c = *in++; } else i--; // Move to next convertor down } }