这个表达有效吗?
Is this expression valid?
我遇到过这段代码:
std::string str;
std::getline(std::cin, str);
std::string sub = str.substr(str.find('.') + 1);
第一反应是——这是无效代码。但是想了想,似乎并没有那么简单。那么它是有效的 C++ 表达式吗(具有可预测的行为)?
PS 如果不是很清楚,问题主要与 '.' 时会发生什么有关。在 str
中找不到,但不限于此,因为可能存在其他问题。
str.find('.')
returns 字符在字符串中第一次出现的索引。 substr
带有一个参数 returns 从给定索引开始的字符串的后缀。因此,该行的作用是 returns 从第一个点之后开始的字符串尾部。所以如果 str
是 "hello.good.bye"
,sub
将是 good.bye
。
但是,如果字符串实际上不包含任何点, 代码可能存在问题。它将 return 整个字符串。这可能是有意的,也可能不是。发生这种情况是因为如果没有点,find
将 return npos
,这是 std::string::size_type
可以容纳的最大数字。向其中添加 1
,您将得到 0(这就是无符号类型的行为方式,模 2n)。
所以代码总是有可预测的行为。
从http://en.cppreference.com/w/cpp/string/basic_string/npos看来std::string::npos = -1;
。当 find
不成功时,该值被 returned。在这种情况下,str.substr(0)
将 return 整个字符串。
看起来它是有效且可预测的代码。
如果您问的是找不到 .
会发生什么,您不必担心。 std::string::find
然后 returns std::string::npos
,标准定义为 -1
,添加 1
后溢出并使参数 0
:
std::string sub = str.substr(0);
这给了你整个字符串。我不知道这是否是所需的行为,但这肯定不是未定义的行为。
据我所知,它是有效的,尽管它不是特别可读。
如果 str
为空,则 find()
方法将 return std::string::npos
。这相当于std::size_type
可表示的最大unsigned int
。通过向其添加 1,您将导致整数溢出,并且它将回绕到 0。这意味着 substr()
方法正在尝试使用从位置 0 到字符串末尾的字符创建一个字符串。如果 str
为空,则 sub
也为空。
实际上,在这种特定情况下——因为包含“...无关紧要...”的字符串确实如此——find()
调用不会找到它要查找的内容return std::string::npos
也会如此。然后你给这个加 1。
npos 是 std::string::size_type
类型,通常是 size_t
,通常是某种无符号整数。
npos
定义为 size_type
.
的最大可能值
size_type
是无符号的,最大可能值加 1 得到 0。
所以你打电话给 std::string::substr(0)
。这是做什么的?它会创建您调用它的整个字符串的副本,因为 substr
需要一个起始位置和长度(默认为 npos
,或 "all the way to the end")。
我遇到过这段代码:
std::string str;
std::getline(std::cin, str);
std::string sub = str.substr(str.find('.') + 1);
第一反应是——这是无效代码。但是想了想,似乎并没有那么简单。那么它是有效的 C++ 表达式吗(具有可预测的行为)?
PS 如果不是很清楚,问题主要与 '.' 时会发生什么有关。在 str
中找不到,但不限于此,因为可能存在其他问题。
str.find('.')
returns 字符在字符串中第一次出现的索引。 substr
带有一个参数 returns 从给定索引开始的字符串的后缀。因此,该行的作用是 returns 从第一个点之后开始的字符串尾部。所以如果 str
是 "hello.good.bye"
,sub
将是 good.bye
。
但是,如果字符串实际上不包含任何点, 代码可能存在问题。它将 return 整个字符串。这可能是有意的,也可能不是。发生这种情况是因为如果没有点,find
将 return npos
,这是 std::string::size_type
可以容纳的最大数字。向其中添加 1
,您将得到 0(这就是无符号类型的行为方式,模 2n)。
所以代码总是有可预测的行为。
从http://en.cppreference.com/w/cpp/string/basic_string/npos看来std::string::npos = -1;
。当 find
不成功时,该值被 returned。在这种情况下,str.substr(0)
将 return 整个字符串。
看起来它是有效且可预测的代码。
如果您问的是找不到 .
会发生什么,您不必担心。 std::string::find
然后 returns std::string::npos
,标准定义为 -1
,添加 1
后溢出并使参数 0
:
std::string sub = str.substr(0);
这给了你整个字符串。我不知道这是否是所需的行为,但这肯定不是未定义的行为。
据我所知,它是有效的,尽管它不是特别可读。
如果 str
为空,则 find()
方法将 return std::string::npos
。这相当于std::size_type
可表示的最大unsigned int
。通过向其添加 1,您将导致整数溢出,并且它将回绕到 0。这意味着 substr()
方法正在尝试使用从位置 0 到字符串末尾的字符创建一个字符串。如果 str
为空,则 sub
也为空。
实际上,在这种特定情况下——因为包含“...无关紧要...”的字符串确实如此——find()
调用不会找到它要查找的内容return std::string::npos
也会如此。然后你给这个加 1。
npos 是 std::string::size_type
类型,通常是 size_t
,通常是某种无符号整数。
npos
定义为 size_type
.
size_type
是无符号的,最大可能值加 1 得到 0。
所以你打电话给 std::string::substr(0)
。这是做什么的?它会创建您调用它的整个字符串的副本,因为 substr
需要一个起始位置和长度(默认为 npos
,或 "all the way to the end")。