Преобразование римских цифр в Int - Получение неправильного вывода - Почему? - PullRequest
0 голосов
/ 26 мая 2018

Вот мой код.Во-первых, я хочу сказать, что я экспериментировал, поэтому, если вы видите ненужные переменные здесь и там, вот почему.Но основная часть моего кода находится в десятичной функции в моем классе romanType.Когда я ввожу определенные римские цифры, я не получаю точных цифр, которые я хочу, и это может быть в моей логике где-то в моих операторах if / else.

Кстати, чтобы показать, как я пересекаю строку - я делаю это путем обратного хода.Я иду от самого конца строки к самому началу строки, что мне кажется проще с римскими цифрами.Кстати, я также сделал тип enum, чтобы я мог сравнивать римские цифры, видя, какая из них меньше, какая больше и т. Д. Затем я использовал карту, чтобы иметь возможность сравнивать значения enum со значением 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 голосов
/ 26 мая 2018

Когда я сделал материал из моего комментария и немного подправил ваш код, я получил это:

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

Как я избавился от ваших temp и roman1,roman2 и switch if/else условий и код работал с первой компиляции ..Я предполагаю, что вы делаете с ними что-то подозрительное (потерялись в комбинациях if / else, в которых отсутствует какой-либо краевой регистр).

...