我目前有以下代码。但是,如果输入3.1?43之类的东西,它仍然被标记为浮动。我知道我之后没有正确检查。但我不确定如何检查。
int floatNum(char *s) {
char *ptr = s;
char *ep = NULL;
long i = strtol(s, &ep, 0);
//check if converted to long int
if (!*ep) {
return false;
}
//Check if char
if (*ep == 'e' || *ep == 'E' || *ep == '.') {
return true;
}
return false;
}
谢谢你,这是我的解决方案。由于我的项目设置方式,我只希望它返回true,如果它是一个有效的浮点数,否则为假。
int floatNum(char *s) {
const char *ptr = s;
double x = strtod(ptr, &s);
//check if converted to long int
if (*s == 0) {
return true;
}
else {
return false;
}
return false;
}
答案 0 :(得分:1)
要测试字符串是否为有效浮点值,请使用strtod
。此函数使用可选的小数点和可选的指数说明符解析数字字符串(" e"或" E"):
char *p;
errno = 0;
double f = strtod(str,&p);
if (errno) {
printf("conversion failed");
}
if (strlen(str)==0) {
printf("empty string\n");
} else {
printf("f=%f\n", f);
if (*p == 0) {
printf("entire string valid\n");
} else {
printf("extra characters: %s\n", p);
}
}
答案 1 :(得分:0)
检查正确性与完全解析它一样困难,没有捷径。我正在重新处理我的任意精度库,其中一个仍然是一个非常混乱的东西是字符串解析,所以我设置并做了一个(希望)正确实现有限状态机(有一些快捷方式,被允许)。近500行代码。我已经使用简单的双重测试(不使用,错误太大了!),以便能够运行一些简单的测试。
请注意,我也允许八进制数字,使用相同的二进制指数和指数标记p
作为标准化的十六进制数字,strtod
不会。
哦,我很确定它有一些错误。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// for pow() only
#include <math.h>
#ifdef DEBUG
# define PUTS(x) puts(x)
#else
# define PUTS(x)
#endif
#define FSM_OK 1
#define FSM_ERROR 0
/*
EBNF (ISO 14977) for the real numbers this code should be able to treat correctly.
(* sign *)
sign = '+'|'-';
(* numbers starting with zero are octal, hence the special treatment for zero *)
zero = '0';
(* binary digit *)
bindig = '1';
(* binary integer *)
binint = bindig , [{(zero | bindig)}];
(* octal digit *);
octdig = bindig|'2'|'3'|'4'|'5'|'6'|'7';
(* octal integer *)
octint = octdig , [{(zero | octdig)}];
(* decimal digit *)
decdig = octdig|'8'|'9';
(* decimal integer *)
decint = decdig , [{(zero | decdig)}];
(* hexadecimal digit *)
hexdig = decdig |'A'|'B'|'C'|'D'|'E'|'F'|'a'|'b'|'c'|'e'|'f';
(* hexadecimal integer *)
hexint = hexdig , [{(zero | hexdig)}];
(* prefix for the base; inclusion of octal numbers made it interesting *)
prefix = '0';
(* Implementing only the four main bases has been deemed sufficient *)
binbase = prefix , ('B'|'b');
octbase = prefix , octdig;
hexbase = prefix , ('X'|'x');
(* decimal point *)
decpoint = '.';
(* exponents *)
expobin = ('P'|'p'), [sign], decint;
expodec = ('E'|'e'), [sign], decint;
(* thousands separator *)
(* tsep = ','|'\''|'_'; *)
(* "xyz", "xyz.", "xyz.zyx", ".zyx" *)
stubrealbin = binint | (binint, decpoint, [binint]) | (decpoint, binint);
stubrealoct = octint | (octint, decpoint, [octint]) | (decpoint, octint);
stubrealdec = decint | (decint, decpoint, [decint]) | (decpoint, decint);
stubrealhex = hexint | (hexint, decpoint, [hexint]) | (decpoint, hexint);
fullrealbin = [sign], binbase, stubrealbin, [expobin];
fullrealoct = [sign], octbase, stubrealoct, [expobin];
fullrealdec = [sign], stubrealdec, [expodec];
fullrealhex = [sign], hexbase, stubrealhex, [expobin];
(* "InF" and "NaN" should be case insensitive in praxi *)
real = ([sign], "Inf") | "NaN" | fullrealbin | fullrealoct | fullrealdec | fullrealhex;
Input characters (grouped for clarity. Case sensitive for brevity only!).
The input is case insensitive, so 'e', 'E', 'b', and 'B' are only
distinguishable by context: once you have hexdigits 'e' and 'b' are hexdigits
and a following sign must trigger an error
'0'
'1' = bin
'2'|'3'|'4'|'5'|'6'|'7' = oct
'8'|'9' = dec
'A'| |'C'|'D' |'F' = hex
'x'
'b'
'e'
'p'
'.'
'+' | '-' = sgn
Any other input character is not valid (state: ERROR), "Inf" and "NaN" get handled
elsewhere to keep things simple.
States
START
SIGN
PREFIX
DECPOINT
DECFRAC
BINBASE
OCTBASE
DECBASE
HEXBASE
BINFRAC
OCTFRAC
HEXFRAC
EXPOMARK
EXPOSIGN
EXPONENT
ERROR
Transition table
START '0' it is a prefix PREFIX
bin it is a binary digit DECBASE
oct it is an octal digit DECBASE
dec it is a decimal digit DECBASE
hex it is a hexadecimal digit HEXBASE
'x' cannot be ERROR
'b' it is a hexadecimal digit HEXBASE
'e' it is a hexadecimal digit HEXBASE
'p' cannot be ERROR
'.' a decimal point DECPOINT (!)
sgn a sign SIGN
SIGN '0' it is a prefix PREFIX
bin it is a binary digit DECBASE
oct it is an octal digit DECBASE
dec it is a decimal digit DECBASE
hex it is a hexadecimal digit HEXBASE
'x' cannot be ERROR
'b' it is a hexadecimal digit HEXBASE
'e' it is a hexadecimal digit HEXBASE
'p' cannot be ERROR
'.' a decimal point DECPOINT (!)
sgn a sign ERROR
PREFIX '0' zero OCTBASE
bin binary digit OCTBASE
oct octal digit OCTBASE
dec cannot be ERROR
hex cannot be ERROR
'x' hexadecimal number HEXBASE
'b' binary number BINBASE
'e' cannot be ERROR
'p' cannot be ERROR
'.' decimal point DECFRAC
sgn cannot be ERROR
The only place, that is still lingering in limbo is the decimal point. We
need to fork again, but we do not know in which base the integral part (if one
exists at all) is, so we still take "decimal" to be the default base.
DECPOINT '0' binary digit DECFRAC
bin binary digit DECFRAC
oct octal digit DECFRAC
dec decimal digit DECFRAC
hex hexadecimal digit HEXFRAC
'x' cannot be ERROR
'b' hexadecimal digit HEXFRAC
'e' hexadecimal digit HEXFRAC
'p' binary exponent EXPOMARK
'.' decimal point ERROR
sgn cannot be ERROR
A fractional part in decimal base is simple enough
DECFRAC '0' binary digit DECFRAC
bin binary digit DECFRAC
oct octal digit DECFRAC
dec decimal digit DECFRAC
hex cannot be ERROR
'x' cannot be ERROR
'b' cannot be ERROR
'e' exponent delimiter EXPOMARK
'p' cannot be ERROR
'.' cannot be ERROR
sgn cannot be ERROR
All other fractions need a base, so handle bases first
BINBASE '0' binary digit BINBASE
bin binary digit BINBASE
oct cannot be ERROR
dec cannot be ERROR
hex cannot be ERROR
'x' cannot be ERROR
'b' cannot be ERROR
'e' cannot be ERROR
'p' exponent delimiter EXPOMARK
'.' decimal point BINFRAC
sgn cannot be ERROR
OCTBASE '0' binary digit OCTBASE
bin binary digit OCTBASE
oct octal digit OCTBASE
dec cannot be ERROR
hex cannot be ERROR
'x' cannot be ERROR
'b' cannot be ERROR
'e' cannot be ERROR
'p' exponent delimiter EXPOMARK
'.' decimal point OCTFRAC
sgn cannot be ERROR
HEXBASE '0' binary digit HEXBASE
bin binary digit HEXBASE
oct octal digit HEXBASE
dec decimal digit HEXBASE
hex hexadecimal digit HEXBASE
'x' cannot be ERROR
'b' cannot be ERROR
'e' cannot be ERROR
'p' exponent delimiter EXPOMARK
'.' decimal point HEXFRAC
sgn cannot be ERROR
It is easy now to fill the gaps.
BINFRAC '0' binary digit BINFRAC
bin binary digit BINFRAC
oct cannot be ERROR
dec cannot be ERROR
hex cannot be ERROR
'x' cannot be ERROR
'b' cannot be ERROR
'e' cannot be ERROR
'p' exponent delimiter EXPOMARK
'.' cannot be ERROR
sgn cannot be ERROR
OCTFRAC '0' binary digit OCTFRAC
bin binary digit OCTFRAC
oct octal digit OCTFRAC
dec cannot be ERROR
hex cannot be ERROR
'x' cannot be ERROR
'b' cannot be ERROR
'e' cannot be ERROR
'p' exponent delimiter EXPOMARK
'.' cannot be ERROR
sgn cannot be ERROR
HEXFRAC '0' binary digit HEXFRAC
bin binary digit HEXFRAC
oct octal digit HEXFRAC
dec decimal digit HEXFRAC
hex hexadecimal digit HEXFRAC
'x' cannot be ERROR
'b' hexadecimal digit HEXFRAC
'e' hexadecimal digit HEXFRAC
'p' exponent delimiter EXPOMARK
'.' decimal point ERROR
sgn cannot be ERROR
The exponent is always encoded in decimal base (IEEE 754 (ISO/IEC 60559) sec. 5.12.3 for
the hexadecimal example)
EXPOMARK '0' binary digit EXPONENT
bin binary digit EXPONENT
oct octal digit EXPONENT
dec decimal digit EXPONENT
hex cannot be ERROR
'x' cannot be ERROR
'b' cannot be ERROR
'e' cannot be ERROR
'p' cannot be ERROR
'.' cannot be ERROR
sgn sign EXPOSIGN
EXPOSIGN '0' binary digit EXPONENT
bin binary digit EXPONENT
oct octal digit EXPONENT
dec decimal digit EXPONENT
hex cannot be ERROR
'x' cannot be ERROR
'b' cannot be ERROR
'e' cannot be ERROR
'p' cannot be ERROR
'.' cannot be ERROR
sgn sign ERROR
EXPONENT '0' binary digit EXPONENT
bin binary digit EXPONENT
oct octal digit EXPONENT
dec decimal digit EXPONENT
hex cannot be ERROR
'x' cannot be ERROR
'b' cannot be ERROR
'e' cannot be ERROR
'p' cannot be ERROR
'.' cannot be ERROR
sgn sign ERROR
ERROR nothing follows an error, only more ERROR
Nothing marking an end-state, it is just the end of the input buffer
ZERO '0'
BINDIG '1'
OCTDIG '2'|'3'|'4'|'5'|'6'|'7'
DECDIG '8'|'9'
HEXDIG 'A'| |'C'|'D' |'F'
PREHEX 'x'
PREBIN 'b'
EXPDEC 'e'
EXPBIN 'p'
DECPNT '.'
SGNCHR '+' | '-'
ZERO BINDIG OCTDIG DECDIG HEXDIG PREHEX PREBIN EXPDEC EXPBIN DECPNT SGNCHR
START PREFIX DECBASE DECBASE DECBASE HEXBASE ERROR HEXBASE HEXBASE ERROR DECPOINT SIGN
SIGN PREFIX DECBASE DECBASE DECBASE HEXBASE ERROR HEXBASE HEXBASE ERROR DECPOINT ERROR
PREFIX OCTBASE OCTBASE OCTBASE ERROR ERROR HEXBASE BINBASE ERROR ERROR DECFRAC ERROR
DECPOINT DECFRAC DECFRAC DECFRAC DECFRAC HEXFRAC ERROR HEXFRAC HEXFRAC EXPOMARK ERROR ERROR
DECFRAC DECFRAC DECFRAC DECFRAC DECFRAC ERROR ERROR ERROR EXPOMARK ERROR ERROR ERROR
BINBASE BINBASE BINBASE ERROR ERROR ERROR ERROR ERROR ERROR EXPOMARK BINFRAC ERROR
OCTBASE OCTBASE OCTBASE OCTBASE ERROR ERROR ERROR ERROR ERROR EXPOMARK OCTFRAC ERROR
DECBASE DECBASE DECBASE DECBASE ERROR ERROR ERROR ERROR EXPOMARK ERROR DECFRAC ERROR
HEXBASE HEXBASE HEXBASE HEXBASE HEXBASE HEXBASE ERROR ERROR ERROR EXPOMARK HEXFRAC ERROR
BINFRAC BINFRAC BINFRAC ERROR ERROR ERROR ERROR ERROR ERROR EXPOMARK ERROR ERROR
OCTFRAC OCTFRAC OCTFRAC OCTFRAC ERROR ERROR ERROR ERROR ERROR EXPOMARK ERROR ERROR
HEXFRAC HEXFRAC HEXFRAC HEXFRAC HEXFRAC HEXFRAC ERROR HEXFRAC HEXFRAC EXPOMARK ERROR ERROR
EXPOMARK EXPON'T EXPON'T EXPON'T EXPON'T ERROR ERROR ERROR ERROR ERROR ERROR EXPOSIGN
EXPOSIGN EXPON'T EXPON'T EXPON'T EXPON'T ERROR ERROR ERROR ERROR ERROR ERROR ERROR
EXPONENT EXPON'T EXPON'T EXPON'T EXPON'T ERROR ERROR ERROR ERROR ERROR ERROR ERROR
ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR ERROR
*/
#if !(defined _BSD_SOURCE || defined _DEFAULT_SOURCE || _POSIX_C_SOURCE >= 200112L)
# include <ctype.h>
static int strncasecmp(const char *s1, const char *s2, size_t n)
{
char c1 = 0;
char c2 = 0;
while (n--) {
c1 = tolower(*s1);
c2 = tolower(*s2);
if (c1 != c2) {
break;
}
if (c1 == '\0') {
break;
}
s1++;
s2++;
}
return (int) (c1 - c2);
}
#endif
#ifdef _MSC_VER
#define strncasecmp(x,y,z) _strnicmp(x,y,z)
#endif
enum fsm_input {
ZERO, // '0'
BINDIG, // '1'
OCTDIG, // '2'|'3'|'4'|'5'|'6'|'7'
DECDIG, // '8'|'9'
HEXDIG, // 'A' |'C'|'D' |'F'
PREHEX, // 'x'
PREBIN, // 'b'
EXPDEC, // 'e'
EXPBIN, // 'p'
DECPNT, // '.'
SGNCHR, // '+' | '-'
OTHER
};
enum fsm_states {
START,
SIGN,
PREFIX,
DECPOINT,
DECFRAC,
BINBASE,
OCTBASE,
DECBASE,
HEXBASE,
BINFRAC,
OCTFRAC,
HEXFRAC,
EXPOMARK,
EXPOSIGN,
EXPONENT,
ERROR
};
#ifdef DEBUG
static const char *st2str[16] = {
"START",
"SIGN",
"PREFIX",
"DECPOINT",
"DECFRAC",
"BINBASE",
"OCTBASE",
"DECBASE",
"HEXBASE",
"BINFRAC",
"OCTFRAC",
"HEXFRAC",
"EXPOMARK",
"EXPOSIGN",
"EXPONENT",
"ERROR"
};
#endif
// transition-table
static int fsm_table[16][11] = {
{PREFIX, DECBASE, DECBASE, DECBASE, HEXBASE, ERROR, HEXBASE, HEXBASE, ERROR,
DECPOINT, SIGN},
{PREFIX, DECBASE, DECBASE, DECBASE, HEXBASE, ERROR, HEXBASE,
HEXBASE, ERROR, DECPOINT, ERROR},
{OCTBASE, OCTBASE, OCTBASE, ERROR, ERROR, HEXBASE, BINBASE, ERROR, ERROR,
DECFRAC,
ERROR},
{DECFRAC, DECFRAC, DECFRAC, DECFRAC, HEXFRAC, ERROR, HEXFRAC, HEXFRAC,
EXPOMARK, ERROR, ERROR},
{DECFRAC, DECFRAC, DECFRAC, DECFRAC, ERROR, ERROR, ERROR, EXPOMARK, ERROR,
ERROR, ERROR},
{BINBASE, BINBASE, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, EXPOMARK,
BINFRAC, ERROR},
{OCTBASE, OCTBASE, OCTBASE, ERROR, ERROR, ERROR, ERROR, ERROR, EXPOMARK,
OCTFRAC, ERROR},
{DECBASE, DECBASE, DECBASE, ERROR, ERROR, ERROR, ERROR, EXPOMARK, ERROR,
DECFRAC, ERROR},
{HEXBASE, HEXBASE, HEXBASE, HEXBASE, HEXBASE, ERROR, ERROR, ERROR, EXPOMARK,
HEXFRAC, ERROR},
{BINFRAC, BINFRAC, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, EXPOMARK, ERROR,
ERROR},
{OCTFRAC, OCTFRAC, OCTFRAC, ERROR, ERROR, ERROR, ERROR, ERROR, EXPOMARK,
ERROR, ERROR},
{HEXFRAC, HEXFRAC, HEXFRAC, HEXFRAC, HEXFRAC, ERROR, HEXFRAC, HEXFRAC,
EXPOMARK, ERROR, ERROR},
{EXPONENT, EXPONENT, EXPONENT, EXPONENT, ERROR, ERROR, ERROR, ERROR, ERROR,
ERROR, EXPOSIGN},
{EXPONENT, EXPONENT, EXPONENT, EXPONENT, ERROR, ERROR, ERROR, ERROR, ERROR,
ERROR, ERROR},
{EXPONENT, EXPONENT, EXPONENT, EXPONENT, ERROR, ERROR, ERROR, ERROR, ERROR,
ERROR, ERROR},
{ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR, ERROR}
};
#include <ctype.h>
static int check_type(char c)
{
int type;
switch (tolower(c)) {
case '0':
type = ZERO;
break;
case '1':
type = BINDIG;
break;
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
type = OCTDIG;
break;
case '8':
case '9':
type = DECDIG;
break;
case 'a':
case 'c':
case 'd':
case 'f':
type = HEXDIG;
break;
case 'x':
type = PREHEX;
break;
case 'b':
type = PREBIN;
break;
case 'e':
type = EXPDEC;
break;
case 'p':
type = EXPBIN;
break;
case '.':
type = DECPNT;
break;
case '+':
case '-':
type = SGNCHR;
break;
default:
type = OTHER;
break;
};
return type;
}
// some variables to hold the relevant parts of a real number
static int main_sign = 1;
static int expo_sign = 1;
static double integral_part = 0.0;
static double fractional_part = 0.0;
static int hex_frac = 0;
static int dec_frac = 0;
static int oct_frac = 0;
static int bin_frac = 0;
static int exponent_part = 0;
// flags with both a boolean and a numerical value
// prob. not the best idea but simple
#define DECIMAL_EXP 10
#define BINARY_EXP 2
static int exponent_binordec = 0;
// assuming ASCII. Full map for more bases in the future.
// Far future.
static const char digit_map[] = {
-1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x07
-1, -1, -1, -1, -1, -1, -1, -1, // 0x08-0x0f
-1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x17
-1, -1, -1, -1, -1, -1, -1, -1, // 0x18-0x1f
-1, -1, -1, -1, -1, -1, -1, -1, // 0x20-0x27
-1, -1, 1, -1, -1, -1, -1, -1, // 0x28-0x2f '+' = 0x2b, '-' = 0x2d
0, 1, 2, 3, 4, 5, 6, 7, // 0x30-0x37
8, 9, -1, -1, -1, -1, -1, -1, // 0x38-0x3F
-1, 10, 11, 12, 13, 14, 15, -1, // 0x40-0x47
-1, -1, -1, -1, -1, -1, -1, -1, // 0x48-0x4f
-1, -1, -1, -1, -1, -1, -1, -1, // 0x50-0x57
-1, -1, -1, -1, -1, -1, -1, -1, // 0x58-0x5f
-1, 10, 11, 12, 13, 14, 15, -1, // 0x60-0x67
-1, -1, -1, -1, -1, -1, -1, -1, // 0x68-0x6f
-1, -1, -1, -1, -1, -1, -1, -1, // 0x70-0x77
-1, -1, -1, -1, -1, -1, -1, -1 // 0x78-0x7f
};
static int fsm(char input, int *state)
{
int res = FSM_OK;
input = tolower(input);
#ifdef DEBUG
printf("INPUT: %c [0x%2x] (%d) STATE: %-10s\n", input, input,digit_map[+input],st2str[*state]);
#endif
switch (*state) {
case START:
fprintf(stderr,
"Something is messed up in quite some hefty way and form!\n");
exit(EXIT_FAILURE);
case SIGN:
main_sign = digit_map[+input];
break;
case PREFIX:
// not used
break;
case DECPOINT:
// not used
break;
case DECBASE:
integral_part *= 10.0;
integral_part += digit_map[+input];
break;
case BINBASE:
integral_part *= 2.0;
integral_part += digit_map[+input];
break;
case OCTBASE:
integral_part *= 8.0;
integral_part += digit_map[+input];
break;
case HEXBASE:
if (input == 'x') {
break;
}
integral_part *= 16.0;
integral_part += digit_map[+input];
break;
case BINFRAC:
if (input == '.') {
break;
}
fractional_part *= 2.0;
fractional_part += digit_map[+input];
bin_frac++;
break;
case OCTFRAC:
if (input == '.') {
break;
}
fractional_part *= 8.0;
fractional_part += digit_map[+input];
oct_frac++;
break;
case DECFRAC:
if (input == '.') {
break;
}
fractional_part *= 10.0;
fractional_part += digit_map[+input];
dec_frac++;
break;
case HEXFRAC:
if (input == '.') {
break;
}
fractional_part *= 16.0;
fractional_part += digit_map[+input];
hex_frac++;
break;
case EXPOMARK:
exponent_binordec = (input == 'e') ? DECIMAL_EXP : BINARY_EXP;
break;
case EXPOSIGN:
expo_sign = digit_map[+input];
break;
case EXPONENT:
exponent_part *= 10;
exponent_part += digit_map[+input];
break;
case ERROR:
fprintf(stderr, "ERROR state reached\n");
exit(EXIT_FAILURE);
// "Run in circles, scream and shout!"
// Infantry Journal, Vol. 35, p. 396, United States Infantry Association, 1929
// Or was it Herman Wouk? The Caine Mutiny? No, that would be 1951 and too late.
break;
default:
fprintf(stderr, "Unexpected state with input %c\n", input);
*state = ERROR;
res = FSM_ERROR;
break;
}
return res;
}
static char *trim_both(char *s)
{
char *end,*p;
p = s;
while (isspace(*p)) {
p++;
}
if (*p == '\0') {
return p;
}
end = p + strlen(p) - 1;
while (end > p && isspace(*end)) {
end--;
}
*(end + 1) = '\0';
return p;
}
static int str2dbl(char *s, double *d)
{
int cur_state = START;
int type;
int res;
s = trim_both(s);
if(*s == '\0'){
// empty input, would an error be better?
*d = 0.0;
return FSM_OK;
}
if(*s == '0' && *(s+1) == '\0'){
*d = 0.0;
return FSM_OK;
}
if (!strncasecmp(s, "-inf", 4)) {
*d = -INFINITY;
return FSM_OK;
}
if (!strncasecmp(s, "+inf", 4) || !strncasecmp(s, "inf", 3)) {
*d = INFINITY;
return FSM_OK;
}
if (!strncasecmp(s, "-nan", 4) || !strncasecmp(s, "+nan", 4) || !strncasecmp(s, "nan", 3) ) {
*d = NAN;
return FSM_OK;
}
while (*s != '\0') {
type = check_type(*s);
if (type == OTHER) {
fprintf(stderr, "OTHER: %c", *s);
return FSM_ERROR;
}
cur_state = fsm_table[cur_state][type];
res = fsm(*s, &cur_state);
if (res != FSM_OK) {
break;
}
s++;
}
printf("exp; %d, intp: %.20g, fracp: %.20g\n", exponent_part, integral_part,
fractional_part);
// The following will work with arbitray precision in production, use of
// a "double" is just for testing and not for real use. The error is
// larger than one ulp in way too many times
// the integral part needs no treatment, yet.
*d += integral_part;
// the fractional part needs to be shifted by the base to the right
if (hex_frac > 0) {
fractional_part /= pow(16, hex_frac);
} else if (dec_frac > 0) {
fractional_part /= pow(10, dec_frac);
} else if (oct_frac > 0) {
fractional_part /= pow(8, oct_frac);
} else if (bin_frac > 0) {
fractional_part /= pow(2, bin_frac);
}
printf("fracp: %.20g\n", fractional_part);
*d += fractional_part;
// (exponent_binordec != 0) also means that there is an exponent in the first place
if (exponent_binordec) {
if (expo_sign >= 0) {
*d *= pow(exponent_binordec, exponent_part);
} else {
*d /= pow(exponent_binordec, exponent_part);
}
}
*d *= main_sign;
return FSM_OK;
}
int main(int argc, char **argv)
{
int res;
char *input, *endptr;
double out, libc;
if (argc != 2) {
fprintf(stderr, "Usage: %s float\n", argv[0]);
exit(EXIT_FAILURE);
}
input = malloc(strlen(argv[1]) + 1);
if (input == NULL) {
fprintf(stderr, "Malloc failed to allocate a measly %zu bytes\n",
strlen(argv[1]) + 1);
exit(EXIT_FAILURE);
}
strcpy(input, argv[1]);
// all checks ommited!
libc = strtod(input, &endptr);
printf("\nINPUT: %s\t%g\t%s\n\n", input, libc, endptr);
out = 0.0;
res = str2dbl(input, &out);
printf
("fsm returned %d and the result (if any) is: \n\tinp: %s\n\town: %.20g\n\tlibc: %.20g\n",
res, trim_both(input) ,out, libc);
free(input);
exit(EXIT_SUCCESS);
}