//FILE: rn.cpp //solution for p7 01F, roman number calculator #include #include // for strchr() #include // for pow() const int MAXSZ = 80; // largest string const char NUL = '\0'; const char ROMDIGITS[8] = "IVXLCDM"; int romanToDec(char rn[]); int apply(int n1, char op, int n2); void decToRoman(int dn, char rn[]); bool isValidDigit(char rd); bool GTE(char rd1, char rd2); int main(){ char rn1[MAXSZ], rn2[MAXSZ], //roman numbers input by user rresult[MAXSZ]; //roman result of applying operator int dn1, dn2, //decimal numbers corres. to Roman numbers dresult; //decimal result of applying operator char op; //operator //prompt and read roman expression cout << endl << "enter Roman expression (c-d to exit): "; cin >> rn1 >> op >> rn2; //convert and evaluate while(cin){ dn1 = romanToDec(rn1); dn2 = romanToDec(rn2); dresult = apply(dn1, op, dn2); decToRoman(dresult, rresult); //display result cout << endl << rn1 << ' ' << op << ' ' << rn2 << " = " << rresult << " (" << dresult << ")" << endl; //prompt and read roman expression cout << endl << "enter Roman expression (c-d to exit): "; cin >> rn1 >> op >> rn2; } cout << "Exiting.." << endl; return 0; } /* romanToDec() ------------------------------------------------------- * converts rn to decimal */ int romanToDec(char rn[]){ int dn = 0, // decimal number accumulator i = 0; // loop index char rd = rn[i]; // get initial roman digit in rn[] //process each roman digit in rn[] while(rd && isValidDigit(rd) && GTE(rn[i], rn[i+1])){ // cout<< endl << "rd= " << rd; if(rd == 'M') dn += 1000; else if (rd == 'D') dn += 500; if (rd == 'C') dn += 100; if (rd == 'L') dn += 50; if (rd == 'X') dn += 10; if (rd == 'V') dn += 5; if (rd == 'I') dn += 1; //extract next roman digit from rn i++; rd = rn[i]; } return dn; } /* apply() ----------------------------------------------- * evaluates and returns "n1 op n2" */ int apply(int n1, char op, int n2){ switch(op){ case '+': return n1+n2; case '-': return n1-n2; case '/': return n1/n2; case '*': return n1*n2; case '^': return (int)pow(n1, n2); default: cerr << endl << "***Error -- illegal operator: " << op; return -1; } } /* decToRoman() ------------------------------------------- * converts decimal number dn to roman number in rn * WARNING: STUB PROCEDURE, not complete * handles only M's, in order to test the driver logic */ void decToRoman(int dn, char rn[]){ //generate correct number of M's int noOfMs = dn / 1000, i = 0; dn = dn % 1000; while(i <= noOfMs){ rn[i] = 'M'; i++; } //generate correct number of L's int noOfLs = dn / 1000; dn = dn % 500; while(i <= noOfLs){ rn[i] = 'L'; i++; } //.. continue with rest of digits //append NUL terminator rn[i] = '\0'; } /* isValidDigit() ------------------------------------------ * returns true if rd is a valid roman digit */ bool isValidDigit(char rd){ if(strchr(ROMDIGITS, rd) != NULL) return true; else{ cerr << endl << "***Error*** unknown digit: " << rd << endl; return false; } } /* GTE() -------------------------------- * returns true if rd1 >= rd2 * used to verify additive notation for rn */ bool GTE(char rd1, char rd2){ //convert char to string, for strstr() char s1[2] = {rd1, '\0'}, s2[2] = {rd2, '\0'}; if(strstr(ROMDIGITS, s1) >= strstr(ROMDIGITS, s2)) return true; else{ cerr << endl << "***Error*** not additive notation: " << rd1 << ' ' << rd2 << endl; return false; } } // ***** ALTERNATE IMPLEMENTATIONS ****** /* rdToDD() ------------------------------------------ * converts roman digit rd to decimal digit * NOT USED ON THIS PROJECT, but could be used * to implement an alternate version of GTE() */ int rdToDD(char rd){ switch(rd){ case 'M': return 1000; case 'D': return 500 ; case 'C': return 100 ; case 'L': return 50 ; case 'X': return 10 ; case 'V': return 5 ; case 'I': return 1 ; defalult: return -1; } } /* GTE() -------------------------------- * returns true if rn[m] >= rn[n] * used to verify additive notation for rn bool GTE(char rn[], int i){ //special case: rn[i+1] is last digit in rn if(rn[i+1] == NUL) return true; //general case: else if(strchr(ROMDIGITS, rn[i]) >= strchr(ROMDIGITS, rn[i+1])) return true; else{ cerr << endl << "***Error*** not additive notation: " << rn << endl; return false; } } */