Next Previous Contents

19. Национальные и Международные Стандарты

Различные страны имеют изменяющиеся стандарты. Эти стандарты содержит преобразования от очень простых, типа формата для представления дат и времени, до очень сложных, типа разговорного языка.

Межнационализация программного обеспечения означает способность к адаптированию программирования для соглашений предпочитаемых пользователем. В ANSI C, межнационализация работает посредством стандартов. Каждый стандарт определяет набор соглашений, одно соглашение для каждой цели. Пользователь выбирает набор соглашений, определяя стандарт (через переменные среды).

Все программы наследуют выбранный стандарт как часть их среды.

19.1 Какие Эффекты Стандарта Имеет Каждый Стандарт ?

Это определяет соглашения для отдельных целей, включая следующие:

Другие аспекты стандартов - вне компетенции библиотеки. Например, библиотека не может автоматически транслировать сообщения вывода вашей программы на другие языки. Единственый способ, которым Вы можете поддерживать вывод на языке пользователя, должен программироваться более или менее вручную. (В конечном счете, мы надеемся обеспечить средства, чтобы делать этот проще.)

Эта глава обсуждает механизм, которым Вы можете изменять текущий стандарт. Эффекты текущего стандарта на специфических библиотечных функциях обсуждены более подробно в описаниях самих функций.

19.2 Выбор Стандарта

Самый простой способ для пользователя, чтобы выбрать стандарт состоит в том, чтобы установить переменную среды LANG. Она определяет один стандарт для всех целей. Например, пользователь мог бы определить гипотетический стандарт, именованный " espana­ castellano " чтобы использовать стандартные соглашения Испании.

Набор обеспечиваемых стандартов зависит от операционной системы, которую Вы используете. Мы не можем делать ни каких обещаний относительно того, что стандарты будут существовать, кроме одного стандартного стандарта, называемого " C " или " POSIX ".

Пользователь также имеет опцию определения различных стандартов для различных целей, выбирая смесь многих стандартов.

19.3 Категории Действий, на которые Воздействуют Стандарты

Цели, которые стандарты обслуживают, сгруппированы в категории так, чтобы пользователь или программа мог выбирать стандарт для каждого класса независимо. Вот таблица категорий: каждое имя является и переменной среды, которую пользователь может устанавливать, и именем макрокоманды, которую Вы можете использовать как аргумент setlocale.

       LC_COLLATE
Этот класс применяется для объединения строк (функции strcoll и strxfrm); см. Раздел 5.6 [Функции Объединения].
       LC_CTYPE
Этот класс применяется для классификации и преобразований символов, и в многобайтовые и в расширенные символы; см. Главу 4 [Обработка Символов] и Главу 18 [Расширенные Символы].
       LC_MONETARY
Этот класс применяется к форматированию валютных значений; см. Раздел 19.6 [Числовое форматирование].
       LC_NUMERIC
Этот класс применяется к форматированию числовых значений; см. раздел 19.6 [Числовое Форматирование].
       LC_TIME
Этот класс применяется для форматирования значений даты и времени; см. Раздел 17.2.4 [Форматирование Даты и времени].
       LC_ALL
Это - не переменная среды, это - только макрокоманда, которую Вы можете использовать с setlocale, чтобы установить одиночный стандарт для всех целей.
       LANG
Если эта переменная среды определена, значение определяет стандарт, используемый для всех целей за исключением того, как отменено переменными выше.

19.4 Как Программы Устанавлиают Стандарт

Программа на Си наследует переменные среды стандарта, когда она начинается. Это случается автоматически. Однако, эти переменные автоматически не управляют стандартом, используемым в соответствии c библиотечными функциями, потому что ANSI C говорит, что все программы начинаются по умолчанию в стандарте " C ". Чтобы использовать стандарты, заданные средой, Вы должны вызвать setlocale. Вызовите ее следующим образом:

                 setlocale (LC_ALL, "");
чтобы выбрать стандарт, основанный на соответствующих переменных среды.

Вы можете также использовать setlocale, чтобы определить специфический стандарт, для общего использования или для специфического класса.

Символы в этом разделе определены в заглавном файле " locale.h".

       char * setlocale (int category, const char *locale) 
