如何在所有平台上使用C++程序显示重音字符
How to display accented characters with a C++ program on all platforms?
我正在尝试将一个C++11程序从Windows移植到Linux(GCC-4.9)。最初,我只是在程序中设置区域设置
setlocale(LC_ALL,");
然而,它在Linux(Linux Mint的最新版本)上显示了缺失的字符。然后,我将所有的源文件保存为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上还不起作用,这很正常。但是,这三行文字将准确地显示在终端上。
在windows中,"è"将是一个不正确的字符。
Système de gestion des abonnements
C++没有为(窄)字符串定义任何编码,Windows使用CP-1252,而Linux使用UTF-8。使用std::wstring
和std::wcout
。
有很多不同的方法来做这类事情,但肯定有一些不好的方法。我强烈建议避免以下几件事:
- 永远不要更改全局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的一些细节。
- Mongodb c++驱动程序:如何查询元素的数组
- C++,系统无法执行指定的程序
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 重载操作程序时出错>>用于类中的字符串 memebr
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 试图在visual studio上用C++创建一个桌面应用程序
- 模板元程序查找相似的连续类型名称
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- 如何通过cpp程序运行shell脚本
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- IPC使用多个管道和分支进程来运行Python程序
- 如何将c++程序的一些输出传递给shell,以便在shell中使用
- 使用C++程序合并排序没有得到正确的输出
- 基于boost的程序的静态链接——zlib问题
- 程序崩溃并显示"std::out_of_range"错误
- 在C应用程序中运行C++(带有STL)函数
- 使用mongocxx驱动程序时包含头文件问题
- 如何在c++程序中找到函数的地址