将罗马数字转换为Int - 获取错误的输出 - 为什么?

时间:2018-05-26 07:09:30

标签: c++ enums roman-numerals

这是我的代码。首先,我想说,我一直在尝试,所以如果你在这里和那里看到不必要的变量,那就是原因。但是我的代码的主要部分是我的类romanType中的函数decimal。当我输入某些罗马数字时,我没有得到我想要的确切数字,它可能在我的if / else语句中的某个地方。

顺便说一下,为了说明我如何遍历字符串 - 我是通过反向遍历来完成的。我从字符串的最后到字符串的最开头,我觉得罗马数字更容易。顺便说一句,我也做了一个枚举类型,所以我可以比较罗马数字,看哪一个更小,哪一个更大等等。然后我用地图来比较枚举值和char值。

所以问题:例如,当我输入CCC时,我得到290而不是300.如果你知道我的逻辑有什么问题,我将非常感激!谢谢。

此外,我对编程很陌生,非常感谢任何风格提示或任何我可以学习的关于编写此代码时遗漏的课程等的内容?请告诉我什么是最好的。谢谢。

#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;
}

编辑:_____________________________________________________________________________

我找到了解决问题的方法。这是我的新代码:

#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;

}

1 个答案:

答案 0 :(得分:1)

当我完成评论中的内容并稍微调整一下代码时,我得到了这个:

//---------------------------------------------------------------------------
      int  roman_ix[256]={-1};
const int  roman_val[]={ 1 , 5 ,10 ,50 ,100,500,1000,0};
const char roman_chr[]={'I','V','X','L','C','D', 'M',0};
//---------------------------------------------------------------------------
int roman2int(char *s)
    {
    int i,x=0,v=0,v0;
    // init table (just once)
    if (roman_ix[0]<0)
        {
        for (i=0;i<256;i++) roman_ix[i]=0;
        for (i=0;roman_chr[i];i++) roman_ix[roman_chr[i]]=i;
        }
    // find end of string
    for (i=0;s[i];i++);
    // proccess string in reverse
    for (i--;i>=0;i--)
        {
        v0=v;                        // remember last digit
        v=roman_val[roman_ix[s[i]]]; // new digit
        if (!v) break;               // stop on non supported character
        if (v0>v) x-=v; else x+=v;   // add or sub
        }
    return x;
    }
//---------------------------------------------------------------------------

我测试了这些:

1776 1776 MDCCLXXVI
1954 1954 MCMLIV
1990 1990 MCMXC
2014 2014 MMXIV
 300  300 CCC

第一个数字是从字符串转换的,第二个是它应该是什么,最后一个是罗马字符串。

如果256条目表太大,您可以将其缩小到范围A-Z,这个范围要小得多,但在代码中需要多一个减法。它也可以用硬编码来摆脱初始化:

//---------------------------------------------------------------------------
int roman2int(char *s)
    {
    // init
    int i,x=0,v=0,v0;       // A  B    C    D  E  F  G  H  I  J  K   L     M  N  O  P  Q  R  S  T  U  V  W   X  Y  Z
    const int val['Z'-'A'+1]={ 0, 0, 100, 500, 0, 0, 0, 0, 1, 0, 0, 50, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 10, 0, 0 };
    // find end of string
    for (i=0;s[i];i++);
    // process string in reverse
    for (i--;i>=0;i--)
        {
        if ((s[i]<'A')||(s[i]>'Z')) break; // stop on non supported character
        v0=v; v=val[s[i]-'A'];
        if (v0>v) x-=v; else x+=v;
        }
    return x;
    }
//---------------------------------------------------------------------------

当我摆脱你的temproman1,roman2以及switch if/else条件并且代码在第一次编译时起作用...我假设你正在做一些与它们有关的事情(在if / else组合中迷失了一些边缘情况)。