3

このプログラムは、私が受けたばかりの試験の一部で、書かなければなりませんでした。ここまでしか行けず、どこにも行けませんでした。プロンプトは次のとおりです。「MMLXVII などのローマ数字を 10 進数表現に変換するテスト関数 toDecimal() を記述します。Main() を使用して関数をテストします。toDecimal() 関数には 2 つの引数が必要です。ローマ数字とヘルパー関数. このヘルパー関数はローマ数字で使用される各文字の数値を返します. 次に、文字列の引数を次のように変換します: 最初の 2 文字を見て、最初の文字が大きい場合は、最初の 2 文字を変換します。それを合計に加算し、2 番目の値を使用して変換関数を再度呼び出し、両方を加算します。最初の文字が 2 番目の文字よりも小さい場合は、2 番目の文字から最初の文字を引きます。結果を文字列の変換に追加します。検証なしでは、「IC」などの文字列も変換されます。文字列引数を検証し、エラーがあればエラー処理関数を呼び出します。少なくとも 2 つのエラー処理関数を提供し、それぞれで toDecimal() をテストします。1 つはユーザーに訂正するように勧めている可能性があり、もう 1 つはそれを訂正している可能性があります。」

I、X、C、M は連続して 3 回以上繰り返すことはできず、D、L、V は連続して繰り返すことはできません。 C は D と M からのみ減算できます。V、L、および D は減算できません。

私はこれで約 2 日間の睡眠を失い、ルールを使用したり破ったりする何百もの異なる方法で書き込もうとしました。これは私が手に入れた中で最も近いものです。

#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <cstring>
using namespace std;

bool checker(string roman);
// Adds each value of the roman numeral together
int toDecimal(string, bool* (*function)(string));
int convert(string roman, int i);

int main(){
    string roman;
    cout << "This program takes a roman numeral the user enters then converts it to decimal notation." << endl;
    cout << "Enter a roman numeral: ";
    cin >> roman;
    transform(roman.begin(), roman.end(), roman.begin(), toupper);
    cout << roman << " is equal to " << toDecimal(roman,  *checker(roman)) << endl;
}

bool checker(string roman){
    int length = roman.length();
    for (int count = 0; count < length; count++){
        string sub = roman.substr(count, count);
        if(sub != "I" || sub != "V" || sub != "X" || sub != "L" || sub != "C" || sub != "D" || sub != "M"){
            cout << "Error. Try Again"<< endl;
            return false;
        }
        else if(convert(roman, count) == convert(roman, count-1) && convert(roman, count) == convert(roman, count+1)){
            if (convert(roman,count) == 1 || convert(roman,count) == 10 || convert(roman,count) == 100 || convert(roman,count) == 1000)
                if(convert(roman, count-1) == convert(roman, count-2) || convert(roman, count+1) == convert(roman, count+2)){
                    cout << "Error Try again" << endl;
                    return false;
                }
            else if (convert(roman,count) == 5 || convert(roman,count) == 50 || convert(roman,count) == 500){
                cout << "Error Try again" << endl;
                    return false;
            }
            else return true;

        }           
    }
    return true;
}

int toDecimal(string s, bool*(checker) (string roman)){
    /**map<char, int> roman;
    roman['M'] = 1000;
    roman['D'] = 500;
    roman['C'] = 100;
    roman['L'] = 50;
    roman['X'] = 10;
    roman['V'] = 5;
    roman['I'] = 1;*/
    checker(s);
    int res = 0;
    for (int i = 0; i < s.length() - 1; ++i){
        int num = convert(s,i);
        res += num;
        /**if (roman[s[i]] < roman[s[i+1]])
            res -= roman[s[i]];
        else
            res += roman[s[i]];
    }
    res += roman[s[s.size()-1]];*/}
    return res;
}

int convert(string roman, int i){
    enum romans {I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000};
    int num = 0;
    char c = roman[0]; 
    switch(c){
        case 'M': 
            num = M; break;
        case 'D':   
            if(i + 1 != roman.size() && roman[i+1] == 'M'){
                num = M - D;break;
            }
            else
                num = D; break;
        case 'C': 
            if(i + 1 != roman.size() && roman[i+1] == 'M' || roman[i+1] == 'D'){
                if(roman[i+1] == 'M') num = M - C; break;
                if(roman[i+1] == 'D') num = D - C; break;
            }
            else
                num = C; break;
        case 'L':
            if(i + 1 != roman.size() && roman[i+1] == 'M' || roman[i+1] == 'D' || roman[i+1] == 'C'){
                if(roman[i+1] == 'M') num = M - L; break;
                if(roman[i+1] == 'D') num = D - L; break;
                if(roman[i+1] == 'C') num = C - L; break;
                }
            else
                num = L; break;
        case 'X': 
            if(i + 1 != roman.size() && roman[i+1] == 'M' || roman[i+1] == 'D' || roman[i+1] == 'C'|| roman[i+1] == 'L'){
                if(roman[i+1] == 'M') num = M - X; break;
                if(roman[i+1] == 'D') num = D - X; break;
                if(roman[i+1] == 'C') num = C - X; break;
                if(roman[i+1] == 'L') num = C - X; break;
            }
                num = X; break;
        case 'V':
            if(i + 1 != roman.size() && roman[i+1] == 'M' || roman[i+1] == 'D' || roman[i+1] == 'C'|| roman[i+1] == 'L' || roman[i+1] == 'X'){
                if(roman[i+1] == 'M') num = M - V; break;
                if(roman[i+1] == 'D') num = D - V; break;
                if(roman[i+1] == 'C') num = C - V; break;
                if(roman[i+1] == 'L') num = L - V; break;
                if(roman[i+1] == 'X') num = X - V; break;
            }
                num = V; break;
        case 'I':
            if ( i + 1 != roman.size() && roman[i + 1] != 'I'){
                if(roman[i+1] == 'M') num = M - I; break;
                if(roman[i+1] == 'D') num = D - I; break;
                if(roman[i+1] == 'C') num = C - I; break;
                if(roman[i+1] == 'L') num = L - I; break;
                if(roman[i+1] == 'X') num = X - I; break;
            }
                num =1; break;
    }
    return num;
}

** ここに人々の助けを加えました。これは、進行状況/会議を表示するための編集です。

4

3 に答える 3

2

Annie Kim によって提供された解決策は機能しますが、 を使用しstd::mapて同じ文字を何度もクエリするため、その理由がわかりません。

int convert_roman_digit(char d)
{
    switch (d)
    {
        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;
        default: throw std::invalid_argument("Invalid digit");
    }
}

int roman_to_int(const std::string& roman)
{
    int result = 0, last_added = 0;

    for (auto it = roman.rbegin(); it != roman.rend(); ++it)
    {
        const int value = convert_roman_digit(*it);
        if (value >= last_added)
        {
            result += value;
            last_added = value;
        }
        else
        {
            result -= value;
        }
    }

    return result;
}

警告IMM: 関数は、「負の」数 (例 ) を含むいくつかの無効な入力 (例 ) を喜んで受け入れますIIIIIIIIIIIIIX。オーバーフロー チェックはなく、スローします。お気軽に改善してください。

于 2015-04-12T22:48:09.507 に答える