"czy znak przy konwersji liczb zmiennoprzecinkowych ("," lub ".") zależy od systemu na jakim pracujemy, ustawień regionalnych itp.?". Ponieważ pytanie mnie zaciekawiło, to trochę poszperałem tu i tam, odpowiedziałem na forum i w końcu stwierdziłem że napisze (metodą Kopiego=Pasta) o tym również tutaj, być może kogoś również to zaciekawi.
Jak się okazuje, "decimal point" w printf/scanf (a także paru innych funkcjach) zależy jest od ustawienia "locale" (ang. miejsce akcji/zdarzenia wg. słownika dict.pl).
Na początku programu jest to kropka - wynika to ze standardu ANSI C (posłużę się C99) oraz dokumentu ISO/IEC 9945-2, ten pierwszy pozwolę sobie zacytować (ISO/IEC 9899:1999 str 205, pkt 7.11.1.1.4 - Locale control):
At program startup, the equivalent of
setlocale(LC_ALL, "C");
is executed.
Rodzaj locale "C" zdefiniowany jest w drugim dokumencie o którym wspomniałem (niestety nie dysponuje tym dokumentem żeby zacytować, więc musicie uwierzyć mi na słowo że decimal_point jest tam zdefiniowany jako kropka).
Jeżeli programista chce zmienić decimal_point, to używa (wymienionej wcześniej) funkcji setlocale z parametrem LC_ALL lub LC_NUMERIC, oraz wartością locale jaka ma być (nazwą zdefiniowanego i obecnego w ?systemie? wzorca). Może to być np.:
"Polish" - tak pod windowsem nazywa się polski wzorzec (zachęcam do rzucenia okiem na Remarks w MSDN, ponieważ oznaczenie może zawierać kilka parametrów)
"pl_PL.UTF-8" - a tak pod kubuntu (polecenie locale -a w konsoli wypisuje dostępne możliwości)
etc.
Można również podać wartość pustą "", w takim przypadku:
(*nix)
If the second argument to setlocale(3) is empty string, "", for the default locale, it is determined using the following steps:
1. If there is a non-null environment variable LC_ALL, the value of LC_ALL is used.
2. If an environment variable with the same name as one of the categories above exists and is non-null, its value is used for that category.
3. If there is a non-null environment variable LANG, the value of LANG is used.
(Windows)
setlocale( LC_ALL, "" );
Sets the locale to the default, which is the user-default ANSI code page obtained from the operating system.
Warto również rzucić okiem na:
- http://msdn.microsoft.com/en-us/library/wyzd2bce.aspx - lista funkcji w MSVCRT korzystających z ustawień locale
- Funkcję "localconv"
- Polecenie "localedef" (definiowanie nowych locale'i pod *nixami)
(niestety nie umiem powiedzieć jak się nowy locale pod windą tworzy / moduje istniejący, ale sądzę że zainteresowani sobie znajdą ;>)
Na koniec jakiś kod przykładowy który napisałem chwilę temu:
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<locale.h>
int
main(void)
{
float f = 12.3456;
printf("Current decimal_point: %s\n", localeconv()->decimal_point);
setlocale(LC_ALL, "");
printf("Current decimal_point: %s\n", localeconv()->decimal_point);
printf("Current: %f\n", f);
setlocale(LC_ALL, "en_US.utf8"); // "English" on windows
printf("Current decimal_point: %s\n", localeconv()->decimal_point);
printf("English: %f\n", f);
setlocale(LC_ALL, "pl_PL.utf8"); // "Polish" on windows
printf("Current decimal_point: %s\n", localeconv()->decimal_point);
printf("Polish: %f\n", f);
// To nie zadziala ;>
localeconv()->decimal_point = strdup("_hi_");
printf("Current decimal_point: %s\n", localeconv()->decimal_point);
printf("Polish: %f\n", f);
return 0;
}
I tyle ;>
Comments:
http://stackoverflow.com/questions/1333451/c-locale-independent-atof
Add a comment: