Читаем Linux программирование в примерах полностью

<p>13.2.2. Установка локали: <code>setlocale()</code></p>

Как уже упоминалось, если вы ничего не делаете, программы на С и библиотека С ведет себя так, как если бы использовалась локаль «С». Функция setlocale() устанавливает соответствующую локаль:

#include /* ISO С */

char *setlocale(int category, const char *locale);

Аргумент category является одной из категорий, описанных в разделе 13.2.1 «Категории локалей и переменные окружения». Аргумент locale является строкой, именующей используемую для этой категории локаль. Когда locale является пустой строкой (""), setlocale() проверяет соответствующие переменные окружения.

Если locale равно NULL, сведения о локали не изменяются. Вместо этого функция возвращает строку, представляющую текущую локаль для данной категории.

Поскольку каждая категория может быть установлена индивидуально, автор приложения решает, насколько будет программа использовать локаль. Например, если main() делает лишь это —

setlocale(LC_TIME, "");

 /* Использование локали только для времени и все */

— тогда, независимо от установленных в окружении других переменных LC_xxx, локали подчиняются лишь функции времени и даты. Все остальные действуют так, как если бы программа по-прежнему работала в локали «С». Сходным образом вызов:

setlocale(LC_TIME, "it_IT"); /* Время всегда итальянское */

заменяет переменную окружения LC_TIME (также, как LC_ALL), заставляя программу использовать для вычислений времени/даты данные для Италии. (Хотя Италия может быть прекрасным местом, программам лучше использовать "", чтобы они могли корректно работать везде; этот пример предназначен лишь для объяснения того, как работает setlocale().)

Можно индивидуально вызывать setlocale() для каждой категории, но простейшим способом является установка всего одним махом:

/* Находясь в Риме, вместо «всего» делайте все как римляне. :-) */

setlocale(LC_ALL, "");

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

char *initial_locale;

initial_locale = strdup(setlocale(LC_ALL, "")); /* сохранить копию */

...

(void)setlocale(LC_ALL, initial_locale); /* восстановить ее */

Здесь мы сохранили копию, использовав функцию POSIX strdup() (см. раздел 3.2.2 «Копирование строк: strdup()»).

<p>13.2.3. Сравнение строк: <code>strcoll()</code> и <code>strxfrm</code>()</p>

Знакомая функция strcmp() сравнивает две строки, возвращая отрицательное, нулевое или положительное значения, если первая строка меньше, равна или больше второй. Это сравнение основано на числовых значениях символов в машинном наборе символов. Из-за этого результаты strcmp() никогда не изменяются.

Однако, при наличии локалей простого числового сравнения недостаточно. Каждая локаль определяет для содержащихся в ней символов последовательность сортировки, другими словами, относительный порядок символов внутри локали. Например, в простом 7-битном ASCII у двух символов 'А' и 'а' десятичные значения равны 65 и 97 соответственно. Соответственно, во фрагменте

int i = strcmp("А", "a");

i имеет отрицательное значение. Однако, в локали "en_US.UTF-8" 'A' идет после 'a', а не перед ним. Таким образом, использование strcmp() для приложений, использующих локаль, является плохой мыслью, мы могли бы сказать, что она возвращает игнорирующий локаль ответ.

Функция strcoll() (string collate — сортировка строк) существует для сравнения строк с использованием локали:

#include /* ISO С */

int strcoll(const char *s1, const char *s2);

Она возвращает такие же отрицательные/нулевые/положительные значения, что и strcmp(). Следующая программа, ch13-compare.c, интерактивно демонстрирует разницу:

1  /* ch13-compare.с --- демонстрация strcmp() против strcoll() */

2

3  #include

4  #include

5  #include

6

7  int main(void)

8  {

9  #define STRBUFSIZE 1024

Перейти на страницу:

Похожие книги

C++ Primer Plus
C++ Primer Plus

C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.In C++ Primer Plus, you'll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:• A new detailed chapter on the changes and additional capabilities introduced in the C++11 standard• Complete, integrated discussion of both basic C language and additional C++ features• Clear guidance about when and why to use a feature• Hands-on learning with concise and simple examples that develop your understanding a concept or two at a time• Hundreds of practical sample programs• Review questions and programming exercises at the end of each chapter to test your understanding• Coverage of generic C++ gives you the greatest possible flexibility• Teaches the ISO standard, including discussions of templates, the Standard Template Library, the string class, exceptions, RTTI, and namespaces

Стивен Прата

Программирование, программы, базы данных