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

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

Запись от bedvit размещена 07.12.2017 в 13:15
Показов 18681 Комментарии 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;
}
Использованные ресурсы:
Кликните здесь для просмотра всего текста


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

В итоге, см.рис.
Миниатюры
Нажмите на изображение для увеличения
Название: Console.PNG
Просмотров: 1230
Размер:	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 Замабувараев вне форума
 
Новые блоги и статьи
Рисование коллайдеров физического движка Box2D-WASM v3 на Three.js
8Observer8 04.06.2025
Erin Catto (автор Box2D) переписал с нуля Box2D v2 с С++ на Си и появилась версия Box2D v3. Birch-san собрал Box2D v3 в WebAssembly (WASM), чтобы можно было использовать Box2D v3 на JavaScript. В. . .
Worker Threads и многопоточность в Node.js
Reangularity 03.06.2025
Если вы когда-нибудь посещали собеседования на позицию Node. js разработчика, почти наверняка слышали заезженную фразу: "Node. js - однопоточная платформа". Звучит как неоспоримый факт, который. . .
Event-Driven CQRS на C# с паттерном Outbox
stackOverflow 03.06.2025
В традиционной модели происходит примерно следующее: вы получаете команду, обрабатываете ее, сохраняете результат в базу данных и затем пытаетесь опубликовать событие в брокер сообщений. Но что если. . .
OwenLogic: перенос сетевых переменных в панель Weintek (EasyBuilder Pro)
ФедосеевПавел 03.06.2025
ВВЕДЕНИЕ ПЕРЕД ЭКСПЕРИМЕНТАМИ - СОЗДАЙТЕ РЕЗЕРВНЫЕ КОПИИ ПРОЕКТОВ На момент написания статьи (02 июня 2025 г. ) самыми актуальными версиями ПО являются: OwenLogic v. 2. 10. 366 EasyBuilder Pro. . .
Dev-c++5.11 Покорение вершины
russiannick 02.06.2025
С утра преследовала одна мысль - вот бы выучить С++. Сказано-сделано. Окончив смену, скачал в интернете бестселлер Дэвиса Dev-C++ для чайников. Книга оказалась интересной и я скачал среду, на примере. . .
Тестирование Pull Request в Kubernetes с GitHub Actions и GKE
Mr. Docker 02.06.2025
Мы все знаем, что тестирование на локальной машине или в изолированном CI-окружении — это не совсем то же самое, что тестирование в реальном кластере Kubernetes. Контекстно-зависимые ошибки, проблемы. . .
Оптимизация CMake для ускорения сборки
bytestream 02.06.2025
Вы когда-нибудь ловили себя на мысле, что пока ваш проект компилируется, можно успеть сварить кофе, прочитать главу книги или даже сбегать в соседний офис? Если да, то добро пожаловать в клуб. . .
JS String.prototype.localeCo­mpare()
mr_dramm 02.06.2025
скопировано из этой темы чтобы не потерялось. localeCompare без указания локали для сравнения строк под капотом использует Intl. Collator , который работает согласно Unicode Collation Algorithm. . .
Облако проектов
russiannick 01.06.2025
Слава Джа, написал прогу для компиляции. Значит написал компилятор? Обьем кода 300+ строк. Язык-яву. Вводим данные, заполняем поля, тычем радиобаттоны. И по итогу в поле результат получам листинг. . .
Rust и квантовые вычисления: интеграция с Q# и Qiskit
golander 01.06.2025
Мир квантовых вычислений традиционно оставался закрытым клубом для высокоуровневых языков типа Python и специализированных DSL вроде Q#. Однако в последние годы Rust начал тихую революцию в этой. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
OSZAR »