utf-8 в Си
Добавлено: 11 авг 2016, 15:28
Писать на Си пользовательские приложение задача не из приятных, но как еще
можно практиковаться на начальном этапе? Решила я написать себе консольное
приложение что бы упростить жизнь на работе. Задача тривиальная. Имеется
база сотрудников нашего управления. И нужно на начальном этапе организовать
поиск в базе по фамилии. Так сказать создать динамическую сортировку совпадений
по мере ввода букафъ. Зачем это надо? Фамилий много, набирать полное соответствующее
имя не хочется. И ошибки сразу на лицо если скажем совпадения не найдены. Применение
шаблонов регулярных выражений это следующий этап и забегать вперед не стану.
Какие трудности поджидали меня в Си. Первое перевод терминала в неканонический режим
работы я уже описывала вот здесь
Но сколько я не гуглила не смогла найти подсказку как мне вводить символы разной длинны
в терминале. Пришлось засучить рукава, обложится подсказками и приняться самой за дело.
Первое что я не забыла это то что в библиотеке управления терминалом termios есть флаги
которые отвечают за размер буфера в неканоническом режиме и флага ожидания с момента
первого введенного байта. Библитеки wchar и wctype любезно предоставили мне функции
по работе со знаками размером в 4 байта и соответствующие к ним типы переменных wchar_t и wint_t.
Префикс 'w' подразумевает слово 'wide' - расширеный. Кирилица состоит из двух байтовых символов.
Но я не стала ограничивать размер вводимых знаков 2 байтами и выбрала буфер ввода размером
в 4 байта, а время ожидания после ввода первого байта определила в долю секунды. Теперь
мой терминальчик может считывать любые символы за раз состоящие от одного байта(аски) до китайских
иероглифов и даже чередовать их ввод. Теперь каждый последующий введенный символ после проверки на
корректность, можно добавлять к предыдущему введенному и в цикле организовать нужный динамический
поиск по базе. Даже закомичу свой кусочек кода .
[album]440[/album]
можно практиковаться на начальном этапе? Решила я написать себе консольное
приложение что бы упростить жизнь на работе. Задача тривиальная. Имеется
база сотрудников нашего управления. И нужно на начальном этапе организовать
поиск в базе по фамилии. Так сказать создать динамическую сортировку совпадений
по мере ввода букафъ. Зачем это надо? Фамилий много, набирать полное соответствующее
имя не хочется. И ошибки сразу на лицо если скажем совпадения не найдены. Применение
шаблонов регулярных выражений это следующий этап и забегать вперед не стану.
Какие трудности поджидали меня в Си. Первое перевод терминала в неканонический режим
работы я уже описывала вот здесь
Но сколько я не гуглила не смогла найти подсказку как мне вводить символы разной длинны
в терминале. Пришлось засучить рукава, обложится подсказками и приняться самой за дело.
Первое что я не забыла это то что в библиотеке управления терминалом termios есть флаги
которые отвечают за размер буфера в неканоническом режиме и флага ожидания с момента
первого введенного байта. Библитеки wchar и wctype любезно предоставили мне функции
по работе со знаками размером в 4 байта и соответствующие к ним типы переменных wchar_t и wint_t.
Префикс 'w' подразумевает слово 'wide' - расширеный. Кирилица состоит из двух байтовых символов.
Но я не стала ограничивать размер вводимых знаков 2 байтами и выбрала буфер ввода размером
в 4 байта, а время ожидания после ввода первого байта определила в долю секунды. Теперь
мой терминальчик может считывать любые символы за раз состоящие от одного байта(аски) до китайских
иероглифов и даже чередовать их ввод. Теперь каждый последующий введенный символ после проверки на
корректность, можно добавлять к предыдущему введенному и в цикле организовать нужный динамический
поиск по базе. Даже закомичу свой кусочек кода .
Код: Выделить всё
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <wctype.h>
#include <wchar.h>
#include <locale.h>
struct termios oldt, newt;
int main()
{
if (! setlocale(LC_ALL, "ru_RU.utf8mb4"))
puts("error locale"), exit(1);
// wchar_t wc[80] = L"ща";
// wint_t ch = L'щ';
wint_t terminate = L'\n';
wchar_t wch;
tcgetattr(0, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON|ECHO);
newt.c_cc[VMIN] = 4;
newt.c_cc[VTIME] = 1;
tcsetattr(0, TCSANOW, &newt);
while((wch = getwchar()) != terminate)
{
putwchar(wch);
putwchar(terminate);
// wprintf(L"%lc %d %zd\n", wch, wch, sizeof(wch));
}
tcsetattr(0, TCSANOW, &oldt);
return 0;
}