【发布时间】:2018-09-29 20:02:50
【问题描述】:
&c 在这个循环和分配c = toupper(c) 时如何工作?
string str = "hello";
for (auto & c: str)
c = toupper(c);
你能解释一下吗?
【问题讨论】:
-
我不确定我是否理解您的问题。您是否有特定的错误或错误消息,或者您是否专门询问
&c声明
&c 在这个循环和分配c = toupper(c) 时如何工作?
string str = "hello";
for (auto & c: str)
c = toupper(c);
你能解释一下吗?
【问题讨论】:
&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,它是对字符串中每个字符的引用。更新引用的值会改变字符串中被引用的字符。
上述代码的结果将是一个大写字符串。
【讨论】:
auto 等同于 到char,而是根据上下文推断这里是char。