Here is an often asked student coding problem ... converting an integer to Roman Numerals ...
// intToRomanNumerals.cpp // this revision 2010-09-14 //
/*
Demo of converting DECIMAL NUMERALS to ROMAN NUMERALS ...
Modified for strings, and to use the MSD, (Most Significant Digit)
rather than the LSD (Least Significant Digit) method used by Randy.
Randall Hyde is the author of HLA (High Level Assembly) ... See ...
http://webster.cs.ucr.edu/AoA/index.html
http://developers-heaven.net/forum/index.php/topic,46.0.html
*/
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
string iToString( int i ) // convert integer 'i' to a string
{
ostringstream oss;
oss << i;
return oss.str(); // return as a string ...
}
string convert( int n )
{
if( n > 3999 ) return "Largest number handled is 3999";
if( n < 1 ) return "Smallest number handled is 1";
string nStr = iToString( n ); // now n is in nStr ...
string rm; // construct an empty string to hold the growing Roman Num...
for( size_t i = 0; i < nStr.length(); ++i ) // traverse nStr ...
{
// On each pass ... extract the NEXT Most Significant Digit (MSD)
// from the number 'n' ... i.e. from 'nStr'
int msd = nStr[i] - '0'; // ok ... now have next Most Significant Digit
// Here is the trick, (from Randy of HLA), that makes this work ...
// On each pass ... 'multiply' the previous Roman Num by 10
// This is achieved by swapping the characters in the char string 's1'
// with their corresponding character in char string 's2' below ...
char s1[] = "IVXLCDM";
char s2[] = "XLCDM**"; // each valid 'char' here is 10 times the above
// On each pass, the folowing set of nested loops will 'multiply by 10',
// (similar to a 'left shift' for decimal numbers), the value in string
// rm (string rm holds the growing Roman Numeral value, empty to start)
// Note: next loops are skipped on first pass when rm.size() is still 0
for( size_t j = 0; j < rm.size(); ++j ) // for each digit in nStr, get rm[j]
{
for( size_t k = 0; k < 7; ++k ) // for each Roman digit above, traverse s1
if( rm[j] == s1[k] ) // find k... so can ... 'multiply by 10'
{
rm[j] = s2[k];
break; // since k was found ... and x10 was done
}
}
// Ok ... all previous Roman Numerals have been multiplied by 10 ... so
// now ... convert the current MSD int ... to a Roman Num string
// and add in ... at the end of the growing 'rm' string ...
string romanNum[] =
{// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"
};
rm = rm + romanNum[msd];
cout << rm << endl; // shows steps ... comment out if desired //
}
return rm; // return the string holding the Roman Numerals ...
}
int main()
{
int n;
string prompt = "Enter a number from the keyboard (q to quit) : ";
// the while loop will exit if the 'n' that was input was NOT a valid int
while( cout << prompt << flush && cin >> n )
cout << "The number " << n << " converted is " << convert(n) << endl;
}
And the other way ...
Note: you will need a C++ 11 or better compiler to compile the following (only lightly tested) demo code ...
// romanNumeralsToInt.cpp // this revision 2017-01-30 //
// Compile with a C++ 11 compiler (or better) //
/*
Demo of converting ROMAN NUMERALS to DECIMAL NUMERALS ...
http://developers-heaven.net/forum/index.php/topic,46.0.html
*/
#include <iostream>
#include <string>
using namespace std;
struct NumToInt
{
string nStr;
int val;
};
const NumToInt ConvTable[] =
{
{"MMM",3000}, {"MM",2000}, {"MCM",1900},
{"MDCCC",1800}, {"MDCC",1700}, {"MDC",1600}, {"MCD",1400}, {"MD",1500},
{"MCCC",1300}, {"MCC",1200}, {"MC",1100}, {"CM",900}, {"M",1000},
{"DCCC",800}, {"DCC",700}, {"DC",600}, {"CD",400}, {"D",500},
{"XC",90}, {"CCC",300}, {"CC",200}, {"C",100},
{"LXXX",80}, {"LXX",70}, {"LX",60}, {"XL",40}, {"L",50}, {"VIII",8}, {"XXX",30}, {"XX",20},
{"IX",9}, {"X",10}, {"IV",4}, {"VI",6}, {"VII",7}, {"VIII",8},
{"V",5}, {"III",3}, {"II",2}, {"I",1}
};
int convert( string nStr )
{
//if( n > 3999 ) return "Largest number handled is 3999";
//if( n < 1 ) return "Smallest number handled is 1";
int val = 0;
for( auto item : ConvTable ) // traverse array ...
{
size_t pos;
if( (pos = nStr.find(item.nStr)) != string::npos )
{
val += item.val;
nStr.erase(pos, item.nStr.size());
if( !nStr.size() ) break;
}
}
return val;
}
int main()
{
string nStr;
string prompt = "Enter a valid Roman Numeral from the keyboard (q to quit) : ";
// the while loop will exit if the 'n' that was input was NOT a valid int
while( cout << prompt << flush && cin >> nStr )
{
if( nStr == "q" ) return 0;
cout << "The number " << nStr << " converted is " << convert(nStr) << endl;
}
}