?
Solved

Roman Numeral

Posted on 2005-04-04
6
Medium Priority
?
444 Views
Last Modified: 2010-04-01
i have a source code, so far i have whats listed below...i have 2 questions: the first is, for some reason and i cant figure out why, but when i run the program once, it works fine, but once i try to repeat it, it stores the answer in the first input and calculates the total w/ the 2nd.  Also, i also need it to convert the numbers back into roman numerals and im unsure of how i could do this...i cant use pointers and nothing too 'advanced'...any help would be greatly appreciated.  

this is my source code:

#include <iostream>
#include <cmath>
#include <string>
using namespace std;

void Roman (int&);
int Operation (int, int, char);

char YesNo;
int answer;
int first;
int second;
int amount;
char Number;

int main()

{
      do{
      {
     

     amount = 0;
     
     cout<<"Enter the first roman numeral"<<endl;
     Roman(first);
     cout<<"Enter the second roman numeral"<<endl;
     Roman(second);
     cout<<"Enter the (+) for Addition (-) for Subtraction, (*) for Multiplication, or (/) for Division"<<endl;
     cin.get(Number);
     Operation (first, second, Number);
     cout<<first<<" "<<Number<<" "<<second<<" is "<<Operation(first,second,Number)<<"."<<endl;
      
      
       cout << "Do you want to Repeat Process Y or N" << endl;
      cin >> YesNo;
}
      }      while ((YesNo =='y' || YesNo =='Y'));
     return 0;
}

void Roman (int& amount)
{
          char RN;
          cin.get(RN);

          while (RN != '\n')
          {
         
          if (RN == 'M')
               amount = amount + 1000;
          if (RN == 'D')
               amount = amount + 500;
          if (RN == 'C')
               amount = amount + 100;
          if (RN == 'L')
               amount = amount + 50;
          if (RN == 'X')
               amount = amount + 10;
          if (RN == 'V')
               amount = amount + 5;
          if (RN == 'I')
               amount = amount + 1;
              cin.get(RN);
          }
         
}
int Operation (int first, int second, char Number)
{
     if (Number == '+')
     {
          answer  = first + second;
     }
     if (Number == '-')
     {
          answer  = first - second;          
     }
     if (Number == '*')
     {
          answer  = first * second;
     }
       return answer;
}
0
Comment
Question by:Kal130
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
6 Comments
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13704821
You should  avoid to use global variables but move them to the function where you need them.

