Salut Nal,
Il manquait une version C à la tradition Unix, c'est maintenant fait !
Du coup, pour préserver l'esprit, options courtes uniquement et pas de version, mais pour le reste, c'est assez complet avec contrôle des bornes pour les paramètres. Il ne manque que la page de manuel, ce sera pour une autre fois :)
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#define NSAMPLES 5
#define MAX_NSAMPLES 20
#define RESET_TIME 5
#define PRECISION 0
extern char *__progname;
static void usage(void);
int
main(int argc, char *argv[])
{
double times[MAX_NSAMPLES];
int curlen = 0;
double curtime;
struct timeval tp;
int ch;
char *p = NULL, *r = NULL, *s = NULL;
int precision = PRECISION, reset_time = RESET_TIME, nsamples = NSAMPLES;
char fmtstr[30];
char *line = NULL;
size_t linesize = 0;
ssize_t linelen;
while ((ch = getopt(argc, argv, "p:r:s:")) != -1)
switch (ch) {
case 'p':
p = optarg;
break;
case 'r':
r = optarg;
break;
case 's':
s = optarg;
break;
default:
usage();
}
argc -= optind;
if (argc > 0)
warnx("too many arguments");
if (p && sscanf(p, "%i", &precision) != 1)
warnx("-p argument: not an integer");
if (r && sscanf(r, "%i", &reset_time) != 1)
warnx("-r argument: not an integer");
if (s && sscanf(s, "%i", &nsamples) != 1)
warnx("-r argument: not an integer");
if (precision < 0 || precision > 6) {
warnx("-p argument: should be an integer between 0 and 6");
precision = PRECISION;
}
if (reset_time < 1) {
warnx("-r argument: should be at least 1");
reset_time = RESET_TIME;
}
if (nsamples < 2 || nsamples > MAX_NSAMPLES) {
fprintf(stderr, "%s: -s argument: should be an integer between 2 and %d\n",
__progname, MAX_NSAMPLES);
nsamples = NSAMPLES;
}
int ret = snprintf(fmtstr, sizeof(fmtstr), "Tempo: %%.%df bpm ", precision);
if (ret == -1 || ret >= sizeof(fmtstr))
errx(1, "snprintf");
printf("Hit enter key for each beat (q to quit).");
while ((fflush(stdout), linelen = getline(&line, &linesize, stdin)) != -1) {
if (!strncmp(line, "q\n", linelen))
break;
gettimeofday(&tp, NULL);
curtime = tp.tv_sec + tp.tv_usec / 1e6;
if (curlen > 0 && curtime - times[curlen-1] > reset_time)
curlen = 0;
if (curlen == nsamples)
for (int i = 0; i < nsamples - 1; i++)
times[i] = times[i+1];
else
curlen++;
times[curlen-1] = curtime;
if (curlen < 2) {
printf("[Hit enter key one more time to start bpm computation...]");
continue;
}
printf(fmtstr, 60 * (curlen-1) / (curtime - times[0]));
}
free(line);
if (ferror(stdin))
warn("getline");
puts("Bye Bye!");
return (0);
}
static void
usage(void)
{
fprintf(stderr, "usage: %s [-p precision] [-r reset-time] [-s samples]\n", __progname);
exit(1);
}
J'ai pas vraiment l'habitude du C, donc c'était l'occasion de s'amuser un peu et essayer d'écrire un programme C sans segfaults :)
# Forum
Posté par Cheuteumi . Évalué à 9.
Ça me rappelle un truc sur le forum…
[^] # Re: Forum
Posté par Kangs . Évalué à 3.
Ce n'est que pur coïncidence ça devait arriver ;)
# Patch de portabilité
Posté par Thierry Thomas (site web personnel, Mastodon) . Évalué à 4.
Avec un gettext pour traduire les chaînes, ça serait mieux, mais l’exercice est laissé au lecteur…
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.