অন্য স্ট্রিংয়ের সাথে একটি স্ট্রিংয়ের অংশটি প্রতিস্থাপন করুন


186

স্ট্রিংয়ের অংশটিকে অন্য স্ট্রিংয়ের সাথে প্রতিস্থাপন করা কি সি ++ তে সম্ভব?

মূলত, আমি এটি করতে চাই:

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

তবে আমি স্ট্যান্ডার্ড সি ++ লাইব্রেরি ব্যবহার করতে চাই।


1
সম্ভাব্য সদৃশ সি এর স্ট্রিং প্রতিস্থাপন ফাংশন কি? - উফ আফসোস যে সি, সি ++ নয়; আমি আশা করি আমি বিজয়ী করতে পারি।
বহুগেনুবিক্যান্টস

1
@ পলি আমি ভাবব যে এটিকে অবশ্যই সি ++ এর জন্যও জিজ্ঞাসা করা হয়েছিল, তবে আমি এটি খুঁজে পাচ্ছি না
মাইকেল মরোজেক

1
প্রশ্নের উপর একটি স্টাডি ট্যাগ রয়েছে, তবে সম্ভবত আপনি বুস্টের স্ট্রিং অ্যালগরিদমগুলির প্রতি আগ্রহী হতে পারেন, যার মধ্যে অ্যালগরিদমগুলি প্রতিস্থাপনের বিস্তৃত পছন্দ অন্তর্ভুক্ত রয়েছে (অন্তর্নিহিত / অনুলিপি, কেস সংবেদনশীল / কেস সংবেদনশীল / সংবেদনশীল, প্রতিস্থাপন প্রথম / শেষ / সমস্ত / এন-ম) )।
আঙ্কেলবেন্স

@Michael Mrozek ধরে এক আছে stackoverflow.com/questions/3418231/... কিন্তু এটা নতুন এবং এখানে আপনার replaceAll পদ্ধতি আরো জোরালো হয়।
ডেভ-হলম

উত্তর:


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আমার জন্য।
এসবিআই

10
@ এসবিআই ফিক্সড, যদিও আপনি এটি আক্রমণগুলির পরিবর্তে প্রস্তাবনা হিসাবে চিহ্নিত করতে পারেন - এটি কেবল আমার কাছে ঘটেছিল না, আমি খুব কমই ব্যবহার করতে পারি বলে মনে করি constএবং যদি আমি এর মতো কোনও ইউটিলিটি পদ্ধতি লিখি তবে আমি কেবল এটিই জানতাম যদি আমি জানতাম প্রতিস্থাপন বৈধ ছিল
মাইকেল মরোজেক

10
@ মিশেল: ভাল, আমি আমার ডাউন-ভোটকে একটি উচ্চ ভোটে পরিণত করেছি। খারিজ constকরা সি ++ 'সেরা সরঞ্জামগুলির মধ্যে একটিকে উপেক্ষা করছে। ফাংশন পরামিতিগুলির জন্য রেফারেন্স প্রতি পাসিং constডিফল্ট মোড হওয়া উচিত। (এফটিআর, ছাড়াই constআপনি এমনকি আপনার ফাংশনে স্ট্রিং লিটারেলও দিতে পারেননি, কারণ আপনি অ- constরেফারেন্সগুলিতে টেম্পোরারিগুলিকে আবদ্ধ করতে পারবেন না the সুতরাং ফাংশন এমনকি এটিতে যা লেখা হয়েছিল তাও করতে পারে না))
এসবিআই

19
এটি কি এখনও 2018 এর একমাত্র সমাধান? যদি তাই হয় এবং কোনও সি ++ কমিটি এটি পড়তে থাকে তবে তা বাছাই করুন। এটা লজ্জাজনক. বিভক্ত (স্ট্রিং, স্ট্রিং) এবং প্রতিস্থাপন (স্ট্রিং, স্ট্রিং) দয়া করে!
ব্যবহারকারী 997112 12

95

সি ++ এর মাধ্যমে আপনি এর std::regexমতো ব্যবহার করতে পারেন :

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

পালানোর চরিত্রটি পালনের জন্য ডাবল ব্যাকস্ল্যাশ প্রয়োজন।


আমি নিশ্চিত std::regex_replaceযে Qt এর স্ট্রিং গ্রহণ করে না pretty
বার্তোসকেপিপি

1
তুমি ঠিক. এটি ঘটে গেলে কিউ স্ট্রিং একটি প্রতিস্থাপন পদ্ধতি সরবরাহ করে যা কিউআরএক্সএক্সপ্যাক্টকে গ্রহণ করে, কিউটির নিজস্ব স্টাফ ব্যবহার করার অনুমতি দেয়। তবে আমি মনে করি বর্তমান উত্তরটি প্রতিস্থাপনের stringমাধ্যমে সংশোধন করা যেতে পারে string.toStdString()
টম

1
বা কেবল পরিবর্তিত Stringহয়ে std::string, কারণ প্রশ্নটি Qt সম্পর্কিত নয়। দয়া করে এটি করা বিবেচনা করুন - আমি পরে আপনার উত্তরটি সানন্দে উপস্থাপন করব।
বার্টোসকেপি

5
কাঁচা স্ট্রিং R"(\$name)"পরিবর্তে লিখতে দেয় "\\$name"
জারোড 42

2
স্টাড :: রেজেক্সের নির্মাণের সময় বিবেচনা না করে এটি সন্ধান / প্রতিস্থাপনের চেয়ে ধীরে ধীরে কত হবে?
jw_

18

std::stringএকটি replaceপদ্ধতি আছে, আপনি কি এটি খুঁজছেন?

