forked from regehr/str2long_contest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bernd.c
55 lines (51 loc) · 1.02 KB
/
bernd.c
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
#include "str2long.h"
long str2long_bernd(const char *s)
{
int plus;
// LONG_(MAX|MIN) w/o LSD; equal but the optimizer should do his job
unsigned long nmax;
// LSD of LONG_(MAX|MIN); used for possible overflow detection
unsigned cmax;
unsigned long n = 0;
// return value
long r;
// ^-?
if (*s == '-') {
++s;
plus = 0;
nmax = -(LONG_MIN / 10);
cmax = -(LONG_MIN + LONG_MIN / -10 * 10);
} else {
plus = 1;
nmax = LONG_MAX / 10;
cmax = LONG_MAX - LONG_MAX / 10 * 10;
}
// [0-9]
if (*s < '0' || *s > '9') {
goto invalid;
}
for (;;) {
unsigned c = *s - '0';
// resulting integer is representable as a long
if (n < nmax || (n == nmax && c <= cmax)) {
n = n * 10 + c;
} else {
goto invalid;
}
++s;
// \0$
if (*s == '\0') {
break;
}
// [0-9]+
if (*s < '0' || *s > '9') {
goto invalid;
}
}
r = n;
return plus ? r : -r;
// otherwise set error to 1 and return any value
invalid:
error = 1;
return 0;
}