![](/img/trans.png)
[英]Function that includes string and float and I call it from main. But error
[英]Check if string from main is a valid float
我目前有以下代码。 但是,如果输入了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;
}
谢谢,这是我的解决方案。 由于我的项目设置方式,我只希望它是有效的float时返回true,否则返回false。
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;
}
要测试字符串是否为有效的浮点值,请使用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);
}
}
检查正确与完全解析一样困难,没有捷径。 我正在重做我的任意精度的lib,并且字符串解析仍然是一件令人讨厌的事情,所以我放下脚步,并(希望)适当地实现了有限状态机(承认有些捷径)。 近500行代码。 我已经使用简单的“ double”进行测试(不能使用,错误太大!),以便能够运行一些简单的测试。
请注意,我也允许八进制数,其二进制指数和指数标记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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.