Функция setlocale устанавливает текущий стандарт для указанного класса.

Если класс - LC_ALL, то она определяет стандарт для всех целей. Другие возможные значения класса определяют индивидуальную цель (см. Раздел 19.3 [Категории Стандарта] ).

Вы можете также использовать эту функцию, чтобы выяснить текущий стандарт, передавая пустой указатель как аргумент стандарта. В этом случае, setlocale возвращает строку, которая является именем стандарта, в настоящее время выбранного для класса class.

Строка, возвращенная setlocale может быть записана поверх последующими обращениями, так что Вы должны делать копию строки (см. Раздел 5.4 [Копирование и Конкатенация]) если Вы хотите сохранять ее после любых дальнейших обращений к setlocale. (Стандартная библиотека, как гарантируют, никогда не вызовет setlocale непосредственно.)

Вы не должны изменять строку, возвращенную setlocale. Это может быть та же самая строка, которая была передана как аргумент в предыдущем обращении к setlocale.

Когда Вы читаете текущий стандарт для класса LC_ALL, значение кодирует всю комбинацию выбранных стандартов для всех категорий. В этом случае, значение не только одиночное имя стандарта. Фактически, мы не делаем ни каких обещаний относительно того, на что это походит. Но если Вы определяете то же самое " имя стандарта" LC_ALL в последующем обращении к setlocale, она восстанавливает ту же самую комбинацию выборов стандарта.

Когда аргумент locale - не пустой указатель, строка, возвращенная setlocale отражает изменяемый стандарт.

Если Вы определяете пустую строку для стандарта, это означает, что нужно читать соответствующую переменную среды и использовать ее значение для установки стандарта указанного класса.

Если Вы определяете недопустимое имя стандарта, setlocale, возвращает пустой указатель и оставляет текущий стандарт неизмененным.

Вот пример, показывающий, как Вы могли бы использовать setlocale, чтобы временно включить к новый стандарт.

                 #include <stddef.h>
                 #include <locale.h>
                 #include <stdlib.h>
                 #include <string.h>
                 void
                 with_other_locale (char *new_locale,
                                         void (*subroutine) (int),
                                         int argument)
                 {
                         char *old_locale, *saved_locale;
                         old_locale = setlocale (LC_ALL, NULL);
                         saved_locale = strdup (old_locale);
                         if (old_locale == NULL)
                                 fatal ("Out of memory");
                         setlocale (LC_ALL, new_locale);
                         (*subroutine) (argument);
                         setlocale (LC_ALL, saved_locale);
                         free (saved_locale);
                 }
Примечание о переносимости: Некоторые системы ANSI C могут определять дополнительные категории стандарта. Для переносимости, запомните, что любой символ, начинающийся с " LC_ " мог бы быть определен в "locale.h".

19.5 Стандартные Стандарты

Единственые имена стандартов, которые Вы можете находить во всех операционных системах - это три стандартных: "C" Это - стандартный стандарт Cи. Атрибуты и поведение, которое он обеспечивает определены в стандарте ANSI C. Когда ваша программа начинается, она первоначально использует этот стандарт по умолчанию. " POSIX " Это - стандартный стандарт POSIX. В настоящее время, это - побочный результат исследования для стандартного стандарта Cи. "" Пустое имя говорит о том, что нужно выбрать стандарт, основанный на переменных среды. См. Раздел 19.3 [Категории Стандарта].

Определение и установка стандартов - обязаность вашего администратора системы (или человека, который установил библиотеку GNU C). Некоторые системы могут позволять пользователям создавать стандарты, но мы не обсуждаем это здесь.

Если ваша программа должна использовать кое-что отличное от "C" стандарт, она будет более переносимой, если Вы используете стандарт, который пользователь определяет со средой, а не пробуя определить некоторый ненормативный стандарт явно именем. Помните, что различные машины могут иметь различные наборы устанавливаемых стандартов.

19.6 Числовое Форматирование

Когда Вы хотите форматировать число или количество валюты, используя соглашения текущего стандарта, Вы можете использовать функцию localeconv, чтобы получить данные относительно того, как делать это. Функция localeconv объявлена в заглавном файле "locale.h ".

       struct lconv * localeconv  
