cha*_*era 14 unicode visual-c++
请考虑以下代码片段,在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;
}
Run Code Online (Sandbox Code Playgroud)
第一个wcout语句输出"hello"(而不是"hello?test!")第二个wcout语句输出什么.
就像0xf021(和其他?)Unicode字符导致wcout失败一样.
这个特殊的Unicode字符0xf021(编码为UTF-16)是Basic Multilingual Plane中"Private Use Area"的一部分.我注意到Windows控制台应用程序没有对Unicode字符的广泛支持,但通常每个字符至少由默认字符(例如"?")表示,即使不支持呈现特定字形.
是什么导致wcout流窒息?有没有办法在它进入这种状态后重置它?
Igo*_*nik 15
wcout或者确切地说,wfilebuf它在内部使用的实例,将宽字符转换为窄字符,然后将这些字符写入文件(在您的情况下为stdout).转换由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;
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*SFT 13
将stdout的模式设置为_O_U16TEXT将允许您将Unicode字符写入wcout流以及wprintf.(参见传统智慧是迟钝的,又名@#%&*是_O_U16TEXT是什么?)这是使这项工作正确的方法.
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout << L"hello\xf021test!" << std::endl;
std::wcout << L"\x043a\x043e\x0448\x043a\x0430 \x65e5\x672c\x56fd" << std::endl;
std::wcout << L"Now this prints!" << std::endl;
Run Code Online (Sandbox Code Playgroud)
它不再是必需的,但您可以通过调用clear重置已进入错误状态的流:
if (std::wcout.fail())
{
std::wcout.clear();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3573 次 |
| 最近记录: |