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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
/* misc.c */
/* Written by Andrew Makhorin <mao@gnu.org>, October 2015. */
#include <ctype.h>
#include <float.h>
#include <limits.h>
#include <stdlib.h>
#include "misc.h"
/***********************************************************************
* NAME
*
* str2int - convert character string to value of int type
*
* SYNOPSIS
*
* #include "misc.h"
* int str2int(const char *str, int *val);
*
* DESCRIPTION
*
* The routine str2int converts the character string str to a value of
* integer type and stores the value into location, which the parameter
* val points to (in the case of error content of this location is not
* changed).
*
* RETURNS
*
* The routine returns one of the following error codes:
*
* 0 - no error;
* 1 - value out of range;
* 2 - character string is syntactically incorrect. */
int str2int(const char *str, int *val_)
{ int d, k, s, val = 0;
/* scan optional sign */
if (str[0] == '+')
s = +1, k = 1;
else if (str[0] == '-')
s = -1, k = 1;
else
s = +1, k = 0;
/* check for the first digit */
if (!isdigit((unsigned char)str[k]))
return 2;
/* scan digits */
while (isdigit((unsigned char)str[k]))
{ d = str[k++] - '0';
if (s > 0)
{ if (val > INT_MAX / 10)
return 1;
val *= 10;
if (val > INT_MAX - d)
return 1;
val += d;
}
else /* s < 0 */
{ if (val < INT_MIN / 10)
return 1;
val *= 10;
if (val < INT_MIN + d)
return 1;
val -= d;
}
}
/* check for terminator */
if (str[k] != '\0')
return 2;
/* conversion has been done */
*val_ = val;
return 0;
}
/***********************************************************************
* NAME
*
* str2num - convert character string to value of double type
*
* SYNOPSIS
*
* #include "misc.h"
* int str2num(const char *str, double *val);
*
* DESCRIPTION
*
* The routine str2num converts the character string str to a value of
* double type and stores the value into location, which the parameter
* val points to (in the case of error content of this location is not
* changed).
*
* RETURNS
*
* The routine returns one of the following error codes:
*
* 0 - no error;
* 1 - value out of range;
* 2 - character string is syntactically incorrect. */
int str2num(const char *str, double *val_)
{ int k;
double val;
/* scan optional sign */
k = (str[0] == '+' || str[0] == '-' ? 1 : 0);
/* check for decimal point */
if (str[k] == '.')
{ k++;
/* a digit should follow it */
if (!isdigit((unsigned char)str[k]))
return 2;
k++;
goto frac;
}
/* integer part should start with a digit */
if (!isdigit((unsigned char)str[k]))
return 2;
/* scan integer part */
while (isdigit((unsigned char)str[k]))
k++;
/* check for decimal point */
if (str[k] == '.') k++;
frac: /* scan optional fraction part */
while (isdigit((unsigned char)str[k]))
k++;
/* check for decimal exponent */
if (str[k] == 'E' || str[k] == 'e')
{ k++;
/* scan optional sign */
if (str[k] == '+' || str[k] == '-')
k++;
/* a digit should follow E, E+ or E- */
if (!isdigit((unsigned char)str[k]))
return 2;
}
/* scan optional exponent part */
while (isdigit((unsigned char)str[k]))
k++;
/* check for terminator */
if (str[k] != '\0')
return 2;
/* perform conversion */
{ char *endptr;
val = strtod(str, &endptr);
if (*endptr != '\0')
return 2;
}
/* check for overflow */
if (!(-DBL_MAX <= val && val <= +DBL_MAX))
return 1;
/* check for underflow */
if (-DBL_MIN < val && val < +DBL_MIN)
val = 0.0;
/* conversion has been done */
*val_ = val;
return 0;
}
/* eof */
|