Форум программистов, компьютерный форум, киберфорум
bedvit
Войти
Регистрация
Восстановить пароль

Настройка консоли:Unicode, размер, шрифт (корректный ввод/вывод строк с кириллицей, пробелами, знаками юникода) С++

Запись от bedvit размещена 07.12.2017 в 13:15
Показов 19879 Комментарии 19
Метки c++

Простой способ больше не вспоминать о кодировках CP866, ANSI(рус.:CP1251) и костылях, типа "setlocale(LC_ALL, "Russian")" или "SetConsoleCP(1251); SetConsoleOutputCP(1251);"
Применимо (протестировано) для Microsoft Visual Studio.
В данном блоге я не буду рассматривать разные способы ввода\вывода в консоль строк с нужной кодировкой и их дальнейшего корректного использования в коде (в сети их предостаточно)
Я рассмотрю и подробно распишу - один, который, по моему мнению, довольно прост, универсален и снимает все проблемы с вводом/выводом строк на разных языках, в т.ч. с пробелами.

Этот способ - переход на Unicode.
Если точнее, то на Unicode(UTF-16) - стандартный 2-х байтный (16-битный). Родной для Win (UTF-16LE) и других программ.

Итак, если вам это подходит, прошу к дальнейшему чтению и обсуждению...

Шаг.1 Создаем проект "Unicode" в Студии ("Файл"-"Создать проект"-"С++-консольное приложение")
Меняем
C++
1
int main()
на широкую версию
C++
1
int wmain(int argc, wchar_t* argv[], wchar_t *envp[])
Шаг.2 Переводим ввод\вывод в консоль на Unicode
C++
1
2
3
    _setmode(_fileno(stdout), _O_U16TEXT);
    _setmode(_fileno(stdin), _O_U16TEXT);
    _setmode(_fileno(stderr), _O_U16TEXT);
Шаг.3 Переводим на Unicode, собственно сам проект: "Файл" - "Сохранить "Unicode.cpp" как" ... далее... на кнопке "сохранить"-список "сохранить с кодировкой" (на вопрос "заменить?" жмем - "да") - выбираем "Юникод, кодовая страница 1200" - "ОК"
или в общепринятый UTF-8 (в Студии по умолчанию кодировка для проектов "UTF-8 с сигнатурой", оставляем её)

Шаг.4 Добавляем возможность поменять размер окна (если вам не нужно можно эту часть пропустить) и сам шрифт (для возможности отображать Unicode-символы) - я выбрал стандартный, присутствующий у всех - Lucida Console.
Если у вас установлен нужный шрифт с поддержкой нужных вам символов, эту часть то же можно пропустить.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
////////////////////меняем размер консоли - опционально - можно пропустить
        system("mode con cols=100 lines=50"); //размер окна, вывод нужного количества строк в консоль
        HANDLE  hout = GetStdHandle(STD_OUTPUT_HANDLE);
        COORD  size{ 100,100 };//символов строки, строк
        SetConsoleScreenBufferSize(hout, size);//размер буфера
        ///////////////////////////////////Меняем шрифт для отображения символов Unicode, можно пропустить - если у вас установлен такой
        CONSOLE_FONT_INFOEX cfi;
        cfi.cbSize = sizeof(CONSOLE_FONT_INFOEX);
        cfi.nFont = 0;
        cfi.dwFontSize.X = 8;
        cfi.dwFontSize.Y = 14;
        cfi.FontFamily = FF_DONTCARE;
        cfi.FontWeight = FW_NORMAL;
        wcscpy_s(cfi.FaceName, L"Lucida Console");
        SetCurrentConsoleFontEx(hout, false, &cfi);
        ///////////////////////////////////Меняем шрифт
Шаг.5 Итоговый - добавляем сам код для тестирования - Готово! - Тестируем.
Я написал тест для двух вариантов, используя "std::" и не используя, выбирайте нужный вам.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// Unicode.cpp: определяет точку входа для консольного приложения.
 
#include <fcntl.h>
#include <io.h>
#include <Windows.h>
#include <iostream>
#include <sstream>
 
