title: How to convert Roman numerals to int while rejecting invalid numbers using standard C?
body: <p>What it means to be proper <a href="https://en.wikipedia.org/wiki/Roman_numerals" rel="nofollow noreferrer">Roman numerals</a> <a href="http://www.numericana.com/answer/roman.htm" rel="nofollow noreferrer">may</a> <a href="https://projecteuler.net/about=roman_numerals" rel="nofollow noreferrer">vary</a>. For simplicity (no Unicode, no multiplicative principle, no double subtractives, no overbars, no large numbers, etc) for the sake of this question, valid Roman numerals are defined by <a href="https://stackoverflow.com/a/267409/4279">the regex</a>: </p>
  
  <pre><code>^(M{0,3})(D?C{0,3}|CM|CD)(L?X{0,3}|XC|XL)(V?I{0,3}|IX|IV)$
  </code></pre>
  
  <p><a href="http://ideone.com/eHLVNq" rel="nofollow noreferrer">Code example with POSIX <code>regexec()</code></a>. The regex matches Roman numerals in 1..3999 range represented using "strict" rules.</p>
  
  <p>There are many solutions that can convert Roman numerals if we don't need to reject invalid numerals, for example:</p>
  
  <pre><code>int roman_numeral_value(unsigned char c)
  {
    switch(toupper(c)) {
    case 'I': return 1;
    case 'V': return 5;
    case 'X': return 10;
    case 'L': return 50;
    case 'C': return 100;
    case 'D': return 500;
    case 'M': return 1000;
    default: return 0; // error
    }
  }
  
  int roman_numeral_to_int(const char *s, int size)
  {
    int total = 0, prev = 0;
    for (int i = size-1; i &gt;= 0; --i) { // in reverse order
      int value = roman_numeral_value(s[i]);
      total += value &lt; prev ? -value : value; // subtract if necessary
      prev = value;
    }
    return total;
  }
  </code></pre>
  
  <p><a href="http://ideone.com/l06SeA" rel="nofollow noreferrer">It works for valid Roman numerals</a>. But <code>roman_numeral_to_int()</code> accepts numerals such as <code>IIIII</code> that are rejected by the regex. Is there a similarly simple cross-platform solution that doesn't require <a href="http://www.pcre.org/" rel="nofollow noreferrer"><code>pcre_exec()</code></a> or other external dependencies that works for valid Roman numerals and <em>only</em> for them?</p>