Reputation: 91
I'm having a very specific problem and haven't found a solution elsewhere. I'm working on a small project and i want to make it more robust by allowing users to input prices with both a comma or dot. So i made a little function that allows me to do that:
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main () {
setlocale(LC_ALL, "Portuguese");
float val;
char str[20];
scanf("%s", str);
for (int i = 0; str[i] != '\0'; ++i)
if (str[i] == ',')
str[i] = '.';
val = atof(str);
printf("String value = %s, Float value = %f\n", str, val);
return(0);
}
This would work as intended, were I not Portuguese. Since we mostly use a comma in decimal numbers, using the atof
function doesn't work because it converts to floats with a dot, and then when I try to printf
the float it will show 0.0 but if you delete the line setlocale(LC_ALL, "Portuguese");
it will work just fine. Any ideas?
Upvotes: 2
Views: 1086
Reputation: 213276
There's two problems:
atof
which is an unsafe function that should never be used - it has no error handling. Use strtof
instead.You can use the standard function localeconv
to get all kind of useful info about the current locale.
Example:
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main (void)
{
setlocale(LC_ALL, "Portuguese");
char ok_decimal_point = localeconv()->decimal_point[0];
char bad_decimal_point = (ok_decimal_point=='.') ? ',' : '.';
float val;
char str[20] = "123.456";
for (int i = 0; str[i] != '\0'; ++i)
{
if (str[i] == bad_decimal_point)
{
str[i] = ok_decimal_point;
}
}
val = strtof(str, NULL);
printf("String value = %s, Float value = %f\n", str, val);
return(0);
}
(Although, coming from another country that uses ,
, I prefer to educate users to use the .
form instead, since this is more of an international standard. Having two different standards for decimal points around the world isn't helping mankind. Those with the least used version should adapt.)
Upvotes: 3
Reputation: 50778
Your code works as expected:
The for
loop transforms all ,
into .
and therefore atof
fails converting a number with .
as decimal point because you have called setlocale(LC_ALL, "Portuguese");
beforehand.
You need this:
if (str[i] == '.') str[i] = ',';
instead of this:
if (str[i] == ',') str[i] = '.';
This sample makes it clear:
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main() {
float val;
// converting with default locale
char str[20] = "1.234";
val = atof(str);
printf("Default locale: String value = %s, Float value = %f\n", str, val);
// converting with Portugese locale
setlocale(LC_ALL, "Portuguese");
char strport[20] = "1,234";
val = atof(strport);
printf("Portugese locale: String value = %s, Float value = %f\n", strport, val);
return(0);
}
Upvotes: 2