/* ************************************************************************ * * cmp11sht.c, v20251221.085434 * * Fuzzy comparison CLI — thin shell over lib11sht * * * * Copyright (C) 2025 by Ruben Carlo Benante * * GNU GPL version 2 or later. * * * * Build: gcc cmp11sht.c lib11sht.c -lm -o cmp11sht * * ************************************************************************ */ #include #include #include #include #include #include "lib11sht.h" /* ---------------------------------------------------------------------- */ /* get two objects a and b (float or string) and a delta (float) * Translates the library's {-1, 0, +1} return convention to CLI exit codes: * return 0 if a ~ b, within range delta * return +1 if a > b, within range delta * return +2 if a < b, within range delta * return +3 if an error occurred */ int main(int argc, char **argv) { int res; /* comparison result (CLI exit code) */ char *fenda, *fendb, *fendd; char s1[LEVN_SBUFF], s2[LEVN_SBUFF]; float a, b, delta, ratio; int opt=0; /* -no-option:0, -v:1, -o:2, -n:3 */ if(argc!=4 && argc!=5) { printf( "cmp11sht - Fuzzy compare strings or floats within range\n\n\ Usage:\n\t$ cmp11sht -h\n\ \t$ cmp11sht o1 o2 delta [-v|-o|-n]\n\n\ After getting two objects o1 and o2 (float or string)\n\ and a FLT_MIN < delta < 1.0 (float), where:\n\ - For strings, delta is the Levenshtein ratio\n\ - For floats, delta is the precision\n\ the comparison will:\n\n\ * return 0 if a ~ b, within range delta\n\ * return +1 if a > b, within range delta\n\ * return +2 if a < b, within range delta\n\ * return +3 if an error occurred\n\n\ Options:\n\t-h Print this help\n\ \t-v Print result to stdout (default is system err)\n\ \t-o Print also the Levenshtein ratio or float difference\n\ \t-n Print also the normalized strings or floats used for comparison\n\n\ cmp11sht v20251221.0718 (C) 2025 by Ruben C. Benante (MIT Lic)\n\n" ); return 3; } a=strtof(argv[1], &fenda); b=strtof(argv[2], &fendb); delta=strtof(argv[3], &fendd); if(argc==5) switch(argv[4][1]) { case 'v': opt=1; break; case 'o': opt=2; break; case 'n': opt=3; break; default: return 3; } if(fendd == argv[3]) /* error, need a threshold */ { if(opt) printf("%d\n", 3); return 3; } if(delta <= FLT_MIN) /* near zero delta not accepted */ { if(opt) printf("%d\n", 3); return 3; } if(delta >= 1.0) /* maximum precision 1.0 */ { if(opt) printf("%d\n", 3); return 3; } if(fenda == argv[1] || fendb == argv[2]) /* string */ { if(opt==3) printf("cmp11sht: string\n"); errno = 0; res = sequal_full(argv[1], argv[2], delta, &ratio, s1, LEVN_SBUFF, s2, LEVN_SBUFF); if(errno == EINVAL) res = 3; /* error → CLI exit 3 */ else if(res > 0) res = 1; /* a > b → CLI exit 1 */ else if(res < 0) res = 2; /* a < b → CLI exit 2 */ /* res == 0 stays 0 (equal) */ if(opt==3) printf("result: "); if(opt) printf("%d\n", res); if(opt==3) printf("ratio: "); if(opt>=2) printf("%f\n", ratio); if(opt==3) printf("s1: %s\ns2: %s\n", s1, s2); } else /* float */ { if(opt==3) printf("cmp11sht: float\n"); res = fequal(a, b, delta); if(res > 0) res = 1; /* a > b → CLI exit 1 */ else if(res < 0) res = 2; /* a < b → CLI exit 2 */ /* res == 0 stays 0 (equal) */ if(opt==3) printf("result: "); if(opt) printf("%d\n", res); if(opt==3) printf("diff: "); if(opt>=2) printf("%f\n", fabs(a - b)); if(opt==3) printf("f1: %E\nf2: %E\n", a, b); } return res; } /* ---------------------------------------------------------------------- */ /* vi: set ai et ts=4 sw=4 tw=0 wm=0 fo=croql : C config for Vim modeline */