int wmain(int argc, wchar_t* argv[], wchar_t *envp[]) //https://msdn.microsoft.com/ru-ru/library/bky3b5dh.aspx?f=255&MSPPError=-2147217396
{   ////////////////////Переводим в Юникод
    _setmode(_fileno(stdout), _O_U16TEXT); // https://msdn.microsoft.com/ru-ru/library/tw4k6df8.aspx
    _setmode(_fileno(stdin), _O_U16TEXT);
    _setmode(_fileno(stderr), _O_U16TEXT);
    ////////////////////Меняем размер консоли - можно пропустить, если вам не надо
    system("mode con cols=100 lines=50"); //размер окна, вывод нужного количества строк в консоль (видимых)
    HANDLE  hout = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD  size{ 100,100 };//символов строки, строк (если больше чем видимых, скрываются под ползунком прокрутки)
    SetConsoleScreenBufferSize(hout, size);//размер буфера
    ////////////////////Меняем шрифт для отображения символов Unicode, можно пропустить - если у вас установлен нужный
    CONSOLE_FONT_INFOEX cfi; //https://docs.microsoft.com/en-us/windows/console/console-font-infoex
    cfi.cbSize = sizeof(CONSOLE_FONT_INFOEX);
    cfi.nFont = 0;
    cfi.dwFontSize.X = 8;
    cfi.dwFontSize.Y = 14;
    cfi.FontFamily = FF_DONTCARE;
    cfi.FontWeight = FW_NORMAL;//400;
    wcscpy_s(cfi.FaceName, L"Lucida Console");
    SetCurrentConsoleFontEx(hout, false, &cfi);
    ////////////////////
 
    //Тест
    wchar_t* wchar_C = new wchar_t[255];
    //или
    std::wstring wstring_cpp;
 
    wprintf(L"%s", L"Testing unicode -- English -- Русский -- Ελληνικά -- Español.\n");
    // или
    std::wcout << L"Testing unicode -- English -- Русский -- Ελληνικά -- Español." << std::endl;
    
    //далее
    wprintf(L"%s", L"Введите строку с пробелами (разными символами, разной раскладки)(C): \n");
    fgetws(wchar_C, 255, stdin); //забираем строку с пробелами
    wchar_C[wcscspn(wchar_C, L"\n")] = 0; //убираем перевод строки
    wprintf(L"%s", wchar_C); //выводим
    //или
    std::wcout << L"\nВведите строку с пробелами (разными символами, разной раскладки)(C++std::): \n";
    std::getline(std::wcin, wstring_cpp); //забираем строку с пробелами
    std::wcout << wstring_cpp + L"\n"; //выводим
 
    system("pause");//пауза для просмотра результата
    return 0;
}
Использованные ресурсы:
Кликните здесь для просмотра всего текста
https://msdn.microsoft.com/ru-... 2147217396
https://msdn.microsoft.com/ru-... k6df8.aspx
https://docs.microsoft.com/en-... ont-infoex
обсуждение на stackoverflow, здесь ссылка рубится, не могу выложить


Мой репозиторий на GitHub

