/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * locale-number.c * * L. David Baron , 2012-12-22 * * Try running this program under different locale settings. On Linux, * for example (at least for some distros), you might try: * gcc -Wall -O2 -std=c99 -o locale-number locale-number.c * ./locale-number * LANG=en_US.UTF_8 locale * LANG=en_US.UTF_8 ./locale-number * LANG=fr_FR.UTF_8 locale * LANG=fr_FR.UTF_8 ./locale-number */ #include #include #include #define SHOW_FUNCTION1(func_, outtype_, format_) \ void \ show_##func_(const char *str) \ { \ printf("%s(%s) == " format_ "\n", #func_, str, (outtype_)func_(str)); \ } #define SHOW_FUNCTION2(func_, outtype_, format_) \ void \ show_##func_(const char *str) \ { \ printf("%s(%s, NULL) == " format_ "\n", \ #func_, str, (outtype_)func_(str, NULL)); \ } #define SHOW_FUNCTION3(func_, outtype_, format_) \ void \ show_##func_(const char *str) \ { \ printf("%s(%s, NULL, 0) == " format_ "\n", \ #func_, str, (outtype_)func_(str, NULL, 0)); \ printf("%s(%s, NULL, 10) == " format_ "\n", \ #func_, str, (outtype_)func_(str, NULL, 10)); \ } SHOW_FUNCTION1(atof, double, "%f") SHOW_FUNCTION2(strtod, double, "%f") SHOW_FUNCTION2(strtof, double, "%f") /* casts to double */ SHOW_FUNCTION2(strtold, long double, "%Lf") SHOW_FUNCTION1(atoi, int, "%d") SHOW_FUNCTION1(atol, long, "%ld") SHOW_FUNCTION1(atoll, long long, "%lld") SHOW_FUNCTION3(strtol, long int, "%ld") SHOW_FUNCTION3(strtoll, long long int, "%lld") SHOW_FUNCTION3(strtoul, unsigned long int, "%lu") SHOW_FUNCTION3(strtoull, unsigned long long int, "%llu") int main(void) { /* Choose the user's locale rather than the default C locale. */ setlocale(LC_ALL, ""); /* Print out the locale we've chosen. */ printf("Numeric locale is %s.\n", setlocale(LC_NUMERIC, NULL)); /* Now print out how various functions behave. */ /* The float formatting functions parse differently depending on locale, and printf prints them differently too. */ show_atof("1.2"); show_atof("1,2"); show_strtod("1.2"); show_strtod("1,2"); show_strtof("1.2"); show_strtof("1,2"); show_strtold("1.2"); show_strtold("1,2"); /* I haven't yet found evidence of integer parsing functions accepting group separators, but code to do so is present (in #ifdefs) in glibc's code, and it's certainly allowed by the C standard. */ show_atoi("123,456"); show_atoi("123 456"); show_atoi("123.456"); show_atol("123,456"); show_atol("123 456"); show_atol("123.456"); show_atoll("123,456"); show_atoll("123 456"); show_atoll("123.456"); show_strtol("123,456"); show_strtol("123 456"); show_strtol("123.456"); show_strtoll("123,456"); show_strtoll("123 456"); show_strtoll("123.456"); show_strtoul("123,456"); show_strtoul("123 456"); show_strtoul("123.456"); show_strtoull("123,456"); show_strtoull("123 456"); show_strtoull("123.456"); return 0; }