CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Mar 2011
    Posts
    15

    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.

    Thanks for any help you guys can offer!

  2. #2
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: 0 Converting Roman Numerals to Decimals

    Quote Originally Posted by xCrusade View Post
    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.

    Thanks for any help you guys can offer!
    Why are you using a single char to represent a roman numeral?

    Your interface is... strange, why does print take an argument?
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  3. #3
    Join Date
    Apr 2008
    Posts
    725

    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.

  4. #4
    Join Date
    Jan 2009
    Posts
    1,689

    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;

  5. #5
    Join Date
    Mar 2011
    Posts
    15

    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!

  6. #6
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: 0 Converting Roman Numerals to Decimals

    Quote Originally Posted by xCrusade View Post
    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.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  7. #7
    Join Date
    Apr 2008
    Posts
    725

    Re: 0 Converting Roman Numerals to Decimals

    Quote Originally Posted by xCrusade View Post

    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.
    ...

  8. #8
    Join Date
    Mar 2011
    Posts
    15

    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.

  9. #9
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    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;
    }
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  10. #10
    Join Date
    Apr 2008
    Posts
    725

    Re: 0 Converting Roman Numerals to Decimals

    Quote Originally Posted by xCrusade View Post
    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
    }

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured