/** Convert valid Roman numerals given on the command line to decimals. */
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <regex.h> // POSIX
static int
roman_numeral_value(unsigned char 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
}
}
static int
roman_numeral_to_int(const char *restrict s, int size)
{
int total = 0, prev = 0;
for (int i = size-1; i >= 0; --i) { // in reverse order
int value = roman_numeral_value(s[i]);
total += value < prev ? -value : value;
prev = value;
}
return total;
}
int main(void) {
const char *argv[] = {"roman-numerals", "IX", "XII", NULL};
regex_t reg;
if (regcomp(®,"^(M{0,3})"
"(D?C{0,3}|CM|CD)"
"(L?X{0,3}|XC|XL)"
"(V?I{0,3}|IX|IV)$", REG_EXTENDED | REG_ICASE))
for (const char **pp = argv + 1; *pp; ++pp) {
if (**pp == '\0' || regexec(®, *pp, 0, NULL, 0)) {
exit(EXIT_FAILURE
); // invalid literal(empty or doesn't match the regex) }
}
regfree(®);
}
LyoqIENvbnZlcnQgdmFsaWQgUm9tYW4gbnVtZXJhbHMgZ2l2ZW4gb24gdGhlIGNvbW1hbmQgbGluZSB0byBkZWNpbWFscy4gKi8KI2luY2x1ZGUgPGN0eXBlLmg+CiNpbmNsdWRlIDxzdHJpbmcuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHJlZ2V4Lmg+IC8vIFBPU0lYCgpzdGF0aWMgaW50CnJvbWFuX251bWVyYWxfdmFsdWUodW5zaWduZWQgY2hhciBjKQp7CiAgc3dpdGNoKHRvdXBwZXIoYykpIHsKICBjYXNlICdJJzogcmV0dXJuIDE7CiAgY2FzZSAnVic6IHJldHVybiA1OwogIGNhc2UgJ1gnOiByZXR1cm4gMTA7CiAgY2FzZSAnTCc6IHJldHVybiA1MDsKICBjYXNlICdDJzogcmV0dXJuIDEwMDsKICBjYXNlICdEJzogcmV0dXJuIDUwMDsKICBjYXNlICdNJzogcmV0dXJuIDEwMDA7CiAgZGVmYXVsdDogcmV0dXJuIDA7IC8vIGVycm9yCiAgfQp9CgoKc3RhdGljIGludApyb21hbl9udW1lcmFsX3RvX2ludChjb25zdCBjaGFyICpyZXN0cmljdCBzLCBpbnQgc2l6ZSkKewogIGludCB0b3RhbCA9IDAsIHByZXYgPSAwOwogIGZvciAoaW50IGkgPSBzaXplLTE7IGkgPj0gMDsgLS1pKSB7IC8vIGluIHJldmVyc2Ugb3JkZXIKICAgIGludCB2YWx1ZSA9IHJvbWFuX251bWVyYWxfdmFsdWUoc1tpXSk7CiAgICB0b3RhbCArPSB2YWx1ZSA8IHByZXYgPyAtdmFsdWUgOiB2YWx1ZTsKICAgIHByZXYgPSB2YWx1ZTsKICB9CiAgcmV0dXJuIHRvdGFsOwp9CgoKaW50IG1haW4odm9pZCkgewogIGNvbnN0IGNoYXIgKmFyZ3ZbXSA9IHsicm9tYW4tbnVtZXJhbHMiLCAiSVgiLCAiWElJIiwgTlVMTH07CgogIHJlZ2V4X3QgcmVnOwogIGlmIChyZWdjb21wKCZyZWcsIl4oTXswLDN9KSIKICAgICAgICAgICAgICAgICAgIihEP0N7MCwzfXxDTXxDRCkiCiAgICAgICAgICAgICAgICAgICIoTD9YezAsM318WEN8WEwpIgogICAgICAgICAgICAgICAgICAiKFY/SXswLDN9fElYfElWKSQiLCBSRUdfRVhURU5ERUQgfCBSRUdfSUNBU0UpKQogICAgZXhpdCgyKTsKCiAgZm9yIChjb25zdCBjaGFyICoqcHAgPSBhcmd2ICsgMTsgKnBwOyArK3BwKSB7CiAgICBpZiAoKipwcCA9PSAnXDAnIHx8IHJlZ2V4ZWMoJnJlZywgKnBwLCAwLCBOVUxMLCAwKSkgewogICAgICBleGl0KEVYSVRfRkFJTFVSRSk7IC8vIGludmFsaWQgbGl0ZXJhbChlbXB0eSBvciBkb2Vzbid0IG1hdGNoIHRoZSByZWdleCkKICAgIH0KICAgIHByaW50ZigiJWRcbiIsIHJvbWFuX251bWVyYWxfdG9faW50KCpwcCwgc3RybGVuKCpwcCkpKTsKICB9CiAgcmVnZnJlZSgmcmVnKTsKfQ==