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

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

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

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

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

Ответы [ 13 ]

1 голос
/ 13 июля 2016

Если вы хотите сделать это быстро, вы можете использовать два сканирования.Псевдокод:

  1. первый анализ.найти, сколько совпадающих символов.
  2. увеличить длину строки.
  3. второй разбор.Начинайте с конца строки, когда мы получим совпадение, которое мы заменим, иначе мы просто скопируем символы из первой строки..

    И пример кода на C ++ 11, но я ищу только один символ.

    #include <string>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    void ReplaceString(string& subject, char search, const string& replace)
    {   
        size_t initSize = subject.size();
        int count = 0;
        for (auto c : subject) { 
            if (c == search) ++count;
        }
    
        size_t idx = subject.size()-1 + count * replace.size()-1;
        subject.resize(idx + 1, '\0');
    
        string reverseReplace{ replace };
        reverse(reverseReplace.begin(), reverseReplace.end());  
    
        char *end_ptr = &subject[initSize - 1];
        while (end_ptr >= &subject[0])
        {
            if (*end_ptr == search) {
                for (auto c : reverseReplace) {
                    subject[idx - 1] = c;
                    --idx;              
                }           
            }
            else {
                subject[idx - 1] = *end_ptr;
                --idx;
            }
            --end_ptr;
        }
    }
    
    int main()
    {
        string s{ "Mr John Smith" };
        ReplaceString(s, ' ', "%20");
        cout << s << "\n";
    
    }
    
0 голосов
/ 18 апреля 2019

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

template <typename T>
std::basic_string<T> replaceAll(const std::basic_string<T>& s, const T* from, const T* to)
{
    auto length = std::char_traits<T>::length;
    size_t toLen = length(to), fromLen = length(from), delta = toLen - fromLen;
    bool pass = false;
    std::string ns = s;

    size_t newLen = ns.length();

    for (bool estimate : { true, false })
    {
        size_t pos = 0;

        for (; (pos = ns.find(from, pos)) != std::string::npos; pos++)
        {
            if (estimate)
            {
                newLen += delta;
                pos += fromLen;
            }
            else
            {
                ns.replace(pos, fromLen, to);
                pos += delta;
            }
        }

        if (estimate)
            ns.resize(newLen);
    }

    return ns;
}

Использование может быть, например, таким:

std::string dirSuite = replaceAll(replaceAll(relPath.parent_path().u8string(), "\\", "/"), ":", "");
0 голосов
/ 02 декабря 2015

Я только сейчас изучаю C ++, но редактируя часть ранее опубликованного кода, я бы, вероятно, использовал что-то вроде этого. Это дает вам возможность заменить 1 или несколько экземпляров, а также позволяет указать начальную точку.

using namespace std;

// returns number of replacements made in string
long strReplace(string& str, const string& from, const string& to, size_t start = 0, long count = -1) {
    if (from.empty()) return 0;

    size_t startpos = str.find(from, start);
    long replaceCount = 0;

    while (startpos != string::npos){
        str.replace(startpos, from.length(), to);
        startpos += to.length();
        replaceCount++;

        if (count > 0 && replaceCount >= count) break;
        startpos = str.find(from, startpos);
    }

    return replaceCount;
}
...