0 Converting Roman Numerals to Decimals

• March 1st, 2011, 04:34 AM
0 Converting Roman Numerals to Decimals
Hi,

I have been working on this program for a few days.. and I am so far gone I lost myself in my own program. I usually just start from scratch when I get frustrated but there is too much time invested into my heap to give up so I thought I would come here. My assignment is as follows:

Write a program that converts a number entered in Roman Numerals to decimal. Needs to consist of a class called romanType and an object that does the following:

Store the number as a Roman numeral
Convert and store the number into decimal form
Print the number as a Roman numeral or decimal number as requested by user

The decimal values of the roman numerals are:
M = 1000
D = 500
C = 100
L = 50
X = 10
V = 5
I = 1

After completion, I need to test the program with the following input: MCXIV, CCCLIX, MDCLXVI

Here's what I have so far in the source file:

Code:

```//romanType.cpp #include <iostream> #include <iomanip> #include "romanType.h" using namespace std; int main() {     romanType r;         char romanNum;     char choice;     int decimal;     int total;         cout << setw(60) << "Welcome! Please follow the directions below." << endl;     cout << endl;     cout << "Please enter a Roman Numeral: ";     cin >> romanNum;     cout << endl;         r.setRoman(romanNum);     r.convertRoman(total);             cout << "Do you want to see the [R]oman Numeral or the [D]ecimal? ";     cin >> choice;     cout << endl;         if(choice == 'R' || choice == 'r')           r.printRoman(romanNum);     else if(choice == 'D' || choice == 'd')           r.printDecimal(total);     else           cout << "That was not an invalid choice.." << endl;         cout << endl;         system("pause");     return 0;  }//End main```

Here's what I have so far in the implementation file:
Code:

```//  romanTypeImp.cpp #include <iostream> #include "romanType.h" using namespace std; romanType::romanType() {                                 }//End romanType Constructor romanType::romanType(char) {     char romanNum;              }//End romanType(string) Constructor romanType:: ~romanType() { }//End ~romanType Destructor void romanType::setRoman(char) {     char romanNum; }//End getRoman int romanType::convertRoman(int& total) {     int len = strlen(romanNum);     int count[len];         for(int i = 0; i > len; i++)     {                    switch(romanNum[i])           {                 case 'M':                       count[i] = 1000;                       break;                 case 'm':                       count[i] = 1000;                       break;                 case 'D':                       count[i] = 500;                       break;                 case 'd':                       count[i] = 500;                       break;                 case 'C':                       count[i] = 100;                       break;                 case 'c':                       count[i] = 100;                       break;                 case 'L':                       count[i] = 50;                       break;                 case 'l':                       count[i] = 50;                       break;                 case 'X':                       count[i] = 10;                       break;                 case 'x':                       count[i] = 10;                       break;                 case 'V':                       count[i] = 5;                       break;                 case 'v':                       count[i] = 5;                       break;                 case 'I':                       count[i] = 1;                       break;                 case 'i':                       count[i] = 1;                       break;           }//End switch              total = total + count[i];     }//End for       total = 0;     for (int i = 0; i < len-1; i++)     {           if(count[i] < count[i+1])                 total = total - 2 * count[i];           }//End for          }//End convertRoman void romanType::printRoman(char romanNum) const {     cout << "Here is your number displayed in Roman Numeral form: " << romanNum << endl; }//End printRoman int romanType::printDecimal(int& total) {     cout << "Here is your number displayed in Decimal form: " << total << endl; }//End printDecimal```

And here's what I have so far in the header file:

Code:

```//romanType.h using namespace std; class romanType { public:       void printRoman(char) const;       int printDecimal(int&);       void setRoman(char);       int convertRoman(int&);             romanType();       romanType(char);       ~romanType();         private:       char romanNum[6];       int decimal;       int total; };//End Class romanType```

If anyone can offer any guidance, that would be much appreciated! I apologize for my code being a mess.. I got frantic and started throwing things in to see if I could get something to work and now I don't know what to keep, what to lose, and what to change.

• March 1st, 2011, 05:28 AM
monarch_dodra
Re: 0 Converting Roman Numerals to Decimals
Quote:

Hi,

I have been working on this program for a few days.. and I am so far gone I lost myself in my own program. I usually just start from scratch when I get frustrated but there is too much time invested into my heap to give up so I thought I would come here. My assignment is as follows:

