Stop counting if a character can't be found in map

Viewed 100

I've got an assignment in which I've to create a roman numeral to integer converter. As my code stands, I've just used a map to relate characters to integer values, which are added to a sum, accounting for values like IV etc. For strings that do not wholly consist of roman numerals, I've been trying to make it stop adding as soon as a character without a mapped value is found but I'm running into issues.

#include <iostream>
#include <cctype>
#include <map>
#include <string>
#include <algorithm>

using namespace std;


int main(int argc, char *argv[]) {

map<char, int> num;
num.insert({ 'I', 1});
num.insert({ 'V', 5});
num.insert({ 'X', 10});
num.insert({ 'L', 50});
num.insert({ 'C', 100});
num.insert({ 'D', 500});
num.insert({ 'M', 1000});

string str;

while(getline(cin,str)){

    int sum = 0;

    transform(str.begin(), str.end(), str.begin(), ::toupper);

    for (int j = 0; j < str.length(); j++){

        if (num.count(str[j]) != 1){
            break;
        }


        if (num[str[j]] < num[str[j+1]]){
            sum += num[str[j+1]] - num[str[j]];
            j++;
            continue;
        }

            sum += num[str[j]];
    }

    cout << sum << "\n";
 }
 return 0;
}

I thought that num.count(str[j]) would return 0 if a mapped value wasn't found, and then I could use that to break the for loop but I'm wrong somewhere. When I give the command line argument of iittii, I would want it to output a sum of 2 (as it would stop when it encounters the first t) but instead I get 4.

Is my implementation incorrect or is there an alternative method to achieveing this?

Thank you

1 Answers

I think the problem is with your following block of code:

if (num[str[j]] < num[str[j+1]]){
    sum += num[str[j+1]] - num[str[j]];
    j++;
    continue;
}

That block of code causes your program to malfunction because it has 2 issues:

  1. It incorrectly calculates the sum.
  2. It may cause your program to crash unexpectedly at some point (i.e. segmentation fault) because the code str[j+1] means that the index j+1 is greater than the length of str at the end of the for loop when j = str.length - 1. In other words, this means that the index j+1 is running out of bound at that point.

So, after I've modified that block of code as shown below, your program works correctly:

    if (j > 0 &&
        num[str[j]] > num[str[j-1]]){
        sum += num[str[j]] - 2 * num[str[j-1]];           
        continue;
    }

Here is my new program (with my new block of code):


#include <iostream>
#include <cctype>
#include <map>
#include <string>
#include <algorithm>

using namespace std;


int main(int argc, char *argv[]) {

map<char, int> num;
num.insert({ 'I', 1});
num.insert({ 'V', 5});
num.insert({ 'X', 10});
num.insert({ 'L', 50});
num.insert({ 'C', 100});
num.insert({ 'D', 500});
num.insert({ 'M', 1000});

string str;

while(getline(cin,str)){

    int sum = 0;

    transform(str.begin(), str.end(), str.begin(), ::toupper);

    for (int j = 0; j < str.length(); j++){

        if ( num.count(str[j]) < 1 ){
            break;
        }

        // HERE IS MY NEW BLOCK OF CODE :-)
        if (j > 0 &&
            num[str[j]] > num[str[j-1]]){

            sum += num[str[j]] - 2 * num[str[j-1]];           
            continue;
        }

            sum += num[str[j]];
    }

    cout << sum << "\n";
 }
 return 0;
}

Please let me know if the answer above works for you.

I have run 2 test cases and verified the program works:

  1. Input = iittii

    Per your description of the problem, I enter the input iittii as you require, and my program produces the correct output 2 as you expect.

  2. Input = IV, IX, CD

    In addition, I have also tested the input such as IV, IX, CD as user @ArminMontigny described, and my new code works correctly.

Related