在字符串迭代中替换(out_of_range)

发布于 2024-11-08 21:09:44 字数 1797 浏览 0 评论 0原文

我编写了一个对字符串进行百分比编码的函数,如下所示:

string percent_encode(string str)
{
  string reserved =
    // gen-delims
    ":/?#[]@"
    // sub-delims
    "!$&'()*+,;="
  ;

  for(string::iterator i = str.begin(); i < str.end(); i++) {
    int c = *i;
    // replaces reserved, unreserved non-ascii and space characters.
    if(c > 127 || c == 32 || reserved.find(*i) != string::npos) {
      std::stringstream ss;
      ss << std::hex << c;
      str.replace(i, i + 1, "%" + ss.str());
    }
  }
  return str;
}

当我为“a&b”之类的字符串调用此函数时,会引发 out_of_range 异常:

terminate called after throwing an instance of 'std::out_of_range'
  what():  basic_string::replace

我用调试器跟踪此异常并发现替换效果很好,但它以某种方式迭代超出了 end();

这就是我在观察迭代器“i”时得到的结果:

{_M_current = 0x7fc43d61bd78 "a&b"}
{_M_current = 0x7fc43d61bd79 "&b"}
{_M_current = 0x7fc43d61bd7a "b"}
{_M_current = 0x7fc43d61bd7b ""}
{_M_current = 0x7fc43d61bd7c "o = a&b\n"}
{_M_current = 0x7fc43d61bd7d " = a&b\n"}

然后它尝试替换“=”并因 out_of_range 异常而失败。 我不明白,迭代器怎么可能明显超出 end() 范围。

如果有人能向我解释这是怎么可能的,我将不胜感激,因为我在网上找不到有同样问题的人。

谢谢和问候,

真正的

编辑:

啊,我真的觉得很复杂。 x) 我现在就是这样解决的。

string percent_encode(string str)
{
  string reserved =
    // gen-delims
    ":/?#[]@"
    // sub-delims
    "!$&'()*+,;="
  ;

  std::stringstream ss;

  for(string::iterator i = str.begin(); i < str.end(); i++) {
    // encodes reserved, unreserved non-ascii and space characters.
    int c = *i;
    if(c > 126 || c == 32 || reserved.find(*i) != string::npos) {
      ss << '%' << std::hex << c;
    } else {
      ss << *i;
    }
  }

  return ss.str();
}

谢谢迭戈:)

I wrote a function which percent-encodes a string, as follows:

string percent_encode(string str)
{
  string reserved =
    // gen-delims
    ":/?#[]@"
    // sub-delims
    "!
amp;'()*+,;="
  ;

  for(string::iterator i = str.begin(); i < str.end(); i++) {
    int c = *i;
    // replaces reserved, unreserved non-ascii and space characters.
    if(c > 127 || c == 32 || reserved.find(*i) != string::npos) {
      std::stringstream ss;
      ss << std::hex << c;
      str.replace(i, i + 1, "%" + ss.str());
    }
  }
  return str;
}

When I call this function for a string like "a&b", an out_of_range exception is thrown:

terminate called after throwing an instance of 'std::out_of_range'
  what():  basic_string::replace

I traced this exception with a debugger and saw, that the replacing worked well, but it iterates somehow beyond end();

This is what I get, when I watch the iterator "i":

{_M_current = 0x7fc43d61bd78 "a&b"}
{_M_current = 0x7fc43d61bd79 "&b"}
{_M_current = 0x7fc43d61bd7a "b"}
{_M_current = 0x7fc43d61bd7b ""}
{_M_current = 0x7fc43d61bd7c "o = a&b\n"}
{_M_current = 0x7fc43d61bd7d " = a&b\n"}

Then it tries to replace "=" and fails with an out_of_range exception.
I do not understand, how it is possible for the iterator to get obviously beyond end().

I would be appreciated, if someone could explain me, how this is possible, because I could not find someone in the web, who had the same problem.

Thanks and regards,

reeaal

Edit:

Argh, I really thought to complicated. x)
This is how I solved it now.

string percent_encode(string str)
{
  string reserved =
    // gen-delims
    ":/?#[]@"
    // sub-delims
    "!
amp;'()*+,;="
  ;

  std::stringstream ss;

  for(string::iterator i = str.begin(); i < str.end(); i++) {
    // encodes reserved, unreserved non-ascii and space characters.
    int c = *i;
    if(c > 126 || c == 32 || reserved.find(*i) != string::npos) {
      ss << '%' << std::hex << c;
    } else {
      ss << *i;
    }
  }

  return ss.str();
}

Thanks Diego :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷…雨湿花 2024-11-15 21:09:44

replace 使当前迭代器无效,因此它可能会超出末尾。

有多种方法可以正确编写此代码。例如,生成(并返回)一个新字符串会更容易,甚至可能更高效(请注意,替换也必须将字符串的其余部分移动一个位置)。此外,还可以使用索引更新字符串长度和位置。

但是返回一个全新字符串的选项是我能想到的最好的选择。更实用:)

replace invalidates current iterator, so it may go beyond the end.

There are several ways of writing this code right. For example, generating (and returning) a new string would be the easier, and maybe even more efficient (note that replace has to move the rest of the string one position too). Also, playing with updated string length and position with indices.

But the option of returning a completely new string is the best I can think of. Much more functional :)

清泪尽 2024-11-15 21:09:44

问题是您在迭代 str 时更改了它。当您更改字符串的内容时,迭代器将失效。解决方案是使用包含转换结果的字符串的另一个副本。

The problem is that you change str while iterating over it. The iterators get invalidated when you change contents of the string. The solution is to use another copy of the string that will contain the transformed result.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文