visual-c++ - 为什么某些 Unicode 字符会导致 std::wcout 在控制台应用程序中失败?

标签 visual-c++ unicode

考虑以下代码片段,在 MS Visual Studio 2010/2012 上编译为控制台应用程序并在 Win7 上执行:

#include "stdafx.h"
#include <iostream>
#include <string>


const std::wstring test = L"hello\xf021test!";

int _tmain(int argc, _TCHAR* argv[])
{
    std::wcout << test << std::endl;
    std::wcout << L"This doesn't print either" << std::endl;

    return 0;
}

第一个 wcout 语句输出“hello”(而不是类似“hello?test!”的内容) 第二个 wcout 语句不输出任何内容。

就好像 0xf021(和其他?)Unicode 字符导致 wcout 失败。

这个特殊的 Unicode 字符 0xf021(编码为 UTF-16)是基本多语言平面中“私有(private)使用区域”的一部分。我注意到 Windows 控制台应用程序没有对 Unicode 字符的广泛支持,但通常每个字符至少由默认字符(例如“?”)表示,即使不支持渲染特定字形。

是什么导致 wcout 流阻塞?进入这个状态后有办法重置吗?

最佳答案

wcout,或者准确地说,它内部使用的 wfilebuf 实例,将宽字符转换为窄字符,然后将它们写入文件(在您的情况下, 标准输出)。转换由流区域设置中的 codecvt 方面执行;默认情况下,这只是 wctomb_s,转换为系统默认的 ANSI 代码页,又名 CP_ACP

显然,字符 '\xf021' 在系统上配置的默认代码页中无法表示。因此转换失败,并且在流中设置了failbit。一旦设置了failbit,所有后续调用都会立即失败。

我不知道有什么方法可以让 wcout 成功地将任意 Unicode 字符打印到控制台。 wprintf 可以工作,但需要进行一些调整:

#include <fcntl.h>
#include <io.h>
#include <string>

const std::wstring test = L"hello\xf021test!";

int _tmain(int argc, _TCHAR* argv[])
{
  _setmode(_fileno(stdout), _O_U16TEXT);
  wprintf(test.c_str());

  return 0;
}

关于visual-c++ - 为什么某些 Unicode 字符会导致 std::wcout 在控制台应用程序中失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19193429/

相关文章:

c - ID3D11XEffectMatrixVariable 替换为什么?

unicode - Unicode文档查看器工具?

c++ - 线程更新类对象

c++ - Cmake 找不到 Boost 文件夹

c++ - 从 cvpoint 转换为 cvpoint2d32f

c# - 寻找 PDF 文件解析器

java - 无论如何要在 Java 中为编译时更改 String 的编码?

java - 从文件中读取 Shorts 和字符

unicode - 无效的 Unicode 代码点 0xd83f

c++ - 如何从多索引中获取值