Форум программистов, компьютерный форум CyberForum.ru

Кириллица в UTF-8 - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 23, средняя оценка - 4.65
Mieczeslaw
0 / 0 / 0
Регистрация: 28.09.2012
Сообщений: 20
30.09.2012, 00:41     Кириллица в UTF-8 #1
Отдельно задам ранее возникший вопрос. При работе с однобайтовой кодировкой (например, в старом борланде 3.1, где, если я правильно понял, использовалась досовская cp866) можно было просто написать:
C++
1
2
3
4
5
6
void main()
{
    char s[6];
    strcpy(s, "ПРИВЕТ");
    printf("%c %c", s[0], s[2]);
}
и получить на выходе то, что и предполагалось: "П И".
Если же исходный код в UTF-8, написанное выше уже не сработает: одному символу кириллицы, если не ошибаюсь, соответствуют 2 байта, и массив 6 символов не вместит.
Объясните дилетанту, пожалуйста - как всё-таки правильно работать с символами в UTF-8?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.09.2012, 00:41     Кириллица в UTF-8
Посмотрите здесь:

кириллица C++
кириллица в памяти C++
Преобразовние Utf-16 <=> Utf-8 C++
C++ Кириллица в языке си++
C++ Кириллица в консоли
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
NoMasters
Псевдослучайный
1737 / 1080 / 69
Регистрация: 13.09.2011
Сообщений: 3,093
30.09.2012, 00:50     Кириллица в UTF-8 #2
Проще всего переводить в wchar и работать уже имея по символу на элемент.
Mieczeslaw
0 / 0 / 0
Регистрация: 28.09.2012
Сообщений: 20
30.09.2012, 01:11  [ТС]     Кириллица в UTF-8 #3
Если речь о wchar_t, то я пробовал вот таким образом:
C++
1
2
3
4
5
6
7
int main()
{
    wchar_t s[6];
    wcscpy(s, "ПРИВЕТ");
    
    getch();
}
, но компилятор (MinGW) выдаёт:

checkthis.c: In function 'int main()':
checkthis.c:14:26: error: cannot convert 'const char*' to 'const wchar_t*' for argument '2' to 'wchar_t* wcscpy(wchar_t*, const wchar_t*)'.

То есть кириллица моя всё равно воспринимается как обычный char, хотя сохранена в UTF-8. Или нужно иначе?
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.09.2012, 01:30     Кириллица в UTF-8 #4
C++
1
wcscpy(s, L"ПРИВЕТ");
И массив нужно на 7 элементов. Одно место под '\0'.
Mieczeslaw
0 / 0 / 0
Регистрация: 28.09.2012
Сообщений: 20
30.09.2012, 01:45  [ТС]     Кириллица в UTF-8 #5
Цитата Сообщение от alsav22 Посмотреть сообщение
C++
1
wcscpy(s, L"ПРИВЕТ");
Так компилируется. А вывод
C++
1
printf("%c", s[0])
как должен измениться?
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.09.2012, 01:54     Кириллица в UTF-8 #6
C++
1
wprintf(L"%c", s[0]);
Mieczeslaw
0 / 0 / 0
Регистрация: 28.09.2012
Сообщений: 20
30.09.2012, 03:20  [ТС]     Кириллица в UTF-8 #7
Ага, спасибо большое. Теперь осталось только разобраться, как это применить к PDCurses. Там простейшая аналогия обычному printf() называется printw(), но поддержки wchar_t я в ней не вижу.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.09.2012, 03:54     Кириллица в UTF-8 #8
A такого как cout там нет?
Mieczeslaw
0 / 0 / 0
Регистрация: 28.09.2012
Сообщений: 20
30.09.2012, 15:41  [ТС]     Кириллица в UTF-8 #9
Потокового ввода-вывода нет. Проштудировал руководство по PDCurses - там целая группа функций для вывода, но все они требуют в качестве аргумента const char или const wchar_t (а точнее, указатель):
C++
1
2
int add_wch(const cchar_t *wch); //вывод одного широкого символа
int addwstr(const wchar_t *wstr); //вывод строки из широких символов
Вот такое работает, кстати:
C++
1
2
3
wchar_t s[7];
wcscpy(s, L"ПРИВЕТ");
addwstr(s);
- выводит "ПРИВЕТ", как и нужно.
Mieczeslaw
0 / 0 / 0
Регистрация: 28.09.2012
Сообщений: 20
02.10.2012, 02:47  [ТС]     Кириллица в UTF-8 #10
Честно говоря, я застрял Вроде бы всё просто:
C++
1
2
wchar_t s = L'П';
add_wch(s);
выдаёт ошибку: error: invalid conversion from 'wchar_t' to 'const cchar_t* {aka const long unsigned int*}' [-fpermissive]
Если добавить атрибут текста:
C++
1
2
wchar_t s = L'u';
add_wch(s | WA_BOLD); //то же, что attron(WA_BOLD)
имеем другую ошибку преобразования типов: error: invalid conversion from 'long unsigned int' to 'const cchar_t* {aka const long unsigned int*}' [-fpermissive].
Наконец, не срабатывает даже вызов от заведомой константы:
C++
1
2
3
4
//и так:
add_wch('s' | WA_BOLD);
//и так:
add_wch(L's' | WA_BOLD);
получаем ошибку, совпадающую с последней. add_wch() срабатывает только при обращении к внутренним макросам:
C++
1
add_wch(WACS_DIAMOND);
действительно выводит ромбик.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
02.10.2012, 03:46     Кириллица в UTF-8 #11
Если так:
C++
1
2
wchar_t s = L'П';
add_wch((cchar_t*)&s);
PDCurses трудно к Студии прикрутить?
Mieczeslaw
0 / 0 / 0
Регистрация: 28.09.2012
Сообщений: 20
02.10.2012, 16:09  [ТС]     Кириллица в UTF-8 #12
Так срабатывает, выводит нужную букву, но по-моему, не работают атрибуты текста.
C++
1
2
3
4
5
6
7
8
9
start_color();
wclear(stdscr);
init_pair(1, COLOR_WHITE, COLOR_BLACK);
 
