Hi,

first of all: the answer to my question is NOT atof()!

I have a char-array that may contain something like "1.2345". I want to convert the contained values to float/doubles but unfortunately atof() depends on the current locale. So whenever a user executes the application on a system where "," is the decimal separator my result is 1.0, only on systems where "." is the decimal separator I get the correct result 1.2345.

Replacing all "," by a "." is not a solution since comma may be a separator within the char array.

So how else can I parse and convert such a float value? Is there a function that can be forced to use "."?

Hi,

How about this approach:
Convert the array into an integer after parsing through the entire number. i.e

say for eg, the number is stored as 123.456
Now, find the integer equivalent by looping through the array, i.e obtain 123456 and then, divide it by an appropriate power of 10 to convert it into a decimal.

The power of 10 is decided by the location of the decimal delimiter(a "." or a "," or whatever it is).

I'm not sure if this approach is feasible for you. But its just a thought.

That's the solution I use at the moment but it is quite complex to parse. Floating point numbers can have very different formats:

1
.1
1.1
1.23e-34

...and combinations of them with a preceding minus sign.

So simply looking for the dot and then dividing does not work...

So whenever a user executes the application on a system where "," is the decimal separator my result is 1.0, only on systems where "." is the decimal separator I get the correct result 1.2345.

You can change the locale temporarily. I assume your problem is that the string is always formatted using '.' as the decimal separator, so just set the locale to "C" (the default C locale) and change it back when you're done with the conversion:

#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *copystr(const char *s)
{
    char *copy = malloc(strlen(s) + 1);
    
    if (copy != NULL)
        strcpy(copy, s);
        
    return copy;
}

double locale_atof(const char *s, const char *loc)
{
    char *p, *old_locale;
    double result;
    
    p = setlocale(LC_NUMERIC, NULL);
    
    if (p != NULL) {
        old_locale = copystr(p);
        setlocale(LC_NUMERIC, loc);
    }
        
    result = atof(s);
    
    if (p != NULL) {
        setlocale(LC_NUMERIC, old_locale);
        free(old_locale);
    }
    
    return result;
}

int main(void)
{
    double result;
    
    /* Switch to a locale with the ',' decimal character */
    setlocale(LC_NUMERIC, "German");
    printf("%s\n", localeconv()->decimal_point);
    
    /* Convert with a forced C locale */
    result = locale_atof("1.234", "C");
    
    /* Switch to the system locale for display */
    setlocale(LC_NUMERIC, "");
    printf("%f\n", result);
    
    return 0;
}
This article has been dead for over six months. Start a new discussion instead.