简体   繁体   English

替换为字符串迭代(out_of_range)

[英]Replace in string iteration (out_of_range)

I wrote a function which percent-encodes a string, as follows: 我编写了一个对字符串进行百分比编码的函数,如下所示:

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;
}

When I call this function for a string like "a&b", an out_of_range exception is thrown: 当我为“ a&b”之类的字符串调用此函数时,将抛出out_of_range异常:

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(); 我使用调试器跟踪了此异常,发现替换效果很好,但是它以某种方式迭代了end();

This is what I get, when I watch the iterator "i": 这是我看到迭代器“ 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. 然后,它尝试替换“ =”,并以out_of_range异常失败。 I do not understand, how it is possible for the iterator to get obviously beyond end(). 我不明白,迭代器如何有可能明显超出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. 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();
}

Thanks Diego :) 谢谢迭戈:)

replace invalidates current iterator, so it may go beyond the end. replace使当前的迭代器无效,因此它可能会超出结尾。

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). 例如,生成(并返回)新字符串会更容易,甚至可能更有效(请注意,replace也必须将字符串的其余部分移动一个位置)。 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 :) 功能更多:)

The problem is that you change str while iterating over it. 问题是您在迭代str时更改了str。 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. 解决方案是使用包含转换结果的字符串的另一个副本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM