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

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

Запись от bedvit размещена 07.12.2017 в 13:15

Простой способ больше не вспоминать о кодировках 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"; //выводим
 
    system("pause");//пауза для просмотра результата
    return 0;
}
Использованные ресурсы:
Кликните здесь для просмотра всего текста

В итоге, см.рис.
Миниатюры
Нажмите на изображение для увеличения
Название: Console.PNG
Просмотров: 272
Размер:	12.4 Кб
ID:	4538  
Размещено в Без категории
Просмотров 602 Комментарии 16
Всего комментариев 16
Комментарии
  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 вне форума
    Обновил(-а) Avazart 07.12.2017 в 17:09
  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 вне форума
    Обновил(-а) Avazart 09.12.2017 в 00:25
  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 вне форума
    Обновил(-а) Avazart 10.12.2017 в 14:52
  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 вне форума
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru