How to limits value user input < INT_MAX in C - c

#include <stdio.h>
#include <stdlib.h>
#include<limits.h>
int getInt() {
int n, check;
char ch;
do {
fflush(stdin);
printf("Enter positive integer n = ");
check = scanf("%d%c", &n, &ch);
if ((check == 2)&&(ch == '\n')) {
if (n > INT_MAX) {
printf("Invalid number\n");
} else if (n < 0) {
printf("n must > 0");
} else {
break;
}
} else printf("Invalid number\n");
} while (1);
return n;
}
int main(int argc, char** argv) {
int n;
n = getInt();
}
My code accepts user input number in range 0 to INT_MAX.
When I input -1, program displays "n must > 0".
But when I input '77777777777777777777777777777777' (> INT_MAX) program still displays "n must > 0", and not 'Invalid number'.

With out of range input in scanf("%d%c", &n, &ch);, the behavior is undefined.
Instead read a line of input with fgets(), then quality using strtol()
for (;;) {
char buf[100];
if (fgets(buf, sizeof buf, stdin) == NULL) {
printf("No more input\n");
return -1;
}
errno = 0;
char *endptr;
long val = strtol(buf, &endptr, 0);
// No numeric conversion done at all?
// Numeric input outside long range?
// Junk after the numeric text?
if (buf == endptr || errno == ERANGE || *endptr != '\n') {
printf("Invalid number\n");
continue;
}
// Outside int range?
if (val < INT_MIN || val > INT_MAX) {
printf("Invalid number\n");
continue;
}
if (val < 0) {
printf("n must > 0");
continue;
}
n = (int) val;
}
I'd recommend a re-usable int get_int(int *val) helper function.

First you need to understand how variables stores data.
In 64 bits architeture, the int type have 4 bytes (either the C long type, regardless architeture), so can store the following values:
00000000 00000000 00000000 00000000 = 0 (decimal value)
01111111 11111111 11111111 11111111 = 2,147,483,647 (decimal value)
11111111 11111111 11111111 11111111 = 4,294,967,294 (unsigned decimal value)
11111111 11111111 11111111 11111111 = -1 (signed decimal value)
Note that the integer types can use the Most Significant Bit (MSB) to represent signal (0 to positive, 1 to negative) using a modular aritmetic.
For more details about integer signal: https://en.wikipedia.org/wiki/Two%27s_complement
So, to store decimal data higher than INT_MAX, you need more bytes than you have using int type. A good way, compatible with 64 bits architeture, is using long long type.
Long long type uses 8 bytes, so can stores value higher than INT_MAX.
You will have to declare:
long long n;
And use scanf() like this:
scanf("%lld%c", &n, &ch);
Your fflush(stdin) have to be after the scanf(), because if your aplication break the loop after the scanf() and before have reached the fflush() instruction you may have problem in further input handling. Like this:
check = scanf("%lld%c", &n, &ch);
fflush(stdin);
However, some developers disapprove use fflush() in stdin, so this is an alternative (a bit more complex) using getch() accepting only numbers and converting char* to long long using strtoll():
char c = 0;
char* input_number = malloc(32);
int accepted_chars = 0;
memset(input_number, 0, 32);
while(c != '\r'){ //loop until user press ENTER
c = getch();
//receive numbers keys pressed
if(c >= '0' && c <= '9'){
*(input_number + accepted_chars) = c;
accepted_chars ++;
printf("%c", c);
}
//receive backspace key pressed
if(c == 8){
if(accepted_chars > 0){ //don't do nothing if there is nothing to clear
accepted_chars --;
*(input_number + accepted_chars) = 0;
printf("\b");
printf(" ");
printf("\b");
}
}
}
printf("\n");
char* endptr;
n = strtoll(input_number, &endptr, 10); //convert string in base 10 (decimal) long long type

