2

我是 C++ 新手,虽然我有 Java 的基本知识,但我正在尝试制作一个程序来转换罗马数字输入,然后找到等效的阿拉伯数字并输出它。但是,我遇到了一个问题,即如何正确地查找罗马数字中的特定前缀,例如,因为它正在单独检查“X”并将其删除;我的程序正在将输入“IX”翻译为 11,而实际上它是 9。我知道这与我的程序在字符串中找到前缀的顺序有关,但是我不确定如何修复它,所以任何这方面的帮助会很棒。

当前代码:

    #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

没有考虑太多,但在我看来,这个问题比你试图解决的问题更简单......我相信你应该能够一次解析字符串一个字符来更新值。

一般的想法是,您从结果设置为 0 开始,一次读取一个字符,同时记住前一个字符(最初设置为不能出现在输入中的内容。对于读取的每个字符,将值增加那个字符(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.

  • 解决您的一个问题的方法是检查它是否不是9

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

编辑:

这只是一个快速破解,从长远来看,您应该遵循 David Rodríguez 的建议并简化您的解决方案。

于 2013-08-30T03:12:10.290 回答