Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

strtod with limited string length

Tags:

c

strtod

If I want to parse the first 3 characters from the char array as a double, ignoring the following characters, do I really need to do this?

int main() {
    const char a[] = "1.23";
    char *b = malloc(sizeof(char) * 4);

    memcpy(b, a, sizeof(char) * 3);
    b[3] = '\0';

    printf("%f\n", strtod(b, NULL)); // Prints 1.20000, which is what I want

    free(b);
}

Isn't there a function like strtod that allows you to specify the maximum string length it should be searching for digits?

Edit: I want it to print 1.2 (which it currently does), not 1.23!

like image 253
Tyilo Avatar asked Dec 27 '22 04:12

Tyilo


1 Answers

While strtod() doesn't allow you to limit the string length, you can use sscanf() with a maximum field width and an optional check for the number of characters consumed, like so:

#include <stdio.h>

double parseDouble(const char *str){
    double val = 0;
    int numCharsRead;

    // Handle errors by setting or returning an error flag.
    if(sscanf(str, "%3lf%n", &val, &numCharsRead) != 1){
        puts("Failed to parse double!");
    }
    else if(numCharsRead != 3){
        puts("Read less than three characters!");
    }

    return val;
}

int main(){
    printf("%lf\n", parseDouble("1.3")); // 1.300000
    printf("%lf\n", parseDouble("1.5999")); // 1.500000
    printf("%lf\n", parseDouble(".391")); // 0.390000
    printf("%lf\n", parseDouble(".3")); // Read less than three characters!\n0.300000
    return 0;
}

sscanf(str, "%3lf%n", &val, &numCharsRead is the important part: you specify a maximum width of 3, which means that sscanf() will read up to 3 characters for that particular field, and also store the number of characters consumed by the end of the parse in numCharsRead. You can then check that value if you care about reading exactly 3 characters every time; if you're fine with 3 or less, you can just use sscanf(str, "%3lf", &val). For reference, here's the documentation for width specifiers:

An optional decimal integer which specifies the maximum field width. Reading of characters stops either when this maximum is reached or when a nonmatching character is found, whichever happens first. Most conversions discard ini‐ tial white space characters (the exceptions are noted below), and these discarded characters don't count toward the maximum field width. String input conversions store a terminating null byte ('\0') to mark the end of the input; the maximum field width does not include this terminator.

like image 107
sevko Avatar answered Jan 04 '23 19:01

sevko