c++, cout and UTF-8

8
希望这是一个简单的问题:在处理以多字节UTF-8字符结尾的字符串时,cout似乎会失败,我做错了什么吗?这是在Win7 x64上使用GCC(Mingw)时出现的问题。
**编辑抱歉如果我没有表达清楚,我并不关心缺失的字形或者字节被如何解释的问题,只是在调用cout<<s4之后它们没有显示出来(缺少BAR)。第一次显示后任何进一步的cout都不显示文本!
#include <cstdio>
#include <iostream>
#include <string>

int main() {
    std::string s1("abc");
    std::string s2("…");  // … = 0xE2 80 A6
    std::string s3("…abc");
    std::string s4("abc…");

    //In C
    fwrite(s1.c_str(), s1.size(), 1, stdout);
    printf(" FOO ");
    fwrite(s2.c_str(), s2.size(), 1, stdout);
    printf(" BAR ");
    fwrite(s3.c_str(), s3.size(), 1, stdout);
    printf(" FOO ");
    fwrite(s4.c_str(), s4.size(), 1, stdout);
    printf(" BAR\n\n"); 

    //C++
    std::cout << s1 << " FOO " << s2 << " BAR " << s3 << " FOO " << s4 << " BAR ";
}

// results:

// abc FOO ��� BAR ���abc FOO abc… BAR

// abc FOO ��� BAR ���abc FOO abc…

5
Windows控制台子系统并没有实际问题。在选择正确字体的情况下,WriteConsoleW的功能相当不错。然而,Windows不支持UTF-8编码,这意味着WriteConsoleA在这里将会出现问题。 - MSalters
在我的Ubuntu/gnome-terminal/GCC上可以工作。我怀疑要想做到正确,需要同时考虑C++的正确性和平台特定性。 - John Bartholomew
@MSalters:哦,没错,我应该更具体些。 - jalf
将输出导入文件并在记事本中打开该文件。会发生什么? - Kerrek SB
调用SetConsoleCP(65001)是必要的,以将控制台切换到utf8。找到一个能够显示Unicode字形的等宽字体将是一个难题。 - Hans Passant
显示剩余5条评论
4个回答

4
如果您希望程序使用当前的语言环境,请在程序的开头调用setlocale(LC_ALL, "")。否则,程序的语言环境将为C,我们这些普通人无法知道它对非ASCII字符会做什么。

在Windows上,调用setlocale(LC_ALL, "")并执行chcp 65001是在控制台中使用Unicode的技巧。+1到n.m. - Matthew

2
这并不奇怪。除非您的终端设置为UTF-8编码,否则它怎么知道s2不应该是"(拉丁小写字母a带抑扬符号)(欧元符号)(管道符)",假设您的终端根据http://www.ascii-code.com/设置为ISO-8859-1。

顺便说一下,cout并没有“死亡”,因为它明显在测试字符串后继续产生输出。

1
好的观点。std::cout只是将一串字节回显到外部世界。它们如何被解释取决于您和最终读取这些字节的程序之间的关系。 - Alexandre C.
@user657267 - 是的,cout 输出为空,但如果你使用 printf,那么你会得到你期望的结果(除非你没有使用正确的控制台字体,并执行了 chcp 65001)。 - Peter Nimmo

0

Windows控制台默认不处理非本地代码页字符。

您需要确保在控制台窗口中设置了支持Unicode的字体,并通过调用chcp将代码页设置为UTF-8。但这并不是一定成功的。 请注意,如果控制台的字体出现问题,无法显示花哨的字符,则`wcout´不会改变任何内容。

在所有现代Linux发行版上,控制台都设置为UTF-8,这应该可以直接使用。


0
正如其他人所指出的,在默认情况下,std::cout 对此并不关心(至少在“C”语言环境下)。另一方面,你的控制台窗口必须设置为显示UTF-8:代码页65001。在执行程序之前尝试调用 chcp 65001。(这在过去对我有效过。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接