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

时间:2012-11-15 03:44:57

标签: c++ windows unicode console latin

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

  

Lachaînequi对应au代码“TEST_CODE”n'apasététroutéeàl'aidelocale“fr”。

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

  

Lacha¯nequi对应au代码“TEST_CODE”n'apasÚtÚtrouvÚeÓ''idea locale“fr”。

如何解决此问题?

2 个答案:

答案 0 :(得分: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\".";

或者在编码之间进行转换的许多方法之一(这个方法需要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,或者违反标准要求并违反标准符合程序。

答案 1 :(得分:3)

如果你想在控制台中编写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撰写的以下博文:

此外,如果您正在阅读文件中的某些文字,您必须知道使用了哪种编码:UTF-8? UTF-16LE? UTF-16BE?一些特定的代码页?然后,您可以从特定编码转换为Unicode UTF-16,并在Windows应用程序中使用UTF-16。要从某些代码页(或从UTF-8)转换为UTF-16,您可以使用MultiByteToWideChar() APIATL conversion helper class CA2W