如何在所有平台上用C ++程序显示重音字符?

我试图从Windows移植到C ++ 11程序到Linux(GCC-4.9)。 本来,我只是设置程序内的区域设置

setlocale(LC_ALL,“”);

但是,它在Linux(最新版本的Linux Mint)上显示缺less的字符。 然后我开始将所有的源文件保存为UTF-8格式,这些文件解决了linux下的问题,但是现在所有的字符都在Windows中混淆了。

如果有帮助,语言是法语。 有没有什么方法可以在两个平台下正确显示文本,而不会有太多的麻烦?

我会很感激帮助,谢谢。

void EcranBienvenue() { char coinHG = (char)201; char coinHD = (char)187; char coinBG = (char)200; char coinBD = (char)188; char ligneH = (char)205; char ligneV = (char)186; #ifdef _WIN32 system("cls"); #elif defined __linux__ system("clear"); #else cout << string(20,'\n'); #endif setlocale(LC_ALL, "C"); cout << coinHG; for (int i = 0; i < 48; i++) cout << ligneH; cout << coinHD << endl; cout << ligneV << " " << ligneV << endl; cout << ligneV << " Les productions inc " << ligneV << endl; cout << ligneV << " " << ligneV << endl; cout << ligneV << " Système de gestion des abonnements " << ligneV << endl; cout << ligneV << " " << ligneV << endl; cout << coinBG; for (int i = 0; i < 48; i++) cout << ligneH; cout << coinBD << endl; setlocale(LC_ALL, ""); } 

但是,边界在Linux上不起作用是正常的。 但是,这三行文字将在terminal上准确显示。

在Windows上,“è”将是一个不正确的字符。

 Système de gestion des abonnements 

做这种事情有很多不同的方法,但肯定有一些不好的方法。 我强烈建议避免一些事情:

  • 不要更改全球C或C ++语言环境。 大部分情况下,完全避免地区。
  • 不要使用wchar_t(除了在跨平台实现的API中隐藏,只能在Windows实现中使用wchar_t)。
  • 除非绝对需要,否则不要使用遗留编码。 (遗留编码除UTF-8,UTF-32和UTF-16外都是。

你看到的问题是因为你使用错误的编码在接口之间传递文本数据。

例如:

 Système de gestion des abonnements 

这是因为您将UTF-8编码的文本传递给期望使用(可能)Microsoft代码页850(控制台的OEM代码页)编码的数据的接口。

您需要知道接口需要什么编码才能使用它。 您还需要知道您的数据正在使用什么编码。 为此,您应该选择一个一致的编码在您的代码中使用,并在接口边界根据需要转换其他数据。 我相信UTF-8是跨平台代码的最佳选择。


由于MSVC执行标准C和C ++ IO设施的缺点,您可能最好使用本机Win32实现来实现自己的IO API。

这是一个介绍在Windows上实现输出功能的页面。

本文中实现的打印功能采用wchar_t输入。 以下是将UTF-8转换为UTF-16 / wchar_t的一种方法:

 #include <codecvt> #include <locale> std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert; std::string str = "Système de gestion des abonnements"; UPrint(convert.from_bytes().c_str()); 

另外,你可以实现一个streambuf来正确处理写入Windows的控制台,并用std::cout替换streambuf,这样打印到cout就可以正确地打印到控制台。 请记住在退出之前恢复原始的streambuf,以便cout的销毁可以成功。 您可以让RAII类型的对象处理流缓冲区并稍后切换回来。

这样的程序可能看起来像:

 int main() { Set_utf8_safe_streambuf buffer_swapper(std::cout); // on windows swaps cout's streambuf with one that can print UTF-8 to the console, does nothing on other platforms std::cout << "Système de gestion des abonnements" << '\n'; // utf-8 data } 

这里有一个关于实现和交换streambuf的一些细节的答案 。

C ++没有为(窄)字符串定义任何编码,而Windows使用CP-1252而Linux使用UTF-8。 使用std::wstringstd::wcout