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

jme*_*fin 6 c++ windows unicode console latin

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

Lachaînequi对应au代码"TEST_CODE"n'apasététrouvéeàl'aidelocale"fr".

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

Lacha¯nequi对应au代码"TEST_CODE"n'apasÚtÚtroutÚeÓ''idea locale"fr".

我该如何解决这个问题?

bam*_*s53 5

问题是控制台使用的代码页与系统的其他代码页不同.例如,通常为美洲和西欧设置的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\".";
Run Code Online (Sandbox Code Playgroud)

或者在编码之间进行转换的许多方法之一(这需要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();
}
Run Code Online (Sandbox Code Playgroud)

后一个例子假设您确实需要在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";
}
Run Code Online (Sandbox Code Playgroud)

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