【问题标题】:String Rev function, strange behavior for out of bounds exception (c++)字符串 Rev 函数,越界异常的奇怪行为 (c++)
【发布时间】:2021-12-10 03:59:56
【问题描述】:

我玩过string函数,我写了下面的,显然我将ret字符串中的第一个字符设置在一个越界的地方,但不是异常,我得到一个字符串一个额外的地方。

std::string StringManipulations::rev(std::string s)
{
    
    std::string ret(s.size(), ' ');

    for (int i = 0; i < s.size(); i++)
    {
        std::string ch;
        ch.push_back(s[i]);
        int place = s.size() -i;
        ret.replace(place,1,ch);
    }
    return ret; 
}

我错误地写在一个位置,该位置比我在函数开头指定的原始字符串大小大一。

为什么我们没有收到错误消息?

s = StringManipulations::rev("abcde");
    std::cout << s.size();
    std::cout << s;

output is : 6 _edcba 

有什么帮助吗?

已解决:将 ch 添加为 String 会自动添加一个空终止符,这样我们就可以得到一个 size+1 的新字符串。

【问题讨论】:

  • 越界会导致未定义的行为。它可能会导致崩溃,它似乎可以工作,或者它可能会召唤nasal demons
  • 这可能会有所帮助:stackoverflow.com/questions/671703/…
  • 是的,感谢您的回复.. 奇怪的是,只要差异大于 1,就会出现异常,否则我们会得到一个大小为 +1 的新字符串。
  • 可能是因为字符串是一个字符数组,末尾有一个额外的字符,如“\0”,表明这是字符串的结尾。它可能会有所帮助:tutorialspoint.com/cprogramming/c_strings.htm
  • 题外话:该函数在效率和可读性方面看起来都很丑。为什么不(例如)ret[s.size() - i - 1] = s[i];?另外,如果这不是手动字符串反转练习,我会使用return std::string{s.rbegin(), s.rend()};,或者,因为您已经复制了s(即按值传递),为什么不避免另一个副本:std::reverse(s.begin(), s.end()); return s;。跨度>

标签: c++ string replace reverse stdstring


【解决方案1】:

C++ 有一个零开销规则。 这意味着不应无意执行任何开销(例如检查索引是否在边界内)。 您不会得到异常,因为 c++ 根本不验证索引是否有效。

对于额外的字符,这可能与(常规)c 字符串有关。 在 c 中,字符串是没有定义大小的 char (char*) 类型的数组。 字符串的结尾用null terminator 表示。 C++ 字符串是向后兼容的,这意味着它们也有一个空终止符。 您可能将终止符替换为其他字符,但下一个字节也是零,这意味着您又添加了一个字符。

【讨论】:

  • 是的,我的怀疑是一样的,我认为它在终止符位置添加了一个字符,然后终止符随后自动添加到字符串的末尾,所以我们得到了一个有效的字符串,多了一个空格.
【解决方案2】:

除了上面关于空终止符的信息之外,您的问题的另一个答案是文档说它只会在位置大于字符串大小而不是超出字符串末尾时抛出。 string replace api

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-11
    • 2014-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-01
    • 2013-12-08
    • 2014-10-16
    相关资源
    最近更新 更多