Заменить в итерации строки (out_of_range) - PullRequest
0 голосов
/ 20 мая 2011

Я написал функцию, которая кодирует строку в процентах, следующим образом:

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 ().

Я был бы признателен, если бы кто-то мог объяснить мне, как это возможно, потому что я не мог найти кого-то вСеть, у которой была такая же проблема.

Спасибо и всего наилучшего,

reeaal

Редактировать:

Ох, я действительно думал, что сложно.х) Вот как я решил это сейчас.

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

Спасибо, Диего :) 1025 *

Ответы [ 2 ]

6 голосов
/ 20 мая 2011

replace делает недействительным текущий итератор, поэтому он может выйти за пределы конца.

Есть несколько способов правильно написать этот код. Например, генерация (и возврат) новой строки будет проще и, возможно, даже более эффективной (обратите внимание, что замена должна переместить остальную часть строки также на одну позицию). Также игра с обновленной длиной строки и позицией с индексами.

Но вариант возврата совершенно новой строки - лучшее, что я могу придумать. Гораздо более функционально:)

0 голосов
/ 20 мая 2011

Проблема в том, что вы меняете str, перебирая его. Итераторы становятся недействительными, когда вы изменяете содержимое строки. Решение состоит в том, чтобы использовать другую копию строки, которая будет содержать преобразованный результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...