एक स्ट्रिंग का हिस्सा दूसरे स्ट्रिंग से बदलें


186

क्या C ++ में एक स्ट्रिंग के भाग को दूसरे स्ट्रिंग से बदलना संभव है?

मूल रूप से, मैं यह करना चाहूंगा:

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

लेकिन मैं मानक C ++ पुस्तकालयों का उपयोग करना चाहूंगा।


1
C में स्ट्रिंग को बदलने के लिए फंक्शन का क्या डुप्लिकेट है? - उफ़ खेद है कि सी है, सी ++ नहीं; काश मैं अनवॉट कर सकूं।
पॉलीजेनैलेबुलेंट्स

1
@ मुझे लगता है कि यह C ++ के लिए भी पूछा गया होगा, लेकिन मैं इसे नहीं पा सकता हूं
माइकल Mrozek

1
प्रश्न पर एक एसटीडी टैग है, लेकिन शायद आप बूस्ट के एल्गोरिदम को बढ़ावा देने में दिलचस्पी ले सकते हैं, जिसमें एल्गोरिदम (inplace / copy, केस संवेदनशील / केस असंवेदनशील, पहले / अंतिम / सभी / n-th) को बदलने का एक विस्तृत विकल्प शामिल है )।
अंकलबीन्स

@Michael Mrozek पर ऊपर एक नहीं है stackoverflow.com/questions/3418231/... लेकिन यह नए और यहाँ replaceAll विधि और अधिक मजबूत है।
dave-holm

जवाबों:


288

एक स्ट्रिंग के भीतर एक विकल्प खोजने के लिए एक फ़ंक्शन है ( 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'
    }
}

2
यदि मूल स्ट्रिंग में "$ नाम" का एक उदाहरण है और मैं उन सभी को प्रतिस्थापित करना चाहता हूं तो मैं इसे कैसे ठीक करूंगा।
टॉम लेसे

1
संदर्भ के अनुसार क्यों नहीं fromऔर toपारित किया गया const? अगर fromवहाँ नहीं है तो आपका कार्य क्या है ? -1उसके लिए मुझसे।
sbi

10
@sbi फिक्स्ड, हालाँकि आप इसे हमलों के बजाय सिफारिशों के रूप में वर्णित कर सकते हैं - यह बस मेरे लिए नहीं हुआ, मैं शायद ही कभी उपयोग करने के लिए सोचता constहूं और अगर मैंने इस तरह से एक उपयोगिता विधि लिखी है, तो मैं केवल इसे कॉल करूंगा यदि मुझे पता था प्रतिस्थापन मान्य थे
माइकल Mrozek

10
@ मिचेल: अच्छा, मैंने अपने वोट को डाउन-वोट में बदल दिया। खारिज constकरना C ++ के सर्वश्रेष्ठ उपकरणों में से एक की अवहेलना है। फ़ंक्शन मापदंडों के लिए प्रति constसंदर्भ पासिंग डिफ़ॉल्ट मोड होना चाहिए। (FTR, बिना const, आप अपने फ़ंक्शन के लिए स्ट्रिंग शाब्दिक भी पास नहीं कर सकते, क्योंकि आप अस्थायी लोगों को गैर- constसंदर्भों से बाँध नहीं सकते । इसलिए फ़ंक्शन भी ऐसा नहीं करेगा जो इसे लिखा गया था।)
sbi

19
क्या यह अभी भी 2018 में एकमात्र समाधान है? यदि ऐसा है और कोई C ++ कमेटी इसे पढ़ रही है, तो इसे हल करें। संकोचशील। विभाजित (स्ट्रिंग, स्ट्रिंग) और बदलें (स्ट्रिंग, स्ट्रिंग) कृपया!
user997112

96

C ++ 11 के साथ आप इसका उपयोग कर सकते हैं std::regex:

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

भागने के चरित्र से बचने के लिए डबल बैकस्लैश की आवश्यकता होती है।


मुझे पूरा यकीन std::regex_replaceहै कि Qt की स्ट्रिंग को स्वीकार नहीं करता।
बार्टोज़कपी

1
तुम सही हो। जैसा कि होता है QString एक प्रतिस्थापित विधि प्रदान करता है जो क्यूआरएक्सएक्सपीपी स्वीकार करता है, क्यूटी के अपने सामान का उपयोग करने की अनुमति देता है। लेकिन मुझे लगता है वर्तमान जवाब की जगह द्वारा ठीक किया जा सकता है stringके साथ string.toStdString()
टॉम

1
या सिर्फ Stringकरने के लिए बदल रहा है std::string, क्योंकि प्रश्न Qt से संबंधित नहीं है। कृपया ऐसा करने पर विचार करें - मैं ख़ुशी से आपके उत्तर को बाद में बढ़ा दूंगा।
बार्टोज़केपी

5
रॉ स्ट्रिंग R"(\$name)"इसके बजाय लिखने की अनुमति देता है "\\$name"
जैरोड42

2
Std :: regex के निर्माण समय पर विचार किए बिना इसे खोजने / बदलने से कितना धीमा होगा?
jw_

18

std::stringएक replaceतरीका है, यह है कि आप क्या देख रहे हैं?

तुम कोशिश कर सकते हो:

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

मैंने अपने आप को आज़माया नहीं है, बस प्रलेखन को पढ़ें find()और replace()