Just checking
int x;
...
if (x > INT_MAX) { ...
is something that will never work. If an int value cannot have values above INT_MAX then it is impossible that you can ever get x stored a value higher than that. So that if will become always false and the compiler will probably eliminate all the code you put inside that if's then block.
Normal reading routines like scanf() actually limit the input to a value in the range of allowable values.
But if you want to read and build the number yourself, you need to ancitipate the possibility, and use better triggers to stop.
For example, checking that the number is above (INT_MAX - 9) / 10 will tell you that if you try to add another digit to it, you'll run the risk of overflowing the integer, when you add the digit. You can simply stop there and don't continue reading, but if you want to read one more digit (who knows, it could be a 0 and that doesn't hurt, you'll have to check for something like
int digit;
int the_integer = 0;
while ( (digit = fgetchar(stdin)) != EOF
&& isdigit(digit)
&& the_integer <= (INT_MAX - (digit - '0')))
{
the_integer *= 10;
the_integer += digit;
} /* while */
if (digit != EOF && isdigit(digit)) {
/* x > (INT_MAX - (digit - '0')) */
/* this is necessary, as if you don't do it, you'll lose
* the next character to read. */
unput(digit, stdin);
}
This way you'll check the number x before multiplying it by 10 and adding the digit - '0' value.

As pointed out in the comments section, there is no point in testing if n > INT_MAX, as n is of type int and therefore by definition unable to represent any value larger than INT_MAX.
A simple, flexible way of checking the size of a number provided as user input would be to read it in as a string and count the number of digits by using the function strlen and possibly also isdigit to count the actual digits.
However, when dealing with potentially large numerical values as user input, it is usually better to first read this input into a data type that is larger than int and do your range checks with this larger data type. After you are satisfied that the number is in the desired range, you can convert it to the smaller int data type. Although the ISO C standard does not guarantee that a long long is larger than an int, this is a reasonable assumption and it is the case on all compilers that I am aware of. However, on some platforms (including 64-bit Windows), the data type long is the same size as int, so a long cannot be reliably used for this on all platforms.
Probably the easiest solution to your problem would be to use the function strtol or strtoll. Using these functions has the advantage that you don't need a larger data type and it explicitly tells you if a number is out of range, by setting errno to ERANGE. However, these functions only support the data types long and long long, but not int. Therefore, if you want to use int, you will have to do your range checks manually before you convert it.

Related

Why does my do while statement work this way?

This code works but I'm confused on how. I was writing this program for a class. I needed to only accept positive integers. I created a do...while loop to do so. My question is, why does this code only check the correct way when I have the or "||" in there and not the "&&". I would assume it would need to test both to make sure that it is taking in the correct integers.
#include <stdio.h>
#include <math.h>
main()
{
float i, number, sum=0;
int k;
do
{
printf( "Sumation Calculator\n" );
printf( "Enter number: " );
scanf( "%f", &number );
k = number;
}while(number < 1 || k != number);
while (i <= number)
{
sum = sum + i;
i++;
}
printf( "The summation of %f is %f.\n", number, sum);
return 0;
}
You have two requirements:
That the value be positive
That the value be an integer (no fractional/decimal component)
Your test needs to be true if you need to ask again, not if you have the correct value; testing for the correct value would involve two "positive tests" joined by &&, but you want to test for incorrect values, which means you want to reject if either "negative test" fails. You need to ask again if either condition is violated. If you test number < 1 && k != number that means "I need to ask again only if it's both not positive and non-integer", so 0 (which is not positive, but is an integer) would be accepted, as would 1.5 (which is not an integer, but is positive).
Testing number < 1 || k != number correctly says "I need to ask again if it's not positive or it's not an integer"; if it fails either criterion, you loop and ask again.
Others have explain OP's logic issue.
why does this code only check the correct way when I have the or "||" in there ...
Code is not corrct with only that change. It has too many problems - many of which can be identified by enabling all compiler warnings.
scanf( "%f", &number); will round numeric input text to a float, losing non-integer detection.
k = number; is undefined behavior when number is much outisde int range.
i <= number is bad as i is not yet assigned.
The return value of scanf( "%f", &number ) is not tested for success.
Below is a more robust way to test for input of only positive integers.
I needed to only accept positive integers.
Best to:
Read the line of text into a string.
Parse it as an integer with strtol().
Test for range, etc.
char buf[100];
while (fgets(buf, sizeof buf, stdin)) {
char *endptr;
errno = 0;
long value = strtol(buf, &endptr, 10);
if (buf == endtpr) {
puts("No conversion");
continue;
}
if (errno) {
puts("Out of long range");
continue;
}
if (*endptr != '\n') {
puts("Non-numeric trailing junk");
continue;
}
if (val < 0) {
puts("Only positive values");
continue;
}
// Success, now do something with val
}
This will fail input like "123.0" or "1e2" - which are both whole numbers. Additional code could handle most of those cases.
do
{
...
k = number; // now k == number
} while (number < 1 || k != number);
} while (number < 1 || FALSE);
} while (number < 1);
As you see the condition is not needed.
What is the initial value of i?
By the way it is "Summation" I believe.

