Link to home
Start Free TrialLog in
Avatar of nartz
nartz

asked on

Roman Numeral Converter

Avatar of sdyx
sdyx

Found this(for I-MMMCMXCIX ):

#include <conio.h>;
#include <ctype.h>;
#include <stdio.h>;
#include <dos.h>;

int main (void) {
      int numR = 0;                  /* Decimal value of roman numeral      */
      int decR = 0;        /* Decimal value of each roman numeral */
      int cont = 0;                /* String position                     */
      int cont3R = 0;            /* 3 incurs counter                    */
      int numsR[15] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
                                                /* Array that store the value of each
                                                      roman letter                        */
      char letterR = ' ';      /* Contain the temporal roman letter   */
      char roman[15] = "";      /* Contain the input string            */

      /* Clear the screen and display the input message */
      clrscr();
      printf ("Enter a roman numeral between range I to MMMCMXCIX:\n");

      /* Read from keyboard until appear an <ENTER> */
      while ((letterR != '\n') && (cont < 15)) {
            letterR = toupper(getchar());

            switch (letterR) {
                  /* V, L y D only can appear one time */
                  case 'V': case 'L': case 'D':
                        /* If appear more of one time, then finish the program */
                        if ((cont > 0) && (roman[cont - 1] == letterR)) {
                                    printf ("\nData incorrect");
                                    delay (1000);
                                    exit (0);
                        }

                        /* If appear one time, be save the char in the string that
                              store the characters of roman numeral                   */
                        else { roman[cont++] = letterR; }
                        break;

                  /* I, X, C y M can appear until 3 times */
                  case 'I': case 'X': case 'C': case 'M':
                        /* If appear correctly, be save the char in the string that
                              that store the characters of roman numeral              */
                        if (cont3R <= 3) {
                              roman[cont++] = letterR;
                        }
                        cont3R++;
                        /* If appear more of 3 times, then finish the program */
                        if ((cont3R > 3) && (roman[cont - 2] == letterR)) {
                              printf ("\nData incorrect");
                              delay (1000);
                              exit (0);
                        }
                        /* If the 3 incurs counter get to be 3 but the preceding char
                              is different of current, then reset the 3 incurs counter   */
                        if ((cont > 1) && ((cont3R > 3) || (roman[cont - 2] != letterR))) {
                              cont3R = 1;
                        }
                        break;
                  /* Invalidate the \n char as default char */
                  case '\n':      break;

                  /* If the input is a char that not concern to roman numerals,
                        then finish the program                                    */
                  default:       printf ("\nData incorrect");
                                          delay (1000);
                                          exit (0);
        }
      }

      /* Reutilization of cont3R var as index of iterations for no create
            a new var and then optimize the program                          */

      /* Convert to decimal each letter of roman numeral that was input */
      for (cont3R = 0; cont3R <= cont; cont3R++) {
            switch (roman[cont3R]) {
            case 'I':       numsR[cont3R] = 1;            break;
            case 'V':       numsR[cont3R] = 5;            break;
            case 'X':       numsR[cont3R] = 10;            break;
            case 'L':       numsR[cont3R] = 50;            break;
            case 'C':       numsR[cont3R] = 100;            break;
            case 'D':       numsR[cont3R] = 500;            break;
            case 'M':       numsR[cont3R] = 1000;      break;
            }
      }

      /* Do a sum over stored numbers */
      for (cont3R = 0; cont3R <= cont; cont3R++) {
            /* */
            /* Add decimal value of each roman numeral */
            if (numsR[cont3R] >= numsR[cont3R + 1]) {
                  decR = numsR[cont3R];
            }
            /* If precedent number is less than current value and this is 10%
                  or 5% of current value, then do a difference between two roman
                  numerals to obtain the final value i.e. IX = 10 - 1 = 9        */
            if ((numsR[cont3R] == (numsR[cont3R + 1] / 10))
                   || (numsR[cont3R] == (numsR[cont3R + 1] / 5))) {
                  decR = numsR[cont3R + 1] - numsR[cont3R];
                  cont3R++;
            }
            /* If precedent numbre is less than current value and not is 10% or
                  5% of current value, then finish the program                    */
            if (decR < numsR[cont3R + 1]) {
                   printf ("\nData incorrect");
                   delay (1000);
                   exit (0);
            }
            numR += decR;
      }

      /* Diplay result in the screen */
      printf ("The value is %d", numR);

      /* Press any key to finish the program */
      printf ("\n\n\t\t\t...Press any key to exit.");
      getch();

      /* Return succesfully */
      return 0;
}
here's a function for converting a Roman to an integer