Write a program that converts a number entered in Roman Numerals to decimal. Needs to consist of a class called romanType and an object that does the following:

Store the number as a Roman numeral
Convert and store the number into decimal form
Print the number as a Roman numeral or decimal number as requested by user

The decimal values of the roman numerals are:
M = 1000
D = 500
C = 100
L = 50
X = 10
V = 5
I = 1

After completion, I need to test the program with the following input: MCXIV, CCCLIX, MDCLXVI

Here's what I have so far in the source file:

Code:

```//romanType.cpp #include <iostream> #include <iomanip> #include "romanType.h" using namespace std; int main() {     romanType r;         char romanNum;     char choice;     int decimal;     int total;         cout << setw(60) << "Welcome! Please follow the directions below." << endl;     cout << endl;     cout << "Please enter a Roman Numeral: ";     cin >> romanNum;     cout << endl;         r.setRoman(romanNum);     r.convertRoman(total);             cout << "Do you want to see the [R]oman Numeral or the [D]ecimal? ";     cin >> choice;     cout << endl;         if(choice == 'R' || choice == 'r')           r.printRoman(romanNum);     else if(choice == 'D' || choice == 'd')           r.printDecimal(total);     else           cout << "That was not an invalid choice.." << endl;         cout << endl;         system("pause");     return 0;  }//End main```
Code:

```//romanType.h using namespace std; class romanType { public:       void printRoman(char) const;       int printDecimal(int&);       void setRoman(char);       int convertRoman(int&);             romanType();       romanType(char);       ~romanType();         private:       char romanNum[6];       int decimal;       int total; };//End Class romanType```

If anyone can offer any guidance, that would be much appreciated! I apologize for my code being a mess.. I got frantic and started throwing things in to see if I could get something to work and now I don't know what to keep, what to lose, and what to change.

Why are you using a single char to represent a roman numeral?

Your interface is... strange, why does print take an argument?
• March 1st, 2011, 05:47 AM
Amleto
Re: 0 Converting Roman Numerals to Decimals
I would suggest thast your romanType has to accept a string, not a char or char array (you main code only takes on char and gives it to your class, but your class has char[6] defined):

it needs to hold, e.g. "MCMXVIII".

your print methods on romanType would then be:
Code:

```void romanType::printRoman() const; void romanType::printDecimal() const;```
You should only need ONE setter method -
Code:

`void setRoman(std::string const & roman);`
Your logic seems a bit confused with your method int romanType::convertRoman(int& total). Your romanType is meant to calculate total. So it should not be given as an argument!

You should think about the algorithm needed to convert e.g. MCXIV to 1114 (assuming I have that right).

Your task requires that you convert the roman string and store the decimal. So again, your class should not be making public any methods with int total as an argument.

* get the roman string
* store it
* convert it to int
* store the int

now whenever you need to print it, you have all the data already.
• March 1st, 2011, 07:02 AM
ninja9578
Re: 0 Converting Roman Numerals to Decimals
just so you know, cases are fall-through. There is no need to have different cases for each letter:

Code:

```case 'M': case 'm':   count[i] += 1000;   break;```
• March 1st, 2011, 11:27 PM
Re: 0 Converting Roman Numerals to Decimals
Thanks for your help guys, I've tweaked it a bit, took out some of the mess. I was confused on the function arguments, but I think I have that straightened out, thanks! I also forgot they cases were fall through, so thanks for that also, makes the code look cleaner. I'm not sure why I gave my print function an argument or let my roman numeral sit as a char, trying many different things after the frustration kicked in, but I think I am on the right track now, I just have a few more questions:

How do I go about have my convert function read the letters from a string one by one and adding the value its suppose to be until the end of the string? I seen a few examples online, one of which I tried to imitate and recreate in my own project but that was a fail.

You posted this:

Code:

```Your task requires that you convert the roman string and store the decimal. So again, your class should not be making public any methods with int total as an argument. * get the roman string * store it * convert it to int * store the int```
Is this just what the convert function is suppose to be doing?

Also here is what my new set function is based on your input, but what exactly is it doing? Am I right in believing it takes whatever the user has input it and sets the romanNum to such?

Code:

```void romanType::setRoman(string& roman) {     romanNum = roman; }//End getRoman```
and I have changed my romanNum to a string.. Idk what I was thinking with the char array.

