C ++中的哪个版本?

时间:2016-05-27 11:24:27

标签: c++ string locale ctype tolower

鉴于string foo,我已就如何使用cctype' answers将字符转换为小写

撰写了tolower
transform(cbegin(foo), cend(foo), begin(foo), static_cast<int (*)(int)>(tolower))

但是我begun to consider locale&#39; tolower,可以像这样使用:

use_facet<ctype<char>>(cout.getloc()).tolower(data(foo), next(data(foo), foo.size()));
  • 是否有理由偏好其中一个而不是另一个?
  • 他们的功能是否完全不同?
  • 我的意思是tolower接受并返回int这个事实,我认为这只是一些过时的C东西?

3 个答案:

答案 0 :(得分:6)

不幸的是,两者都同样糟糕。虽然std::string假装是一个utf-8编码的字符串,但是非方法/函数(包括tolower),实际上是utf-8识别的。因此,tolower / tolower +语言环境可能与单字节(= ASCII)字符一起使用,对于每一组其他语言,它们都会失败。

在Linux上,我使用ICU库。在Windows上,我使用CharUpper功能。

答案 1 :(得分:4)

在第一种情况(cctype)中,隐含设置了语言环境:

  

根据字符将给定字符转换为小写   由当前安装的C语言环境定义的转换规则。

http://en.cppreference.com/w/cpp/string/byte/tolower

在第二个(区域设置)情况下,您必须明确设置区域设置:

  

如果c是大写,则将参数c转换为小写的等效值   字母和小写等价物,由ctype决定   locale loc的方面。如果没有可能的转换,则为该值   返回是不变的。

http://www.cplusplus.com/reference/locale/tolower/

答案 2 :(得分:1)

应该注意的是,当cctype的{​​{1}}被创建时,语言设计者 知道tolower的{​​{1}}。它以两种主要方式改进:

  1. 正如progressive_overload's answer中提到的那样,locale版本允许使用tolower,即使是用户修改过的也没有要求改组来自locale的新facet ctype以及之前LC_CTYPE
  2. 的恢复
  3. 来自第7.1.6.2节[dcl.type.simple] 3:
  4.   

    实现定义了setlocale类型的对象是表示为有符号数还是无符号数。 LC_CTYPE说明符强制char个对象被签名

    如果它是tolowerJSFiddle for live demo版本的signed版本,则会产生未定义行为的可能性:

      

    无法表示为char且不等于cctype

    因此unsigned char EOF版本的static_cast版本需要额外的输入和输出cctype

    tolower

    由于transform(cbegin(foo), cend(foo), begin(foo), [](const unsigned char i){ return tolower(i); }); 版本直接在locale上运行,因此无需进行类型转换。

    因此,如果您不需要在另一个char中执行转换,那么您只是希望facet ctype更喜欢transform所需的lambda。您是否更喜欢cctype版本:

    locale