UTF-8与cpp案例所需的解释

时间:2012-09-22 15:47:55

标签: c++ visual-studio utf-8

我在Windows 7 64bit上安装了Microsoft Visual Studio 2010。 (在项目属性中,“字符集”设置为“未设置”,但每个设置都会导致相同的输出。)

源代码:

  using namespace std;
  char const charTest[] = "árvíztűrő tükörfúrógép ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP\n";
  cout << charTest;
  printf(charTest);
  if(set_codepage()) // SetConsoleOutputCP(CP_UTF8); // *1
    cerr << "DEBUG: set_codepage(): OK" << endl;
  else
    cerr << "DEBUG: set_codepage(): FAIL" << endl;
  cout << charTest;
  printf(charTest);

* 1:包括windows.h混淆了一些东西,所以我将它从一个单独的cpp包含起来。

编译后的二进制文件包含正确的UTF-8字节序列。如果我将控制台设置为带有chcp 65001的UTF-8并发出type main.cpp,则字符串会正确显示。

测试(控制台设置为使用Lucida Console字体):

D:\dev\user\geometry\Debug>chcp
Active code page: 852

D:\dev\user\geometry\Debug>listProcessing.exe
├írv├şzt┼▒r┼Ĺ t├╝k├Ârf├║r├│g├ęp ├üRV├ŹZT┼░R┼É T├ťK├ľRF├ÜR├ôG├ëP
├írv├şzt┼▒r┼Ĺ t├╝k├Ârf├║r├│g├ęp ├üRV├ŹZT┼░R┼É T├ťK├ľRF├ÜR├ôG├ëP
DEBUG: set_codepage(): OK
��rv��zt��r�� t��k��rf��r��g��p ��RV��ZT��R�� T��K��RF��R��G��P
árvíztűrő tükörfúrógép ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP

背后的解释是什么?我可以以某种方式要求cout作为printf工作吗?

ATTACHMENT

许多人说Windows控制台根本不支持UTF-8字符。我是匈牙利的匈牙利人,我的Windows设置为英语(日期格式除外,它们设置为匈牙利语),西里尔字母仍然与匈牙利字母一起正确显示:

Hungarian and Cyrillic letters on console at the same time

(我的默认控制台代码页是CP852)

4 个答案:

答案 0 :(得分:4)

这里的不同之处在于C ++运行时和C库如何处理系统区域设置。

要使用std :: cout获得相同的结果,您可以尝试使用std::ios::imbue方法和std::locale

但是utf-8和C ++的主要问题描述了here

  

C ++ 03提供两种字符串文字。包含在双引号内的第一种类型生成一个类型为const char的以null结尾的数组。第二种,定义为L“”,产生一个类型为const wchar_t的以null结尾的数组,其中wchar_t是一个宽字符。这两种文字类型都不支持使用UTF-8,UTF-16或任何其他类型的Unicode编码的字符串文字。

所以无论如何它都是特定于实现的,因此是不可移植的,因为非标准C ++输出流可以理解utf-8。

答案 1 :(得分:2)

对于我的理解,命令行看起来似乎与UTF-8一起工作

  1. 能够显示UTF-8字符的字体
  2. 在命令行中设置正确的代码页(chcp 65001),不确定此代码页是否支持完整的UTF-8字符,但它似乎是最好的
  3. 查看herehere

    [编辑]实际上65001在我签入PowerShell后实际上是UTF-8

    PS C:\Users\forcewill> chcp 65001
    Active code page: 65001
    PS C:\Users\forcewill>  [Console]::OutputEncoding
    
    
    BodyName          : utf-8
    EncodingName      : Unicode (UTF-8)
    HeaderName        : utf-8
    WebName           : utf-8
    WindowsCodePage   : 1200
    IsBrowserDisplay  : True
    IsBrowserSave     : True
    IsMailNewsDisplay : True
    IsMailNewsSave    : True
    IsSingleByte      : False
    EncoderFallback   : System.Text.EncoderReplacementFallback
    DecoderFallback   : System.Text.DecoderReplacementFallback
    IsReadOnly        : True
    CodePage          : 65001
    

    您可以使用比旧的cmd.exe

    更强大的PowerShell

    Edit:关于使用cout,如果我们在视觉工作室谈论正确的答案是here,可以找到关于visual studio中最佳做法的更为简单的解释here

答案 2 :(得分:1)

在Windows上,单字节字符串通常被解释为ASCII或一些256个字符的代码页。这意味着你将无法获得真正的unicode支持。

简短的回答是:使用宽字符串(例如L""árvíztűr..." - 注意L)然后写入wcout而不是cout。 Windows通常将宽(Windows上的2个字节)字符串解释为UTF-16(或至少是一个紧密变体),因此它将按预期工作。在Windows上,始终使用宽字符串以避免编码问题。

答案 3 :(得分:1)

首先,windows控制台不支持UTF-8(代码页65001,为了测试这个打开一个UTF-8编码文件,该文件在控制台中用记事本保存,你会在控制台中看到垃圾数据),所以按顺序检查你的输出你应该将它重定向到一个文件或类似的东西,并从那里检查结果(myapp&gt; test.txt)。

C / C ++中的第二个char []是一个字符序列,无论如何都可以解释程序员想要的,但是UTF-8是一个特殊的协议来编码unicode字符集,所以没有办法(除了C ++ 11)你写了一个字符序列和那些用UTF8编码的字符,因为我会说char p[3] = "اب",但如果编译器想用UTF-8编码它,那么它需要5个字节而不是3.所以你应该使用一些理解UTF-的东西8。

我建议将boost::locale::conv::utf_to_utf与宽字符串常量一起使用。例如

std::string sUTF8 = boost::locale::conv::utf_to_utf(L"árvíztűrő tükörfúrógép ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP\n");
std::cout << sUTF8; // or printf( "%s", sUTF8.c_str() );

这将确保你有UTF-8字符串,但是再次不用控制台检查它,因为它根本不理解UTF-8 !!