127 lines
4.4 KiB
C
127 lines
4.4 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_full(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 */
|