mycompare_alternative.c
von RobertDebiannutzer- SNIPPET_TEXT:
-
- #include <ctype.h>
- #include <limits.h>
- #include <locale.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define ISDIGIT(c) (isdigit((unsigned char)(c)))
- static int
- getnextchar(const char *str, char *buf)
- {
- int j, r;
- r = mblen(str, MB_LEN_MAX);
- if (buf != NULL) {
- for (j=0; j<r; j++, str++) { buf[j] = *str; };
- buf[j] = '\0';
- } else {
- for (j=0; j<r; j++, str++) {};
- }
- return r;
- }
- /* version compare combined with strcoll */
- static int
- mycompare(const char *s1, const char *s2)
- {
- const char *str1 = s1, *str2 = s2;
- char u1[strlen(s1)+MB_LEN_MAX+1], u2[strlen(s2)+MB_LEN_MAX+1];
- int r, rs;
- size_t d1, d2, i;
- for (;;) {
- for (i=0; ((*s1 != '\0') && (*s2 != '\0')); i++, s1++, s2++) {
- if (ISDIGIT(*s1) || ISDIGIT(*s2)) {
- break;
- }
- u1[i] = *s1;
- u2[i] = *s2;
- }
- u1[i] = '\0';
- u2[i] = '\0';
- if ((rs = strcoll(u1, u2)) == 0) {
- if ((*s1 == '\0') && (*s2 == '\0')) {
- return 0;
- } else if (*s1 == '\0') {
- return -1;
- } else if (*s2 == '\0') {
- return 1;
- }
- } else {
- return rs;
- }
- if (ISDIGIT(*s1) && ISDIGIT(*s2)) {
- /* skip leading zeros */
- if (getnextchar(s1, u1) < 1) {
- return 0;
- }
- if (getnextchar(s2, u2) < 1) {
- return 0;
- }
- for (d1=0; strcoll(u1, "0") == 0; d1++) {
- if ((r = getnextchar(s1, u1)) < 0) {
- return 0;
- }
- s1 += r;
- }
- for (d2=0; strcoll(u2, "0") == 0; d2++) {
- if ((r = getnextchar(s2, u2)) < 0) {
- return 0;
- }
- s2 += r;
- }
- if (d1 != d2) {
- /* more zeros = smaller string */
- return d2-d1;
- }
- /* loop over following digits */
- for (d1=d2=0; ISDIGIT(*(s1+d1)) && ISDIGIT(*(s2+d2));) {
- if ((r = getnextchar(s1, NULL)) < 1) {
- return 0;
- }
- d1 += r;
- if ((r = getnextchar(s2, NULL)) < 1) {
- return 0;
- }
- d2 += r;
- }
- /* longer number = greater string */
- if (ISDIGIT(*(s1+d1))) {
- return 1;
- } else if (ISDIGIT(*(s2+d2))) {
- return -1;
- } else {
- memcpy(u1, s1, d1);
- memcpy(u2, s2, d2);
- u1[d1] = '\0';
- u2[d2] = '\0';
- if ((rs = strcoll(u1, u2)) != 0) {
- return rs;
- }
- s1 += d1;
- s2 += d2;
- }
- } else if (ISDIGIT(*s1)) {
- return s1-str1 ? 1 : -1;
- } else if (ISDIGIT(*s2)) {
- return s2-str2 ? -1 : 1;
- }
- /* number = greater string - but only if not at position 0 */
- }
- }
- static int
- test_lt(const char *a, const char *b)
- {
- /* printf("%d - %d\n",
- mycompare(a, b),
- mycompare(b, a));*/
- return (mycompare(a, b) >= 0)
- + (mycompare(b, a) <= 0);
- }
- static int
- test_eq(const char *a, const char *b)
- {
- return mycompare(a, b) != 0;
- }
- int
- main(int argc, char *argv[])
- {
- unsigned long long i;
- setlocale(LC_ALL, "de_DE.UTF-8");
- if (argc == 3) {
- printf("%d\n", mycompare(argv[1], argv[2]));
- exit(EXIT_SUCCESS);
- } else if (argc == 2 && strcmp(argv[1], "--debug") == 0) {
- printf("%d\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n",
- test_eq("", ""),
- test_lt("0", "1"),
- test_lt("1", "2"),
- test_lt("a", "b"),
- test_lt("abc-1.007.tgz", "abc-1.01a.tgz"),
- test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm"),
- test_lt("1file", "file1"),
- test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
- );
- exit(EXIT_SUCCESS);
- } else if (argc == 2 && strcmp(argv[1], "--perftest") == 0) {
- for (i=0; i<1000000; i++) {
- test_eq("", "");
- test_lt("0", "1");
- test_lt("1", "2");
- test_lt("a", "b");
- test_lt("abc-1.007.tgz", "abc-1.01a.tgz");
- test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm");
- test_lt("1file", "file1");
- test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm");
- }
- } else if (argc == 1) {
- return
- + test_eq("", "")
- + test_lt("0", "1")
- + test_lt("1", "2")
- + test_lt("a", "b")
- + test_lt("abc-1.007.tgz", "abc-1.01a.tgz")
- + test_lt("abc-1.2.3.x86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
- + test_lt("1file", "file1")
- + test_lt("abc-1.2.3.ä86_64.rpm", "abc-1.2.3.4.x86_64.rpm")
- ;
- } else {
- fprintf(stderr, "Usage: %s string1 string2\n"
- " or: %s\n"
- " or: %s --debug\n",
- argv[0], argv[0], argv[0]);
- exit(EXIT_FAILURE);
- }
- }
Quellcode
Hier kannst du den Code kopieren und ihn in deinen bevorzugten Editor einfügen. PASTEBIN_DOWNLOAD_SNIPPET_EXPLAIN