- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Linux программирование в примерах - Арнольд Роббинс
Шрифт:
Интервал:
Закладка:
decimal_point = [.]
thousands_sep = []
int_curr_symbol = []
currency_symbol = []
mon_decimal_point = []
mon_thousands_sep = []
positive_sign = []
negative_sign = []
Обратите внимание, что значение int_curr_symbol в локали "en_US" включает завершающий символ пробела, который служит для отделения символа от последующего денежного значения.
13.2.5. Высокоуровневое числовое и денежное форматирование: strfmon() и printf()
После рассмотрения всех полей struct lconv вы можете поинтересоваться: «Нужно ли мне на самом деле выяснять, как использовать все эти сведения, просто для форматирования денежного значения?» К счастью, ответом является «нет».[140] Функция strfmon() делает за вас всю работу:
#include <monetary.h> /* POSIX */
ssize_t strfmon(char *s, size_t max, const char *format, ...);
Эта функция во многом подобна strftime() (см. раздел 6.1.3.2 «Сложное форматирование времени: strftime()»), используя format для копирования символов букв и форматированных числовых значений в s, помещая в нее не более max символов. Следующая простая программа, ch13-strfmon.c, демонстрирует работу strfmon():
/* ch13-strfmon.c --- демонстрация strfmon() */
#include <stdio.h>
#include <locale.h>
#include <monetary.h>
int main(void) {
char buf[BUFSIZ];
double val = 1234.567;
setlocale(LC_ALL, "");
strfmon(buf, sizeof buf, "You owe me %n (%i)n", val, val);
fputs(buf, stdout);
return 0;
}
При запуске в двух различных локалях она выдает такой результат:
$ LC_ALL=en_US ch13-strfmon /* В Соединенных Штатах */
You owe me $1,234.57 (USD 1,234.57)
$ LC_ALL=it_IT ch13-strfmon /* В Италии */
You owe me EUR 1.235 (EUR 1.235)
Как вы можете видеть, strfmon() подобна strftime(), копируя обычные символы в буфер назначения без изменений и форматируя аргументы в соответствии со своими собственными спецификациями форматирования. Их всего три.
%n Вывести национальное (т.е. местное) представление значения валюты.
%i Вывести международное представление значения валюты.
%% Вывести символ '%'.
Форматируемые значения должны иметь тип double. Разницу между %n и %i мы видим в локали "en_US": %n использует символ $, тогда как %i использует USD, которая означает «доллары США».
Гибкость — и соответственно определенная сложность — сопровождают многие функции API, разработанные для POSIX, и strfmon() не является исключением. Как и с printf(), несколько необязательных элементов, которые могут быть между % и i или n, обеспечивают повышенный контроль. Полные формы следующие:
%[флаги][ширина поля][#точность_слева][.точность_справа]i
%[флаги][ширина поля][#точность_слева][.точность_справа]n
%% /* Не допускаются поля флагов, ширины и т.д. */
Флаги перечислены в табл. 13.2.
Таблица 13.2. Флаги для strfmon()
Флаг Значение =с Использовать символ с в качестве символа числового заполнения слева. Символом по умолчанию является пробел. Обычной альтернативой является 0 ^ Запретить использование символа группировки (например, запятой в Соединенных Штатах) ( Отрицательные значения заключать в скобки. Несовместим с флагом + + Обрабатывать положительные/отрицательные значения обычным образом. Использовать положительные и отрицательные знаки локали. Несовместим с флагом ( ! Не включать символ валюты. Этот флаг полезен, если вы хотите использовать strfmon() для более гибкого форматирования обычных чисел, чем это предусматривает sprintf() - Выровнять результат слева. По умолчанию используется выравнивание справа. Этот флаг не действует без указания ширины поляШирина поля является строкой десятичных цифр, представляющих минимальную ширину. По умолчанию использует столько символов, сколько необходимо, основываясь на оставшейся части спецификации. Значения, меньшие ширины поля, дополняются пробелами слева (или справа, если указан флаг '-').
Точность слева состоит из символа # и строки десятичных цифр. Она указывает минимальное число цифр, которые должны быть слева от десятичного символа-разделителя дробной части[141]; если преобразованное значение меньше этого, результат выравнивается символом числового заполнения. По умолчанию используется пробел, однако для его изменения можно использовать флаг =. Символы группировки не включаются в общий счет.
Наконец, точность справа состоит из символа '.' и строки десятичных цифр. Она указывает, с каким числом значащих цифр округлить значение до форматирования. По умолчанию используются поля frac_digits и int_frac_digits в struct lconv. Если это значение равно 0, десятичная точка не выводится.
strfmon() возвращает число символов, помещенных в буфер, не включая завершающий нулевой байт. Если недостаточно места, функция возвращает -1 и устанавливает errno в E2BIG.
Помимо strfmon(), POSIX (но не ISO С) предусматривает специальный флаг — символ одинарной кавычки, ' — для форматов printf() %i, %d, %u, %f, %F, %g и %G. В локалях, имеющих разделитель тысяч, этот флаг добавляет и его. Следующая простая программа, ch13-quoteflag.c, демонстрирует вывод:
/* ch13-quoteflag.c --- демонстрация флага кавычки printf */
#include <stdio.h>
#include <locale.h>
int main(void) {
setlocale(LC_ALL, ""); /* Это нужно, иначе не будет работать */
printf("%'dn", 1234567);
return 0;
}
Вот что происходит для двух различных локалей: в одной есть разделитель тысяч, в другой нет:
$ LC_ALL=C ch13-quoteflag /* Обычное окружение без разделителя */
1234567
$ LC_ALL=en_US ch13-quoteflag /* Локаль с разделителем (англ.) */
1,234,567
На время написания лишь GNU/Linux и Solaris поддерживают флаг '. Дважды проверьте справочную страницу printf(3) на своей системе.
13.2.6. Пример: форматирование числовых значений в gawk
gawk реализует свои собственные версии функций printf() и sprintf(). Для полного использования локали gawk должен поддерживать флаг ', как в С. Следующий фрагмент из файла builtin.c в gawk 3.1.4 показывает, как gawk использует struct lconv для числового форматирования:
1 case 'd':
2 case 'i':
3 ...
4 tmpval = force_number(arg);
5
6 ...
7 uval = (uintmax_t)tmpval;
8 ...
9 ii = jj = 0;
10 do {
11 *--cp = (char)('0' + uval % 10);
12 #ifdef HAVE_LOCALE_H
13 if (quote_flag && loc.grouping[ii] && ++jj == loc.grouping[ii]) {
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, когда в спецификации преобразования был отмечен символ '.

