5

cppreference 说std::ctype基于经典的“C”语言环境提供字符分类。当我们创建这样的语言环境时,这是否正确:

std::locale loc(std::locale("en_US.UTF8"), new std::ctype<char>);

仍然会loc根据“C”语言环境或 Unicode 对字符进行分类吗?如果按前者分类,为什么我们还要将语言环境名称指定为“en_US.UTF8”?

4

3 回答 3

2

该标准要求默认构造 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]);
}
于 2013-07-16T21:45:45.550 回答
1

根据我在 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>.

于 2013-07-16T16:31:53.717 回答
0

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.5locale静态成员 [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)) { ... }
于 2013-07-16T16:28:20.893 回答