//FILE: rn.cpp //solution for p7 01F, roman number calculator #include #include // for strchr() #include // for pow() using namespace std; const int MAXSZ = 80; // largest string const char NUL = '\0'; const string ROMDIGITS = "IVXLCDM"; int romanToDec(string 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() ------------------------------------------------- * returns decimal equivalent of romanNumeral */ int romanToDec(string rn){ int sum = 0, i = 0; while((i < rn.length()) && (isValidDigit(rn[i])) && GTE(rn[i], rn[i+1])){ if(rn[i] == 'I') sum = sum + 1; else if (rn[i] == 'V') sum = sum + 5; else if (rn[i] == 'X') sum += 10; else if (rn[i] == 'L') sum += 50; else if (rn[i] == 'C') sum += 100; else if (rn[i] == 'D') sum += 500; else if (rn[i] == 'M') sum += 1000; ++i; } return sum; } /* 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((double)n1, (double)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){ // cout << endl << "rd = " << rd << "ROMDIGITS.find(rd, 0) = " // << ROMDIGITS.find(rd, 0) << endl; if(ROMDIGITS.find(rd, 0) != string::npos) 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){ int i, j; i = ROMDIGITS.find(rd1, 0); j = ROMDIGITS.find(rd2, 0); cout << endl << "rd1 = " << rd1 << " rd2 = " << rd2 << " i, j = " << i << ' ' << j << endl; if(i >= j) 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; } } */