命令我检查字符串输出错误

时间:2013-08-30 02:51:08

标签: c++ string if-statement find

我是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;

}

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:2)

使用贪婪的解析策略。也就是说,只要你有一个有效数字,就尽可能多地消耗输入。例如,使用您的示例输入:

MCCCXXXVII

首先查看M,这是一个有效数字。然后,您查看MC,这不是有效数字,因此您使用M,然后从C重新开始。

C是有效数字吗?是。 CC是有效数字吗?是。 CCC是有效数字吗?是。 CCCX是有效数字吗?不,请消费CCC,然后再次从X开始。

了解图片?

答案 1 :(得分:1)

没有想太多,但在我看来,问题比你想要做的更简单...我相信你应该能够一次解析一个字符的字符串更新值

一般的想法是,你将结果设置为0并一次读取一个字符,同时记住前一个字符(最初设置为输入中不能出现的字符。对于每个字符读取,增加值为该字符的值(M = 1000,D = 500,C = 100,...)

当最后一个字符读取的字母比这个字符低时,会出现这种奇怪的情况。在这种情况下,您只需要修复该值。

例如,在MCD中,你会开始递增1000,然后是100,然后你会找到500,但是这比C大,所以你需要修复:递减你之前添加的100,总计加400 1400年。

答案 2 :(得分: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")

编辑:

这只是一个快速的黑客攻击,从长远来看,你应该遵循DavidRodríguez的建议并简化你的解决方案。