Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

14 *--cp = loc.thousands_sep[0]; /* XXX - предположение, что это один символ */

15 if (loc.grouping[ii+1] == 0)

16 jj = 0; /* продолжить использовать текущий val в loc.grouping [ii] */

17 else if (loc.grouping[ii+1] == CHAR_MAX)

18 quote_flag = FALSE;

19 else {

20 ii++;

21 jj = 0;

22 }

23 }

24 #endif

25 uval /= 10;

26 } while (uval > 0);

(Номера строк даны относительно начала фрагмента.) Некоторые части кода, не имеющие отношения к обсуждению, были опущены, чтобы облегчить фокусировку на важных частях.

Переменная

loc
, используемая в строках 13–17, представляет
struct lconv
. Она инициализируется в
main
. Здесь для нас интерес представляет
loc.thousands_sep
, который является символом разделителя тысяч, и
loc.grouping
, который является массивом, описывающим число цифр между разделителями. Нулевой элемент означает «использовать для всех последующих цифр значение предыдущего элемента», а значение
CHAR_MAX
означает «прекратить вставку разделителей тысяч».

С таким введением, давайте посмотрим на код. Строка 7 устанавливает

uval
, которая является беззнаковой версией форматируемого значения.
ii
и
jj
отслеживают положение в
loc.grouping
и число цифр в текущей группе, которые были преобразованы, соответственно [142] .
quote_flag
равен true, когда в спецификации преобразования был отмечен символ
'
.

Цикл

do-while
генерирует символы цифр в обратном порядке, заполняя буфер с конца к началу. Каждая цифра создается в строке 11. Затем строка 25 делится на 10 путем смещения значения вправо на одну десятичную цифру.

142

Нам, вероятно, следовало выбрать более осмысленные имена вместо простых

ii
и
jj
, поскольку использующий их код короткий, отсутствие у нас воображения не представляет значительной проблемы — Примеч. автора.

Нас интересуют строки 12–24. Эта работа осуществляется только на системе, поддерживающей локали, на что указывает наличие заголовочного файла

<locale.h>
. Именованная константа
HAVE_LOCALE
в такой системе будет равна true [143] .

Когда условие в строке 13 истинно, настало время добавить символ разделителя тысяч. Это условие можно прочесть как «если требуется группировка и текущее положение в

loc.grouping
указывает нужное для группировки количество и текущее число цифр равно группируемому количеству». Если это условие истинно, строка 14 добавляет символ разделителя тысяч. Комментарий обращает внимание на предположение, которое, вероятно, истинно, но которое может вновь появиться позже. ('XXX' является традиционным способом выделения опасного или сомнительного кода. Его легко отыскать, и он весьма заметен для читателя кода.)

143

Это устанавливается механизмом Autoconf и Automake. Autoconf и Automake являются мощными программными наборами, дающими возможность поддержки широкого круга Unix-систем систематическим образом — Примеч. автора.

После использования текущего положения в

loc.grouping
строки 15–22 заглядывают в значение в следующем положении. Если это 0, продолжает использоваться значение текущего положения. Мы указываем на это, восстанавливая 0 в
jj
(строка 16). С другой стороны, если в следующем положении
CHAR_MAX
, группировка должна быть прекращена, и строка 18 убирает ее, устанавливая
quote_flag
в false. В противном случае, следующее значение является значением группировки, поэтому строка 20 восстанавливает 0 в
jj
, а строка 21 увеличивает значение
ii
.

Это низкоуровневый, подробный код. Однако, поняв один раз, как представляется информация в

struct lconv
, код читать просто (и его было просто писать).

13.2.7. Форматирование значений даты и времени:

ctime
и
strftime

В разделе 6.1 «Времена и даты» описаны функции для получения и форматирования значений времени и даты. Функция

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

/* ch13-times.c --- демонстрация времени на основе локали */

#include <stdio.h>

#include <locale.h>

#include <time.h>

int main(void) {

 char buf[100];

 time_t now;

 struct tm *curtime;

 setlocale(LC_ALL, "");

 time(&now);

 curtime = localtime(&now);

 (void)strftime(buf, sizeof buf,

"It is now %A, %B %d, %Y, %I:%M %p", curtime);

 printf("%s\n", buf);

 printf("ctime says: %s", ctime(&now));

 exit(0);

}

При запуске программы мы видим, что результаты

strftime
в самом деле варьируют, тогда как результаты
ctime
— нет:

$ LC_ALL=en_US ch13-times /* Время в Соединенных Штатах */

It is now Friday, July 11, 2003, 10:35 AM

ctime says: Fri Jul 11 10:35:55 2003

$ LC_ALL=it_IT ch13-times /* Время в Италии */

It is now venerdi, luglio 11, 2003, 10:36

ctime says: Fri Jul 11 10:36:00 2003

$ LC_ALL=fr_FR ch13-times /* Время во Франции */

It is now vendredi, juillet 11, 2003, 10:36

ctime says: Fri Jul 11 10:36:05 2003

Причина отсутствия изменений в том, что

ctime
asctime
, на которой основана
ctime
) является традиционным интерфейсом; он существует для поддержки старого кода,
strftime
, будучи более новым интерфейсом (первоначально разработанным для C89), свободен использовать локали.

13.2.8. Другие данные локали:

nl_langinfo

Хотя ранее мы сказали, что API

catgets
трудно использовать, одна часть этого API обычно полезна:
nl_langinfo
. Она предоставляет дополнительные связанные с локалью сведения, помимо тех, которые доступны из
struct lconv
:

Поделиться:
Популярные книги

Личный аптекарь императора. Том 4

Карелин Сергей Витальевич
4. Личный аптекарь императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Личный аптекарь императора. Том 4

Последний Паладин. Том 2

Саваровский Роман
2. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 2

Неучтенный элемент. Том 8

NikL
8. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 8

Черный Маг Императора 20

Герда Александр
20. Черный маг императора
Фантастика:
юмористическое фэнтези
аниме
сказочная фантастика
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Черный Маг Императора 20

Л. Пантелеев — Л. Чуковская. Переписка (1929–1987)

Пантелеев Леонид
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Л. Пантелеев — Л. Чуковская. Переписка (1929–1987)

Ученик. Книга 4

Первухин Андрей Евгеньевич
4. Ученик
Фантастика:
фэнтези
5.67
рейтинг книги
Ученик. Книга 4

Наследие Маозари 9

Панежин Евгений
9. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
сказочная фантастика
6.25
рейтинг книги
Наследие Маозари 9

Кодекс Охотника. Книга XIX

Винокуров Юрий
19. Кодекс Охотника
Фантастика:
фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XIX

Тринадцатый IX

NikL
9. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
сказочная фантастика
5.00
рейтинг книги
Тринадцатый IX

Война

Валериев Игорь
7. Ермак
Фантастика:
боевая фантастика
альтернативная история
5.25
рейтинг книги
Война

Последний Паладин

Саваровский Роман
1. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин

Князь Андер Арес 3

Грехов Тимофей
3. Андер Арес
Фантастика:
рпг
аниме
фэнтези
5.00
рейтинг книги
Князь Андер Арес 3

Справочник логопеда

Коллектив авторов
Научно-образовательная:
медицина
6.25
рейтинг книги
Справочник логопеда

Сирийский рубеж

Дорин Михаил
5. Рубеж
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Сирийский рубеж