Thanks for all the help, I really appreciate it!
• March 2nd, 2011, 02:51 AM
monarch_dodra
Re: 0 Converting Roman Numerals to Decimals
Quote:

Also here is what my new set function is based on your input, but what exactly is it doing? Am I right in believing it takes whatever the user has input it and sets the romanNum to such?

Code:

```void romanType::setRoman(string& roman) {     romanNum = roman; }//End getRoman```

not necessarily "user input". The function just takes the roman argument, and assigns it to its romanNum attribute.

ANyways, from a purelly interface point of view, this is what I would recommend for your project:

Code:

```#include <string> #include <iostream> class romanType {   public:     romanType() : roman(),                   decimal()     {}     void setRoman(const std::string& i_roman)     {       roman = i_roman;       decimal = roman2decimal(i_roman);     }     void setDecimal(int i_decimal)     {       decimal = i_decimal;       roman = decimal2roman(i_decimal);     }     const std::string& getRoman() const       {return roman;}     int getDecimal() const       {return decimal;}   private:   //private attributes     std::string roman;     int decimal;   //private implementation details     static int roman2decimal(const std::string& i_roman);     static std::string decimal2roman(int i_decimal); }; int romanType::roman2decimal(const std::string& i_roman) {return 1666;} std::string romanType::decimal2roman(int i_decimal) {return "MCXIV";} int main() {   romanType rt;   rt.setRoman("MDCLXVI");   std::cout << "MDCLXVI" << " converts to: " << rt.getDecimal() << std::endl;   rt.setDecimal(1114);   std::cout << 1114 << " converts to: " << rt.getRoman() << std::endl; }```
This is all you need, nothing less, nothing more, to make your class function as expected. Notice I did not provide any implementations for decimal2roman and roman2decimal, that's your task.
• March 2nd, 2011, 04:30 AM
Amleto
Re: 0 Converting Roman Numerals to Decimals
Quote:

You (Amleto) posted this:

Code:

```Your task requires that you convert the roman string and store the decimal. So again, your class should not be making public any methods with int total as an argument. * get the roman string * store it * convert it to int * store the int```
Is this just what the convert function is suppose to be doing?

Also here is what my new set function is based on your input, but what exactly is it doing? Am I right in believing it takes whatever the user has input it and sets the romanNum to such?

Code:

```void romanType::setRoman(string& roman) {     romanNum = roman; }//End getRoman```

Thanks for all the help, I really appreciate it!

The convert function should accept a string and return an int. It should do the job of ONE of those bullet points, not all.
e.g.
Code:

```int ConvertRoman(std::string const & roman) {   int result(0);   // do stuff with roman   result = ??;   return result; }```
the setRoman method accepts a string argument and saves it in the class with member variable romanName. It wont save anything automatically, it must be called in code, e.g.

Code:

```string userInput; cout << "give roman: "; cin >> userInput; romanType rType; rType.setRoman(userInput); // now userInput is saved to romanNum in rType. ...```
• March 3rd, 2011, 01:06 AM
Re: 0 Converting Roman Numerals to Decimals
Thanks for all your help. It was due at midnight, and I turned it in as I had it, but I thought I would end the thread by showing what I had finished with.

Code:

```int romanType::convertRoman(string& roman) {     int length = romanNum.length();     int num[length];     int i;         for(i = 0; i < length; i++)     {                    switch(romanNum[i])           {                 case 'M':                 case 'm':                       num[i] = 1000;                       break;                 case 'D':                 case 'd':                       num[i] = 500;                       break;                 case 'C':                 case 'c':                       num[i] = 100;                       break;                 case 'L':                 case 'l':                       num[i] = 50;                       break;                 case 'X':                 case 'x':                       num[i] = 10;                       break;                 case 'V':                 case 'v':                       num[i] = 5;                       break;                 case 'I':                 case 'i':                       num[i] = 1;                       break;                 default:                         cout << "Error.." << endl;           }//End switch              decimal = decimal + num[i];     }//End for         return decimal; }//End convertRoman```

Above is my converting function, it adds the numerals as the user enters them, which I got to work thanks to you guys and a fellow classmate. The only problem I could not figure out was how to get the roman numerals to tell the difference between something like IV ( 4 ) or VI ( 6 ), by default it went automatically to 6 because it just added.