2
मैं क्या देख सकता हूँ std :: string प्रतिस्थापित विधि दो स्ट्रिंग्स नहीं लेता जैसा कि मैं चाहूंगा।
टॉम लीज

2
यह मेरे लिए काम नहीं करता है। sizeof को स्ट्रिंग ("सोमनाम") से बदला जाना चाहिए। आकार () - 1
टिमज़मन

@ टिमजमैन: यह पहेली मुझे स्पष्ट रूप से बताती है कि आप सी-स्टाइल स्ट्रिंग से आरंभ कर सकते हैं।
SC मैडसन

5
दूसरा तर्क "$ नाम" की लंबाई ("सोमनाम" की लंबाई के बजाय) होना चाहिए, क्या यह नहीं होना चाहिए?
डैनियल चुंबन

10

नया स्ट्रिंग वापस करने के लिए इसका उपयोग करें:

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

रिप्लेसमेंट स्ट्रिंग () में subject.replace पर आपका कॉल है कि क्या वास्तव में स्ट्रिंग इनलाइन को संशोधित किया जा रहा है?
डेमियन

मैंने संक्षेप में स्रोत को देखा और ऐसा लग रहा है कि यह पुराने शब्द को सामने रखने के लिए चालित शब्दार्थ का उपयोग करता है, इसलिए इसे कॉपी नहीं किया जाता है, लेकिन डाला गया नया टुकड़ा पुराने स्ट्रिंग और पुराने स्ट्रिंग की पूंछ में कॉपी किया जाता है पुराने स्ट्रिंग के आकार के बफ़र्ड में कॉपी किया जाता है। यह संभव है कि स्ट्रिंग का विस्तार इतना है कि पूरे अंतर्निहित बफर को फिर से विभाजित किया गया है, लेकिन यदि आप 1 से 1 को उसके उदाहरण के रूप में प्रतिस्थापित करते हैं, तो मुझे लगता है कि यह "जगह में" होता है, या किसी भी नकल के बिना, लेकिन अगर आप स्ट्रिंग का विस्तार करते हैं, केवल पुराने स्ट्रिंग का पहला भाग कॉपी नहीं किया गया है, और केवल तब शायद।
Motes

6

हां, आप इसे कर सकते हैं, लेकिन आपको पहले स्ट्रिंग की खोज () सदस्य के साथ स्ट्रिंग की स्थिति का पता लगाना होगा, और फिर इसे प्रतिस्थापित () सदस्य के साथ बदलना होगा।

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

यदि आप मानक पुस्तकालय का उपयोग करने की योजना बना रहे हैं, तो आपको वास्तव में पुस्तक C ++ मानक पुस्तकालय की एक प्रति पकड़ लेनी चाहिए जो इस सभी सामान को अच्छी तरह से कवर करती है


1
यह size_t और नहीं size_type
रेवो

1
यह std :: string :: size_type, not size_t या unadorned size_type है।
jmucchiello

5

मैं आम तौर पर इसका उपयोग करता हूं:

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()की स्थिति की वापसी में हमें पुनरावृत्तियों को अमान्य करने की समस्या नहीं है।


4

यह एक विकल्प की तरह लगता है

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

आप इसे एक फ़ंक्शन में लपेट सकते हैं लेकिन यह एक-पंक्ति समाधान स्वीकार्य लगता है। समस्या यह है कि यह केवल पहली घटना को बदल देगा, आप इसके ऊपर लूप करना चाहते हैं, लेकिन यह आपको एक ही टोकन के साथ इस स्ट्रिंग में कई चर डालने की अनुमति देता है ( %s)


1
शैली की तरह, लेकिन अलग-अलग तार पाए गए ^ ^str.replace(str.find("%s"), string("%s").size(), "Something");
पॉल वुर्ट्ज़

3

यदि सभी स्ट्रिंग्स std :: string हैं, तो आपको वर्णों के कटऑफ के साथ अजीब समस्याएं मिलेंगी यदि उपयोग करना है sizeof()क्योंकि यह C स्ट्रिंग्स के लिए है, C ++ स्ट्रिंग्स के लिए नहीं। का .size()वर्ग विधि का उपयोग करने के लिए ठीक है std::string

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

वह sHaystack इनलाइन को प्रतिस्थापित करता है - उस पर वापस = a असाइनमेंट करने की आवश्यकता नहीं है।

उदाहरण उपयोग:

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

यदि आप इसे जल्दी से करना चाहते हैं तो आप दो स्कैन दृष्टिकोण का उपयोग कर सकते हैं। छद्म कोड:

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

}

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

2
क्या आप कृपया इस कोड (अपने उत्तर में) की व्याख्या कर सकते हैं? आप इस तरह से अधिक upvotes प्राप्त कर सकते हैं!
द हैट विथ द हैट

1

मेरा अपना कार्यान्वयन, इस बात को ध्यान में रखते हुए कि स्ट्रिंग को केवल एक बार फिर से आकार देने की आवश्यकता है, फिर प्रतिस्थापित किया जा सकता है।

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

मैं अभी 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;
}

0

यह उपयोग करने के लिए और भी बेहतर हो सकता है

void replace(string& input, const string& from, const string& to)
{
    while(true)
    {
        size_t startPosition = input.find(from);
        if(startPosition == string::npos)
            break;
        input.replace(startPosition, from.length(), to);
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.