В итоге, см.рис.
Миниатюры
Нажмите на изображение для увеличения
Название: Console.PNG
Просмотров: 1341
Размер:	12.4 Кб
ID:	4538  
Метки c++
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 19
Комментарии
  1. Старый комментарий
    Аватар для bedvit
    Должно быть так в коде:

    wprintf(L"%s", L"Testing unicode -- English -- Русский -- Ελληνικά -- Español.\n");
    // или
    std::wcout << L"Testing unicode -- English -- Русский -- Ελληνικά -- Español." << std::endl;


    Здесь, на сайте, в текст. редакторе С++ отображаются, видимо, не все знаки Юникода, о чем собственно говорится в Шаг.4 или кодировка не Unicode(UTF-16).
    Для этого комментария выбрал шрифт "Lucida Console".
    Запись от bedvit размещена 07.12.2017 в 13:24 bedvit вне форума
  2. Старый комментарий
    Аватар для Avazart
    UTF-16 ? Обычно исходники в UTF-8 так что стоило бы на него ориентироваться.

    С другой стороны стоит ли менять шрифт консоли, кодировку ипр. когда это можно сделать вне программы, например батником.
    Запись от Avazart размещена 07.12.2017 в 17:07 Avazart вне форума
  3. Старый комментарий
    Аватар для bedvit
    Цитата Сообщение от Avazart
    исходники в UTF-8
    Все верно, поэтому есть Шаг.3 - исходники в UTF-16. Ибо в противном случае, текст из исходников (в "const wchar_t") будет отражаться не верно, ведь типов wchar_t и char16_t, std::wstring - 16 битные.
    А UTF-8 (1-4 байта в зависимости от символа, насколько я знаю).
    Конечно, если вы работаете с char или std::string, то для ввода/вывода консоли нужно будет перейти на широкие символы, это не всегда удобно, но в моем случае это было несложно (проект маленький)
    Запись от bedvit размещена 07.12.2017 в 19:09 bedvit вне форума
  4. Старый комментарий
    Аватар для bedvit
    Сейчас посмотрел, если перейти на UTF-8 и проект и консоль
    _setmode(_fileno(stdout), _O_U8TEXT);
    _setmode(_fileno(stdin), _O_U8TEXT);
    _setmode(_fileno(stderr), _O_U8TEXT);
    Кириллицу не понимает, а жаль...
    Запись от bedvit размещена 07.12.2017 в 19:29 bedvit вне форума
  5. Старый комментарий
    Аватар для Avazart
    Все верно, поэтому есть Шаг.3 - исходники в UTF-16.
    А смысл тогда? В таком уже случае может стоить проще использовать сp1251
    Запись от Avazart размещена 08.12.2017 в 20:23 Avazart вне форума
  6. Старый комментарий
    Аватар для bedvit
    сp1251 это русская ansi, в не локализованной win кириллица и прочие языки выводиться не будут. Чем удобен UTF-16: почти все символы 2 байта (4 только спец. китайский, музыкальные символы и прочая экзотика), wchar_t то же два байта, win на UTF-16 (api тоже) Все в одном размере, не нужно преобразований. Размер строки легко считается. Работает на любом win (кроме старокитайского) с вводом/отображением почти всех языков. Минусы - несколько большой объём занимаемой памяти.
    Запись от bedvit размещена 09.12.2017 в 00:07 bedvit вне форума
  7. Старый комментарий
    Аватар для Avazart
    Ansi это ansi, а cp1251 это как раз ее расширенная версия т.е ansi+кириллица.
    Если пишется под русскоязычную винду этого достаточно.

    Кстати у вас в коде только вывод символов, а ввод кириллицы проверяли, работает ?
    Запись от Avazart размещена 09.12.2017 в 00:20 Avazart вне форума
  8. Старый комментарий
    Аватар для bedvit
    Windows-1251 (сp1251) это русская ansi (расширенная ascii, в которой часть символов, со 128-го, заменены/добавлены на русский алфавит и проч. символы), т.е. одна из разновидности набора ANSI, содержащая символы русского алфавита. Собственно поэтому и гемор с разными локализациями при использовании ANSI(локализованных) .
    Да, и ввод и вывод работает на русском и других языках, можете попробовать
    В приложенном рис. это строки 4-5, 7-8 (ввод-вывод).
    Запись от bedvit размещена 09.12.2017 в 21:54 bedvit вне форума
  9. Старый комментарий
    Аватар для Avazart
    Да только главную проблему это не решает (кодировка исходника нестандартная)
    Запись от Avazart размещена 10.12.2017 в 14:19 Avazart вне форума
  10. Старый комментарий
    Аватар для Avazart
    Кстати там UCS BE или LE ?
    Запись от Avazart размещена 10.12.2017 в 14:40 Avazart вне форума
  11. Старый комментарий
    Аватар для bedvit
    Да, шаг.3 необходим для данного решения. Сфера применения - или новые проекты или проекты, легко переходящие с UTF-8, на UTF-16 или для тех, кто и так пользуется wchar_t или std::wstring. Минусом - нужно больше памяти под проект и под строку. Плюсом - нормальная кодировка почти всех языков на всех win, любой локализации.
    Запись от bedvit размещена 10.12.2017 в 14:49 bedvit вне форума
  12. Старый комментарий
    Аватар для bedvit
    Для win родной Win (UTF-16LE), поэтому думаю LE.
    Запись от bedvit размещена 10.12.2017 в 14:51 bedvit вне форума
  13. Старый комментарий
    Аватар для Avazart
    Ну под линуксом исходники обычно в UTF-8 и используют char, std::string
    То сколько памяти нужно это дело последнее в наше время.
    Запись от Avazart размещена 10.12.2017 в 14:51 Avazart вне форума
  14. Старый комментарий
    Аватар для bedvit
    Да и под win используют UTF-8 и используют char, std::string. Хотя больше чем под линуксом, используют и двухбайтовые wchar_t (TCHAR - пока не завоевал моего доверия ). Насколько я знаю, wchar_t в линуксе - 4х байтовый? (не работал в данной ОС)
    Запись от bedvit размещена 10.12.2017 в 15:45 bedvit вне форума
  15. Старый комментарий
    Аватар для Avazart
    wchar_t может плавать от платформы к платформе.
    Запись от Avazart размещена 10.12.2017 в 18:06 Avazart вне форума
  16. Старый комментарий
    Аватар для Замабувараев
    Высокоуровневые си плас плас функции.
    Если хотите низкоуровневую работу, то можно использовать WriteConsoleW.
    Запись от Замабувараев размещена 05.05.2018 в 14:34 Замабувараев вне форума
  17. Старый комментарий
    Все-таки переводить исходники в UTF-16 не нужно. Компилятор перекодирует строки, помеченные префиксом L.
    Файл в может быть спокойно в UTF-8, как общепринято.
    Запись от DrOffset размещена 28.06.2020 в 18:42 DrOffset вне форума
  18. Старый комментарий
    Аватар для bedvit
    DrOffset, Спасибо за корректировку. Все верно. Отметил этот момент в главном топике.
    Запись от bedvit размещена 26.10.2022 в 11:01 bedvit вне форума
  19. Старый комментарий
    Аватар для Замабувараев
    Круто конечно, но никак не могу отогнать от себя мысль что Си Плас Плас вместо программ создаёт Bloatware.
    На фрибесике такой екзешник займёт полтора‐два килобайта.
    А на Си Плас Плас сколько?
    Запись от Замабувараев размещена 26.10.2022 в 19:23 Замабувараев вне форума
 
Новые блоги и статьи
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru