Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
bedvit
449 / 157 / 18
Регистрация: 20.05.2016
Сообщений: 619
Записей в блоге: 6
#1

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

08.12.2017, 12:43. Просмотров 379. Ответов 11
Метки нет (Все метки)

Всем Привет!
Решил поделится опытом, к обсуждению:
Простой способ больше не вспоминать о кодировках 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" - "ОК"

Шаг.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 "stdafx.h"
#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"; //выводим
 
    _wsystem(L"pause");//пауза для просмотра результата
    return 0;
}
Использованные ресурсы:
Кликните здесь для просмотра всего текста

Блог по Теме.
В итоге, см.рис.
1
Миниатюры
Настройка консоли: Unicode, размер, шрифт (корректный ввод/вывод строк с кириллицей, пробелами, знаками юникода)  
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.12.2017, 12:43
Ответы с готовыми решениями:

Осуществить ввод с клавиатуры в символьный массив со всеми пробелами, знаками препинания и т.д.
1) Как осуществить ввод с клавиатуры в символьный массив со всеми пробелами,...

Как программно в консоли установить точечный шрифт, и его размер?
Как программно в консоли установить точечный шрифт, и его размер? Формулируйте...

Ввод длинных строк с пробелами
Доброго времени суток!!! Собственно как организовать ввод строки вида &quot;один...

Строка с пробелами (ввод и вывод)
Как вывести строку с пробелами? char domadres; own; if(sch&lt;20) {...

Не отображается символ Юникода в консоли
Всем привет. Скажите, как правильно вывести символ квадрата в консоли (0x00B2)?...

11
bedvit
449 / 157 / 18
Регистрация: 20.05.2016
Сообщений: 619
Записей в блоге: 6
08.12.2017, 12:45  [ТС] #2
Должно быть так в коде:

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

Здесь, на сайте, в текст. редакторе С++ отображаются, видимо, не все знаки Юникода, о чем собственно говорится в Шаг.4 или кодировка не Unicode(UTF-16)
0
bedvit
449 / 157 / 18
Регистрация: 20.05.2016
Сообщений: 619
Записей в блоге: 6
11.12.2017, 11:15  [ТС] #3
Плюсы: UTF-16 - почти все символы 2 байта (4 только спец. китайский, музыкальные символы и прочая экзотика), wchar_t то же два байта, win на UTF-16 (api тоже). Все в одном размере, не нужно преобразований. Размер строки легко считается. Работает на любом win (кроме старокитайского) с вводом/отображением почти всех языков. Минусы - бОльший объём занимаемой памяти под проект и под строку.
Сфера применения - или новые проекты или проекты, легко переходящие с UTF-8, на UTF-16 или для тех, кто и так пользуется wchar_t или std::wstring.
0
nmcf
6267 / 5575 / 2535
Регистрация: 14.04.2014
Сообщений: 23,468
11.12.2017, 14:02 #4
Что за старокитайский Windows?
0
bedvit
449 / 157 / 18
Регистрация: 20.05.2016
Сообщений: 619
Записей в блоге: 6
11.12.2017, 21:06  [ТС] #5
так обозвал часть символов не влезающие в 16 бит, в диапазоне 1000016..10FFFF16 и диапазон D80016..DFFF16 для кодирования так называемых суррогатных пар - 4 байтовые. И ОС на них.
0
bedvit
449 / 157 / 18
Регистрация: 20.05.2016
Сообщений: 619
Записей в блоге: 6
12.12.2017, 10:00  [ТС] #7
В случаях работы на разной локализации видны и на разных языках - да. Вы не согласны? Прошу аргументировать.
0
h3mbr0
294 / 104 / 30
Регистрация: 12.03.2012
Сообщений: 419
12.12.2017, 12:33 #8
bedvit, с этим я согласен
Я сослался на конкретные фразы
Цитата Сообщение от bedvit Посмотреть сообщение
Простой способ больше не вспоминать о кодировках CP866, ANSI(рус.:CP1251) и костылях, типа "setlocale(LC_ALL, "Russian")" или "SetConsoleCP(1251); SetConsoleOutputCP(1251);"
Цитата Сообщение от bedvit Посмотреть сообщение
_setmode
Безусловна, для новичков статья может оказаться полезной
К слову, относительно новые версии Consolas поддерживают
1252 Latin 1
1250 Latin 2: Eastern Europe
1251 Cyrillic
1253 Greek
1254 Turkish
1257 Windows Baltic
1258 Vietnamese
Mac Roman Macintosh Character Set (US Roman)
OEM OEM Character Set
869 IBM Greek
866 MS-DOS Russian
865 MS-DOS Nordic
863 MS-DOS Canadian French
861 MS-DOS Icelandic
860 MS-DOS Portuguese
857 IBM Turkish
855 IBM Cyrillic; primarily Russian
852 Latin 2
775 MS-DOS Baltic
737 Greek; former 437 G
850 WE/Latin 1
437 US
0
bedvit
449 / 157 / 18
Регистрация: 20.05.2016
Сообщений: 619
Записей в блоге: 6
12.12.2017, 15:02  [ТС] #9
h3mbr0, несколько грубо, но это было в контексте топика (универсальности), если оценивать вне топика, вполне рабочие инструменты в своей области, здесь не могу не согласится. А за информацию спасибо!
0
nmcf
6267 / 5575 / 2535
Регистрация: 14.04.2014
Сообщений: 23,468
12.12.2017, 15:25 #10
Цитата Сообщение от h3mbr0 Посмотреть сообщение
К слову, относительно новые версии Consolas поддерживают
И что? Он же предлагает радикально решить вопрос.
0
bedvit
449 / 157 / 18
Регистрация: 20.05.2016
Сообщений: 619
Записей в блоге: 6
12.12.2017, 18:00  [ТС] #11
Информация от h3mbr0, интересна (как инфо. связанная с консолью), но в предложенном решении кодовые страницы не нужны, здесь решается проблема глобально - переходом на Unicode, как и отметил nmcf.

Добавлено через 5 минут
Соответственно поддерживается значительно больше языков и символов (почти в полном диапазоне Unicode).
0
CDECLARATE
0 / 0 / 0
Регистрация: 05.12.2017
Сообщений: 7
Завершенные тесты: 1
29.03.2018, 19:11 #12
Автор, огромное тебе спасибо)
0
29.03.2018, 19:11
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.03.2018, 19:11

Количество выводимых строк в консоли (размер буфера экрана)
Такая проблема - по умолчанию в Windows размер &quot;буфера экрана&quot; для консоли -...

Структуры и ввод строк с пробелами: программа пропускает второй шаг, сразу переходя к третьему - почему?
Здравствуйте, уважаемые форумчане! Я новичок и в С++ и на этом форуме, так что...

Как в консоли автоматически выбрать шрифт Lucida Console, а не точечный шрифт?
Например №36 (размер шрифта 22х36).


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru