C ++ String манипуляция не имеет смысла для меня - PullRequest
1 голос
/ 25 апреля 2010

Это конкретное назначение связано с удалением подстрок из строк; Я пробую некоторые онлайн-курсы в Стэнфорде, чтобы выучить несколько новых языков.

То, что у меня так далеко, ниже, но если text = "hello hello" и remove ="el", оно застревает в цикле, но если я изменяю текст на text = "hello hllo", это работает, заставляя меня думать, что я делаю что-то явно глупое.

В назначении есть условие не изменять входящие строки, а вместо этого возвращать новую строку.

string CensorString1(string text, string remove){
    string returned;
    size_t found=0, lastfound=0;
    found = (text.substr(lastfound,text.size())).find(remove);
    while (string::npos != found ){
        returned += text.substr(lastfound,found);
        lastfound = found + remove.size();
        found = (text.substr(lastfound,text.size())).find(remove);
    }
    returned += text.substr(lastfound,found);
    return returned;
}

Руководство будет оценено :-) Спасибо

UPDATE

Принял очень дельный совет и изменил мой код так:

string CensorString1(string text, string remove){
string returned;
size_t found=0, lastfound=0;
found = text.find(remove);
while (string::npos != found ){
    returned += text.substr(lastfound,found);
    lastfound = found + remove.length();
    found = text.find(remove,lastfound);
}
returned += text.substr(lastfound);
return returned;
}

Но все же ведет себя так же

Есть еще идеи, ребята?

Ответы [ 3 ]

5 голосов
/ 25 апреля 2010

found = (text.substr(lastfound,text.size())).find(remove); неверно. Возвращает индекс искомой строки в text.substr(lastfound,text.size()), но не в text.

Возможно, вам следует изменить это на found = text.find(text, lastfound);.

Помимо неправильности, взятие подстроки (это значит, выделение новой строки) и вычисление индекса в ней весьма неэффективно, если оптимизатор не является супер-умным.

Более того, последний returned += text.substr(lastfound,found); также неверен: вам нужно добавить последний фрагмент текста, а не индекс до found (который, скорее всего, пуст, так как lastfound может быть меньше, чем found. Лучше было бы returned += text.substr(lastfound);

Edit:
Во втором примере вам нужно заменить returned += text.substr(lastfound,found); на returned += text.substr(lastfound,found-lastfound);. Второй аргумент substr - это длина, а не позиция.

С этим изменением тестовый пример отлично работает в моей тестовой программе.

(Дополнение И.Ф. Себастьяна:)

string CensorString1(string const& text, string const& remove){
  string returned;
  size_t found = string::npos, lastfound = 0;
  do {
    found = text.find(remove, lastfound);
    returned += text.substr(lastfound, found-lastfound);
    lastfound = found + remove.size();
  } while(found != string::npos);
  return returned;
}
0 голосов
/ 25 апреля 2010

found = (text.substr(lastfound,text.size())).find(remove); начинает отсчет для функции find() снова с нуля (т.е. первый символ после последнего совпадения будет иметь индекс 0 и будет выглядеть как начало text). Однако find может принимать 2 параметра, где второй параметр - это индекс, с которого нужно начинать. Таким образом, вы можете изменить эту строку на found = text.find(remove,lastfound)

Более четко:

text =                      hellohello
find "el" in here            ^ is at index 1 in `text`
substring after match          lohello
find "el" in here                 ^ is at index 3 in the substring
                                    but your program doesn't know
                                    that's actually index 6 in `text`
0 голосов
/ 25 апреля 2010

text.substr(lastfound,text.size()) начинается где-то в середине text и продолжается для всего размера text. Это не имеет смысла, хотя я полагаю, что это работает из-за того, что эти конкретные функции обрабатывают ошибки диапазона. string::npos заявит о вашем намерении лучше, чем size.

Вообще говоря, члены манипуляции string менее элегантны, чем более общие алгоритмы в <algorithm>. Вместо этого я рекомендую использовать их, например, std::search вместе с string::iterator вместо целочисленных смещений.

ОБНОВЛЕНИЕ: Такая же ошибка существует во втором примере. Используйте string::npos для второго аргумента substr, чтобы получить подстроку в конце.

...