控制台配置相关 设置控制台代码页为UTF-8 简中版Windows下控制台默认代码页为936(GBK), 如果直接显示UTF8内容会乱码, 此时需要用以下代码将代码页修改到兼容UTF-8的代码页.
首先如果你使用msvc开发应用,必须确保启用编译器的utf8模式
如果你使用Visual Studio项目进行构建, 你需要在项目属性中找到Configuration Properties > C/C++ > Command Line
, 在Additional Options
中添加/utf-8
参数(详见此文档 )
如果你正在使用cmake进行构建,添加下面这段代码到CMakeList.txt
中
1 2 add_compile_options ("$<$<C_COMPILER_ID:MSVC>:/utf-8>" )add_compile_options ("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>" )
此时编译器将使用UTF8模式编译应用.
接下来在Main函数开头执行下列之一函数:
Method1: 使用std::setlocale 1 2 3 4 5 6 #include <clocale> void setConsoleUTF8 () { std::setlocale (LC_ALL, "chs.utf8" ); }
Method2: 使用Windows.h中的native方法 (实测此方法在输出效率上会优于Method1 (待验证))
1 2 3 4 5 6 7 8 9 10 11 12 #include <Windows.h> #include <codecvt> void setConsoleUTF8 () { SetConsoleOutputCP (CP_UTF8); #pragma warning (disable: 4996) std::locale utf8 (std::locale(), new std::codecvt_utf8_utf16<wchar_t >) ; std::wcout.imbue (utf8); #pragma warning (default: 4996) }
启用虚拟终端(VT Mode) 启用虚拟终端模式后可以在Windows中使用在Linux/Mac中可用的转义字符序列控制终端行为 经测试虚拟终端功能仅支持win10及更新的系统. 可参考相关文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <Windows.h> bool EnableVTMode () { HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE); if (hOut == INVALID_HANDLE_VALUE) { return false ; } DWORD dwMode = 0 ; if (!GetConsoleMode (hOut, &dwMode)) { return false ; } dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; if (!SetConsoleMode (hOut, dwMode)) { return false ; } return true ; }
控制台输出相关 获取/修改光标位置信息 使用以下方法可以快速获取/修改光标位置,或者按照相对距离移动光标
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 #include <Windows.h> void setCursorPos (int x, int y) { HANDLE hOut; COORD Position; hOut = GetStdHandle (STD_OUTPUT_HANDLE); Position.X = x; Position.Y = y; SetConsoleCursorPosition (hOut, Position); } COORD getCursorPos () { CONSOLE_SCREEN_BUFFER_INFO csbi; HANDLE hOut; COORD Position; hOut = GetStdHandle (STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo (hOut, &csbi); Position.X = csbi.dwCursorPosition.X; Position.Y = csbi.dwCursorPosition.Y; return Position; } void moveCursorPos (int vecX, int vecY) { auto initPos = getCursorPos (); HANDLE hOut; COORD Position; hOut = GetStdHandle (STD_OUTPUT_HANDLE); Position.X = initPos.X + vecX; Position.Y = initPos.Y + vecY; SetConsoleCursorPosition (hOut, Position); }
修改输出字符颜色 修改字符颜色建议使用VT模式完成 下面代码首先需要启用VT模式
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 53 54 55 #include <iostream> const char ESC = '\033' ;const int ATTR_NORMAL = 0 ; enum ConsoleForeground : int { FG_BLACK = 30 , FG_RED = 31 , FG_GREEN = 32 , FG_YELLOW = 33 , FG_BLUE = 34 , FG_MAGENTA = 35 , FG_CYAN = 36 , FG_WHITE = 37 , FG_DEFAULT = 39 , FG_LIGHT_BLACK = 90 , FG_LIGHT_RED = 91 , FG_LIGHT_GREEN = 92 , FG_LIGHT_YELLOW = 93 , FG_LIGHT_BLUE = 94 , FG_LIGHT_MAGENTA = 95 , FG_LIGHT_CYAN = 96 , FG_LIGHT_WHITE = 97 }; enum ConsoleBackground : int { BG_BLACK = 40 , BG_RED = 41 , BG_GREEN = 42 , BG_YELLOW = 43 , BG_BLUE = 44 , BG_MAGENTA = 45 , BG_CYAN = 46 , BG_WHITE = 47 , BG_DEFAULT = 49 , BG_LIGHT_BLACK = 100 , BG_LIGHT_RED = 101 , BG_LIGHT_GREEN = 102 , BG_LIGHT_YELLOW = 103 , BG_LIGHT_BLUE = 104 , BG_LIGHT_MAGENTA = 105 , BG_LIGHT_CYAN = 106 , BG_LIGHT_WHITE = 107 }; void setColorAttr (int attr) { std::cout << ESC << "[" << attr << "m" ; }
除此之外,部分终端还支持设置自定义的RGB颜色 详见Microsoft docs
清空控制台屏幕 Method1 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 void clearScreen () { HANDLE hConsole = GetStdHandle (STD_OUTPUT_HANDLE); COORD coordScreen = {0 , 0 }; DWORD cCharsWritten; CONSOLE_SCREEN_BUFFER_INFO csbi; DWORD dwConSize; if ( !GetConsoleScreenBufferInfo (hConsole, &csbi )) { return ; } dwConSize = csbi.dwSize.X * csbi.dwSize.Y; if ( !FillConsoleOutputCharacter (hConsole, (TCHAR) ' ' , dwConSize, coordScreen, &cCharsWritten )) { return ; } if ( !GetConsoleScreenBufferInfo ( hConsole, &csbi )) { return ; } if ( !FillConsoleOutputAttribute (hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )) { return ; } SetConsoleCursorPosition ( hConsole, coordScreen ); }
Method2: 需启用VT模式 此方法执行效率略低于Method1(待验证)
1 2 3 4 void clearScreen () {std::cout << "\033[H\033[2J\033[3J" ; }
处理键盘输入相关 使用io库操作标准输入时, 用户的输入都会被存储在缓冲区 如需直接对键盘输入进行处理, 可以使用conio.h
中的_getch()
与_kbhit()
函数
_getch()
可用于获取键盘输入的一个字符(不会回显), 当缓冲区内没有待处理的键盘输入时, 将阻塞程序
_kbhit()
可用于判断键盘是否有输入, 若缓冲区内没有待处理的键盘输入时, 将返回false
一个典型的键盘处理方法如下
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 void InputService::tickInput () { while (_kbhit()) { int key = _getch(); if (key == 0xE0 || key == 0 ) { key = _getch(); switch (key) { case 72 : break ; case 80 : break ; case 75 : break ; case 77 : break ; default : break ; } } else { } } }