cppreference 说std::ctype
基于经典的“C”语言环境提供字符分类。当我们创建这样的语言环境时,这是否正确:
std::locale loc(std::locale("en_US.UTF8"), new std::ctype<char>);
仍然会loc
根据“C”语言环境或 Unicode 对字符进行分类吗?如果按前者分类,为什么我们还要将语言环境名称指定为“en_US.UTF8”?
cppreference 说std::ctype
基于经典的“C”语言环境提供字符分类。当我们创建这样的语言环境时,这是否正确:
std::locale loc(std::locale("en_US.UTF8"), new std::ctype<char>);
仍然会loc
根据“C”语言环境或 Unicode 对字符进行分类吗?如果按前者分类,为什么我们还要将语言环境名称指定为“en_US.UTF8”?
该标准要求默认构造 std::ctype<char>
以匹配最小的“C”语言环境§22.4.1.3.3[facet.ctype.char.statics]/1
static const mask* classic_table() noexcept;
返回:指向大小数组的初始元素的指针,
table_size
它表示“C”语言环境中字符的分类
分类成员函数is()
是根据table()
定义的,classic_table()
除非向ctype<char>
的构造函数提供另一个表
我已经更新了 cppreference 以更恰当地匹配这些要求(它也说“C” std::ctype<wchar_t>
)
要回答您的第二个问题,使用构造的语言环境std::locale loc(std::locale("en_US.UTF8"), new std::ctype<char>);
将使用您指定的 ctype 方面(因此,“C”)对窄字符进行分类,但它是多余的:普通的窄字符分类std::locale("en_US.UTF8")
(至少在 GNU 实现中)正是相同:
#include <iostream>
#include <cassert>
#include <locale>
int main()
{
std::locale loc1("en_US.UTF8");
const std::ctype_base::mask* tbl1 =
std::use_facet<std::ctype<char>>(loc1).table();
std::locale loc2(std::locale("en_US.UTF8"), new std::ctype<char>);
const std::ctype_base::mask* tbl2 =
std::use_facet<std::ctype<char>>(loc2).table();
for(size_t n = 0; n < 256; ++n)
assert(tbl1[n] == tbl2[n]);
}
根据我在 C++11 N3376 §22.4.1.1 的工作草案中读到的内容,std::ctype<char>
应该这样做:
Class ctype encapsulates the C library <cctype> features. istream members
are required to use ctype<> for character classing during input parsing.
The specializations required in Table 81 (22.3.1.1.1), namely ctype<char> and
ctype<wchar_t>, implement character classing appropriate to the
implementation’s native character set.
它在那里的任何地方都没有提到 C 语言环境,cppreference 可能指的是<cctype>
.
setlocale()
在 C 中,C 语言环境适用,直到您使用from更改语言环境<locale.h>
。C++ 可能也是如此,尽管您可能还有其他设置语言环境的机制。
您的声明似乎创建了一个语言环境;不过,尚不清楚它是否将该语言环境设置为默认语言环境。然后可以使用该语言环境来指定比较:
ISO/IEC 14882:2011(C++ 2011 标准)有第 22.3 节题为Locales。它部分说:
// 22.3.3, convenience interfaces:
template <class charT> bool isspace (charT c, const locale& loc);
template <class charT> bool isprint (charT c, const locale& loc);
此外,在标准的稍后部分,它说:
22.3.1.5
locale
静态成员 [locale.statics]
static locale global(const locale& loc);
1 将全局语言环境设置为其参数。
2效果:导致未来对构造函数 locale() 的调用返回参数的副本。如果参数有名称,
std::setlocale(LC_ALL, loc.name().c_str());
否则,对 C 语言环境的影响(如果有)是实现定义的。任何库函数locale::global()
都不会影响返回的值locale()
。[注意:setlocale
调用时的数据竞争注意事项见 22.6 。——尾注]3返回:的前一个值
locale()
。
所以如果我想
std::ctype
基于“en_US.UTF8”进行分类,我必须在运行上述行之前更改全局语言环境?
我从最初的引文中读到的是,鉴于您loc
可以写:
if (isspace(ch, loc)) { ... }
明确指定要使用的语言环境。如果您不想这样做,那么您需要调用std::locale::global(loc)
以设置全局语言环境,因此简单的调用 ofisspace()
将起作用:
if (isspace(ch)) { ... }