Функция setlocale
Функция setlocale задает локаль, которая будет использоваться текущей программой. Можно изменить все параметры локали, или конкретные её части. Эта функция также может быть использована для получения имени текущей локали, передав NULL в через параметр locale .
Локаль содержит информацию о том, как интерпретировать и выполнять определенные операции ввода/вывода и преобразования с учетом географического расположения и специфики языков в определённых условиях.
Большинство используемых сред программирования имеют определенную информацию о локали, установленной в соответствии с предпочтениями пользователя или автоматической локализации. Но, независимо от этой системной локали, в момент запуска, все Си-программы имеют установленную Cи -локаль, которая является нейтральной локалью с минимальной информацией, что позволяет предсказать результат программы. Для того чтобы использовать, по умолчанию, локаль установленную в среде программирования, необходимо вызвать функцию setlocale с параметром locale равным «» .
По умолчанию, установлена локаль: SetLocale (LC_ALL, «C») .
Вся локаль, по умолчанию, может быть установлена вызовом функции SetLocale (LC_ALL, «»);
Если необходимо изменить часть текущей локали, вместо параметра LC_ALL определяем параметр определённой категории. Какие именно категории есть, вы можете увидеть в таблице, ниже.
Чтобы изменить все параметры локали, необходимо вызвать функцию setlocale с параметром category LC_ALL , на пример, так: setlocale(LC_ALL,"");
Конкретные параметры текущей локали зависят от вызова функции setlocale , предварительно указав параметр category .
Параметры:
- category
Параметры локали, можно задавать отдельно каждый параметр или все сразу. В заголовочном файлеопределены константы, содержащие значения для этого параметра:
- locale
Строка, содержащая имя локали. Как минимум существуют два значения, передаваемые через этот параметр:
Если значение этого параметра равно NULL , функция не вносит никаких изменений в текущую локаль, но имя текущей локали возвращается функцией.
Возвращаемое значение
В случае успеха, функция возвращает указатель на строку с установленной локалью для данной категории.
Если установлена категория LC_ALL и для различных частей локали установлены различные значения, возвращаемая строка предоставляет эту информацию в формате, который может варьироваться от реализации компилятора.
Если функции не удалось установить новую локаль, текущая локаль остается неизменной и возвращается нулевой указатель.
Пример: исходный код программы
// пример использования функции setlocale #include // для оператора cout #include // для функции time и localtime #include // для функций настройки локали int main () < time_t numb_sec; // кол. сек прошедших с 00:00 , 1 января 1970 года struct tm * timeinfo; // структура хранения даты и времени char buffer [80]; struct lconv * lc; // инфрмация о форматировании числовых значений time ( &numb_sec ); // записать в numb_sec кол. сек прошедших с 00:00 , 1 января 1970 года timeinfo = localtime ( &numb_sec ); // заполняем структуру timeinfo, используя только значение количества сек. int twice = 0; // управляющая переменная циклом do while do < std::cout currency_symbol while (!twice++); // цикл сработает всего 2 раза return 0; >
Пример работы программы
Одним из возможных выводов программы при запуске этого кода является:
CppStudio.com
Локаль: C
Дата: Mon Oct 8 08:42:17 2012
Символ валюты:
Локаль: ru_UA.UTF-8
Дата: Пнд 08 Окт 2012 08:42:17
Символ валюты: гр
char *setlocale(int type, const char *locale)
Эта функция позволяет запрашивать или устанавливать определенные параметры, зависящие от географического положения. Например, в Европе вместо десятичной точки используется запятая.
Если параметр local задан как NULL, то функция setlocale() возвращает указатель на строку текущей локализации. В противном случае функция setlocale() пытается использовать заданную строку локализации для установки локальных параметров в соответствии со спецификацией переменной type.
В момент вызова переменная type должна иметь одно из следующих значений, заданных в виде макросов:
LC_ALL
LC_COLLATE
LC_CTYPE
LC_MONETARY
LC_NUMERIC
LC_TIME
Макрос LC_ALL относится ко всем категориям локализации. Макрос LC_COLLATE воздействует на функцию strcoll(). Макрос LC_CTYPE изменяет работу функций с символами. Макрос LC_MONETARY определяет формат валюты. LC_NUMERIC изменяет способ изображения десятичной части при форматировании ввода/вывода. Наконец, макрос LC_TIME определяет поведение функции strftime().
Функция setlocale() возвращает указатель на строку, ассоциированную с параметром type. При возникновении ошибки возвращается нулевой указатель.
What does «LC_ALL=C» do?
What does the C value for LC_ALL do in Unix-like systems? I know that it forces the same locale for all aspects but what does C do?
- environment-variables
- locale
72.3k 34 34 gold badges 193 193 silver badges 226 226 bronze badges
asked Aug 22, 2013 at 7:32
9,732 16 16 gold badges 56 56 silver badges 75 75 bronze badges
If you want to resolve a problem with xclock warning( Missing charsets in String to FontSet conversion ), it will be better if you will use LC_ALL=C.UTF-8 to avoid problems with cyrillic. To set this environment variable you must add the following line to the end of ~/.bashrc file — export LC_ALL=C.UTF-8
Jun 19, 2019 at 12:42
@fedotsoldier you should probably ask question and give the answer yourself, I don’t think it’s related to the question. It’s just answer to different problem you’re having.
Jun 19, 2019 at 13:20
Yeah, you are right, ok
Jun 19, 2019 at 13:22
legendary C locales rant github.com/mpv-player/mpv/commit/…
Sep 4, 2022 at 6:28
6 Answers 6
LC_ALL is the environment variable that overrides all the other localisation settings (except $LANGUAGE under some circumstances).
Different aspects of localisations (like the thousand separator or decimal point character, character set, sorting order, month, day names, language or application messages like error messages, currency symbol) can be set using a few environment variables.
You’ll typically set $LANG to your preference with a value that identifies your region (like fr_CH.UTF-8 if you’re in French speaking Switzerland, using UTF-8). The individual LC_xxx variables override a certain aspect. LC_ALL overrides them all. The locale command, when called without argument gives a summary of the current settings.
For instance, on a GNU system, I get:
$ locale LANG=en_GB.UTF-8 LANGUAGE= LC_CTYPE="en_GB.UTF-8" LC_NUMERIC="en_GB.UTF-8" LC_TIME="en_GB.UTF-8" LC_COLLATE="en_GB.UTF-8" LC_MONETARY="en_GB.UTF-8" LC_MESSAGES="en_GB.UTF-8" LC_PAPER="en_GB.UTF-8" LC_NAME="en_GB.UTF-8" LC_ADDRESS="en_GB.UTF-8" LC_TELEPHONE="en_GB.UTF-8" LC_MEASUREMENT="en_GB.UTF-8" LC_IDENTIFICATION="en_GB.UTF-8" LC_ALL=
I can override an individual setting with for instance:
$ LC_TIME=fr_FR.UTF-8 date jeudi 22 août 2013, 10:41:30 (UTC+0100)
$ LC_MONETARY=fr_FR.UTF-8 locale currency_symbol €
Or override everything with LC_ALL.
$ LC_ALL=C LANG=fr_FR.UTF-8 LC_MESSAGES=fr_FR.UTF-8 cat / cat: /: Is a directory
In a script, if you want to force a specific setting, as you don’t know what settings the user has forced (possibly LC_ALL as well), your best, safest and generally only option is to force LC_ALL.
The C locale is a special locale that is meant to be the simplest locale. You could also say that while the other locales are for humans, the C locale is for computers. In the C locale, characters are single bytes, the charset is ASCII (well, is not required to, but in practice will be in the systems most of us will ever get to use), the sorting order is based on the byte values¹, the language is usually US English (though for application messages (as opposed to things like month or day names or messages by system libraries), it’s at the discretion of the application author) and things like currency symbols are not defined.
On some systems, there’s a difference with the POSIX locale where for instance the sort order for non-ASCII characters is not defined.
You generally run a command with LC_ALL=C to avoid the user’s settings to interfere with your script. For instance, if you want [a-z] to match the 26 ASCII characters from a to z , you have to set LC_ALL=C .
On GNU systems, LC_ALL=C and LC_ALL=POSIX (or LC_MESSAGES=C|POSIX ) override $LANGUAGE , while LC_ALL=anything-else wouldn’t.
A few cases where you typically need to set LC_ALL=C :
- sort -u or sort . | uniq. . In many locales other than C, on some systems (notably GNU ones), some characters have the same sorting order. sort -u doesn’t report unique lines, but one of each group of lines that have equal sorting order. So if you do want unique lines, you need a locale where characters are byte and all characters have different sorting order (which the C locale guarantees).
- the same applies to the = operator of POSIX compliant expr or == operator of POSIX compliant awk s ( mawk and gawk are not POSIX in that regard), that don’t check whether two strings are identical but whether they sort the same.
- Character ranges like in grep . If you mean to match a letter in the user’s language, use grep ‘[[:alpha:]]’ and don’t modify LC_ALL . But if you want to match the a-zA-Z ASCII characters, you need either LC_ALL=C grep ‘[[:alpha:]]’ or LC_ALL=C grep ‘[a-zA-Z]’ ². [a-z] matches the characters that sort after a and before z (though with many APIs it’s more complicated than that). In other locales, you generally don’t know what those are. For instance some locales ignore case for sorting so [a-z] in some APIs like bash patterns, could include [B-Z] or [A-Y] . In many UTF-8 locales (including en_US.UTF-8 on most systems), [a-z] will include the latin letters from a to y with diacritics but not those of z (since z sorts before them) which I can’t imagine would be what you want (why would you want to include é and not ź ?).
- floating point arithmetic in ksh93 . ksh93 honours the decimal_point setting in LC_NUMERIC . If you write a script that contains a=$((1.2/7)) , it will stop working when run by a user whose locale has comma as the decimal separator:
$ ksh93 -c 'echo $((1.1/2))' 0.55 $ LANG=fr_FR.UTF-8 ksh93 -c 'echo $((1.1/2))' ksh93: 1.1/2: arithmetic syntax error
Then you need things like:
#! /bin/ksh93 - float input="$1" # get it as input from the user in his locale float output arith() < typeset LC_ALL=C; (($@)); >arith output=input/1.2 # use the dot here as it will be interpreted # under LC_ALL=C echo "$output" # output in the user's locale
As a side note: the , decimal separator conflicts with the , arithmetic operator which can cause even more confusion.
- When you need characters to be bytes. Nowadays, most locales are UTF-8 based which means characters can take up from 1 to 6 bytes³. When dealing with data that is meant to be bytes, with text utilities, you’ll want to set LC_ALL=C. It will also improve performance significantly because parsing UTF-8 data has a cost.
- a corollary of the previous point: when processing text where you don’t know what character set the input is written in, but can assume it’s compatible with ASCII (as virtually all charsets are). For instance grep ‘<.*>‘ to look for lines containing a < , >pair will no work if you’re in a UTF-8 locale and the input is encoded in a single-byte 8-bit character set like iso8859-15. That’s because . only matches characters and non-ASCII characters in iso8859-15 are likely not to form a valid character in UTF-8. On the other hand, LC_ALL=C grep ‘<.*>‘ will work because any byte value forms a valid character in the C locale.
- Any time where you process input data or output data that is not intended from/for a human. If you’re talking to a user, you may want to use their convention and language, but for instance, if you generate some numbers to feed some other application that expects English style decimal points, or English month names, you’ll want to set LC_ALL=C:
$ printf '%g\n' 1e-2 0,01 $ LC_ALL=C printf '%g\n' 1e-2 0.01 $ date +%b août $ LC_ALL=C date +%b Aug
That also applies to things like case insensitive comparison (like in grep -i ) and case conversion ( awk ‘s toupper() , dd conv=ucase . ). For instance:
grep -i i
is not guaranteed to match on I in the user’s locale. In some Turkish locales for instance, it doesn’t as upper-case i is İ (note the dot) there and lower-case I is ı (note the missing dot).
Notes
¹ again, only on ASCII based systems (the immense majority of systems). POSIX requires the collation order for the C locale to be that of the order of characters in the ASCII charset, even on EBCDIC systems which are not allowed to do the strcoll() === strcmp() optimisation in the C locale.
² Depending on the encoding of the text, that’s not necessarily the right thing to do though. That’s valid for UTF-8 or single-byte character sets (like iso-8859-1), but not necessarily non-UTF-8 multibyte character sets.
For instance, if you’re in a zh_HK.big5hkscs locale (Hong Kong, using the Hong Kong variant of the BIG5 Chinese character encoding), and you want to look for English letters in a file encoded in that charsets, doing either:
LC_ALL=C grep '[[:alpha:]]'
LC_ALL=C grep '[a-zA-Z]'
would be wrong, because in that charset (and many others, but hardly used since UTF-8 came out), a lot of characters contain bytes that correspond to the ASCII encoding of A-Za-z characters. For instance, all of A䨝䰲丕乙乜你再劀劈呸哻唥唧噀噦嚳坽 (and many more) contain the encoding of A . 䨝 is 0x96 0x41, and A is 0x41 like in ASCII. So our LC_ALL=C grep ‘[a-zA-Z]’ would match on those lines that contain those characters as it would misinterpret those sequences of bytes.
LC_COLLATE=C grep '[A-Za-z]'
would work, but only if LC_ALL is not otherwise set (which would override LC_COLLATE ). So you may end up having to do:
grep '[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]'
if you wanted to look for English letters in a file encoded in the locale’s encoding.
³ some would argue it’s rather 1 to 4 bytes these days now that Unicode code points (and the libraries that encode/decode UTF-8 data) have been arbitrarily restricted to code points U+0000 to U+10FFFF (0xD800 to 0xDFFF excluded) down from U+7FFFFFFF to accommodate the UTF-16 encoding, but some applications will still happily encode/decode 6-byte UTF-8 sequences (including the ones that fall in the 0xD800 .. 0xDFFF range).
setlocale
The setlocale function installs the specified system locale or its portion as the new C locale. The modifications remain in effect and influences the execution of all locale-sensitive C library functions until the next call to setlocale . If locale is a null pointer, setlocale queries the current C locale without modifying it.
Contents
[edit] Parameters
| category | — | locale category identifier, one of the LC_xxx macros. May be null. |
| locale | — | system-specific locale identifier. Can be «» for the user-preferred locale or «C» for the minimal locale |
[edit] Return value
pointer to a narrow null-terminated string identifying the C locale after applying the changes, if any, or null pointer on failure.
A copy of the returned string along with the category used in this call to setlocale may be used later in the program to restore the locale back to the state at the end of this call.
[edit] Notes
During program startup, the equivalent of setlocale ( LC_ALL , «C» ) ; is executed before any user code is run.
Although the return type is char * , modifying the pointed-to characters is undefined behavior.
POSIX also defines a locale named «POSIX», which is always accessible and is exactly equivalent to the default minimal «C» locale.
POSIX also specifies that the returned pointer, not just the contents of the pointed-to string, may be invalidated by subsequent calls to setlocale .
[edit] Example
Run this code
#include #include #include #include int main(void) { // the C locale will be UTF-8 enabled English; // decimal dot will be German // date and time formatting will be Japanese setlocale(LC_ALL, "en_US.UTF-8"); setlocale(LC_NUMERIC, "de_DE.utf8"); setlocale(LC_TIME, "ja_JP.utf8"); wchar_t str[100]; time_t t = time(NULL); wcsftime(str, 100, L"%A %c", localtime(&t)); wprintf(L"Number: %.2f\nDate: %ls\n", 3.14, str); }
Number: 3,14 Date: 月曜日 2017年09月25日 13時00分15秒
[edit] References
- C17 standard (ISO/IEC 9899:2018):
- 7.11.1.1 The setlocale function (p: 163-164)
- C11 standard (ISO/IEC 9899:2011):
- 7.11.1.1 The setlocale function (p: 224-225)
- C99 standard (ISO/IEC 9899:1999):
- 7.11.1.1 The setlocale function (p: 205-206)
- C89/C90 standard (ISO/IEC 9899:1990):
- 4.4.1.1 The setlocale function
