Here is my code. First, I want to say, I have been experimenting, so if you see unnecessary variables here and there, that's why. But the main part of my code is in the function decimal in my class romanType. When I input certain roman numerals, I am not getting the exact numbers I want and it might be in my logic somewhere in my if/else statements.
By the way, to show how I traverse the string - I do it by reverse traversing. I go from the very end of the string to the very beginning of the string, which I think is easier with roman numerals. By the way, I also made an enum type so I could compare the roman numerals seeing which one is lesser, which one is greater etc. Then I used a map to be able to compare the enum values with the char value.
So the problem: For instance, when I type in CCC, I get 290 instead of 300. If you know what is wrong in my logic, I would greatly appreciate that! Thank you.
Furthermore, I am quite new to programming and would greatly appreciate any stylistic tips or anything I can learn about classes etc that I missed in writing this code? Please let me know what is best. Thank you.
#include <iostream>
#include <string>
#include <map>
using namespace std;
class romanType {
string numeral;
int k;
public:
romanType();
void rnumeral (string b) {numeral = b;}
int decimal(string num, char b, int temp) {
num = "";
enum RomanNumerals {I, V, X, L, C, D, M };
map<char, RomanNumerals> m;
m['I'] = I;
m['V'] = V;
m['X'] = X;
m['L'] = L;
m['C'] = C;
m['D'] = D;
m['M'] = M;
RomanNumerals roman1;
RomanNumerals roman2;
cout << "Please type in your roman numeral:" ;
cin >> num;
for (int i =0; i <num.length()-1; i++){
}
for(long i = num.length()-1; i>=0; i--)
{
b = num[i];
if (islower(b)) b=toupper(b);
roman1 = m[num[i]];
roman2 = m[num[i-1]];
switch(b){
case 'I':
if(num[i] == num.length()-1){
temp += 1;
}
break;
case 'V':
if(roman1 > roman2){
temp += 4;
continue;
}
else {
temp += 5;
}
break;
case 'X':
if(roman1 > roman2){
temp += 9;
continue;
}
else {
temp += 10;
}
break;
case 'L' :
if(roman1 > roman2){
temp += 40;
continue;
}
else {
temp += 50;
}
break;
case 'C':
if(roman1 > roman2){
temp += 90;
continue;
}
else {
temp += 100;
}
break;
case 'D' :
if(roman1 > roman2){
temp += 400;
continue;
}
else {
temp += 500;
}
break;
case 'M':
if(roman1 > roman2){
temp += 900;
continue;
}
else {
temp += 1000;
}
break;
}
}
return temp;
}
};
romanType::romanType () {
numeral = "";
}
int main() {
string k = "";
char b = ' ';
int temp = 0;
romanType type;
type.rnumeral(k);
int c = type.decimal(k, b, temp);
cout << c;
return 0;
}
EDIT: _____________________________________________________________________________
I found the solution to my problem. Here is my new code:
#include <iostream>
#include <string>
#include <map>
using namespace std;
string acceptRN();
class romanType {
string numeral;
int temp2;
int l;
// VARIABLES
public:
romanType();
//DEFAULT CONSTRUCTOR
void getRnumeral (string b)
{
numeral = b;
}
//SETTER
void decimal(string num, int temp, char b) {
num = numeral;
enum RomanNumerals {I, V, X, L, C, D, M };
map<char, RomanNumerals> m;
m['I'] = I;
m['V'] = V;
m['X'] = X;
m['L'] = L;
m['C'] = C;
m['D'] = D;
m['M'] = M;
RomanNumerals roman1;
RomanNumerals roman2;
RomanNumerals roman3;
for(long i = num.length()-1; i>=0; i--)
{
b = num[i];
if (islower(b)) b=toupper(b);
roman1 = m[num[i]];
roman2 = m[num[i-1]];
roman3 = m[num[i+1]];
switch(b){
case 'I':
if( roman3 > roman1 && i != num.length()-1){
continue;
}
else {
temp += 1;
break;
}
case 'V':
if(roman1 > roman2 && i != 0){
temp += 4;
continue;
}
else {
temp += 5;
}
break;
case 'X':
if( roman3 > roman1 && i != num.length()-1)
continue;
if(roman1 > roman2 && i!= 0){
temp += 9;
continue;
}
else {
temp += 10;
}
break;
case 'L' :
if(roman1 > roman2 && i!= 0){
temp += 40;
continue;
}
else {
temp += 50;
}
break;
case 'C':
if( roman3 > roman1 && i != num.length()-1)
continue;
if(roman2 == X && i!= 0){
temp += 90;
continue;
}
else {
temp += 100;
}
break;
case 'D' :
if(roman2 == C && i!= 0){
temp += 400;
continue;
}
else {
temp += 500;
}
break;
case 'M':
if(roman2 == C && i!= 0){
temp += 900;
continue;
}
else {
temp += 1000;
}
break;
}
}
temp2 = temp;
}
void showDecimal() {
cout << "Here is your roman numeral in decimal format:";
cout << temp2 << " \n \n \n";
}
};
romanType::romanType () {
numeral = "";
}
int main() {
string k = acceptRN();
int m = 0;
char l= ' ';
romanType type;
type.getRnumeral(k);
type.decimal(k, m, l);
type.showDecimal();
return 0;
}
string acceptRN(){
string num = "";
cout << "Please type in your roman numeral:" ;
cin >> num;
return num;
}
When I done the stuff from my comment and tweaked your code a bit I got this:
I tested on these:
first number is converted from string, second is what it should be and last is the roman string.
If 256 entry table is too big you can shrink it to range
A-Z
which is significantly smaller but that require one more substraction in the code. It can be also hardcoded to get rid of the initialization:As I got rid of your
temp
androman1,roman2
and theswitch if/else
conditions and the code worked from the first compilation ... I am assuming that you are doing something fishy with them (got lost in the if/else combinations missing some edge case).