wchar_t s = L'П';
attron(COLOR_PAIR(1) | WA_BOLD);
add_wch((cchar_t*)&s);
    
wrefresh(stdscr);
Должна выводиться ярко-белая "П", а выводится тёмно-серым. Как я понял из руководства, cchar_t - это тип данных, описанный в самой curses и содержащий информацию о самом символе, его атрибутах и цвете.
Кликните здесь для просмотра всего текста

------------------------------------------------------------------------------------------
|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|..| 3| 2| 1| 0|
------------------------------------------------------------------------------------------
---------color number---------|-------modifiers--------------|-------character eg 'a'

The available non-color attributes are bold, underline, invisible,
right-line, left-line, protect, reverse and blink. 256 color pairs (8
bits), 8 bits for other attributes, and 16 bits for character data.

Однако в руководстве напрямую не говорится, как это тип формируется.
Не уверен насчёт Студии, однако к своему MinGW я подключил довольно просто. В простейшем варианте качается с sourceforge архив с уже собранной dll-кой и парой .h-файлов, всё это раскидывается по /bin и /include, потом
C++
1
#include <curses.h>
Правда, для поддержки UTF-8 я собирал из исходников. Аналогично, скачал архив, собрал
Кликните здесь для просмотра всего текста
mingw32-make.exe -f mingwin32.mak WIDE=Y UTF8=Y DLL=Y
далее так же - раскидал файлы по соответствующим папкам, #include. Думаю, в Студии дело обстоит не сложнее.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
02.10.2012, 16:29     Кириллица в UTF-8 #13
Почему нельзя задать: cchar_t s; ?

Добавлено через 2 минуты
Цитата Сообщение от Mieczeslaw Посмотреть сообщение
В простейшем варианте качается с sourceforge архив с уже собранной dll-кой и парой .h-файлов, всё это раскидывается по /bin и /include, потом
C++
1
#include <curses.h>
Я так, в общем-то, и сделал. Всё компилируется, но ничего не выводится на экран.
Mieczeslaw
0 / 0 / 0
Регистрация: 28.09.2012
Сообщений: 20
02.10.2012, 17:32  [ТС]     Кириллица в UTF-8 #14
Совсем ничего или, например, курсор сдвигается на одно знакоместо вправо, оставляя за собой пустоту?
C++
1
wrefresh(stdscr);
не забыли?

Добавлено через 6 минут
Вот, точно. Наконец-то нечто приличное:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <curses.h>
 
int main()
{
    initscr();
    start_color();
    wclear(stdscr);
    
           init_pair(1, COLOR_WHITE, COLOR_BLACK);
    
    cchar_t s = L'П';
    attron(COLOR_PAIR(1) | A_BOLD);
    
    add_wch(&s);
    
    wrefresh(stdscr);
 
    getch();
 
    endwin();
    
    return 0;
}
Выводит ярко-белую "П".
Вроде я уже пробовал в одном из вариантов сразу объявлять свой символ как cchar, но что-то меня тогда сбило.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
02.10.2012, 18:10     Кириллица в UTF-8 #15
Последний код сработал. Предыдущие совсем ничего не выводили.

Добавлено через 26 минут
Это в Студии сработал. А Code Blocks (mingv) не хочет компилироваться. С русской буквой показывает в этой строке ошибку: cchar_t s = L'П'; error: converting to execution character set: Invalid argument
Если заменить на ангилийскую, то эта строка проходит, но выдаёт кучу ошибок, если я правильно понял, линковщик (не понимает вот это: initscr(); и пр.). Наверное, не видит библиотеку pdcurses.lib. Я её насовал везде, где только можно, и ещё отдельно в установках линковщика, в Code Blocks, прописал. Что ещё нужно, не пойму.
Mieczeslaw
0 / 0 / 0
Регистрация: 28.09.2012
Сообщений: 20
02.10.2012, 19:23  [ТС]     Кириллица в UTF-8 #16
Google выдаёт в самом верху обсуждение на форуме codeblocks.org, там кому-то помог такой совет:
Try to use compiler switch "-finput-charset=<source charset>" in build options.
Сам не работал с Code::Blocks, честно говоря.

Добавлено через 2 минуты
MinGW в чистом виде вроде бы воспринимает опции для линкера через опцию -l в командной строке. Соответственно, g++ checkthis.c -o checkthis.exe -lpdcurses.
Mieczeslaw
0 / 0 / 0
Регистрация: 28.09.2012
Сообщений: 20
04.10.2012, 22:53  [ТС]     Кириллица в UTF-8 #17
Ну как, удалось заставить код сработать в Code::Blocks?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.10.2012, 23:05     Кириллица в UTF-8
Еще ссылки по теме:

Конвертация из ASCII в UTF-32 или UTF-8 в UTF-32 C++
Кириллица C++
Подсчитать количество вхождений буквы (кириллица) в строку (кириллица) C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
alsav22
04.10.2012, 23:05     Кириллица в UTF-8
  #18

Не по теме:

Цитата Сообщение от Mieczeslaw Посмотреть сообщение
Ну как, удалось заставить код сработать в Code::Blocks?
Нет. Если бы сильно нужно было, а просто так - время дорого.

Yandex
Объявления
04.10.2012, 23:05     Кириллица в UTF-8
Ответ Создать тему
Опции темы

Текущее время: 09:45. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru