fork download
  1. /** Convert valid Roman numerals given on the command line to decimals. */
  2. #include <ctype.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <regex.h> // POSIX
  7.  
  8. static int
  9. roman_numeral_value(unsigned char c)
  10. {
  11. switch(toupper(c)) {
  12. case 'I': return 1;
  13. case 'V': return 5;
  14. case 'X': return 10;
  15. case 'L': return 50;
  16. case 'C': return 100;
  17. case 'D': return 500;
  18. case 'M': return 1000;
  19. default: return 0; // error
  20. }
  21. }
  22.  
  23.  
  24. static int
  25. roman_numeral_to_int(const char *restrict s, int size)
  26. {
  27. int total = 0, prev = 0;
  28. for (int i = size-1; i >= 0; --i) { // in reverse order
  29. int value = roman_numeral_value(s[i]);
  30. total += value < prev ? -value : value;
  31. prev = value;
  32. }
  33. return total;
  34. }
  35.  
  36.  
  37. int main(void) {
  38. const char *argv[] = {"roman-numerals", "IX", "XII", NULL};
  39.  
  40. regex_t reg;
  41. if (regcomp(&reg,"^(M{0,3})"
  42. "(D?C{0,3}|CM|CD)"
  43. "(L?X{0,3}|XC|XL)"
  44. "(V?I{0,3}|IX|IV)$", REG_EXTENDED | REG_ICASE))
  45. exit(2);
  46.  
  47. for (const char **pp = argv + 1; *pp; ++pp) {
  48. if (**pp == '\0' || regexec(&reg, *pp, 0, NULL, 0)) {
  49. exit(EXIT_FAILURE); // invalid literal(empty or doesn't match the regex)
  50. }
  51. printf("%d\n", roman_numeral_to_int(*pp, strlen(*pp)));
  52. }
  53. regfree(&reg);
  54. }
Success #stdin #stdout 0s 9424KB
stdin
Standard input is empty
stdout
9
12