8

我在 Windows 7 64 位上有 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如果我使用和 issue将控制台设置为 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吗?

附件

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

控制台上同时显示匈牙利文和西里尔文字母

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

4

4 回答 4

4

这里的区别在于 C++ 运行时和 C 库如何处理系统语言环境。

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

但是这里描述的 utf-8 和 C++ 的主要问题

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

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

于 2012-09-28T09:57:26.520 回答
2

就我的理解而言,命令行似乎确实适用于 UTF-8

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

在这里这里看看

[编辑]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

您可以使用 PowerShell,它比旧的 cmd.exe 更强大

Edit:关于使用 cout 如果我们在 Visual Studio 中交谈,正确答案这里

于 2012-10-01T22:24:59.977 回答
1

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

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

于 2012-09-22T16:00:17.980 回答
1

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

于 2012-10-01T12:37:31.407 回答