Files
lib11sht/cmp11sht.c

127 lines
4.4 KiB
C
Raw Normal View History

2026-05-22 19:02:03 -03:00
/* ************************************************************************ *
* cmp11sht.c, v20251221.085434 *
2026-05-22 19:41:10 -03:00
* Fuzzy comparison CLI thin shell over lib11sht *
2026-05-22 19:02:03 -03:00
* *
2026-05-22 19:41:10 -03:00
* Copyright (C) 2025 by Ruben Carlo Benante <rcb@beco.cc> *
* GNU GPL version 2 or later. *
2026-05-22 19:02:03 -03:00
* *
2026-05-22 19:41:10 -03:00
* Build: gcc cmp11sht.c lib11sht.c -lm -o cmp11sht *
* ************************************************************************ */
2026-05-22 19:02:03 -03:00
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include <errno.h>
2026-05-22 19:02:03 -03:00
2026-05-22 19:41:10 -03:00
#include "lib11sht.h"
2026-05-22 19:02:03 -03:00
/* ---------------------------------------------------------------------- */
2026-05-22 19:41:10 -03:00
/* 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:
2026-05-22 19:02:03 -03:00
* return 0 if a ~ b, within range delta
* return +1 if a > b, within range delta
2026-05-22 19:41:10 -03:00
* return +2 if a < b, within range delta
* return +3 if an error occurred
2026-05-22 19:02:03 -03:00
*/
int main(int argc, char **argv)
{
2026-05-22 19:41:10 -03:00
int res; /* comparison result (CLI exit code) */
2026-05-22 19:02:03 -03:00
char *fenda, *fendb, *fendd;
2026-05-22 19:41:10 -03:00
char s1[LEVN_SBUFF], s2[LEVN_SBUFF];
2026-05-22 19:02:03 -03:00
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\
2026-05-22 19:41:10 -03:00
After getting two objects o1 and o2 (float or string)\n\
2026-05-22 19:02:03 -03:00
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\
2026-05-22 19:41:10 -03:00
the comparison will:\n\n\
2026-05-22 19:02:03 -03:00
* 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\
2026-05-22 19:41:10 -03:00
\t-n Print also the normalized strings or floats used for comparison\n\n\
2026-05-22 19:02:03 -03:00
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;
}
2026-05-22 19:41:10 -03:00
if(fendd == argv[3]) /* error, need a threshold */
2026-05-22 19:02:03 -03:00
{
if(opt) printf("%d\n", 3);
return 3;
}
2026-05-22 19:41:10 -03:00
if(delta <= FLT_MIN) /* near zero delta not accepted */
2026-05-22 19:02:03 -03:00
{
if(opt) printf("%d\n", 3);
return 3;
}
2026-05-22 19:41:10 -03:00
if(delta >= 1.0) /* maximum precision 1.0 */
2026-05-22 19:02:03 -03:00
{
if(opt) printf("%d\n", 3);
return 3;
}
2026-05-22 19:41:10 -03:00
if(fenda == argv[1] || fendb == argv[2]) /* string */
2026-05-22 19:02:03 -03:00
{
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) */
2026-05-22 19:02:03 -03:00
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);
}
2026-05-22 19:41:10 -03:00
else /* float */
2026-05-22 19:02:03 -03:00
{
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) */
2026-05-22 19:02:03 -03:00
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 */