2

I am looking for a way to get floating point input from a user.

My way of going about this is to use a self-made getstrn function and plug that into another function which would convert the string into a double.

My safe get string:

void safeGetString(char arr[], int limit){
    int c, i;
    i = 0;
    c = getchar();
    while (c != '\n'){
        if (i < limit -1){
            arr[i] = c;
            i++;
        }
        c = getchar();
    }
    arr[i] = '\0';
}

What would be the best way to write this get_double function?

not_l33t
  • 1,315
  • 4
  • 15
  • 17

4 Answers4

13

Try the strtod function:

char *end;
double num = strtod(arr, &end);

The end will point after the last char that was processed. You can set the second to NULL if you don't care about that. Or you can use atof: atof(str) is equivalent to strtod(str, (char **)NULL).

But you should care, since you can check if the input is malformed:

if (*end != '\0')
  // Handle malformed input
terminus
  • 13,745
  • 8
  • 34
  • 37
  • But if you don't care about the end, then you can't tell the difference between malformed input and 0, and out-of-range values result in undefined behavior for `atof`. – Steve Jessop Nov 29 '10 at 22:09
  • @Steve: If you want to tell the difference between malformed input and 0, then by definition you care about the end pointer. – Stephen Canon Nov 29 '10 at 22:13
  • @Stephen: that's what I said. They call it the "contrapositive" ;-) – Steve Jessop Nov 29 '10 at 22:13
  • @Terminus: the check for malformed input should be `(end == arr)`. – Stephen Canon Nov 29 '10 at 22:15
  • @Stephen: Won't that still accept inputs like `0.1a` where `end` will be `arr + 3`? – terminus Nov 29 '10 at 22:17
  • @terminus: if you want to get really pernickity, you should do the check you already have, *and* check somewhere that `*arr != 0`. Unless there's a reason to treat an empty string as 0, which sometimes there is. – Steve Jessop Nov 29 '10 at 22:20
  • @Terminus: Right. I suppose it depends on what you consider "malformed". In my usage of `strtod`, I'm usually parsing a double and then doing something else with the remainder of the string, so `0.1a` isn't malformed. Other usage may differ. – Stephen Canon Nov 29 '10 at 22:20
4

Use strtod, that's what it's for. And fgets can replace your safeGetString function.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
4

Any of:

Of these sscanf offers the strongest validation, since the other two return a valid double value of 0.0 if the input cannot be interpreted as a double, while sscanf() returns the number of format specifiers successfully matched to the input. So:

input_valid = (sscanf( arr, "%lf", value ) != 0 ) ;
Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Clifford
  • 88,407
  • 13
  • 85
  • 165
2
  1. Why are you not using fgets()?
  2. You're looking for atof().

(Thanks to R. for fixing my idiotic suggestion in part 1)

EboMike
  • 76,846
  • 14
  • 164
  • 167
  • 1
    (1) `gets` is unsafe, it overruns buffers because there's no way to stop it reading other than for the user to enter a newline character before your buffer is full. `fgets` is OK. – Steve Jessop Nov 29 '10 at 22:06
  • Regarding 1. I think the question makes it clear that a safe function is intended. "gets does not let you specify a limit on how many characters are to be read, so you must be careful with the size of the array pointed by str to avoid buffer overflows" – Pascal Cuoq Nov 29 '10 at 22:08
  • 1
    Good point. And I'm usually the one whining about functions like strcpy and strcat. – EboMike Nov 29 '10 at 22:09
  • 3
    You can stop with the downvoting already, the answer has been edited. – EboMike Nov 29 '10 at 22:09