1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| #include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int toui64_scanf(uint64_t *num, const char *s) {
int c;
uint64_t n;
const int ret = sscanf(s, "%" SCNu64 "%n", &n, &c);
if (ret != 1)
return 1;
if ((size_t)c != strlen(s))
return 2;
*num = n;
return 0;
}
int toui64_strtoul(uint64_t *num, const char *s) {
_Static_assert(sizeof(unsigned long long) <= sizeof(uint64_t), "possible overflow");
errno = 0;
char *end;
const uint64_t n = (uint64_t)strtoull(s, &end, 10);
if (errno == ERANGE)
return 1;
if (end - s != (ssize_t)strlen(s))
return 2;
*num = n;
errno = 0;
return 0;
}
void dump(int (*toui64)(uint64_t *, const char *), const char *from[], size_t size) {
uint64_t u64 = UINT64_C(0);
for (size_t i = 0; i < size; ++i) {
const int ret = toui64(&u64, from[i]);
printf(" %10s: ", from[i]);
if (ret)
printf("parsing failed\n");
else
printf("successfully parsed %" PRIu64 "\n", u64);
}
}
const char *test[] = {
"64junk",
"zzz64junk",
";64",
"..64.2",
"3.141592",
"18",
"abc",
"-18",
"-18a42"
};
int main(int argc, char *argv[]) {
(void)argc; (void)argv;
puts("sscanf:");
dump(toui64_scanf, test, sizeof test / sizeof *test);
puts("\nstrtoull:");
dump(toui64_strtoul, test, sizeof test / sizeof *test);
return 0;
} |
Partager