2

Javaの基本的な知識はありますが、C++は初めてです。ローマ数字の入力を変換し、同等のアラビア数字を見つけて出力するプログラムを作成しようとしています。ただし、たとえば、「X」を個別にチェックして削除しているため、ローマ数字で特定の接頭辞を見つける際に正しい順序を見つける方法を見つけるという問題があります。私のプログラムは、実際には 9 である入力 "IX" を 11 に変換しています。これは、プログラムが文字列内の接頭辞を見つける順序に関係していることはわかっていますが、修正方法がわかりません。それについての助けは素晴らしいでしょう。

現在のコード:

    #include <cstdlib>
#include <iostream>
#include <cctype>



using namespace std;

/*
 * 
 */
int main() {

    string roman_digits [] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
    string roman_tens [] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
    string roman_hundreds [] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
    string roman_thousands [] = {"", "M", "MM", "MMM"};
    string line, substr;

    int arabic = 0;


    // MCCCXXXVII

    cout << "Type in a Roman numeral: ";

    // Loops through inputted Roman Numerals.    
    while (cin >> line) {
        if (!cin.eof()) {
            int i = 0;

            // Loops through a Roman numeral and changes it to uppercase.
            while (line[i]) {
                char c;
                c = line[i];
                c = (toupper(c));
                line[i] = c;
                i++;
            }
            // Loops through checking roman numeral with the thousands array and if there is a match prints out the equivalent arabic number.
            for (int i = 0; i < 4; i++) {


                if (line.find("MMM") != string::npos) {
                    unsigned pos = line.find("MMM");
                    substr = line.substr(pos, 3);
                    line.erase(pos, 3);
                } else if (line.find("MM") != string::npos) {
                    unsigned pos = line.find("MM");
                    substr = line.substr(pos, 2);
                    line.erase(pos, 2);
                } else if (line.find("M") != string::npos) {
                    unsigned pos = line.find("M");
                    substr = line.substr(pos, 1);
                    line.erase(pos, 1);
                }
                if (roman_thousands[i] == substr){
                    arabic = arabic + (i * 1000);

                }
            }
            // Loops through checking roman numeral with the hundreds array and if there is a match prints out the equivalent arabic number.
            for (int i = 0; i < 10; i++) {

                if (line.find("CM") != string::npos){
                    unsigned pos = line.find("CM");
                    substr = line.substr(pos, 2);  
                    line.erase(pos, 2);
                } else  if (line.find("DCCC") != string::npos){
                    unsigned pos = line.find("DCCC");
                    substr = line.substr(pos, 4);
                    line.erase(pos, 4);
                } else  if (line.find("DCC") != string::npos){
                    unsigned pos = line.find("DCC");
                    substr = line.substr(pos, 3);
                    line.erase(pos, 3);
                } else  if (line.find("DC") != string::npos){
                    unsigned pos = line.find("DC");
                    substr = line.substr(pos, 2);
                    line.erase(pos, 2);
                } else  if (line.find("D") != string::npos){
                    unsigned pos = line.find("D");
                    substr = line.substr(pos, 1);
                    line.erase(pos, 1);
                } else  if (line.find("CD") != string::npos){
                    unsigned pos = line.find("CD");
                    substr = line.substr(pos, 2);
                    line.erase(pos, 2);
                } else  if (line.find("CCC") != string::npos){
                    unsigned pos = line.find("CCC");
                    substr = line.substr(pos, 3);
                    line.erase(pos, 3);
                }else  if (line.find("CC") != string::npos){
                    unsigned pos = line.find("CC");
                    substr = line.substr(pos, 2);
                    line.erase(pos, 2);
                } else  if (line.find("C") != string::npos){
                    unsigned pos = line.find("C");
                    substr = line.substr(pos, 1);
                    line.erase(pos, 1);
                }

                if (roman_hundreds[i] == substr) {
                    arabic = arabic + (i * 100);

                }
            }
            // Loops through checking roman numeral with the tens array and if there is a match prints out the equivalent arabic number.
            for (int i = 0; i < 10; i++) {

                if (line.find("XC") != string::npos){
                    unsigned pos = line.find("XC");
                    substr = line.substr(pos, 2);
                    line.erase(pos, 2);
                } else  if (line.find("LXXX") != string::npos){
                    unsigned pos = line.find("LXXX");
                    substr = line.substr(pos, 4);
                    line.erase(pos, 4);
                }else  if (line.find("LXX") != string::npos){
                    unsigned pos = line.find("LXX");
                    substr = line.substr(pos, 3);
                    line.erase(pos, 3);
                } else  if (line.find("LX") != string::npos){
                    unsigned pos = line.find("LX");
                    substr = line.substr(pos, 2);
                    line.erase(pos, 2);
                }else  if (line.find("L") != string::npos){
                    unsigned pos = line.find("L");
                    substr = line.substr(pos, 1);
                    line.erase(pos, 1);
                }else  if (line.find("XL") != string::npos){
                    unsigned pos = line.find("XL");
                    substr = line.substr(pos, 2);
                    line.erase(pos, 2);
                }else  if (line.find("XXX") != string::npos){
                    unsigned pos = line.find("XXX");
                    substr = line.substr(pos, 3);  
                    line.erase(pos, 3);
                }else  if (line.find("XX") != string::npos){
                    unsigned pos = line.find("XX");
                    substr = line.substr(pos, 2);  
                    line.erase(pos, 2);
                }else  if (line.find("X") != string::npos){
                    unsigned pos = line.find("X");
                    substr = line.substr(pos, 1); 
                    line.erase(pos, 1);
                }


                if (roman_tens[i] == substr) {
                    arabic = arabic + (i * 10);

                }
            }
            // Loops through checking roman numeral with the digits array and if there is a match prints out the equivalent arabic number.
            for (int i = 0; i < 10; i++) {

                if (line.find("IX") != string::npos){
                    unsigned pos = line.find("IX");
                    substr = line.substr(pos, 2);
                    line.erase(pos, 2);
                } else  if (line.find("VIII") != string::npos){
                    unsigned pos = line.find("VIII");
                    substr = line.substr(pos, 4); 
                    line.erase(pos, 4);
                } else  if (line.find("VII") != string::npos){
                    unsigned pos = line.find("VII");
                    substr = line.substr(pos, 3);
                    line.erase(pos, 3);
                } else  if (line.find("VI") != string::npos){
                    unsigned pos = line.find("VI");
                    substr = line.substr(pos, 2);
                    line.erase(pos, 2);
                } else  if (line.find("V") != string::npos){
                    unsigned pos = line.find("V");
                    substr = line.substr(pos, 1);
                    line.erase(pos, 1);
                } else  if (line.find("IV") != string::npos){
                    unsigned pos = line.find("IV");
                    substr = line.substr(pos, 2);
                    line.erase(pos, 2);
                } else  if (line.find("III") != string::npos){
                    unsigned pos = line.find("III");
                    substr = line.substr(pos, 3);
                    line.erase(pos, 3);
                } else  if (line.find("II") != string::npos){
                    unsigned pos = line.find("II");
                    substr = line.substr(pos, 2);  
                    line.erase(pos, 2);
                }else  if (line.find("I") != string::npos){
                    unsigned pos = line.find("I");
                    substr = line.substr(pos, 1);                  
                }


                if (roman_digits[i] == substr) {
                    arabic = arabic + i;

                }
            }
            cout << "The Arabic equivalent of " << line << " is: " << arabic << endl;
            arabic = 0;
        } else {
            cout << "Invalid Roman numeral." << endl;
        }


    }
    return 0;

}