Функция localeconv возвращает указатель на структуру, чьи компоненты содержат информацию относительно того, как числовые и валютные значения должны форматироваться в текущем стандарте.

Вы не должны измениять структуру или ее содержимое. Структура может быть записана поверх последующими обращениями к localeconv, или обращениями к setlocale, но никакая другая функция в библиотеке не записывает поверх этого значения.

       struct lconv 
Это - тип данных значения, возвращенного localeconv.

Если элемент структуры struct lconv имеет тип char, и значение ­ CHAR_MAX, это означает что текущий стандарт не имеет никакого значения для этого параметра.

Обобщенные Параметры Числового Форматирования

Это - стандартные элементы struct lconv; хотя могут иметься и другие.

       char *decimal_point
       char *mon_decimal_point
Это - разделители Десятичных точек, используемые в форматировании невалютных и валютных чисел, соответственно. В "C" стандарте, значение decimal_point - ".", а значение mon_decimal_point - "".
       char *thousands_sep
       char *mon_thousands_sep
Это - разделители, используемые, чтобы разграничить группы цифр налево от десятичной точки при форматировании невалютных и валютных чисел, соответственно. В "C" стандарте, оба элемента имеет значение "" (пустая строка).
       char *grouping
       char *mon_grouping
Это - строки, которые определяют, как группировать цифры налево от десятичной точки. Группировка grouping применяется к невалютным количествам, а mon_grouping применяется к валютным числам. Используются или thousands_sep или mon_thousands_sep, чтобы отделить группы цифры.

Каждая строка состоит из десятичных чисел, отделяемых точками с запятой. Последовательные числа (слева направо) дают размеры последовательных групп (справа налево, начиная с десятичной точки). Последнее число в строке используется много раз для всех оставшихся групп.

Если последним целым числом является -1, это означает, что любые остающиеся цифры формируются в одну большую группу без разделителей.

Например, при - "4;3;2", правильная группировка для числа 123456787654321 будет " 12 ", " 34 ", " 56 ", " 78 ", " 765 ", " 4321 ". С разделителем ",", число было бы напечатано как " 12,34,56,78,765,4321 ".

Значение "3" указывает повторение группы из трех цифр, как обычно используется в США.

В стандарте " C ", и grouping и mon_grouping имеют значения "". Это значение не определяет никакой группировки вообще.

       char int_frac_digits
       char frac_digits
Это - целые, указывающие, сколько дробных цифр (направо от десятичной точки) должны отобразиться в валютном значении в международных и местных форматах, соответственно. (Наиболее часто, оба элемента имеют то же самое значение.)

В стандарте " C ", оба этих элемента имеют значение CHAR_MAX, означая "неопределенный".

Мы рекомендуем не печатать никаких дробных цифр. (Этот стандарт также определяет пустую строку для mon_decimal_point, так печать любых дробных цифр только путала бы!)

Печать Символа Валюты

Эти элементы структуры struct lconv определяют, как печатать символ, чтобы идентифицировать валютное значение международный аналог " $ ".

Каждая страна имеет два стандартных символа валюты. Местный символ валюты используется обычно внутри страны, в то время как международный символ валюты используется всемирно, чтобы обратиться к валюте этой страны, когда необходимо указать страну недвусмысленно.

Например, многие страны используют доллар в качестве денежной единицы, но для международных валют важно определить, что мы имеем дело с Канадскими долларами, вместо Американских долларов или Австралийских долларов. Но когда контекст известен, не имеется никакой потребности объявлять эти явные долларовые количества в Канадских долларах.

       char *currency_symbol
Местный символ валюты для выбранного стандарта.

В стандарте " C ", этот элемент имеет значение "" (пустая строка), означая "неопределенный". Стандарт ANSI не говорит, что делать, когда Вы находите это значение; мы рекомендуем, чтобы Вы просто печатали пустую строку, как Вы печатали бы любую другую строку, найденную в соответствующем элементе.

       char *int_curr_symbol
Международный символ валюты для выбранного стандарта.

Значение int_curr_symbol должно обычно состоять из трех­ символьного сокращения, определенного Международной организацией по стандартизации международного эталона как один из 4217 Кодов для Представления Валюты и Фондов, сопровождаемых разделителем (часто пробел).

