如何正确使用std::locale::global?

问题描述 投票:0回答:1

我正在使用一个调用 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 语言环境设置?

c++ locale
1个回答
0
投票

为什么 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(""));
    
© www.soinside.com 2019 - 2024. All rights reserved.