int main()
{
    char YesNo;
    int answer;
    int first;
    int second;
     
    do
    {
             ...

>>>> void Roman (int& amount)

Better is

    int Roman()

where you would return the value entered by the user.

Note, you used 'int amount' as global variable and as an argument, what is bad (but isn't an error as the latter was used). The reason, why your variable increases in the second run is cause you never initialize it to 0.

int Roman ()
{
          int amount = 0;  // make a local variable *but* remove the global one
          char RN;
          cin.get(RN);

          while (RN != '\n')
          {
              switch(RN)
              {
                  case 'M':
                      amount = amount + 1000; break;
                  case 'C'':
                      amount = amount + 100; break;
                  case 'L':
                      amount = amount + 50; break;
                  case 'X':
                      amount = amount + 10; break;
                  case 'V':
                      amount = amount + 5; break;
                  case 'I':
                      amount = amount + 1; break;
                  default:
                      return -1;         // bad value
                }  
          }
          return amount;
}

Note, you didn't consider the case where numbers have to be subtracted rather than added as in IX == 9. Your result would be 11.

Regards, Alex
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13708714
To build (and parse) roman numbers (M, D, C, L, X, V, I) you have to apply the following rules:

1. The composite number is build up in thousands, hundreds, tens and ones from left to right.
2. To build 900, 400, 90, 40, 9, 4 you have to precede the next number by one single
    C (M and D), X (C and L) or I (X and V).
3. You have to take the minimum notation if there are more than one possible


Samples:

 99     == XCIX (90 + 9) and not LXXXXVIIII (breaks rule 3) or IC (breaks rule 2) or LIL (breaks rule 2).
 2321 == MMCCCXXI and not  MDDCCDXXI (MDD breaks rule 3) (CCD  breaks rule 1 and rule 2)

Here is an attempt to consider these rules in function Roman.

Some comments:

I changed char input to char array input in order to be able to peek to the next char. Tell me, if you would be allowed to use std::string instead of char array.

I also moved user input to main function as Roman function should be free of I/O stuff (cause you could use it generally for transforming a Roman number to an integer).

Regards, Alex


int Roman ()
{
    int amount = 0;  // make a local variable *but* remove the global one
    char input[256];
   
    cin >> input;
    if (stricmp(input, "Q") == 0)
        return 0;
 
    char RP  = ' ';     // previous
    char RN  = '\0';    // current
    char RNN = '\0';    // next
   
    int expected  = 1000;
    int duplicate = 0;  
    for (int i = 0; i < strlen(input); ++i)
    {
        RP  = RN;
        RN  = input[i];
        RNN = input[i+1];
        if (RP == RN)
            duplicate++;
        else
            duplicate = 0;
        switch(RN)
        {
        case 'M':
            if (expected < 1000)
                return -2;
            amount += 1000;
            break;
        case 'D':
            if (expected < 500)
                return -2;
            if (duplicate)
                return -3;
            amount += 500;
            expected = 100;
            break;
        case 'C':
            if (expected < 100)
                return -2;
            if (duplicate > 2)
                return -3;
            if (duplicate == 0 && (RNN == 'M' || RNN == 'D'))
            {
                amount += (RNN == 'M')? 900 : 400;
                expected = 50;
                i++;
            }
            else
                amount += 100;
            if (expected > 100)
                expected = 100;
            break;
        case 'L':
            if (expected < 50)
                return -2;
            if (duplicate)
                return -3;
            amount += 50;
            expected = 10;
            break;
        case 'X':
            if (expected < 10)
                return -2;
            if (duplicate > 2)
                return -3;
            if (duplicate == 0 && (RNN == 'L' || RNN == 'C'))
            {
                amount += (RNN == 'C')? 90 : 40;
                expected = 5;
                i++;
            }
            else
                amount += 10;
            if (expected > 10)
                expected = 10;
            break;
        case 'V':
            if (expected < 5)
                return -2;
            if (duplicate)
                return -3;
            amount += 5;
            expected = 1;
            break;
            break;
        case 'I':
            if (expected < 1)
                return -2;
            if (duplicate > 2)
                return -3;
            if (duplicate == 0 && (RNN == 'V' || RNN == 'X'))
            {
                amount += (RNN == 'X')? 9 : 4;
                expected = 0;
                i++;
            }
            else
                amount += 1;
            if (expected > 1)
                expected = 1;
            break;
        default:
            return -1;         // bad value
        }  
    }
    return amount;
}

int Operation (int first, int second, char Number)
{
     int answer = -1;
     if (Number == '+')
     {
         answer  = first + second;
     }
     if (Number == '-')
     {
         answer  = first - second;          
     }
     if (Number == '*')
     {
         answer  = first * second;
     }
     return answer;
}


int main()
{
     char input[256];
     int first, second, result;
     while (true)
     {
        cout << "First Roman  [Q to quit] ==>  ";
        cin >> input;
        if (stricmp(input, "Q") == 0)
            return 0;
 
        first = Roman(input);
        cout << endl << "First = " << first << endl << endl;
        if (first <= 0)
            continue;

        cout << "Second Roman [Q to quit] ==>  ";
        cin >> input;
        if (stricmp(input, "Q") == 0)
            return 0;
 
        second = Roman(input);
        cout << endl << "Second = " << second << endl << endl;

        if (second <= 0)
            continue;
        cout<<"(+) Addition \n(-) Subtraction \n(*) Multiplication \n(/) Division \n(Q) Quit \n\nEnter Choice ==> ";
        cin >> input;      

        if (stricmp(input, "Q") == 0)
            return 0;

        result = Operation(first, second, input[0]);
        cout << endl << "result = " << result << endl << endl;
     }
     return 0;
}


0
 

Author Comment

by:Kal130
ID: 13708759
hey im sorry to note, that i dont have to put 4 like IV, it have to be IIII
same w/ the rest of them
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:Kal130
ID: 13708822
std:: string i tink would be better because we havent gotten in depth w/ char array
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13709265
>>>> hey im sorry to note, that i dont have to put 4 like IV, it have to be IIII

Are you crazy? It costs me hours to correctly parse the input and you say, it's all for nothing?

Actually IIII is an invalid number and you would get error -2 if entering it.


>>>> std:: string i tink would be better

Add

    #include <string>
    using namespace std;

to the top of your cpp file.

Change the first part of Roman function to

int Roman (const string& input)
{
    int amount = 0;  // make a local variable *but* remove the global one
    char RP  = ' ';     // previous
    char RN  = '\0';    // current
    char RNN = '\0';    // next
   
    int expected  = 1000;
    int duplicate = 0;  
    for (int i = 0; i < input.length(); ++i)
    {
        RP  = RN;
        RN  = input[i];
        RNN = input.c_str()[i+1];  // input[i+1] isn't valid for std::string
                                   // if i+1 == input.length()
        ...
        // remainder didn't change


Change main function to

int main()
{
     string input;
     int first, second, result;
     while (true)
     {
        cout << "First Roman  [Q to quit] ==>  ";
        cin >> input;
        if (input == "Q" || input == "q")
            return 0;
 
        first = Roman(input);
        cout << endl << "First = " << first << endl << endl;
        if (first <= 0)
            continue;

        cout << "Second Roman [Q to quit] ==>  ";
        cin >> input;
        if (input == "Q" || input == "q")
            return 0;
 
        second = Roman(input);
        cout << endl << "Second = " << second << endl << endl;

        if (second <= 0)
            continue;
        cout<<"(+) Addition \n(-) Subtraction \n(*) Multiplication \n(/) Division \n(Q) Quit \n\nEnter Choice ==> ";
        cin >> input;      

        if (input == "Q" || input == "q")
            return 0;

        result = Operation(first, second, input[0]);
        cout << endl << "result = " << result << endl << endl;
     }
}

Regards, Alex
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 2000 total points
ID: 13709369
>>>> that i dont have to put 4 like IV, it have to be IIII

If you really need a wrong parsing, you have to

- remove all lines and if blocks using RNN variable

- use

    if (duplicate > 3)  

  instead of

    if (duplicate > 2)

  to allow 4 occurences of C, X and I

- use

    if (duplicate > 3)  

  instead of

    if (duplicate)

  to allow 4 occurences of D, L and V

- remove all lines and if blocks using 'expected' variable if you want to allow any order

- remove all lines and if blocks using 'duplicate' variable if you want to allow any number of repetitions

(But save the original if you do any of this. As it is the correct version!!!)

Regards, Alex
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
Suggested Courses

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question