&c
如何在这个循环和分配中工作,c = toupper(c)
?
string str = "hello";
for (auto & c: str)
c = toupper(c);
你能解释一下吗?
首先,请注意,如果std::toupper
提供除EOF
以外的负值,则它具有未定义的行为。对于大多数编译器,默认情况下char
是有符号类型。在典型的 8 位字节计算机上,这意味着如果c
的值不在 ASCII 范围内,即 0 到 127,则它是负数,并且会得到 UB。
该问题的简单解决方案是将参数转换为unsigned char
:
auto to_upper( const char c )
-> char
{
using Byte = unsigned char;
return static_cast<char>( toupper( static_cast<Byte>( c ) );
}
默认情况下,此函数仅适用于 ASCII 字符(字母 A 到 Z(,因为它采用 C 级区域设置指定的编码,并且默认情况下"C"
,基本上仅限于 ASCII。但至少它避免了未定义的行为。因此,让我们假设您的示例使用它,
for( auto& c : str ) c = to_upper( c );
这是一个基于范围的循环for
它贯穿str
中的所有项目,将引用c
绑定到每个项目,并执行循环体,该绑定生效。由于str
的项目是char
型,auto
将被推导出为char
。所以这和写for( char& c : str ) ...
一样.
因此,默认情况下,它将str
中的所有ASCII字符大写。
在 Windows 中,如果C 语言环境是通过setlocale( LC_ALL, "" )
设置的,则假定的编码将是 Windows ANSI,如果str
包含具有该编码的字符,则to_upper
将正确完成其大写工作。这意味着在Windows中,可以使用它来例如大写的挪威字符串,如"Blåbærsyltetøy"
,前提是Windows的语言环境是使用Windows ANSI Western的区域设置。
在 *nix 中,调用setlocale
没有帮助,因为用户的本机语言环境将指定 UTF-8 编码,其中 ASCII 之外的每个字符表示为 127>两个或多个字节。
auto & c
等效于char & c
,它是对字符串中每个字符的引用。更新引用的值会更改字符串中的引用字符。
上述代码的结果将是大写字符串。