আপনি চেষ্টা করতে পারেন:

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

আমি নিজেকে চেষ্টা করিনি, শুধু উপর ডকুমেন্টেশন পড়া find()এবংreplace()


2
আমি যা দেখতে পাচ্ছি তাতে স্ট্যান্ড :: স্ট্রিং প্রতিস্থাপন পদ্ধতিটি আমার পছন্দ মতো দুটি স্ট্রিং নেয় না।
টম লিজ

2
এটি আমার পক্ষে কাজ করে না। আকারের স্ট্রিং ("সোমেনাম") দ্বারা প্রতিস্থাপন করা উচিত size আকার () - 1
টিমজামান

@ টিমজামান: এটি আমার ধাঁধা দেয়, ডকুমেন্টেশনে পরিষ্কারভাবে বলা হয়েছে যে আপনি সি-স্টাইলের স্ট্রিং থেকে শুরু করতে পারবেন।
এসসি ম্যাডসেন

5
২ য় আর্গুমেন্টটি "of নাম" এর দৈর্ঘ্য হওয়া উচিত ("সোমেনাম" দৈর্ঘ্যের পরিবর্তে), এটি কি উচিত নয়?
ড্যানিয়েল কিস

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

রিপ্লেসস্ট্রিংইনপ্লেস () এ সাবজেক্ট.রেপ্লেসে আপনার কলটি কি সত্যই স্ট্রিংটি অন্তর্ভুক্ত করছে?
দামিয়ান

আমি সংক্ষেপে উত্সটির দিকে লক্ষ্য করেছি এবং দেখে মনে হচ্ছে এটি পুরানো স্ট্রিংয়ের সামনের অংশটিকে জায়গায় স্থানান্তর করতে মুভ সিঁটমিকগুলি ব্যবহার করে, যাতে এটি অনুলিপি করা হয় না, তবে নতুন টুকরাটি পুরানো স্ট্রিং এবং পুরাতন স্ট্রিংয়ের লেজের মধ্যে অনুলিপি করা হয় পুরানো স্ট্রিংয়ের পুনরায় আকার দেওয়া বাফারে অনুলিপি করা হয়। এটা সম্ভব যে স্ট্রিংটি এত বিস্তৃত হয় যে পুরো অন্তর্নিহিত বাফারটিকে পুনরায় স্থানান্তরিত করা হয়, তবে আপনি যদি তার উদাহরণ অনুসারে 1 থেকে 1 প্রতিস্থাপন করেন তবে আমার ধারণা এটি "স্থানে" বা কোনও অনুলিপি ছাড়াই ঘটেছিল, তবে আপনি যদি স্ট্রিংটি প্রসারিত করেন, শুধুমাত্র পুরানো স্ট্রিংয়ের প্রথম অংশটি অনুলিপি করা হয়নি, এবং কেবল তখনই হতে পারে।
মোটস

6

হ্যাঁ, আপনি এটি করতে পারেন, তবে আপনাকে স্ট্রিংয়ের সন্ধান () সদস্যের সাথে প্রথম স্ট্রিংয়ের অবস্থানটি অনুসন্ধান করতে হবে এবং তারপরে এটি প্রতিস্থাপন () সদস্যের সাথে প্রতিস্থাপন করতে হবে।

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

আপনি যদি স্ট্যান্ডার্ড লাইব্রেরিটি ব্যবহার করার পরিকল্পনা করে থাকেন তবে আপনার সত্যিকারের সি ++ স্ট্যান্ডার্ড লাইব্রেরি বইটির একটি অনুলিপি পাওয়া উচিত যা এই সমস্ত জিনিস খুব ভালভাবে কভার করে।


1
এটা size_t এবং size_type
Revo

1
এটি স্ট্যান্ড :: স্ট্রিং :: সাইজ_প্রকার, আকার_টি বা অচেনা আকার_প্রকার নয়।
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

সমস্ত স্ট্রিং যদি স্ট্যান্ড :: স্ট্রিং হয় তবে আপনি অক্ষরগুলির কাট অফের সাথে অদ্ভুত সমস্যাগুলি ব্যবহার করতে পারেন sizeof()কারণ এটি সি স্ট্রিংগুলির জন্য বোঝানো হয়েছে, সি ++ স্ট্রিং নয়। ফিক্সটি হল .size()ক্লাসের পদ্ধতিটি ব্যবহার করা std::string

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

এটি হাইস্ট্যাক ইনলাইন প্রতিস্থাপন করে - এটির জন্য একটি = এসাইনমেন্ট করার দরকার নেই।

ব্যবহারের উদাহরণ:

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. দ্বিতীয় পার্স আমরা প্রতিস্থাপন করা একটি ম্যাচ পেলে স্ট্রিংয়ের শেষে থেকে শুরু করুন, অন্যথায় আমরা কেবল প্রথম স্ট্রিং থেকে অক্ষরগুলি অনুলিপি করি।

আমি নিশ্চিত না যে এটি কোনও স্থানের পূর্ববর্তী স্থানে অনুকূলিত করা যায় কিনা।

এবং একটি সি ++ 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
আপনি কি দয়া করে এই কোডটি ব্যাখ্যা করতে পারেন (আপনার উত্তরে)? আপনি সম্ভবত আরও উপার্জন পেতে পারেন!
দ্য হাট উইথ দ্য হাট

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

আমি এখনই সি ++ শিখছি, তবে পূর্বে পোস্ট করা কিছু কোড সম্পাদনা করছি, আমি সম্ভবত এরকম কিছু ব্যবহার করব। এটি আপনাকে 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);
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.