home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snpd9707.zip / L2ROMAN.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  4KB  |  125 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /*
  4. **        L2ROMAN.C  -  Converts long integers to Roman numerals
  5. **
  6. **        Jim Walsh, Dann Corbit, Bob Stout, and Others made this.
  7. **
  8. **        This Program Is Released To The Public Domain
  9. **
  10. ** ----------------------------------------------------------------------
  11. ** Compiling:
  12. **    If the symbol ALLOW_BAR_NOTATION is defined, then bar notation is
  13. **    allowed.  If the Romans wanted to record one million, they did not
  14. **    write down 1000 M's.  They would right one M with a bar over it.
  15. **    Any Roman numeral with a bar over it is multiplied by 1000.
  16. **    Unfortunately, this is not a standard character in most character sets.
  17. **    If you choose to #define ALLOW_BAR_NOTATION, then you will have to
  18. **    translate the symbols to final form yourself.
  19. */
  20.  
  21. #include <stdlib.h>
  22. #include "sniptype.h"
  23.  
  24. typedef struct tag_RomanToDecimal {
  25.       long  PostValue;
  26.       char *PostLetter;
  27.       long  PreValue;
  28.       char *PreLetter;
  29. } R2D;
  30.  
  31. /*
  32. **  Set PrefixesAreOK = True_ to enable prefix notation (e.g. 4 = "IV")
  33. **  Set PrefixesAreOK = False_ to disable prefix notation (e.g. 4 = "IIII")
  34. */
  35.  
  36. static Boolean_T PrefixesAreOK = True_;
  37.  
  38. static R2D RomanConvert[] = {
  39. #if defined(ALLOW_BAR_NOTATION)
  40.         /*
  41.         ** A Roman numeral with a bar over it is
  42.         ** that value multiplied by 1000.
  43.         */
  44.         {1000000L, "<M-bar>", 900000L, "<CM-bar>"},
  45.         {500000L, "<D-bar>", 400000L, "<CD-bar>"},
  46.         {100000L, "<C-bar>", 90000L, "<XC-bar>"},
  47.         {50000L, "<L-bar>", 40000L, "<XL-bar>"},
  48.         {10000L, "<X-bar>", 9000L, "<IX-bar>"},
  49.         {5000L, "<V-bar>", 4000L, "<IV-bar>"},
  50. #endif
  51.         {1000L, "M", 900L, "CM"},
  52.         {500L, "D", 400L, "CD"},
  53.         {100L, "C", 90L, "XC"},
  54.         {50L, "L", 40L, "XL"},
  55.         {10L, "X", 9L, "IX"},
  56.         {5L, "V", 4L, "IV"},
  57.         {1L, "I", 1L, "I"}
  58.     };
  59.  
  60. /*
  61. **  long2roman() - Convert a long integer into roman numerals
  62. **
  63. **  Arguments: 1 - Value to convert
  64. **             2 - Buffer to receive the converted roman numeral string
  65. **             3 - Length of the string buffer
  66. **
  67. **  Returns: Pointer to the buffer, else NULL if error or buffer overflow
  68. */
  69.  
  70. char *long2roman(long val, char *buf, size_t buflen)
  71. {
  72.       size_t posn = 0;
  73.       size_t place = 0;
  74.  
  75. #if !defined(ALLOW_BAR_NOTATION)
  76.       if (val > 3999L)
  77.             return NULL;
  78. #endif
  79.       do
  80.       {
  81.             while (val >= RomanConvert[place].PostValue)
  82.             {
  83.                   posn += sprintf(&buf[posn], "%s",
  84.                                   RomanConvert[place].PostLetter);
  85.                   val -= RomanConvert[place].PostValue;
  86.                   if (posn >= buflen)
  87.                         return NULL;
  88.             }
  89.             if (PrefixesAreOK)
  90.             {
  91.                   if (val >= RomanConvert[place].PreValue)
  92.                   {
  93.                         posn += sprintf(&buf[posn], "%s",
  94.                                         RomanConvert[place].PreLetter);
  95.                         val -= RomanConvert[place].PreValue;
  96.                         if (posn >= buflen)
  97.                               return NULL;
  98.                   }
  99.             }
  100.             place++;
  101.       } while (val > 0);
  102.  
  103.       return buf;
  104. }
  105.  
  106. #ifdef TEST
  107.  
  108. #include <stdio.h>
  109.  
  110. int main(int argc, char *argv[])
  111. {
  112.       long value;
  113.       char buf[128];
  114.  
  115.       while (--argc)
  116.       {
  117.             value = atol(*(++argv));
  118.             printf("\n%ld = %s\n", value, long2roman(value, buf, 128));
  119.       }
  120.  
  121.       return 0;
  122. }
  123.  
  124. #endif /* TEST */
  125.