Заменить часть строки другой строкой - PullRequest
167 голосов
/ 05 августа 2010

Возможно ли в C ++ заменить часть строки другой строкой?

В принципе, я хотел бы сделать это:

QString string("hello $name");
string.replace("$name", "Somename");

Но я бы хотел использовать стандартные библиотеки C ++.

Ответы [ 13 ]

261 голосов
/ 05 августа 2010

Есть функция для поиска подстроки в строке (find) и функция для замены определенного диапазона в строке другой строкой (replace) , так что вы можете комбинировать их, чтобы получить желаемый эффект:

bool replace(std::string& str, const std::string& from, const std::string& to) {
    size_t start_pos = str.find(from);
    if(start_pos == std::string::npos)
        return false;
    str.replace(start_pos, from.length(), to);
    return true;
}

std::string string("hello $name");
replace(string, "$name", "Somename");

В ответ на комментарий, я думаю replaceAll будет выглядеть примерно так:

void replaceAll(std::string& str, const std::string& from, const std::string& to) {
    if(from.empty())
        return;
    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(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
    }
}
76 голосов
/ 23 марта 2015

С C ++ 11 вы можете использовать std::regex примерно так:

    std::string string("hello $name");
    string = std::regex_replace(string, std::regex("\\$name"), "Somename");

Двойная косая черта необходима для экранирования escape-символа.

18 голосов
/ 05 августа 2010

std::string имеет метод replace, это то, что вы ищете?

Вы можете попробовать:

s.replace(s.find("$name"), sizeof("$name") - 1, "Somename");

У меня нетпопробовал сам, просто прочитал документацию по find() и replace().

8 голосов
/ 04 февраля 2013

Чтобы получить возвращенную новую строку, используйте:

std::string ReplaceString(std::string subject, const std::string& search,
                          const std::string& replace) {
    size_t pos = 0;
    while ((pos = subject.find(search, pos)) != std::string::npos) {
         subject.replace(pos, search.length(), replace);
         pos += replace.length();
    }
    return subject;
}

Если вам нужна производительность, вот оптимизированная функция, которая изменяет входную строку, она не создает копию строки:

void ReplaceStringInPlace(std::string& subject, const std::string& search,
                          const std::string& replace) {
    size_t pos = 0;
    while ((pos = subject.find(search, pos)) != std::string::npos) {
         subject.replace(pos, search.length(), replace);
         pos += replace.length();
    }
}

Тесты:

std::string input = "abc abc def";
std::cout << "Input string: " << input << std::endl;

std::cout << "ReplaceString() return value: " 
          << ReplaceString(input, "bc", "!!") << std::endl;
std::cout << "ReplaceString() input string not modified: " 
          << input << std::endl;

ReplaceStringInPlace(input, "bc", "??");
std::cout << "ReplaceStringInPlace() input string modified: " 
          << input << std::endl;

Вывод:

Input string: abc abc def
ReplaceString() return value: a!! a!! def
ReplaceString() input string not modified: abc abc def
ReplaceStringInPlace() input string modified: a?? a?? def
6 голосов
/ 05 августа 2010

Да, вы можете сделать это, но вы должны найти позицию первой строки с помощью элемента find () строки, а затем заменить его элементом replace ().

string s("hello $name");
size_type pos = s.find( "$name" );
if ( pos != string::npos ) {
   s.replace( pos, 5, "somename" );   // 5 = length( $name )
}

Если выпланируя использовать Стандартную библиотеку, вы действительно должны получить копию книги Стандартная библиотека C ++ , которая очень хорошо охватывает все эти вещи.

4 голосов
/ 04 апреля 2015

Звучит как опция

string.replace(string.find("%s"), string("%s").size(), "Something");

Вы можете обернуть это в функцию, но это однострочное решение звучит приемлемо. Проблема в том, что это изменит только первый случай, вы можете захотеть зациклить его, но он также позволяет вам вставить несколько переменных в эту строку с одним и тем же токеном (%s)

4 голосов
/ 29 сентября 2014

Я обычно использую это:

std::string& replace(std::string& s, const std::string& from, const std::string& to)
{
    if(!from.empty())
        for(size_t pos = 0; (pos = s.find(from, pos)) != std::string::npos; pos += to.size())
            s.replace(pos, from.size(), to);
    return s;
}

Он постоянно вызывает std::string::find(), чтобы найти другие вхождения искомой строки, пока std::string::find() ничего не найдет. Поскольку std::string::find() возвращает позицию соответствия, у нас нет проблемы признания итераторов недействительными.

3 голосов
/ 04 февраля 2016

Если все строки являются std :: string, вы обнаружите странные проблемы с обрезкой символов при использовании sizeof(), потому что он предназначен для строк C, а не строк C ++. Исправление заключается в использовании .size() метода класса std::string.

sHaystack.replace(sHaystack.find(sNeedle), sNeedle.size(), sReplace);

Это заменяет встроенный sHaystack - нет необходимости возвращать задание =.

Пример использования:

std::string sHaystack = "This is %XXX% test.";
std::string sNeedle = "%XXX%";
std::string sReplace = "my special";
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
std::cout << sHaystack << std::endl;
2 голосов
/ 27 января 2016
wstring myString = L"Hello $$ this is an example. By $$.";
wstring search = L"$$";
wstring replace = L"Tom";
for (int i = myString.find(search); i >= 0; i = myString.find(search))
    myString.replace(i, search.size(), replace);
2 голосов
/ 17 апреля 2014
std::string replace(std::string base, const std::string from, const std::string to) {
    std::string SecureCopy = base;

    for (size_t start_pos = SecureCopy.find(from); start_pos != std::string::npos; start_pos = SecureCopy.find(from,start_pos))
    {
        SecureCopy.replace(start_pos, from.length(), to);
    }

    return SecureCopy;
}
...