int toDec( string roman )
{
     int val=0;
     map<char, int> valMap;
     valMap['I']=1;
     valMap['V']=5;
     valMap['X']=10;
     valMap['L']=50;
     valMap['C']=100;
     valMap['D']=500;
     valMap['M']=1000;

     string::iterator i=roman.begin();
     while( i!=roman.end() )
     {
          int t=0;
          string::iterator old=i;
          for(; *i==*old && i!=roman.end(); i++ ) t+=valMap[*i];
          if( valMap[ *i ] > valMap[ *old ] && i!=roman.end() ) val -= t;
          else val +=  t;
     }
     return val;
}
I'v a question for the reverse

is XIVX == XVI? I suppose the latter is correct.
XVI==16
XIVX==No roman number,only I is allowed to the
      left of higher signs(like IV,IX,...)not VX

so you can write IV but not XL ?
To express XL you'd have to XXXX?
on a sidemark, the romans where crazy, they used a number system on a nonregular-symetric base and a "depends" left/right write rule.

if one'v had to express their base i'd look like.

n%2 ? n^2 : n^5

Crazy!
here's a function to generate Roman Numbers

string toRoman( unsigned int dec )
{
     typedef list<int>::iterator lIter;
     typedef string::iterator sIter;
     map<int,char> cMap;
     cMap[1]='I';
     cMap[5]='V';
     cMap[10]='X';
     cMap[50]='L';
     cMap[100]='C';
     cMap[500]='D';
     cMap[1000]='M';

     list<int> nLst;
     nLst.push_back( 1000 );
     nLst.push_back( 500 );
     nLst.push_back( 100 );
     nLst.push_back( 50 );
     nLst.push_back( 10 );
     nLst.push_back( 5 );
     nLst.push_back( 1 );

     int div;
     string result;
     for( lIter i= nLst.begin(); i!=nLst.end(); i++ )
     {
          div = dec/(*i);
          if( div!=4 || i==nLst.begin() )
               result += string( div, cMap[*i] );
          else if( div==4 )
          {
               lIter t=i; sIter cLast = result.end()-1;
               --t;
               if( *cLast == cMap[*t] )
               {
                    *cLast = cMap[*--t];
                    result.insert( cLast, cMap[*i] );
               }
               else
               {
                    result += cMap[*i];
                    result += cMap[*t];
               }
          }
          dec %= *i;
     }

     return result;
}

The toDec and to toRoman functions are complementary, testing showed that for every case they match in results, thus the algorithm is correct.
nartz,
Is this a homework question?

If so, experts can assist in finding errors in code written, but not provide the whole code.

Please refrain from posting here until I get a response from nartz.

Computer101
E-E Admin
I'd think it's time to close this topic, since answers have been provided...
Recommending question be PAQ'ed and points NOT refunded. Any objections? If none in 72 hours I will close this.

DigitalXtreme
CS Moderator
Avatar of nartz

ASKER

LOL, omg something was wrong with E-E that day! omg, I tried to post all my code and everything together, but for some reason when i tried to view my post, all it said was "no text" and i was like wtf! So then i tried to repost it and it still didnt' work (losing muchos puntos in the process) and the code didn't get attached but somehow it just posted the comment, i finish the proggie...oh well =)
Nartz
ASKER CERTIFIED SOLUTION
Avatar of Mindphaser
Mindphaser

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
nartz, instead of omging and loling around you either should have posted your solution or promoted an answer!