448,669 Members | 1,634 Online
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,669 IT Pros & Developers. It's quick & easy.

# atof equivalent for long double in standard ANSI C?

 P: n/a Greetings again, I will burden the group with yet another tenderfoot question, but since conscientious googling hasn't yield a lucid answer I thought I would risk the shortcut of asking here since I am so very keen to learn to code in standard C. Could someone tell me the long double equivalent of atof()? I was getting some peculiar behaviour in a little bit of math code I am working with. I thought the problem was in the math algorithms, but not so--it is the input interface. I get my desired numeric input with gets(), put it to a character string txt, and put it into a long double variable x with x = atof(x). But a little testing as revealed that when the string txt actually represents a numeral outside of the double range, atof() translates it not to its long double equivalent, but inf. For example the entered text string 1e500 is not converted to the long double quantity 1.0E500L, but, as I said, inf. What is the appropriate ANSI C approach to this? I am aware of non-standard functions such as atold() or _atold() in other compilers, but I want to be good boy and speak standard C. Many thanks for your patient assistance. Les Aug 9 '06 #1
5 Replies

 P: n/a "lcw1964"

 P: n/a "lcw1964"

 P: n/a Use sscanf() instead. It's a lot better to boot. Aug 9 '06 #4

 P: n/a "Dann Corbit" San Diego Supercomputer Center <* We must do something. This is something. Therefore, we must do this. Aug 9 '06 #5

 P: n/a "Keith Thompson" Use sscanf() instead.It's a lot better to boot. Instead of what? Please provide context. sscanf() invokes undefined behavior if the input string cannot be represented in the specified type. Good point. Maybe something like this could be used as a starting point. It's not very robust for error checking, but it could easily be improved to a useful state. #include #include typedef enum {FALSE=0,TRUE=1} BOOL; BOOL asciiToLongDouble(const char * const numberString, long double *pldNumber) { /* Convert ASCII string to long double data type. */ long double ldReturnValue; long double ldOneTenth = 0.1e0L; long double ldTen = 10.0e0L; long double ldZero = 0.0e0L; BOOL bFoundDigits = FALSE; BOOL bIsNegative = FALSE; const char * pszNum; /* Check pointers. */ if (pldNumber == NULL) { return FALSE; } if (numberString == NULL) { *pldNumber = ldZero; return FALSE; } ldReturnValue = ldZero; pszNum = numberString; /* Advance past white space. */ while ((*pszNum == ' ') || (*pszNum == '\t')) pszNum++; /* Check for sign. */ if (*pszNum == '+') pszNum++; else if (*pszNum == '-') { bIsNegative = TRUE; pszNum++; } /* Calculate the integer part. */ while ((*pszNum >= '0') && (*pszNum <= '9')) { bFoundDigits = TRUE; ldReturnValue *= ldTen; ldReturnValue += *pszNum - '0'; pszNum++; } /* Calculate the fractional part. */ if (*pszNum == '.') { long double ldScale = ldOneTenth; pszNum++; while ((*pszNum >= '0') && (*pszNum <= '9')) { bFoundDigits = TRUE; ldReturnValue += ldScale * (*pszNum - '0'); pszNum++; ldScale *= ldOneTenth; } } /* If this is not a number, return error condition. */ if (!bFoundDigits) { *pldNumber = ldZero; return FALSE; } /* If all digits of integer & fractional part are 0, return 0.0 */ if (ldReturnValue == ldZero) { *pldNumber = ldZero; return TRUE; /* Not an error condition, and no need to continue. */ } /* Process the exponent (if any) */ if ((*pszNum == 'e') || (*pszNum == 'E')) { BOOL bIsNegativeExponent = FALSE; BOOL bGetOut = FALSE; long lIndex; long lExponent = 0; long double ldTooBigTest = LDBL_MAX*ldOneTenth; long double ldTooSmallTest= LDBL_MIN*ldTen; pszNum++; if (*pszNum == '+') pszNum++; else if (*pszNum == '-') { pszNum++; bIsNegativeExponent = TRUE; } /* What if the exponent is empty? Return the current result. */ if ((*pszNum < '0') || (*pszNum '9')) { if (bIsNegative) ldReturnValue = -ldReturnValue; *pldNumber = ldReturnValue; return (TRUE); } /* Convert char exponent to number <= 2 billion. */ while ((*pszNum >= '0') && (*pszNum <= '9') && (lExponent < 200000000)) { lExponent *= 10; lExponent += *pszNum - '0'; pszNum++; } /* Compensate for the exponent. */ if (bIsNegativeExponent) { for (lIndex = 1; lIndex <= lExponent && !bGetOut; lIndex++) if (ldReturnValue < ldTooSmallTest) { bGetOut = TRUE; ldReturnValue = LDBL_MIN; } else ldReturnValue *= ldOneTenth; } else for (lIndex = 1; lIndex <= lExponent && !bGetOut; lIndex++) { if (ldReturnValue ldTooBigTest) { bGetOut = TRUE; ldReturnValue = LDBL_MAX; } else ldReturnValue *= ldTen; } } if (bIsNegative) ldReturnValue = -ldReturnValue; *pldNumber = ldReturnValue; return (TRUE); } -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <*> We must do something. This is something. Therefore, we must do this. Aug 9 '06 #6

### This discussion thread is closed

Replies have been disabled for this discussion.