C++中的哪个版本?

Jon*_*Mee 20 c++ string locale ctype tolower

鉴于string foo,我已经写了关于如何使用's 将字符转换为小写的答案cctypetolower

transform(cbegin(foo), cend(foo), begin(foo), static_cast<int (*)(int)>(tolower))
Run Code Online (Sandbox Code Playgroud)

但我已经开始考虑 localetolower,这可以这样使用:

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

小智 6

不幸的是,两者都同样糟糕.虽然std::string 假装是一个utf-8编码的字符串,但是没有方法/功能(包括tolower),真的是utf-8.因此,tolower/ tolower+ locale可能与单字节(= ASCII)的字符一起使用,对于每一组其他语言,它们都会失败.

在Linux上,我使用ICU库.在Windows上,我使用CharUpper函数.


Jon*_*Mee 1

应该指出的是,语言设计者知道scctype的创建时间tolower。它在两个主要方面进行了改进:localetolower

  1. 正如Progressive_overload 的回答中提到的,该locale版本允许使用facet ctype,即使用户修改了该版本,也不需要重新洗牌新的LC_CTYPE过孔setlocale并恢复之前的过孔LC_CTYPE
  2. 从第 7.1.6.2[dcl.type.simple]3 节:

char类型对象是否表示为有符号数量或无符号数量是由实现定义的。说明符signed强制char对对象进行签名

如果它是参数,则 scctype的版本可能会产生未定义行为的可能性:tolower

不能表示为unsigned char且不等于EOF

因此,yield版本static_cast需要额外的输入和输出:cctypetolower

transform(cbegin(foo), cend(foo), begin(foo), [](const unsigned char i){ return tolower(i); });
Run Code Online (Sandbox Code Playgroud)

由于locale版本直接在chars 上运行,因此不需要类型转换。

因此,如果您不需要以不同的方式执行转换,facet ctype那么它就变成了一个风格问题,即您是否更喜欢版本transform所需的 lambda cctype,或者您是否更喜欢locale版本的:

use_facet<ctype<char>>(cout.getloc()).tolower(data(foo), next(data(foo), size(foo)));
Run Code Online (Sandbox Code Playgroud)