这个表达式有效吗?

时间:2015-12-17 15:52:23

标签: c++ string integer-overflow

我遇到了这段代码:

std::string str;
std::getline(std::cin, str);
std::string sub = str.substr(str.find('.') + 1);

第一反应是 - 这是无效的代码。但经过一些想法似乎并不那么简单。那么它是有效的C ++表达式(具有可预测的行为)吗?

PS如果不是那么清楚问题主要与“。”时会发生什么有关。不会在str中找到,但不限于此,因为可能存在其他问题。

5 个答案:

答案 0 :(得分:5)

str.find('.')返回字符串中第一次出现的字符的索引。带有一个参数的substr返回从给定索引开始的字符串的后缀。那么该行的作用是返回第一个点后面的字符串尾部。因此,如果str"hello.good.bye"sub将为good.bye

但是,如果字符串实际上不包含任何点,则 可能会导致代码出现问题。它将返回整个字符串。这可能是也可能不是。这是因为如果没有点,find将返回npos,这是std::string::size_type可以容纳的最大数字1。向其添加String[] parts = yourString.split("-"); //You can then access each part with: parts[index] ,您将获得0(这是无符号类型的行为,模2 n )。

因此代码总是具有可预测的行为。

答案 1 :(得分:2)

来自http://en.cppreference.com/w/cpp/string/basic_string/npos,似乎是std::string::npos = -1;find失败时返回该值。在这种情况下,str.substr(0)将返回整个字符串。

它似乎是有效且可预测的代码。

答案 2 :(得分:2)

如果您询问如果找不到.会发生什么,您不必担心。 std::string::find然后返回http://appleid-localdev.apple.com:19380,标准定义为-1,在添加1溢出后生成参数0

std::string sub = str.substr(0);

给你整个字符串。我不知道这是否是所期望的行为,但它肯定不是未定义的行为。

答案 3 :(得分:1)

实际上,在这种特定情况下 - 因为包含“......无关紧要......”的字符串确实存在 - find()调用无法找到它所寻找的内容,因此将返回std::string::npos。然后你加1。

npos的类型为std::string::size_type,通常为size_t,通常是某种无符号整数。

npos被定义为size_type的最大可能值。

size_type无符号时,将最大可能值加1会创建0。

所以你打电话给std::string::substr(0)。这是做什么的?它会创建您调用它的整个字符串的副本,因为substr采用起始位置和长度(默认为npos,或“一直到最后”)。

答案 4 :(得分:0)

据我所知,它虽然不是特别易读,但仍然有效。

如果str为空,则find()方法将返回std::string::npos。这相当于unsigned int可表示的最大std::size_type。通过向此添加1,您将导致整数溢出并且它将回绕到0.这意味着substr()方法正在尝试使用从位置0到字符串结尾的字符创建字符串。如果str为空,则sub也为空。