Files
lib11sht/cmp11sht.c

127 lines
4.3 KiB
C

/* ************************************************************************ *
* cmp11sht.c, v20251221.085434 *
* Fuzzy comparison CLI — thin shell over lib11sht *
* *
* Copyright (C) 2025 by Ruben Carlo Benante <rcb@beco.cc> *
* GNU GPL version 2 or later. *
* *
* Build: gcc cmp11sht.c lib11sht.c -lm -o cmp11sht *
* ************************************************************************ */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <errno.h>
#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(argv[1], argv[2], delta, &ratio, s1, s2);
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 */