如何在所有平台上使用 C++ 程序显示重音字符?
How to display accented characters with a C++ program on all platforms?
我正在尝试将 C++11 程序从 Windows 移植到 Linux (GCC-4.9)。
本来我只是在程序里面设置locale
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 中的跨平台实现,仅将 wchar_t 用于 Windows 实现)。
- 除非绝对需要,否则不要使用旧编码。 (传统编码是除 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。
Here's 讨论在 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
}
这里有一个 answer,其中包含一些关于实现和交换 streambuf 的细节。
我正在尝试将 C++11 程序从 Windows 移植到 Linux (GCC-4.9)。 本来我只是在程序里面设置locale
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 中的跨平台实现,仅将 wchar_t 用于 Windows 实现)。
- 除非绝对需要,否则不要使用旧编码。 (传统编码是除 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。
Here's 讨论在 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
}
这里有一个 answer,其中包含一些关于实现和交换 streambuf 的细节。