NoPaste

mycmp.c

von RobertDebiannutzer

SNIPPET_TEXT:
  1. #include <ctype.h>
  2. #include <limits.h>
  3. #include <locale.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. #define ISDIGIT(c)   (isdigit((unsigned char)(c)))
  9.  
  10.  
  11. static int     digitcmp(char *buf1, char *buf2, size_t len1, size_t len2);
  12. static size_t  get_digits(const char *str, char *buf);
  13. static int     lettercmp(char *buf1, char *buf2, size_t i);
  14. static int     mycmp(const char *s1, const char *s2);
  15. /* test functions */
  16. static int     test_eq(const char *a, const char *b);
  17. static int     test_lt(const char *a, const char *b);
  18.  
  19.  
  20. /* compares two digit sequences */
  21. int
  22. digitcmp(char *buf1, char *buf2, size_t len1, size_t len2)
  23. {
  24.         size_t i, minlen;
  25.  
  26.         if (len1 == len2) {
  27.                 return strcmp(buf1, buf2);
  28.         }
  29.  
  30.         /* get len of shorter number */
  31.         minlen = len1 < len2 ? len1 : len2;
  32.  
  33.         /* skip leading zeros */
  34.         while (*buf1 == '0' && *buf2 == '0') {
  35.                 buf1++;
  36.                 buf2++;
  37.         }
  38.  
  39.         /* loop over equal digits */
  40.         for (i=0; *buf1 == *buf2 && i<minlen; i++) {
  41.                 buf1++;
  42.                 buf2++;
  43.         }
  44.  
  45.         /* if end of one number is reached, the other is greater */
  46.         if (i == len1) {
  47.                 return -1;
  48.         }
  49.         if (i == len2) {
  50.                 return 1;
  51.         }
  52.         return *buf1-*buf2;
  53. }
  54.  
  55. /* copy sequence of digits from str to buf and return number of copied digits */
  56. size_t
  57. get_digits(const char *str, char *buf)
  58. {
  59.         const char *base = str;
  60.  
  61.         for (; ISDIGIT(*str); buf++, str++) {
  62.                 *buf = *str;
  63.         }
  64.         *buf = '\0';
  65.         return str-base;
  66. }
  67.  
  68. int
  69. lettercmp(char *buf1, char *buf2, size_t i)
  70. {
  71.         buf1[i] = '\0';
  72.         buf2[i] = '\0';
  73.  
  74.         return strcoll(buf1, buf2);
  75. }
  76.  
  77. int
  78. mycmp(const char *s1, const char *s2)
  79. {
  80.         char buf1[strlen(s1)+1], buf2[strlen(s2)+1];
  81.         int r;
  82.         size_t i, len1, len2;
  83.  
  84.         for (i=0; (*s1 != '\0') && (*s2 != '\0'); i++, s1++, s2++) {
  85.                 if (ISDIGIT(*s1) || ISDIGIT(*s2)) {
  86.                         if ((r = lettercmp(buf1, buf2, i)) != 0) {
  87.                                 return r;
  88.                         }
  89.                         len1 = get_digits(s1, buf1);
  90.                         len2 = get_digits(s2, buf2);
  91.                         /* if not at position 0, digit > letter */
  92.                         if (len1 == 0 || len2 == 0) {
  93.                                 return (i == 0) ? len2-len1 : len1-len2;
  94.                         }
  95.                         if ((r = digitcmp(buf1, buf2, len1, len2)) != 0) {
  96.                                 return r;
  97.                         }
  98.                         s1 += len1;
  99.                         s2 += len2;
  100.                         i = 0;
  101.                 }
  102.                 buf1[i] = *s1;
  103.                 buf2[i] = *s2;
  104.         }
  105.         buf1[i] = *s1;
  106.         buf2[i] = *s2;
  107.         return lettercmp(buf1, buf2, i+1);
  108. }
  109.  
  110. int
  111. test_eq(const char *a, const char *b)
  112. {
  113.         return mycmp(a, b) != 0;
  114. }
  115.  
  116. int
  117. test_lt(const char *a, const char *b)
  118. {
  119.         return (mycmp(a, b) >= 0)
  120.                 +  (mycmp(b, a) <= 0);
  121. }
  122.  
  123. int
  124. main(int argc, char *argv[])
  125. {
  126.         unsigned long long i;
  127.  
  128.         setlocale(LC_ALL, "de_DE.UTF-8");
  129.  
  130.         if (argc == 3) {
  131.                 printf("%d\n", mycmp(argv[1], argv[2]));
  132.                 exit(EXIT_SUCCESS);
  133.         }
  134.  
  135.         if (argc == 2 && strcmp(argv[1], "--debug") == 0) {
  136.                 printf("%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n",
  137.                                 test_eq("", ""),
  138.                                 test_lt("0", "1"),
  139.                                 test_lt("1", "2"),
  140.                                 test_lt("a", "b"),
  141.                                 test_lt("abc-1.007.tgz", "abc-1.01a.tgz"),
  142.                                 test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm"),
  143.                                 test_lt("1file", "file1"),
  144.                                 test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
  145.                       );
  146.                 exit(EXIT_SUCCESS);
  147.         }
  148.  
  149.         if (argc == 2 && strcmp(argv[1], "--perftest") == 0) {
  150.                 for (i=0; i<1000000; i++) {
  151.                         test_eq("", "");
  152.                         test_lt("0", "1");
  153.                         test_lt("1", "2");
  154.                         test_lt("a", "b");
  155.                         test_lt("abc-1.007.tgz", "abc-1.01a.tgz");
  156.                         test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm");
  157.                         test_lt("1file", "file1");
  158.                         test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm");
  159.                 }
  160.                 exit(EXIT_SUCCESS);
  161.         }
  162.  
  163.         if (argc == 1) {
  164.                 return
  165.                         + test_eq("", "")
  166.                         + test_lt("0", "1")
  167.                         + test_lt("1", "2")
  168.                         + test_lt("a", "b")
  169.  
  170.                         + test_lt("abc-1.007.tgz", "abc-1.01a.tgz")
  171.                         + test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
  172.                         + test_lt("1file", "file1")
  173.                         + test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
  174.                         ;
  175.         }
  176.  
  177.         fprintf(stderr, "Usage: %s string1 string2\n"
  178.                         "   or: %s\n"
  179.                         "   or: %s --debug\n",
  180.                         argv[0], argv[0], argv[0]);
  181.         exit(EXIT_FAILURE);
  182. }

Quellcode

Hier kannst du den Code kopieren und ihn in deinen bevorzugten Editor einfügen. PASTEBIN_DOWNLOAD_SNIPPET_EXPLAIN