How to make this code scanf a sequence of integers until I enter negative integer? I thaught %u won't take negative integers

I want that while loop ends when I enter number that's not unsigned
(lower than zero), but that just not happen until I type some symbol
on my keyboard (letter etc.) and then debugging stops. Can anyone help
me, please?
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define ALLOC_CHECK(p) if (!(p)) puts("Neuspesna alokacija"), exit(1)
bool is_palindrome(unsigned x)
{
unsigned i, j, n = 8 * sizeof x; // Broj bita unsigned x
for (i = 1 << n-1, j = 1; i > j; i >>= 1, j <<= 1)
if (!(x & i) != !(x & j)) // Proverava da li su biti logicki razliciti
return false;
return true;
}
int main(void)
{
unsigned size = 10, n = 0, i;
unsigned *a = malloc(size * sizeof(*a));
ALLOC_CHECK(a);
puts("Enter a sequence of integers:");
while (scanf("%u", &a[n++]))
if (n == size) {
size *= 2;
a = realloc(a, size * sizeof(*a));
ALLOC_CHECK(a);
}
// Moze i da se skrati na pravu duzinu sa a = realloc(a, n * sizeof(*a));
puts("Binary palindromes are:");
for (i = 0; i < n; i++)
if (is_palindrome(a[i]))
printf("%u ", a[i]);
free(a);
}
I want that while loop ends when I enter number that's not unsigned (lower than zero).
Think of input as text that needs testing.
// input examples
"-12345678901234567890" should stop the loop
"-1" should stop the loop
"123" should be read successfully as an `unsigned`
" +123" should be read successfully as an `unsigned`
"12345678901234567890" is outside `unsigned` range and results are TBD
"abc" is not `unsigned`, so should stop loop.
"" is not `unsigned`, so should stop loop.
" 123 xyz" is not `unsigned`, so should stop loop.
etc.
Using fgets() is more robust, yet let us try a scanf() solution.
I thought %u won't take negative integers
scanf("%u",... will take input like "-123" and convert that to an unsigned. So code is needed to detect a -
Following will not detect overflow nor white-space only lines nor consume text after a -.
// consume leading white space, look for `-` (various approaches)
int n = 0;
scanf(" -%n", &n);
if (n > 0) exit_loop(); // `-` found
unsigned x;
if (scanf("%u", &x) != 1) exit_loop(); // non numeric input
// Success, use `x`
...
In an ugly while loop that use " %1[-]" to look for a -
char minus[2];
// while a search for `-` failed and `unsigned` succeeded
while (scanf(" %1[-]", minus) != 1 && scanf("%u", &x) == 1) {
...
}
As pointed out by #AnT, a negative value is a valid input for scanf("%u" ...
I suggest to use a signed type long in conjunction with fgets and strtol in order to catch negative values:
puts("Enter a sequence of integers:");
char str[32], *ptr;
long val;
while (fgets(str, sizeof str, stdin)) {
val = strtol(str, &ptr, 10);
if ((*ptr == '\n') && (val >= 0)) {
a[n++] = strtoul(str, NULL, 10);
} else break;
if (n == size) {
size *= 2;
a = realloc(a, size * sizeof(*a));
ALLOC_CHECK(a);
}
}
Negative numbers are considered valid input for %u.
This is what C90 says about %u:
Matches an optionally signed decimal integer, whose format is the same as expected for the subject sequence of the strtoul function with the value 10 for the base argument. The corresponding argument shall be a pointer to unsigned integer.
And it says this about strtoul():
the expected form of the subject sequence is a sequence of letters and digits representing an integer with the radix specified by base, optionally preceded by a plus or minus sign, but not including an integer suffix.
...
If the subject sequence begins with a minus sign, the value resulting from the conversion is negated.
Instead you should read the input as an int and then check whether it is positive or negative. i.e:
scanf("%d", &a[n]);
if(a[n++] >= 0)
And yes, that reduces the range of positive number you can input to half but that's the way to go about it.
Other than that you can get the input as char and then parse them yourself which isn't that hard to be honest. something like
unsigned int num = 0;
while(isdigit(c = getchar()))
num = num * 10 + c;
as a very simple solution. of course you can check for an optional + at the beginning and probably accept other bases and much more but this was just a simple code to show you the idea.
I want that while loop ends when I enter number that's not unsigned (lower than zero).
scanf("%u", ...) will read text "-123" in and successfully convert that to an unsigned.
A fairly safe assumption is UINT_MAX <= INTMAX_MAX. In other words, the widest signed integer covers the unsigned range. On rare machines, this is not true - as allowed by C.
Use scanf() (which lacks OF protection) or fgets()/strtoimax()
#include <limits.h>
#include <stdint.h>
#if UINT_MAX > INTMAX_MAX
#error range issue
#endif
intmax_t big_input;
while (scanf("%jd", &big_input) == 1 && (big_input >= 0)) {
if (big_input > UINT_MAX) TBD_Code();
a[n++] = (unsigned) big_input;
// do stuff
}
char buff[20];
while (1)
{
do
{
printf("Enter number: ");
fgets(buff, 20, stdin);
} while (!sscanf(buff, "%u", &a_a));
if(a[n] == (0UL - 1UL)) break;
if (++n == size) {
size *= 2;
a = realloc(a, size * sizeof(*a));
ALLOC_CHECK(a);
}
}

Hexadecimal number comparison?

I'm a new to C language and a bit confused about how hexadecimal, decimal numbers work. I am trying to work with maximum of 4 bytes, so 0xFFFFFFFF. I basically want the program to give an alert if any number is entered with 9 digits or higher. I have written a code as below but it still lets me input numbers bigger than 0xFFFFFFFF. What am I doing wrong? Thanks in advance!
int main()
{
uint32_t rgba;
printf("Enter rgba value: ");
scanf("%x", &rgba);
if (rgba > 0xFFFFFFFF){
printf("Maximum number of 8 digits!\n");
}
else{
rgba_values(rgba);
}
return 0;
}
As #Jongware commented, "You cannot check for a number larger than it is possible to store."
To detect if user input is outside the range of uint32_t rgba, code needs to understand that the user input has or will exceed that range.
Method 1: Use larger integer type: This method will detect "100000000" as too large an input, but will have trouble with numbers larger than "FFFFFFFFFFFFFFFF".
unsigned long long UserInput;
uint32_t rgba;
printf("Enter rgba value: ");
if (scanf("%llx", &UserInput) != 1) {
puts("EOF or Scan Failure");
return 1;
}
if (UserInput > 0xFFFFFFFFu) {
puts("Range error");
return 1;
}
rgba = UserInput;
rgba_values(rgba);
Method 2: Use fgets()/strtoul(). The following will work for input up to 99 char long (which includes the '\n').
uint32_t rgba;
char *buf[100];
printf("Enter rgba value: ");
if(fgets(buf, sizeof buf, stdin) == NULL) {
puts("EOF");
return 1;
}
char *endptr = 0;
errno = 0;
unsigned long ul = strtoul(buf, &endptr, 16);
if (buf == endptr) {
puts("No conversion");
return 1;
}
if (errno || ul > 0xFFFFFFFFu) {
puts("value out of range");
return 1;
}
rgba = (uint32_t) ul;
rgba_values(rgba);
Other methods include counting the number of hexadecimal characters or converting user input 1 char at a time.
if (rgba > 0xFFFFFFFF)
rgba is a 32-bit unsigned integer value, the condition above is always false. A 32-bit unsigned integer value is always <= 0xFFFFFFFF.
Check the return value of scanf: it returns 1 if and only if the input is a valid hexadecimal number without overflow. Note that this will only fit your purpose if the int is exactly 32 bits on your platform.
What you could do is store the user-input into a char* first:
char rgba_str[20]; // 20 is an arbitrary larger buffer size
printf("Enter rgba value: ");
scanf("%s", &rgba_str);
Then check and see if the length of the string is greater than 9 digits:
if ( strlen( rgba_str ) > 8 )
// Error
If not, turn rgba_str into a hexadecimal integer:
else
rgba = strtoul(rgba_str, NULL, 16);

Bizzare behavior from C program:: Kernighan & Ritchie exercise 2-3

all.
I've written a program as a solution to Kernighan & Ritchie's exercise 2-3, and its behaviour during testing is (IMHO) wildly unintuitive.
The problem spec says to write a program that converts hex values to their decimal equivalent. The code I've written works fine for smaller hex values, but for larger hex values things get a little... odd. For example, if I input 0x1234 the decimal value 4660 pops out on the other end, which happens to be the correct output (the code also works for letters, i.e. 0x1FC -> 508). If, on the other hand, I were to input a large hex value, say as a specific example 0x123456789ABCDEF, I should get 81985529216486895, though instead I get 81985529216486896 (off by one digit!).
The error in conversion is inconsistent, sometimes with the decimal value being too high and other times too low. Generally, much larger hex values result in more incorrect place values in the decimal output.
Here's my program in its entirety:
/*Kernighan & Ritchie's Exercise 2-3
Write a function 'htoi' which converts a string of hexadecimal digits (including an
optional 0x or 0X) into its equivalent integer value.
*/
#include <stdio.h>
#define MAXLINE 1000 //defines maximum size of a hex input
//FUNCTION DEFINITIONS
signed int htoi(char c); //converts a single hex digit to its decimal value
//BEGIN PROGRAM////////////////////////////////////////////////////////////
main()
{
int i = 0; //counts the length of 'hex' at input
char c; //character buffer
char hex[MAXLINE]; //string from input
int len = 0; //the final value of 'i'
signed int val; //the decimal value of a character stored in 'hex'
double n = 0; //the decimal value of 'hex'
while((c = getchar()) != '\n') //store a string of characters in 'hex'
{
hex[i] = c;
++i;
}
len = i;
hex[i] = '\0'; //turn 'hex' into a string
if((hex[0] == '0') && ((hex[1] == 'x') || (hex[1] == 'X'))) //ignore leading '0x'
{
for(i = 2; i < len; ++i)
{
val = htoi(hex[i]); //call 'htoi'
if(val == -1 ) //test for a non-hex character
{
break;
}
n = 16.0 * n + (double)val; //calculate decimal value of hex from hex[0]->hex[i]
}
}
else
{
for(i = 0; i < len; ++i)
{
val = htoi(hex[i]); //call 'htoi'
if(val == -1) //test for non-hex character
{
break;
}
n = 16.0 * n + (double)val; //calc decimal value of hex for hex[0]->hex[i]
}
}
if(val == -1)
{
printf("\n!!THE STRING FROM INPUT WAS NOT A HEX VALUE!!\n");
}
else
{
printf("\n%s converts to %.0f\n", hex, n);
}
return 0;
}
//FUNCTION DEFINITIONS OUTSIDE OF MAIN()///////////////////////////////////
signed int htoi(char c)
{
signed int val = -1;
if(c >= '0' && c <= '9')
val = c - '0';
else if(c == 'a' || c == 'A')
val = 10;
else if(c == 'b' || c == 'B')
val = 11;
else if(c == 'c' || c == 'C')
val = 12;
else if(c == 'd' || c == 'D')
val = 13;
else if(c == 'e' || c == 'E')
val = 14;
else if(c == 'f' || c == 'F')
val = 15;
else
{
;//'c' was a non-hex character, do nothing and return -1
}
return val;
}
pastebin: http://pastebin.com/LJFfwSN5
Any ideas on what is going on here?
You are probably exceeding the precision with which double can store integers.
My suggestion would be to change your code to use unsigned long long for the result; and also add in a check for overflow here, e.g.:
unsigned long long n = 0;
// ...
if ( n * 16 + val < n )
{
fprintf(stderr, "Number too big.\n");
exit(EXIT_FAILURE);
}
n = n * 16 + val;
My less-than check works because when unsigned integer types overflow they wrap around to zero.
If you want to add more precision than unsigned long long then you will have to get into more advanced techniques (probably beyond the scope of Ch. 2 of K&R but once you've finished the book you could revisit).
NB. You also need to #include <stdlib.h> if you take my suggestion of exit; and don't forget to change %.0f to %llu in your final printf. Also, a safer way to get the input (which K&R covers) is:
int c;
while((c = getchar()) != '\n' && c != EOF)
The first time I ran the code on ideone I got segfault, because I didn't put a newline on the end of the stdin so this loop kept on shoving EOF into hex until it buffer overflowed.
This is a classic example of floating point inaccuracy.
Unlike most of the examples of floating point errors you'll see, this is clearly not about non-binary fractions or very small numbers; in this case, the floating point representation is approximating very big numbers, with the accuracy decreasing the higher you go. The principle is the same as writing "1.6e10" to mean "approximately 16000000000" (I think I counted the zeros right there!), when the actual number might be 16000000001.
You actually run out of accuracy sooner than with an integer of the same size because only part of the width of a floating point variable can be used to represent a whole number.

C converting string/char input to floating point

I'm writing a program in C, and one of the requirements is that the user input a number as a string value, and then the program must convert it to floating point format, and then do various things to that value. I can't seem to figure out how to simply convert the input string into a number. How would I write the first chunk of code like that? I know there are posts similar to this, but they haven't been helpful. I need to do this fairly simply, and I'd like to not have to #include anything besides ...
#include <stdio.h>
int main(int argc,char* argv[]) {
/*having issues with this in particular...*/
int number;
int newNumber;
int i;
printf("Enter a number in decimal...");
scanf("%d",&number);
/* */
printf("%d in binary is: ",number);
for(i = 31;i >= 0;i--) {
newNumber = (number>>i);
if(newNumber & 1) {
printf("1");
}
else {
printf("0");
}
}
return 0;
}
Thanks!
Following up on the comment I made:
Your code appears to "work" - in that it reads the input and produces
output. You might consider adding \n at the end of your printf
statements. What exactly isn't working for you? Consider using
8*sizeof(int)-1 rather than 31. You don't know ahead of time how big
an int is on your system.
With a tiny change your code works very nicely for me:
#include <stdio.h>
int main(int argc,char* argv[]) {
/*having issues with this in particular...*/
int number;
int newNumber;
int i;
printf("Enter a number in decimal...\n"); // <<< added a newline
scanf("%d",&number);
/* */
printf("%d in binary is: ",number);
for(i = sizeof(int)*8 - 1;i >= 0;i--) { // make sure `i` starts with the right size
newNumber = (number>>i);
if(newNumber & 1) {
printf("1");
}
else {
printf("0");
}
}
printf("\n"); // <<< print a newline
return 0;
}
When I run it:
Enter a number in decimal...
123
123 in binary is: 00000000000000000000000001111011
note - you do have to input an integer for this to work. If you need your code to be more robust to user "error" in the input, your best bet is to read the input as a string, then do some more parsing. For example:
char buffer[100];
printf("enter an integer:\n");
fgets(buffer, 100, stdin);
// now you can look for spaces, letters, anything you want to skip, in the string
// you could even use sscanf().
// scanf() is a terribly fragile function to use, especially with "free form user input".
if(sscanf(buffer, "%d", &number) == 1) {
// successfully converted number... run your code
} else {
printf("unable to convert input to a number!\n%s\n", buffer);
return 0;
}
another note re-reading your question, you said "program has to convert to a floating point number. This means you should do
float fnumber;
sscanf(buffer, "%f", &fnumber);
or
double dnumber;
sscanf(buffer, "%lf", &dnumber);
to do the conversion. But then, if you want to print as a binary, you need to cast the number from floating point to unsigned integer - a bit shifting operation is not well defined for a floating point number. So
unsigned int *intPtr, number;
intPtr = (unsigned int*) *fnumber; // this is hairy but it works
number = *intPtr;
and now use number as before - you will be able to print out the binary equivalent of the floating point number. There are people who will complain that the above is not "true to the standard". They might prefer it if you created a union:
union f2i
{
float fvalue;
unsigned int ivalue;
} Values;
Then assign the input to Values.fvalue, and use Values.ivalue to print out the binary number. It is still a hack...
You can use strtod(). Read the number into a buffer as a string (say with fgets()), and then do:
double x;
char *endptr;
errno = 0;
x = strtod(buffer, &endptr);
if (endptr == buffer) {
//... parse error or empty input ...
} else if (*endptr != '\n' && *endptr != '\0') {
//... parse error extraneous data ...
} else if ((x == HUGE_VAL || x == -HUGE_VAL) && errno != 0) {
//... error overflow ...
} else if (x <= DBL_MIN && x >= -DBL_MIN) {
if (errno != 0) {
//... error underflow (detected) ....
} else {
// ... underflow still possible, but is undiagnosed ...
}
}
Error checking is done by checking both the value returned for x, and if errno got set. Parse errors is done by checking the endptr. The C standard says underflow detection is implementation defined (C.11 §7.22.1.3 ¶10).
Simple scanf example tested with GCC 4.7.3
$ gcc -Wall -Wextra -pedantic -std=c99 cstring-double.c
#include <stdio.h>
int main() {
double v;
int err;
err = scanf("%lf", &v);
if (1 == err) {
printf("%lf\n", v);
} else {
printf("read failed\n"); }
return 0; }
Just use atof. cplusplus documentation

Resources