And*_*rew 68 c++ unicode iostream windows-console
嗨,我试图将unicode字符串输出到带有iostreams的控制台并失败.
我发现了这一点: 在c ++控制台应用程序中使用unicode字体 ,这个代码片段有效.
SetConsoleOutputCP(CP_UTF8);
wchar_t s[] = L"èéøÞ????æ?a";
int bufferSize = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
char* m = new char[bufferSize];
WideCharToMultiByte(CP_UTF8, 0, s, -1, m, bufferSize, NULL, NULL);
wprintf(L"%S", m);
Run Code Online (Sandbox Code Playgroud)
但是,我没有找到任何方法来使用iostream正确输出unicode.有什么建议?
这不起作用:
SetConsoleOutputCP(CP_UTF8);
utf8_locale = locale(old_locale,new boost::program_options::detail::utf8_codecvt_facet());
wcout.imbue(utf8_locale);
wcout << L"¡Hola!" << endl;
Run Code Online (Sandbox Code Playgroud)
编辑 我找不到任何其他解决方案,而不是在流中包装此片段.希望,有人有更好的想法.
//Unicode output for a Windows console
ostream &operator-(ostream &stream, const wchar_t *s)
{
int bufSize = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL);
char *buf = new char[bufSize];
WideCharToMultiByte(CP_UTF8, 0, s, -1, buf, bufSize, NULL, NULL);
wprintf(L"%S", buf);
delete[] buf;
return stream;
}
ostream &operator-(ostream &stream, const wstring &s)
{
stream - s.c_str();
return stream;
}
Run Code Online (Sandbox Code Playgroud)
Duc*_*tro 82
我在这里使用Visual Studio 2010验证了一个解决方案.通过这篇MSDN文章和MSDN博客文章.诀窍是一个模糊的调用_setmode(..., _O_U16TEXT)
.
解:
#include <iostream>
#include <io.h>
#include <fcntl.h>
int wmain(int argc, wchar_t* argv[])
{
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout << L"Testing unicode -- English -- ???????? -- Español." << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
截图:
vit*_*aut 24
在 C++23 中,您将能够用于可std::print
移植地打印 Unicode 文本:
import std;\n\nint main() {\n std::print("\xd0\xa8\xd1\x87\xd1\x83\xd1\x87\xd1\x8b\xd0\xbd\xd1\x88\xd1\x87\xd1\x8b\xd0\xbd\xd0\xb0");\n}\n
Run Code Online (Sandbox Code Playgroud)\n输出:
\n\xd0\xa8\xd1\x87\xd1\x83\xd1\x87\xd1\x8b\xd0\xbd\xd1\x88\xd1\x87\xd1\x8b\xd0\xbd\xd0\xb0\n
Run Code Online (Sandbox Code Playgroud)\n这需要使用/utf-8
MSVC中的编译器选项进行编译。
在它可用之前,您可以使用基于开源的 {fmt} 库std::print
。例如:
\xd0\xa8\xd1\x87\xd1\x83\xd1\x87\xd1\x8b\xd0\xbd\xd1\x88\xd1\x87\xd1\x8b\xd0\xbd\xd0\xb0\n
Run Code Online (Sandbox Code Playgroud)\n我不建议使用,wcout
因为它是不可移植的,如果不付出额外的努力,甚至无法在 Windows 上运行,例如:
#include <fmt/core.h>\n\nint main() {\n fmt::print("\xd0\xa8\xd1\x87\xd1\x83\xd1\x87\xd1\x8b\xd0\xbd\xd1\x88\xd1\x87\xd1\x8b\xd0\xbd\xd0\xb0");\n}\n
Run Code Online (Sandbox Code Playgroud)\n将打印:
\n\xe2\x94\x9c\xd0\xb8\xe2\x94\x9c\xd0\xb9\xe2\x94\x9c\xe2\x95\x95\xe2\x94\x9c\xd0\xae\xe2\x95\x9f\xe2\x95\x9c\xe2\x95\xa8\xe2\x95\x97\xe2\x95\xa4\xd0\xa9\xe2\x95\xac\xd0\xb3\xe2\x94\x9c\xd0\xb6\xe2\x94\x80\xd0\x9da\n
Run Code Online (Sandbox Code Playgroud)\n在西里尔文 Windows 中(ACP 1251,控制台 CP 866)。
\n免责声明:我是 {fmt} 和 C++23 的作者std::print
。
这是中文的世界。其实只是“你好”。我在Windows 10上对此进行了测试,但是我认为自Windows Vista起它可能会起作用。在Windows Vista之前,如果您需要编程解决方案,而不是配置控制台/注册表等,将很难。如果您确实需要在Windows 7上执行此操作,请查看此处: 更改控制台字体Windows 7
我不想声称这是唯一的解决方案,但这对我有用。
std::wcout
我正在使用Visual Studio 2017 CE。我创建了一个空白的控制台应用程序。可以使用默认设置。但是,如果您遇到问题或使用其他想法,则可能需要检查以下问题:
在项目属性中,找到配置属性->常规->项目默认值->字符集。它应该是“使用Unicode字符集”,而不是“多字节”。这将为您定义_UNICODE
和UNICODE
预处理器宏。
int wmain(int argc, wchar_t* argv[])
Run Code Online (Sandbox Code Playgroud)
另外我认为我们应该使用wmain
函数而不是main
。它们都可以工作,但是在unicode环境中wmain
可能更方便。
我的源文件也是UTF-16-LE编码的,这似乎是Visual Studio 2017中的默认文件。
这是很明显的。我们需要控制台中的unicode代码页。如果要检查默认代码页,只需打开控制台并输入chcp
任何参数即可。我们必须将其更改为65001,这是UTF-8代码页。Windows代码页标识符
该代码页有一个预处理程序宏:CP_UTF8
。我需要设置输入和输出代码页。当我省略任何一个时,输出是不正确的。
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
Run Code Online (Sandbox Code Playgroud)
您可能还需要检查这些函数的布尔返回值。
到目前为止,我还没有找到支持每个字符的控制台字体。所以我不得不选择一个。如果您要输出部分仅以一种字体提供而部分以另一种字体提供的字符,那么我认为找不到解决方案。仅当那里有支持每个字符的字体时,才可能。但是我也没有研究如何安装字体。
我认为不可能在同一控制台窗口中同时使用两种不同的字体。
如何找到兼容的字体?打开控制台,单击窗口左上角的图标,转到控制台窗口的属性。转到字体选项卡,然后选择一种字体,然后单击确定。然后尝试在控制台窗口中输入您的字符。重复此过程,直到找到可以使用的字体。然后记下字体名称。
您也可以在属性窗口中更改字体的大小。如果找到满意的尺寸,请记下在属性窗口中“所选字体”部分中显示的尺寸值。它将以像素为单位显示宽度和高度。
要以编程方式实际设置字体,请使用:
CONSOLE_FONT_INFOEX fontInfo;
// ... configure fontInfo
SetCurrentConsoleFontEx(hConsole, false, &fontInfo);
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参见此答案末尾的示例。或者在精美的手册中找到它:SetCurrentConsoleFont。从Windows Vista开始,此功能才存在。
您需要将语言环境设置为您要打印的字符的语言的语言环境。
char* a = setlocale(LC_ALL, "chinese");
Run Code Online (Sandbox Code Playgroud)
返回值很有趣。它将包含一个字符串,以准确描述选择的语言环境。尝试一下:-)我用chinese
和测试过german
。更多信息:setlocale
这里没有太多要说的。如果要输出宽字符,请使用此示例:
std::wcout << L"??" << std::endl;
Run Code Online (Sandbox Code Playgroud)
哦,别忘了L
宽字符的前缀!并且,如果您在源文件中键入像这样的文字unicode字符,则源文件必须是unicode编码的。就像Visual Studio中的默认值是UTF-16-LE。或者也许使用notepad ++并将编码设置为UCS-2 LE BOM
。
最后,我将其全部作为一个示例:
#include <Windows.h>
#include <iostream>
#include <io.h>
#include <fcntl.h>
#include <locale.h>
#include <wincon.h>
int wmain(int argc, wchar_t* argv[])
{
SetConsoleTitle(L"My Console Window - ??");
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
char* a = setlocale(LC_ALL, "chinese");
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
CONSOLE_FONT_INFOEX fontInfo;
fontInfo.cbSize = sizeof(fontInfo);
fontInfo.FontFamily = 54;
fontInfo.FontWeight = 400;
fontInfo.nFont = 0;
const wchar_t myFont[] = L"KaiTi";
fontInfo.dwFontSize = { 18, 41 };
std::copy(myFont, myFont + (sizeof(myFont) / sizeof(wchar_t)), fontInfo.FaceName);
SetCurrentConsoleFontEx(hConsole, false, &fontInfo);
std::wcout << L"Hello World!" << std::endl;
std::wcout << L"??!" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
干杯!
归档时间: |
|
查看次数: |
64523 次 |
最近记录: |