C++中的Unicode问题,但不是C

Bra*_*don 12 c c++ unicode utf-8

我正在尝试在Windows上用C++编写unicode字符串到屏幕上.我将控制台字体更改为Lucida Console,并将输出设置为CP_UTF8aka 65001.

我运行以下代码:

#include <stdio.h>  //notice this header file..
#include <windows.h>
#include <iostream>

int main()
{
    SetConsoleOutputCP(CP_UTF8);
    const char text[] = "??????";
    printf("%s\n", text);
}
Run Code Online (Sandbox Code Playgroud)

打印出来就好了!

但是,如果我这样做:

#include <cstdio>  //the C++ version of the header..
#include <windows.h>
#include <iostream>

int main()
{
    SetConsoleOutputCP(CP_UTF8);
    const char text[] = "??????";
    printf("%s\n", text);
}
Run Code Online (Sandbox Code Playgroud)

它打印: ????????????

我不知道为什么..

另一件事是我做的时候:

#include <windows.h>
#include <iostream>

int main()
{
    std::uint32_t oldcodepage = GetConsoleOutputCP();
    SetConsoleOutputCP(CP_UTF8);

    std::string text = u8"??????";
    std::cout<<text<<"\n";

    SetConsoleOutputCP(oldcodepage);
}
Run Code Online (Sandbox Code Playgroud)

我得到与上面相同的输出(非工作输出).

使用printfstd::string,它工作正常,但:

#include <stdio.h>
#include <windows.h>
#include <iostream>

int main()
{
    std::uint32_t oldcodepage = GetConsoleOutputCP();
    SetConsoleOutputCP(CP_UTF8);

    std::string text = u8"??????";
    printf("%s\n", text.c_str());

    SetConsoleOutputCP(oldcodepage);
}
Run Code Online (Sandbox Code Playgroud)

但只有我使用stdio.h和不cstdio.

任何想法我怎么用std::cout?我怎么用cstdio?为什么会这样?不cstdio只是一个c ++版本stdio.h

编辑:我刚试过:

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

int main()
{
    _setmode(_fileno(stdout), _O_U8TEXT);
    std::wcout << L"??????" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

并且它是有效但只有我使用std::wcoutwide strings.我真的想避免wide-strings,到目前为止我看到的唯一解决方案是C-printf:l

所以问题仍然存在......

Max*_*ert 2

尽管您已将控制台设置为期望 UTF-8 输出,但我怀疑您的编译器将字符串文字视为采用其他字符集。我不知道为什么 C 编译器的行为不同。

\n\n

好消息是 C++11 包含对 UTF-8 的一些支持,并且 Microsoft 已经实现了该标准的相关部分。代码有点复杂,但您需要查看std::wstring_convert(与 UTF-8 之间的转换)和<cuchar>标头。

\n\n

您可以使用这些函数转换为 UTF-8,并且假设您的控制台需要 UTF-8,那么事情应该可以正常工作。

\n\n

就我个人而言,当我需要调试类似的东西时,我经常将输出定向到文本文件。文本编辑器似乎比 Windows 控制台更好地处理 Unicode。就我而言,我经常正确输出代码点,但控制台设置不正确,因此我最终仍然打印垃圾。

\n\n
\n\n

我可以告诉你,这在 Linux(使用 Clang)和 Windows(使用 GCC 4.7.3 和 Clang 3.5)中都对我有用;你需要在命令行中添加“std=c++11”才能使用 GCC 或 Clang 进行编译):

\n\n
#include <cstdio>\n\nint main()\n{\n    const char text[] = u8"\xd0\xa0\xd0\xbe\xd1\x81\xd1\x81\xd0\xb8\xd1\x8f";\n    std::printf("%s\\n", text);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用 Visual C++(2012 年,但我相信它也适用于 2010 年),我必须使用:

\n\n
#include <codecvt>\n#include <cstdio>\n#include <locale>\n#include <string>\n\nint main()\n{\n    std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;\n    auto text = converter.to_bytes(L"\xd0\xa0\xd0\xbe\xd1\x81\xd1\x81\xd0\xb8\xd1\x8f");\n    std::printf("%s\\n", text.c_str());\n}\n
Run Code Online (Sandbox Code Playgroud)\n