Search code examples
c++arraysroman-numerals

C++ Unexpected Array Overflow


About 50 minutes ago I started working on a project where I convert a string with roman numerals to an integer. I am having an issue where there is an "array overflow", and I've been troubleshooting for 30 minutes, and am getting kind of frustrated because I can't find a solution. The error that is shown is as follows

terminate called after throwing an instance of 'std::out_of_range'
what():  basic_string::at: __n (which is 3) >= this->size() (which is 3)

Here is my code:

class Solution {
  public:
    int romanToInt(string s) {
      int result = 0;
      char letters[7] = {'M','D','C','L','X','V','I'};
      int numbers[7] = {1000,500,100,50,10,5,1};
      for(int i=0; i<s.length(); i++) {
        if(i!=(s.length()-1)) {
          char *foo = std::find(std::begin(letters), std::end(letters), s.at(i));
          char *nfoo = std::find(std::begin(letters), std::end(letters), s.at(i+1));
          int num = numbers[std::distance(letters, foo)];
          int num2 = numbers[std::distance(letters, nfoo)];
          if(num<num2) {
            result+=(num2-num);
          }
          else {
            result+=num2;
          }
        }
        else {
          char *foo = std::find(std::begin(letters), std::end(letters), s.at(i));
          int num = numbers[std::distance(letters, foo)];
          result+=num;
        }
      }
      return result;
    }
};

Solution

  • Your code can be cleaned up a bit:

    int Roman_To_Decimal(const std::string& roman_number)
    {
        static const char roman_letters[] = {'M','D','C','L','X','V','I'};
        static const int  values[] = {1000, 500, 100, 50, 10, 5, 1};
        const unsigned int string_length = roman_number.length();
        int decimal_value = 0;
        char const * const end_letter_iterator = &roman_letters[sizeof(roman_letters)];
        char const * const begin_letter_iterator = &roman_letters[0];
        for (unsigned int i = 0; i < string_length; ++i)
        {
           const char roman_digit = roman_number[i];
           char * position = std::find(begin_letter_iterator,
                                       end_letter_iterator,
                                       roman_digit);
           if (position != end_letter_iterator)
           {
               unsigned int index = position - begin_letter_iterator;
               const int digit_value = values[index];
               decimal_value += digit_value;
           }
        }
        return decimal_value;
    }
    

    The code above does not handle the case where a smaller Roman Numeral (letter) precedes a larger one, such as the cases of IX (9) and IV (4). This is an exercise for the OP or the reader.

    Also, the above function is free standing, i.e. outside of a class, because not everything has to be in a class in C++.