为了账号安全,请及时绑定邮箱和手机立即绑定

在Windows控制台应用程序中输出Unicode字符串

在Windows控制台应用程序中输出Unicode字符串

C++ C
PIPIONE 2019-06-10 16:35:20
在Windows控制台应用程序中输出Unicode字符串嗨,我试图将Unicode字符串输出到控制台碘流但失败了。我发现了这个:在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);但是,我没有找到任何方法来正确输出ioStreams的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;编辑我找不到任何其他的解决方案,只能把这个片段包在一个流里。希望有人有更好的主意。//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; }
查看完整描述

3 回答

?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

我在这里使用VisualStudio 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;}


查看完整回答
反对 回复 2019-06-10
?
偶然的你

TA贡献1841条经验 获得超3个赞

中文Unicode Hello World

这里是中文的“你好世界”。其实只是“你好”。我在Windows 10上测试了这一点,但我认为它可能会在WindowsVista之后工作。在WindowsVista之前,如果您想要一个编程解决方案,而不是配置控制台/注册表等,这将是很困难的。如果您真的需要在Windows 7上这样做,请看这里:更改控制台字体Windows 7

我不想说这是唯一的解决办法,但这才是对我有用的。

提纲

  1. Unicode项目设置
  2. 将控制台代码页设置为Unicode
  3. 查找并使用支持要显示的字符的字体。
  4. 使用要显示的语言的区域设置。
  5. 使用宽字符输出,即

    std::wcout

1项目设置

我正在使用VisualStudio2017 CE。我创建了一个空白控制台应用程序。默认设置没有问题。但是,如果您遇到问题或使用了不同的ide,您可能需要检查以下内容:

在项目属性中找到配置属性->General->Project Default->字符集。应该是“使用Unicode字符集”,而不是“多字节”。这将定义_UNICODEUNICODE预处理宏给你。

int wmain(int argc, wchar_t* argv[])

而且我觉得我们应该用wmain功能代替main..它们都可以工作,但是在unicode环境中。wmain可能更方便。

另外,我的源文件是UTF-16-le编码的,这似乎是默认的在VisualStudio 2017。

2.控制台代码页

这很明显。我们需要控制台中的Unicode代码页。如果要检查默认代码页,只需打开控制台并键入chcp任何争论。我们必须将它更改为65001,这是UTF-8代码页。Windows代码页标识符该代码页有一个预处理宏:CP_UTF8..我需要同时设置输入和输出代码页。当我忽略其中任何一个时,输出都是不正确的。

SetConsoleOutputCP(CP_UTF8);SetConsoleCP(CP_UTF8);

还可以检查这些函数的布尔值返回值。

3.选择字体

直到现在,我还没有找到支持每个字符的控制台字体。所以我不得不选择一个。如果您想要输出只在一种字体中部分可用,部分在另一种字体中可用的字符,那么我认为不可能找到解决方案。只有当有一种字体支持每一个字符时,才有可能。但我也没有研究如何安装字体。

我认为不可能同时在同一个控制台窗口中使用两种不同的字体。

如何找到兼容的字体?打开控制台,单击窗口左上方的图标,转到控制台窗口的属性。转到“字体”选项卡,选择一种字体,然后单击“确定”。然后尝试在控制台窗口中输入您的字符。重复此操作,直到找到可以使用的字体。然后记下字体的名称。

此外,还可以在“属性”窗口中更改字体的大小。如果您找到满意的大小,请记下“选定字体”部分“属性”窗口中显示的大小值。它将显示宽度和高度(以像素为单位)。

若要以编程方式实际设置字体,请使用:

CONSOLE_FONT_INFOEX fontInfo;// ... configure fontInfoSetCurrentConsoleFontEx(hConsole, false, &fontInfo);

有关详细信息,请参阅本答案末尾的示例。或者在精细的手册里查一查:SetCurrentConsoleFont..此功能只存在于WindowsVista之后。

4.设置地区

您需要将区域设置为要打印的字符的语言区域设置。

char* a = setlocale(LC_ALL, "chinese");

返回值很有趣。它将包含一个字符串,用于准确描述所选的区域设置。试试看:-)我用chinesegerman..更多信息:赛特

5.使用宽字符输出

这里没什么好说的。如果要输出宽字符,请使用以下示例:

std::wcout << L"你好" << std::endl;

哦,别忘了L宽字符的前缀!如果在源文件中键入这样的文本Unicode字符,则必须对源文件进行Unicode编码。与VisualStudio中的默认设置一样,UTF-16-le也是。或者用记事本+并将编码设置为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;}

干杯!


查看完整回答
反对 回复 2019-06-10
?
慕虎7371278

TA贡献1802条经验 获得超4个赞

wcout必须设置与CRT不同的区域设置。下面是如何解决这个问题的方法:

int _tmain(int argc, _TCHAR* argv[]){
    char* locale = setlocale(LC_ALL, "English"); // Get the CRT's current locale.
    std::locale lollocale(locale);
    setlocale(LC_ALL, locale); // Restore the CRT.
    std::wcout.imbue(lollocale); // Now set the std::wcout to have the locale that we got from the CRT.
    std::wcout << L"¡Hola!";
    std::cin.get();
    return 0;}

我刚刚测试了它,它显示这里的字符串非常好。


查看完整回答
反对 回复 2019-06-10
  • 3 回答
  • 0 关注
  • 1501 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信