IT story

문자열의 일부를 다른 문자열로 교체

hot-time 2020. 5. 25. 08:09
반응형

문자열의 일부를 다른 문자열로 교체


C ++에서 문자열의 일부를 다른 문자열로 바꿀 수 있습니까?

기본적 으로이 작업을 수행하고 싶습니다.

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

그러나 Standard C ++ 라이브러리를 사용하고 싶습니다.


문자열 ( 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'
    }
}

C ++ 11을 사용하면 다음 std::regex과 같이 사용할 수 있습니다 .

    #include <regex>
    ...
    std::string string("hello $name");
    string = std::regex_replace(string, std::regex("\\$name"), "Somename");

이스케이프 문자를 이스케이프 처리하려면 이중 백 슬래시가 필요합니다.


std::stringreplace당신을 위해 무엇을 찾고있는 것을, 방법을 무엇입니까?

시도해 볼 수 있습니다 :

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

난 그냥에 대한 설명서를 읽고, 자신을 시도하지 않은 find()replace().


새 문자열을 반환하려면 다음을 사용하십시오.

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

예, 할 수 있지만 string의 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 ++ 표준 라이브러리 사본을 실제로 얻어야 합니다.


이것은 옵션처럼 들립니다

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

이것을 함수로 포장 할 수는 있지만이 한 줄 솔루션은 받아 들일 수 있습니다. 문제는 이것이 첫 번째 발생만을 변경한다는 것입니다. 반복하고 싶을 수도 있지만 동일한 토큰 ( %s) 을 사용 하여이 문자열에 여러 변수를 삽입 할 수도 있습니다


I use generally this:

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

It repeatedly calls std::string::find() to locate other occurrences of the searched for string until std::string::find() doesn't find anything. Because std::string::find() returns the position of the match we don't have the problem of invalidating iterators.


If all strings are std::string, you'll find strange problems with the cutoff of characters if using sizeof() because it's meant for C strings, not C++ strings. The fix is to use the .size() class method of std::string.

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

That replaces sHaystack inline -- no need to do an = assignment back on that.

Example usage:

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;

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

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

If you want to do it quickly you can use a two scan approach. Pseudo code:

  1. first parse. find how many matching chars.
  2. expand the length of the string.
  3. second parse. Start from the end of the string when we get a match we replace, else we just copy the chars from the first string.

I am not sure if this can be optimized to an in-place algo.

And a C++11 code example but I only search for one char.

#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";

}

I'm just now learning C++, but editing some of the code previously posted, I'd probably use something like this. This gives you the flexibility to replace 1 or multiple instances, and also lets you specify the start point.

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

My own implementation, taking into account that string needs to be resized only once, then replace can happen.

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

Usage could be for example like this:

std::string dirSuite = replaceAll(replaceAll(relPath.parent_path().u8string(), "\\", "/"), ":", "");

참고URL : https://stackoverflow.com/questions/3418231/replace-part-of-a-string-with-another-string

반응형