Even though the assignment is finished, can anyone think of any code that could attach onto mine to make it work as such for future reference? How could I have read each string to make it tell the difference between these letters/numbers? I have seen examples with the cin.peek but I did not understand. Also, I seen one piece of code that used case switches within case switches rather cleverly but I didn't want to steal it so I turned it in as is.
• March 3rd, 2011, 03:59 AM
monarch_dodra
Re: 0 Converting Roman Numerals to Decimals
I may be mistaken, but your first iteration of convert2roman seemed to work. I actually found the solution clever too.

When you write functions like convert2roman, it is usually pretty easy to get them to work for valid input. The hard implementation is the one that tells you when it fails.

Anyways, here is a wikipedia inspired implementation:
Code:

```#include <iostream> #include <string> int roman_2_decimal(const std::string& i_string) {   static const std::string roman[]  = {"M", "CM", "CD", "D", "C", "XC", "XL", "L", "X", "IX", "IV", "V", "I"};   static const int decimal[] = { 1000, 900, 400, 500, 100, 90, 40, 50, 10, 9, 4, 5, 1};   static const size_t size = sizeof(decimal)/sizeof(decimal[0]);   int value = 0;   size_t index = 0;   for(int i = 0; i<size; ++i)   {     while(i_string.substr(index, roman[i].length()) == roman[i])     {       value += decimal[i];       index += roman[i].length();     }   }   return value; } int main() {   std::cout << "MCXIV" << ": " << roman_2_decimal("MCXIV") << std::endl;   std::cout << "CCCLIX" << ": " << roman_2_decimal("CCCLIX") << std::endl;   std::cout << "MDCLXVI" << ": " << roman_2_decimal("MDCLXVI") << std::endl; }```
• March 3rd, 2011, 07:39 AM
Amleto
Re: 0 Converting Roman Numerals to Decimals
Quote:

Thanks for all your help. It was due at midnight, and I turned it in as I had it, but I thought I would end the thread by showing what I had finished with.

...

Even though the assignment is finished, can anyone think of any code that could attach onto mine to make it work as such for future reference? How could I have read each string to make it tell the difference between these letters/numbers? I have seen examples with the cin.peek but I did not understand. Also, I seen one piece of code that used case switches within case switches rather cleverly but I didn't want to steal it so I turned it in as is.

I would code the algorithm how I 'think' it myself. When looking at numerals, you check the next numeral and if you:

a) find a numeral smaller than the current one.
b) find the same numeral again
c) find a numeral larger than the current on
d) reach the end

then

a1) add the current numeral to the subtotal, then add subtotal to the total. reset the subtotal.
b1) add the numeral to a subtotal
c1) add the current numeral to the subtotal, then subtract the subtotal from the total & reset the subtotal
d1) do a1

move on the next numeral.

e.g.

MMCCMXIX

total = 0
subtotal = 0;

current = M, next = M, therefore b1
total = 0, subtotal = 1000.

current = M, next = C, therefore a1.
total = 2000, subtotal = 0.

current = C, next = C, therefore b1
total = 2000, subtotal = 100.

current = C, next = M, therefore c1
total = 1800, subtotal = 0.

current = M, next = X, therefore a1
total = 2800, subtotal = 0.

current = X, next = I, therefore a1
total = 2810, subtotal = 0.

current = I, next = X, therefore c1
total = 2799, subtotal = 0.

current = X, next = 'END', therefore a1
total = 2809, subtotal = 0.

This method, I presume, will be similar to the cin.peek method - you need to look one numeral in advance. This method would also handle 'bad' roman numerals like MIM, which isnt technically correct.

the outline would be something like
Code:

``` // use a map for the values - this'll be a bit easier to read/follow than big switch statement imo. map<string, int> romanToVal; romanToVal["M"] = 1000; romanToVal["C"] = 100; // etc ... string roman = "MCML..."; int total = 0; int subtotal = 0; for(int letterNum = 0; letterNum < roman.size() - 1; ++letterNum) {   string current = roman[letterNum];   string next = roman[letterNum + 1];   if (romanToVal[current] < romanToVal[next])   {     // do a1 with current   }   else if (romanToVal[current] == romanToVal[next])   {     // do b1 with current   }   else   {     // do c1 with current   }   // handle the last numeral:   // do a1 with roman.back();  // total should now be equivalent in value to the roman numeral string }```