2013-08-29 3 views
1

Я новичок в C++, хотя у меня есть базовые знания Java, я пытаюсь создать программу, которая преобразует римский цифровой ввод, а затем находит эквивалентное арабское число и выводит его. Однако у меня возникает проблема поиска конкретных префиксов в римских цифрах. Я пытаюсь использовать функцию str.find, а затем используя str.substr для проверки, существует ли префикс и если да, то он дает арабское значение и затем перейдет к следующему префиксу. Однако мой код, кажется, не работает или распечатывает «0». Мне интересно, неправильно ли я использую str-функции или будет ли более простой способ найти префиксы в строке?Проблема с поиском символов в строке

Вот мой текущий код:

#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; 

} 

Любая помощь будет принята с благодарностью спасибо.

EDIT: Итак, я принял совет, и все это работает нормально (Код был отредактирован), поэтому большое спасибо за это. ^^

Однако, поскольку он проверяет «X» отдельно и удаляет его, моя программа переводит вход «IX» как 11, когда это на самом деле 9. Я знаю, что это связано с тем, что моя программа находит префиксы в строках, однако я не уверен, как это исправить, поэтому любая помощь в этом будет замечательной.

Еще раз спасибо

+0

Проверка на 'станд :: cin.eof () 'на самом деле не имеет большого смысла. Поскольку вы уже проверяете, что вход был успешным, он не наносит большого вреда, но он предотвратит последнее значение, если за ним не будет пробел, например, отсутствующая строка новой строки в конце файла. Просто удалите его! BTW, 'std :: cin >> строка' не читает строку, а слово. Если вы действительно хотите прочитать строку, используйте вместо нее 'std :: getline (std :: cin, line)'. –

+0

Предлагаю вам взглянуть на 'std :: map'. Вы можете использовать строку Roman Numeral в качестве ключа и десятичное значение в качестве значения в паре [ключ, значение]. –

ответ

1

string::find не возвращает bool (как вы видите на следующей строке). Если строка не найдена, она возвращает специальную константу string::npos. Значение 0 означает, что строка была найдена в начале, а не сбой.

Попробуйте вместо

string::size_type pos = line.find("MMM"); 
if (pos != string::npos) 
{ 
    ... 
} 

Другие комментарии

Вот одна линия способ, чтобы преобразовать строку в верхний регистр. Вам нужно будет включать <algorithm>

std::transform(s.begin(), s.end(), s.begin(), ::toupper); 

Вы можете сделать свои массивы данных, таких как roman_digits const string для предотвращения изменения их случайно.

Попробуйте объявить переменные как можно ближе к их первому использованию. char c должен быть определен только в вашем цикле while.

+0

Спасибо, я буду учитывать это в будущем. ^^ – 4593DDJS

1

std::string::find() функции не возвращает логическое значение, а возвращает позицию найденной подстроки или std::string::npos если нет такой позиции. Таким образом, тесты, вероятно, должен выглядеть следующим образом:

if (line.find("MMM") != std::string::npos) { ... } 

Конечно, это на самом деле не имеет особого смысла, чтобы попробовать ту же последовательность испытаний в четыре раза. Вероятно, вы указали на индекс i, чтобы выбрать подходящую строку из массива тысяч и иметь только один тест. Конечно, вы захотите изменить порядок строк или количество отсчетов, чтобы быть полезным.

Для других проверок вы, вероятно, должны использовать find(), а также следующие дополнительные цифры.

1

Я думаю, что этот код проще, я не выполнил проверку ошибок, но это не должно быть трудно:

#include <iostream> 
#include <map> 
using namespace std; 

int fromRoman(string n) 
{ 
    map<char, int> m; 
    m['I'] = 1; 
    m['V'] = 5; 
    m['X'] = 10; 
    m['L'] = 50; 
    m['C'] = 100; 
    m['D'] = 500; 
    m['M'] = 1000; 
    int tmp = 0; 
    int res = 0; 
    for (string::iterator i = n.begin(); i != n.end(); ++i) 
    { 
     int d = m[*i]; 
     if (d < tmp) 
     { 
      res += tmp; 
      tmp = d; 
     } 
     else if (d > tmp) 
     { 
      if (tmp == 0) 
       tmp = d; 
      else 
      { 
       res += d - tmp; 
       tmp = 0; 
      } 
     } 
     else if (d == tmp) 
     { 
      res += tmp + d; 
      tmp = 0; 
     } 
    } 
    return res + tmp; 
} 

int main() 
{ 
    const char *romanNumbers[] = { 
     "IV", "VIII", "IX", "XXXI", "XLVI", "XCIX", "DLXXXIII", "DCCCLXXXVIII", 
     "MDCLXVIII", "MCMLXXXIX", "MMX", "MMXII", "MMMCMXCIX" 
    }; 
    for (const char **r = romanNumbers; r != romanNumbers + sizeof(romanNumbers)/sizeof(*romanNumbers); ++r) 
     cout << *r << " is " << fromRoman(*r) << endl; 
} 

Выход:

IV is 4 
VIII is 8 
IX is 9 
XXXI is 31 
XLVI is 46 
XCIX is 99 
DLXXXIII is 583 
DCCCLXXXVIII is 888 
MDCLXVIII is 1668 
MCMLXXXIX is 1989 
MMX is 2010 
MMXII is 2012 
MMMCMXCIX is 3999 
Смежные вопросы