c++ - 如何在 Windows 上正确地将拉丁字符打印到 C++ 控制台?

标签 c++ windows unicode console latin

我在用 C++ 将法语字符写入控制台时遇到问题。该字符串使用 std::ifstreamstd::getline 从文件加载,然后使用 std::cout 打印到控制台。这是文件中的字符串:

La chaîne qui correspond au code "TEST_CODE" n'a pas été trouvée à l'aide locale "fr".

下面是字符串的打印方式:

La cha¯ne qui correspond au code "TEST_CODE" n'a pas ÚtÚ trouvÚe Ó l'aide locale "fr".

我该如何解决这个问题?

最佳答案

问题是控制台使用与系统其余部分不同的代码页。例如,通常为美洲和西欧设置的 Windows 系统使用 CP1252,但这些地区的控制台使用 CP437 或 CP850。

您可以设置控制台输出代码页以匹配您正在使用的编码,或者您可以转换字符串以匹配控制台的输出代码页。

设置控制台输出代码页:

SetConsoleOutputCP(GetACP()); // GetACP() returns the system codepage.
std::cout << "La chaîne qui correspond au code \"TEST_CODE\" n'a pas été trouvée à l'aide locale \"fr\".";

或者在编码之间进行转换的多种方法之一(这需要 VS2010 或更高版本):

#include <codecvt> // for wstring_convert
#include <locale>  // for codecvt_byname
#include <iostream>

int main() {
    typedef std::codecvt_byname<wchar_t,char,std::mbstate_t> codecvt;

    // the following relies on non-standard behavior, codecvt destructors are supposed to be protected and unusable here, but VC++ doesn't complain.
    std::wstring_convert<codecvt> cp1252(new codecvt(".1252"));
    std::wstring_convert<codecvt> cp850(new codecvt(".850"));

    std::cout << cp850.to_bytes(cp1252.from_bytes("...été trouvée à...\n")).c_str();
}

后一个示例假设您确实需要在 1252 和 850 之间进行转换。您可能应该使用函数 GetOEMCP() 来确定实际的目标代码页,而源代码页实际上取决于您使用的源代码代码而不是运行程序的机器上 GetACP() 的结果。

另请注意,此程序依赖于标准未保证的内容:wchar_t 编码在语言环境之间共享。在大多数平台上都是如此——通常一些 Unicode 编码用于所有语言环境中的 wchar_t——但不是所有平台。


理想情况下,你可以在任何地方都使用 UTF-8,下面的代码就可以正常工作,就像现在在其他平台上所做的那样:

#include <iostream>

int main() {
    std::cout << "La chaîne qui correspond au code \"TEST_CODE\" n'a pas été trouvée à l'aide locale \"fr\".\n";
}

不幸的是,Windows 不能以这种方式支持 UTF-8,除非放弃 UTF-16 作为 wchar_t 编码并采用 4 字节 wchar_t,或者违反标准要求并破坏符合标准的程序。

关于c++ - 如何在 Windows 上正确地将拉丁字符打印到 C++ 控制台?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13391252/

相关文章:

windows - 将 Windows 服务项目更新到 .NET 5,System.Configuration.Installer,如何将它添加到我的项目中?

string - 当 YAML 文件包含 unicode 字符(如 "a\u0000b")时,在 golang 中读取 YAML 文件

c++ - switch 语句 C++ 和 glut

c++ - for std::queue remove all of element swap 和 pop 的时间差

c++ - 你如何键入别名嵌套类?

windows - 找出正在运行的批处理文件的文件名

c++ - C++ 中的异常处理 : Throwing a double when using "throw(int)"

windows - 使用cmd或双击执行exe

python - 如何使用 Python 保存数据库响应中字符串的完整性

unicode - Unicode 的换行规则是否要求最后一个字符是强制换行符?