どんな助けでも大歓迎ですありがとう。

4

3 に答える 3

2

貪欲な解析戦略を使用します。つまり、有効な数字がある限り、できるだけ多くの入力を消費します。たとえば、入力例では次のようになります。

MCCCXXXVII

まずM、有効な数字である を確認します。次に を調べますがMC、これは有効な数字ではないため、M を消費してから からやり直しCます。

C有効な数字ですか? はい。CC有効な数字ですか? はい。CCC有効な数字ですか? はい。CCCX有効な数字ですか? いいえ、 を消費しCCCて からやり直してXください。

写真をゲット?

于 2013-08-30T03:04:32.563 に答える
1

あまり考えたことはありませんが、問題はあなたが作成しようとしているものよりも単純であるように思えます...一度に1文字ずつ文字列を解析して値を更新できるはずです。

一般的な考え方は、結果を 0 に設定して開始し、前の文字を記憶しながら一度に 1 文字ずつ読み取ることです (最初は入力に表示されない何かに設定されています。読み取った文字ごとに、値を の値だけ増やします)。その文字 (M = 1000、D = 500、C = 100、...)

奇妙なケースは、最後に読み取った文字がこの文字よりも低い額面である場合に発生します。この場合、値を修正するだけです。

たとえば、MCD では、1000 ずつインクリメントを開始し、次に 100 を増やしてから 500 を見つけますが、これは C よりも大きいため、修正する必要があります。前に追加した 100 を減らし、400 を追加して合計 1400 にします。

于 2013-08-30T03:04:37.290 に答える
0

デバッガを使用する必要があります。これが私が見つけたものです:

  • ユーザーの入力IX

  • 配列forを実行するループに到達するまで、すべて問題ありません。tens

  • 配列をループしているときtens、チェックがあります
    else if (line.find("X") != string::npos)

  • 返しますtrue。それは想定されていますか?9に入ってはいけませんtens

  • あなたの問題の1つの解決策は、それがではないかどうかを確認すること9です:

    else if (line.find("X") != string::npos && line != "IX")

編集:

これは簡単なハックにすぎません。長期的には、David Rodríguez のアドバイスに従い、ソリューションを簡素化する必要があります。

于 2013-08-30T03:12:10.290 に答える