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

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

Lachaînequi对应的au代码“TEST_CODE”n'a pasététrouvéeàl'aide locale“fr”。

这里是如何打印string:

La chanene qui对应au代码“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编码在locale之间共享。 在大多数平台上都是如此 – 通常一些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"; } 

不幸的是,如果不放弃UTF-16作为wchar_t编码并采用4字节的wchar_t,或违反标准要求并违反标准的程序,Windows就不能支持UTF-8。

如果要在控制台中编写Unicode字符,则必须进行一些初始化

 _setmode(_fileno(stdout), _O_U16TEXT); 

然后你的法文字符显示正确(我已经测试了它使用Consolas作为我的控制台字体):

 #include <fcntl.h> #include <io.h> #include <iostream> #include <ostream> #include <string> using namespace std; int main() { // Prepare console output in Unicode _setmode(_fileno(stdout), _O_U16TEXT); // // Build Unicode UTF-16 string with French characters // // 0x00EE - LATIN SMALL LETTER I WITH CIRCUMFLEX // 0x00E9 - LATIN SMALL LETTER E WITH ACUTE // 0x00E0 - LATIN SMALL LETTER A WITH GRAVE wstring str(L"La cha"); str += L'\x00EE'; str += L"ne qui correspond au code \"TEST_CODE\" "; str += L"n'a pas "; str += L'\x00E9'; str += L't'; str += L'\x00E9'; str += L" trouv"; str += L'\x00E9'; str += L"e "; str += L'\x00E0'; str += L" l'aide locale \"fr\"."; // Print the string to the console wcout << str << endl; } 

考虑阅读Michael Kaplan的以下博客文章:

  • 神话在控制台中破坏
  • 传统智慧迟缓,又名@#%&*是_O_U16TEXT?

而且,如果您正在读取文件中的某些文本,则必须知道使用哪种编码 :UTF-8? UTF-16LE? UTF-16BE? 一些特定的代码页? 然后,您可以从特定编码转换为Unicode UTF-16,并在Windows应用程序中使用UTF-16。 要从一些代码页(或从UTF-8)转换为UTF-16,您可以使用MultiByteToWideChar() API或ATL转换助手类CA2W