Fixing validfmt and optimizing the algorithm. (Thanks David Galos)

This commit is contained in:
Christoph Lohmann 2012-04-18 13:41:05 +02:00
parent dbe8e73237
commit 96b15a5afa

69
seq.c
View File

@ -5,7 +5,6 @@
#include <unistd.h> #include <unistd.h>
#include <stdbool.h> #include <stdbool.h>
#include <libgen.h> #include <libgen.h>
#include <regex.h>
#include "util.h" #include "util.h"
@ -30,12 +29,12 @@ digitsleft(char *d)
char *exp; char *exp;
int shift; int shift;
if (d[0] == '-' || d[0] == '+') if (d[0] == '+')
d++; d++;
exp = strpbrk(d, "eE"); exp = strpbrk(d, "eE");
shift = exp? atoi(exp+1) : 0; shift = exp? atoi(exp+1) : 0;
return MAX(0, strspn(d, "0123456789")+shift); return MAX(0, strspn(d, "-0123456789")+shift);
} }
int int
@ -44,8 +43,6 @@ digitsright(char *d)
char *exp; char *exp;
int shift, after; int shift, after;
if (d[0] == '-' || d[0] == '+')
d++;
exp = strpbrk(d, "eE"); exp = strpbrk(d, "eE");
shift = exp ? atoi(exp+1) : 0; shift = exp ? atoi(exp+1) : 0;
after = (d = strchr(d, '.'))? strspn(d+1, "0123456789") : 0; after = (d = strchr(d, '.'))? strspn(d+1, "0123456789") : 0;
@ -56,15 +53,36 @@ digitsright(char *d)
int int
validfmt(char *fmt) validfmt(char *fmt)
{ {
regex_t reg; int occur;
int ret;
regcomp(&reg, "\\([^%]|%%\\)*%[0-9]*\\.[0-9]*[fFgG]" occur = 0;
"\\([^%]|%%\\)*", REG_NOSUB);
ret = regexec(&reg, fmt, 0, NULL, 0);
regfree(&reg);
return (ret == 0); NonFormat:
while(*fmt) {
if (*fmt++ == '%')
goto Format;
}
return (occur == 1);
Format:
if (*fmt == '%') {
fmt++;
goto NonFormat;
}
fmt += strspn(fmt, "-+#0 '");
fmt += strspn(fmt, "0123456789");
if (*fmt == '.') {
fmt ++;
fmt += strspn(fmt, "0123456789");
}
if (*fmt == 'L')
fmt++;
if (*fmt == '\0')
return 0;
if (strchr("fFgGeEaA", *fmt)) {
occur++;
goto NonFormat;
}
return 0;
} }
int int
@ -72,7 +90,7 @@ main(int argc, char *argv[])
{ {
char c, *fmt, ftmp[4096], *sep, *starts, *steps, *ends; char c, *fmt, ftmp[4096], *sep, *starts, *steps, *ends;
bool wflag, fflag; bool wflag, fflag;
double start, step, end, out; double start, step, end, out, dir;
int left, right; int left, right;
sep = "\n"; sep = "\n";
@ -134,17 +152,12 @@ main(int argc, char *argv[])
start = atof(starts); start = atof(starts);
step = atof(steps); step = atof(steps);
end = atof(ends); end = atof(ends);
dir = (step > 0)? 1.0 : -1.0;
if (step == 0) if (step == 0)
return EXIT_FAILURE; return EXIT_FAILURE;
if (start * dir > end * dir)
if (start > end) { return EXIT_FAILURE;
if (step > 0)
return EXIT_FAILURE;
} else if (start < end) {
if (step < 0)
return EXIT_FAILURE;
}
right = MAX(digitsright(starts), right = MAX(digitsright(starts),
MAX(digitsright(ends), MAX(digitsright(ends),
@ -163,18 +176,8 @@ main(int argc, char *argv[])
printf(fmt, out); printf(fmt, out);
out += step; out += step;
if (start > end) { if (out * dir <= end * dir) {
if (out >= end) { printf("%s", sep);
printf("%s", sep);
} else {
break;
}
} else if (start < end) {
if (out <= end) {
printf("%s", sep);
} else {
break;
}
} else { } else {
break; break;
} }