我正在使用一个调用 std::locale:global 的库来保存和恢复 C++ 区域设置。
但是 std::locale::global 设置 C++ 语言环境设置和 C 语言环境设置,如本优秀用户指南中所述:https://stdcxx.apache.org/doc/stdlibug/24-3.html
此代码显示了潜在的问题:
#include <clocale>
#include <iostream>
class C
{
public:
void Open()
{
// Save current locale settings and set standard one
currentLocale = std::locale::global(std::locale::classic());
std::cout << "Open" << std::endl;
}
void Close()
{
// Restore the previous locale settings
std::locale::global(currentLocale);
std::cout << "Close" << std::endl;
}
std::locale currentLocale;
};
int main(int argc, char** argv)
{
std::setlocale(LC_CTYPE, "");
std::cout << "LC_CTYPE = " << std::setlocale(LC_CTYPE, nullptr) << std::endl;
C myObject;
myObject.Open();
myObject.Close();
std::cout << "LC_CTYPE = " << std::setlocale(LC_CTYPE, nullptr) << std::endl;
return 0;
}
打印:
LC_CTYPE = en_US.UTF-8
Open
Close
LC_CTYPE = C
但是调用 Open & Close 不应修改任何 C 语言环境设置,我们应该得到:
LC_CTYPE = en_US.UTF-8
Open
Close
LC_CTYPE = en_US.UTF-8
目前我只关心 LC_CTYPE 设置,因此我在调用 Open&Close 之前将 C++ LC_CTYPE 设置设置为等于 C LC_CTYPE 设置,问题已解决:
int main(int argc, char** argv)
{
std::setlocale(LC_CTYPE, "");
std::cout << "LC_CTYPE = " << std::setlocale(LC_CTYPE, nullptr) << std::endl;
C myObject;
// set c++ locale settings equal to C settings to keep C settings
const std::string ctypeValue = std::setlocale(LC_CTYPE, nullptr);
std::locale cppLocale;
std::locale modifiedcppLocale(cppLocale, ctypeValue, std::locale::ctype);
std::locale::global(modifiedcppLocale);
myObject.Open();
myObject.Close();
std::cout << "LC_CTYPE = " << std::setlocale(LC_CTYPE, nullptr) << std::endl;
return 0;
}
所以我有关于 std::locale::global: 的一般问题
1°)为什么 std::locale::global 也设置 C 语言环境设置?
2°)是否可以通过仅调用 std::locale::global 来存储/恢复区域设置?看来我们还应该通过调用 std::setlocale 来存储/恢复 C 语言环境设置
3°)有没有办法让 C++ 语言环境设置始终= C 语言环境设置?
为什么 std::locale::global 也设置 C 语言环境设置?
所以就有了 C++ std::locale 和 C locale。而且它们是分开的。一种是 C++ 语言。另一个是在 C 语言中。在 C 语言中,区域设置是全局的。在 C++ 中,区域设置实际上只是默认的
std::locale()
构造函数。
还有诸如
LC_CTYPE
之类的语言环境类别。然后是整个区域设置LC_ALL
。 LC_ALL
将所有语言环境类别合并为一个。
使用
std::setlocale(LC_CTYPE, "");
,您可以设置一个 LC_CTYPE
C 语言环境类别。
设置
std::setlocale(LC_CTYPE, "")
后,glibc上的LC_ALL
语言环境变为LC_CTYPE=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;LC_IDENTIFICATION=C
,您可以通过std::cout << std::setlocale(LC_ALL, nullptr)
来检查。
使用
std::locale::global(std::locale::classic())
,您正在设置 C++ 语言环境并覆盖 C 语言环境 LC_ALL
,并且您将获得 std::locale 的前一个 仅 C++ 部分。
现在您已经覆盖了 C 语言环境并存储了以前的 C++ 语言环境。之前的 C 语言环境丢失。
是否可以通过仅调用 std::locale::global 来存储/恢复区域设置?当然。
看来我们还应该通过调用 std::setlocale 来存储/恢复 C 语言环境设置是的。
是否有解决方案始终让 C++ 语言环境设置 = C 语言环境设置?您可以将 C++ 默认
std::global
全局与 C 语言环境“同步”。
int main(int argc, char** argv) {
std::setlocale(LC_CTYPE, "");
std::locale::global(std::locale(std::setlocale(LC_ALL, nullptr)));
总的来说,只setlocale(LC_CTYPE
设置单个区域设置类别感觉很奇怪。通常,我会看到
setlocale(LC_ALL, "")
将所有区域设置设置为用户定义的区域设置。通常,在 C++ 中,只需执行以下操作:
int main(int argc, char** argv) {
std::locale::global(std::locale(""));