Как заменить все вхождения символа в строку? - PullRequest
432 голосов
/ 24 мая 2010

Как эффективно заменить все вхождения персонажа другим персонажем в std::string?

Ответы [ 12 ]

665 голосов
/ 24 мая 2010

std::string не содержит такой функции, но вы можете использовать отдельную функцию replace из заголовка algorithm.

#include <algorithm>
#include <string>

void some_func() {
  std::string s = "example string";
  std::replace( s.begin(), s.end(), 'x', 'y'); // replace all 'x' to 'y'
}
120 голосов
/ 27 февраля 2013

Я думал, что добавлю бустер :

#include <boost/algorithm/string/replace.hpp>

// in place
std::string in_place = "blah#blah";
boost::replace_all(in_place, "#", "@");

// copy
const std::string input = "blah#blah";
std::string output = boost::replace_all_copy(input, "#", "@");
108 голосов
/ 20 июня 2014

Вопрос касается замены character, но, поскольку я нашел эту страницу очень полезной (особенно замечание Конрада ), я хотел бы поделиться этой более обобщенной реализацией, которая позволяетиметь дело также с substrings:

std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
    size_t start_pos = 0;
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
    }
    return str;
}

Использование:

std::cout << ReplaceAll(string("Number Of Beans"), std::string(" "), std::string("_")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("X")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("h")) << std::endl;

Выходы:

Number_Of_Beans

XXjXugtXty

hhjhugthty


РЕДАКТИРОВАТЬ:

Выше может быть реализовано более подходящим способом, в случае если ваши выступлениябеспокойство, ничего не возвращая (void) и внося изменения непосредственно в строку str, заданную в качестве аргумента, передавая по адресу вместо по значению .Это позволило бы избежать бесполезного и дорогостоящего копирования исходной строки при возврате результата.Ваш звонок, затем ...

Код:

static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
    // Same inner code...
    // No return statement
}

Надеюсь, что это будет полезно для некоторых других ...

27 голосов
/ 20 апреля 2015

Представьте себе большой двоичный двоичный объект, в котором все байты 0x00 должны быть заменены на "\ 1 \ x30", а все байты 0x01 на "\ 1 \ x31", поскольку транспортный протокол не допускает \ 0-байтов.

В тех случаях, когда:

  • замещающая и заменяемая строки имеют разную длину,
  • есть много раз заменяемой строки в исходной строке и
  • исходная строка большая,

предоставленные решения не могут быть применены (потому что они заменяют только отдельные символы) или имеют проблемы с производительностью, потому что они будут вызывать string :: replace несколько раз, что будет генерировать копии размера большого двоичного объекта снова и снова. (Я не знаю, решение для повышения, возможно, это нормально с этой точки зрения)

Он проходит по всем вхождениям в исходной строке и строит новую строку по частям один раз :

void replaceAll(std::string& source, const std::string& from, const std::string& to)
{
    std::string newString;
    newString.reserve(source.length());  // avoids a few memory allocations

    std::string::size_type lastPos = 0;
    std::string::size_type findPos;

    while(std::string::npos != (findPos = source.find(from, lastPos)))
    {
        newString.append(source, lastPos, findPos - lastPos);
        newString += to;
        lastPos = findPos + from.length();
    }

    // Care for the rest after last occurrence
    newString += source.substr(lastPos);

    source.swap(newString);
}
20 голосов
/ 24 мая 2010

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

s.replace(s.find("x"), 1, "y")

Чтобы сделать это для всей строки, проще всего сделать цикл доваш s.find начинает возвращаться npos.Я полагаю, вы могли бы также поймать range_error, чтобы выйти из цикла, но это довольно уродливо.

6 голосов
/ 07 февраля 2016

Если вы хотите заменить более одного символа и имеете дело только с std::string, этот фрагмент будет работать, заменяя sNeedle в sHaystack на sReplace, а sNeedle и sReplace не обязательно должны быть одинакового размера. , Эта процедура использует цикл while для замены всех вхождений, а не только первый найденный слева направо.

while(sHaystack.find(sNeedle) != std::string::npos) {
  sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}
4 голосов
/ 24 мая 2010

Как предложил Кирилл, либо используйте метод replace, либо итерируйте по строке, заменяя каждый символ независимо.

В качестве альтернативы вы можете использовать метод find или find_first_of в зависимости от того, что вам нужно сделать.Ни одно из этих решений не выполнит работу за один раз, но с несколькими дополнительными строками кода вы должны заставить их работать на вас.: -)

3 голосов
/ 25 февраля 2015
#include <iostream>
#include <string>
using namespace std;
// Replace function..
string replace(string word, string target, string replacement){
    int len, loop=0;
    string nword="", let;
    len=word.length();
    len--;
    while(loop<=len){
        let=word.substr(loop, 1);
        if(let==target){
            nword=nword+replacement;
        }else{
            nword=nword+let;
        }
        loop++;
    }
    return nword;

}
//Main..
int main() {
  string word;
  cout<<"Enter Word: ";
  cin>>word;
  cout<<replace(word, "x", "y")<<endl;
  return 0;
}
0 голосов
/ 20 мая 2018

Старая школа: -)

std::string str = "H:/recursos/audio/youtube/libre/falta/"; 

for (int i = 0; i < str.size(); i++) {
    if (str[i] == '/') {
        str[i] = '\\';
    }
}

std::cout << str;

Результат:

H: \ recursos \ audio \ youtube \ libre \ falta \

0 голосов
/ 29 января 2018

Для простых ситуаций это работает довольно хорошо без использования какой-либо другой библиотеки, кроме std :: string (которая уже используется).

Заменить все вхождения символа a на символ b в some_string :

for (size_t i = 0; i < some_string.size(); ++i) {
    if (some_string[i] == 'a') {
        some_string.replace(i, 1, "b");
    }
}

Если строка большая или несколько вызовов для замены - это проблема, вы можете применить метод, упомянутый в этом ответе: https://stackoverflow.com/a/29752943/3622300

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