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 */
|