В стандарте " C ", этот элемент имеет значение "" (пустая строка), означая "неопределенный". Мы рекомендуем, чтобы Вы просто печатали пустую строку, как Вы печатали бы любую другую строку, найденную в соответствующем элементе.

       char p_cs_precedes
       char n_cs_precedes
Эти элементы равны 1, если currency_symbol строка предшествует значению валютного количества, или 0, если строка следует за значением. P_cs_precedes лемент применяется к положительным значениям (или нулю), а n_cs_precedes элемент применяется к отрицательным значениям.

В стандарте " C ", оба этих элемента имеют значение CHAR_MAX, означая "неопределенный". Стандарт ANSI не говорит, что делать, когда Вы находите это значение, но мы рекомендуем печатать символ валюты перед числом. Это - правильно для большинства стран. Другими словами, обработайте все значения отличные от нуля подобно этим элементам.

Стандарт POSIX говорит, что эти два элемента обращаются к int_curr_symbol также как currency_symbol. Стандарт ANSI C, кажется, подразумевает, что они должны применяться только к currency_symbol_so, int_curr_symbol должен всегда предшествовать количеству.

Мы можем только предполагать, которое из этих соответствует обычному соглашению для печати международных символов валюты. Наше предположение - то, что они должны всегда предшествовать количеству. Если мы выясим точный ответ, мы поместим его здесь.

       char p_sep_by_space
       char n_sep_by_space
Эти элементы равны 1, если между currency_symbol строкой и количеством ставится пробел, или 0, если никакого пробела не ставится. P_sep_by_space элемент применяется к положительным количествам (или нулю), и n_sep_by_space элемент применяется к отрицательным количествам.

В стандарте "C", оба этих элемента имеют значение CHAR_MAX, означая "неопределенный". Стандарт ANSI не говорит, что Вы должны делать, когда Вы находите это значение; мы предлагаем, чтобы Вы обрабатывали это как 1 (печатайте пробел). Другими словами, обрабатывайте все значения отличные от нуля подобно этому элементу.

Эти элементы применяются только к currency_symbol. Когда Вы используете int_curr_symbol, Вы никогда не печатаете дополнительный пробел, потому что int_curr_symbol непосредственно содержит соответствующий разделитель.

Стандарт POSIX говорит, что эти два элемента обращаются к int_curr_symbol также как currency_symbol. Но пример в стандарте ANSI C ясно подразумевает, что они должны применяться только к currency_symbol_that, int_curr_symbol содержит любой соответствующий разделитель, так что Вы никогда не должны печатать дополнительный пробел.

Мы рекомендуем, чтобы Вы игнорировали эти элементы при печати международных символов валюты и не печатали никаких дополнительных пробелов.

Печать Значения Количества Денег

Эти элементы структуры struct lconv определяют, как печатать знак в валютном значении.

       char *positive_sign
       char *negative_sign
Это - строки, используемые, чтобы указать положительное (или нуль) и отрицательное (соответственно) валютные количества.

В стандарте "C", оба этих элемента имеет значение "" (пустая строка), означая "неопределенный".

Стандарт ANSI не говорит, что делать, когда Вы находите это значение; мы рекомендуем печатать positive_sign. Для отрицательного значения, печатайте negative_sign, если Вы находите его, если оно и positive_sign пусты, тогда печатайте "-" взамен. (Не указывать знак вообще - кажется довольно неблагоразумным.)

       char p_sign_posn
       char n_sign_posn
Эти элементы имеют значения типа integer и указывают, как позиционировать знак для неотрицательных и отрицательных валютных количеств, соответственно. (Строка, используется знаком определенным в positive_sign или negative_sign.) возможные значения следующие:
       0 Символ валюты и количество должны быть окружены круглыми скобками.
       1 Печатает строку перед символом валюты и количеством.
       2 Печатает строку после символа валюты и количества.
       3 Печатает строку сразу перед символом валюты.
       4 Печатает строку сразу за символом валюты.
CHAR_MAX "Неопределен". Оба элемента имеют это значение в стандарте " C ". Стандарт ANSI не говорит, что Вы должны делать, когда значение - CHAR_MAX. Мы рекомендуем, чтобы Вы печатали знак после символа валюты.


Next Previous Contents