স্ট্রিংয়ে কোনও চরিত্রের সমস্ত উপস্থিতি কীভাবে প্রতিস্থাপন করবেন?


480

কোনও চরিত্রের সমস্ত ঘটনাকে অন্য চরিত্রের সাথে প্রতিস্থাপনের কার্যকর উপায় কী std::string?

উত্তর:


742

std::stringএই জাতীয় ফাংশন নেই তবে আপনি শিরোনাম replaceথেকে একা একা ফাংশন ব্যবহার করতে পারেন algorithm

#include <algorithm>
#include <string>

void some_func() {
  std::string s = "example string";
  std::replace( s.begin(), s.end(), 'x', 'y'); // replace all 'x' to 'y'
}

6
std::stringহয় একটি ধারক বিশেষভাবে অক্ষরের ক্রমের সাথে সাথে কাজ চালানোর জন্য পরিকল্পিত। লিঙ্ক
কিরিল ভি। লায়াডভিনস্কি

164
দুর্ভাগ্যক্রমে, এটি কেবল একটি চরকে অন্য চর দ্বারা প্রতিস্থাপন করতে দেয়। এটি কোনও চরকে আরও অক্ষরের সাথে প্রতিস্থাপন করতে পারে না (এটি স্ট্রিং দ্বারা)। আরও অক্ষরের সাথে অনুসন্ধান-প্রতিস্থাপন করার কোনও উপায় আছে কি?
সাসকিউ

6
@ কিরিল ভি। লায়াডভিনস্কি যদি আমি কেবল কোনও ঘটনা সরাতে চাই তবে কী হবে।
SIFE

4
@ কিরিলভি.লায়াডভিনস্কি: আমি যখন এই পদ্ধতিটি সমস্ত এক্স এর সাথে প্রতিস্থাপন করতে ব্যবহার করি তখন মূল স্ট্রিংটি নির্বিশেষে ফলাফল দীর্ঘতর স্ট্রিং হয়। আমি কি কৌতুহল করছি আপনি কি মনে করেন সমস্যা হবে। (কোডটি আপনি যেমন লিখেছেন ঠিক
তেমনই

6
@ ট্রান্সসেন্ডেন্ট: এর std::string::replace()পরিবর্তে ঠিক একই ঘটনা ঘটে std::replace()! 'x' ( char) নিখুঁতভাবে size_t[মান 120] এ কাস্ট করা হয়, সুতরাং পুরো স্ট্রিং বা এর কিছু অংশ 'y' এর 120 কপি দিয়ে পূর্ণ হবে।
আইবিউ

128

আমি ভেবেছিলাম আমিও বুস্ট সলিউশনে টস করব :

#include <boost/algorithm/string/replace.hpp>

// in place
std::string in_place = "blah#blah";
boost::replace_all(in_place, "#", "@");

// copy
const std::string input = "blah#blah";
std::string output = boost::replace_all_copy(input, "#", "@");

তারপরে আপনি -Iআপনার সিস্টেমে বুস্ট লাইব্রেরিগুলি সন্ধান করার জন্য আপনার সংকলকটির জন্য কয়েকটি পতাকা হারিয়েছেন । সম্ভবত আপনার এটি প্রথমে ইনস্টল করা প্রয়োজন।
মার্টিন উয়েডিং

উপরেরটি আরও কার্যকর কারণ এটি স্ট্যান্ড লাইব নিয়ে আসে all সমস্তই বুস্ট লাইব্রেরি ব্যবহার করে না ;-)
এইচফ্রোমাইল

122

প্রশ্নটি characterপ্রতিস্থাপনকে কেন্দ্র করে , তবে, যেমন আমি এই পৃষ্ঠাটি খুব দরকারী (বিশেষত কনরাডের মন্তব্য) পেয়েছি, আমি এই আরও সাধারণীকরণ বাস্তবায়নটি ভাগ করতে চাই, যা এটির সাথে মোকাবিলা করার অনুমতি দেয় substrings:

std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
    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(); // Handles case where 'to' is a substring of 'from'
    }
    return str;
}

ব্যবহার:

std::cout << ReplaceAll(string("Number Of Beans"), std::string(" "), std::string("_")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("X")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("h")) << std::endl;

আউটপুট:

Number_Of_Beans

XXjXugtXty

hhjhugthty


সম্পাদনা করুন:

উপরোক্তগুলি আরও উপযুক্ত উপায়ে প্রয়োগ করা যেতে পারে, যদি পারফরম্যান্সগুলি আপনার উদ্বেগের বিষয় থাকে তবে কিছুই না ফিরিয়ে ( void) এবং মানের পরিবর্তে ঠিকানায়str পাস করে যুক্তি হিসাবে দেওয়া স্ট্রিংয়ে সরাসরি পরিবর্তনগুলি সম্পাদন করে । ফলাফলটি ফেরত দেওয়ার সময় এটি মূল স্ট্রিংয়ের অকেজো এবং ব্যয়বহুল অনুলিপি এড়াতে পারে। আপনার কল, তারপর ...

কোড:

static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
    // Same inner code...
    // No return statement
}

আশা করি এটি অন্য কারও জন্য সহায়ক হবে ...


4
উত্সের স্ট্রিং বড় এবং স্ট্রিং প্রতিস্থাপনের অনেকগুলি উপস্থিতি রয়েছে যেখানে এটির ক্ষেত্রে পারফরম্যান্স সমস্যা রয়েছে। স্ট্রিং :: রিপ্লেজ () কে অনেক সময় ডাকা হবে যার ফলে প্রচুর স্ট্রিং কপি হয়। আমার সমাধান দেখুন যা সমস্যার সমাধান করে।
মিনিস্টারোস

1
নীট এগিয়ে নেওয়া: ঠিকানা দ্বারা => রেফারেন্স দ্বারা । এটি ঠিকানা বা না তা বাস্তবায়নের বিশদ।
ম্যাক্স ট্রুকসা

1
আপনার fromস্ট্রিং ফাঁকা আছে কিনা তা অবশ্যই পরীক্ষা করা উচিত , অন্যথায় একটি অন্তহীন লুপ আসবে।
নবাগত

34

একটি বড় বাইনারি ব্লব কল্পনা করুন যেখানে সমস্ত 0x00 বাইটগুলি "\ 1 \ x30" এবং সমস্ত 0x01 বাইট "\ 1 \ x31" দ্বারা প্রতিস্থাপন করা হবে কারণ পরিবহন প্রোটোকলটি কোনও \ 0-বাইটের অনুমতি দেয় না।

ক্ষেত্রে যেখানে:

  • প্রতিস্থাপন এবং প্রতিস্থাপন স্ট্রিং বিভিন্ন দৈর্ঘ্য আছে,
  • উত্স স্ট্রিং এবং এর মধ্যে প্রতিস্থাপিত স্ট্রিংয়ের অনেকগুলি উপস্থিতি রয়েছে
  • উত্সের স্ট্রিংটি বড়,

প্রদত্ত সমাধানগুলি প্রয়োগ করা যায় না (কারণ তারা কেবলমাত্র একক অক্ষর প্রতিস্থাপন করে) বা একটি কার্য সম্পাদনের সমস্যা রয়েছে, কারণ তারা স্ট্রিংকে ডাকবে :: বেশ কয়েকবার প্রতিস্থাপন করবে যা বার বার ব্লকের আকারের অনুলিপি তৈরি করে। (আমি বুস্ট সমাধানটি জানি না, সম্ভবত এটি সেই দৃষ্টিকোণ থেকে ঠিক আছে)

এইটি উত্স স্ট্রিংয়ের সমস্ত উপস্থিতিগুলি ধরে নিয়ে হাঁটে এবং একবারে নতুন স্ট্রিং টুকরো টুকরো টুকরো করে তোলে :

void replaceAll(std::string& source, const std::string& from, const std::string& to)
{
    std::string newString;
    newString.reserve(source.length());  // avoids a few memory allocations

    std::string::size_type lastPos = 0;
    std::string::size_type findPos;

    while(std::string::npos != (findPos = source.find(from, lastPos)))
    {
        newString.append(source, lastPos, findPos - lastPos);
        newString += to;
        lastPos = findPos + from.length();
    }

    // Care for the rest after last occurrence
    newString += source.substr(lastPos);

    source.swap(newString);
}

এটি এখন পর্যন্ত সেরা সমাধান যা কেবল এসটিএলে নির্মিত। আপনি যদি সহজেই কোথাও ব্যবহারের জন্য কোনও কাস্টম ফাংশন ছেড়ে চলে যান তবে এটি এটিকে তৈরি করুন।
রজার স্যান্ডার্স

21

একটি একক চরিত্রের জন্য একটি সাধারণ সন্ধান এবং প্রতিস্থাপন এরকম কিছু হবে:

s.replace(s.find("x"), 1, "y")

পুরো স্ট্রিংয়ের জন্য এটি করার জন্য, সহজ কাজটি আপনার s.findফিরে আসা শুরু না করা অবধি লুপ করা npos। আমি মনে করি আপনি range_errorলুপটি প্রস্থান করতেও ধরতে পারেন তবে এটি কুরুচিপূর্ণ।


7
স্ট্রিংয়ের দৈর্ঘ্যের তুলনায় অক্ষরের সংখ্যা প্রতিস্থাপনের ক্ষেত্রে এটি সম্ভবত একটি উপযুক্ত সমাধান, যদিও এটি ভাল স্কেল করে না। মূল স্ট্রিংয়ের অক্ষরের অনুপাত যেহেতু প্রতিস্থাপন করা প্রয়োজন বৃদ্ধি পাবে, এই পদ্ধতিটি সময়মতো ও (N ^ 2) এর কাছে পৌঁছাবে।
1010

7
সত্য। আমার সাধারণ দর্শনটি হ'ল সহজ (লেখার এবং পড়ার) কাজটি করা অবধি অদক্ষতার কারণে আসল সমস্যা সৃষ্টি করছে। কিছু পরিস্থিতি রয়েছে যেখানে আপনার (হুমকির স্ট্রিং) ও (এন ** 2) গুরুত্বপূর্ণ হতে পারে তবে আমার স্ট্রিংগুলি 1K বা তার চেয়ে কম সময় 99% হয়।
টেড

3
... যা বলা হচ্ছে, আমি কিরিলের পদ্ধতিটি আরও ভাল পছন্দ করি (এবং ইতিমধ্যে এটি ভোট দিয়ে দিয়েছিল)।
টেড

"X" পাওয়া না গেলে কী হয়? এছাড়াও, আপনি কেন ডাবল বন্ধনী ব্যবহার করছেন?
প্রসথ গোবিন্দ 11

@ প্রসথগোবিন্দ - আমি কেবল প্রয়োজনীয় কলগুলি দেখছিলাম (অতএব "কিছু" এর মতো)। যথাযথ ত্রুটি পরিচালনার মতো গুরুত্বপূর্ণ তবে অস্পষ্ট বিবরণ পাঠকের জন্য অনুশীলন হিসাবে রেখে দেওয়া হয়েছিল। "ডাবল ধনুর্বন্ধনী" হিসাবে, আমি নিশ্চিত না সেগুলি কী বা আপনি কী সম্পর্কে কথা বলছেন। আমার জন্য একটি "ব্রেস" {চরিত্রটি। "ডাবল ব্রেস" কী তা আমি জানি না। সম্ভবত আপনি ফন্ট সমস্যা কিছু আছে?
টেড

6

আপনি যদি একটি একক চরিত্রের চেয়ে বেশি প্রতিস্থাপন করতে চান এবং কেবল তার সাথেই std::stringকাজ করে থাকেন তবে এই স্নিপেটটি sHaystack এ sNeple প্রতিস্থাপন করে sReplace, এবং sNeedle এবং sReplace একই আকারের প্রয়োজন হবে না। এই রুটিনটি বাম থেকে ডানদিকে পাওয়া প্রথমটির পরিবর্তে সমস্ত উপস্থিতিগুলি প্রতিস্থাপন করতে উইল লুপ ব্যবহার করে।

while(sHaystack.find(sNeedle) != std::string::npos) {
  sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}

এটি ও (এন ^)। আপনি ও (এন) সময়ে এটি করতে পারেন।
চ্যাংমিং সান

3
@ চ্যাংমিংসুন কোন ও (এন) সমাধানটির অর্থ?
হাবাকুক

2
কে-নিডল এস-রিপ্লেসের একটি সাবস্ট্রিং হিসাবে দেখা দিলে এটি অসীম লুপ তৈরি করবে।
গর্বিত

এছাড়াও findদু'বার ফোন এসেছে। সেই ফলাফলটিকে একটি অস্থায়ী পরিবর্তনশীল করার বিষয়ে বিবেচনা করুন।
লুক ব্লুম

4

কিরিল প্রস্তাবিত হিসাবে, হয় প্রতিস্থাপন পদ্ধতিটি ব্যবহার করুন বা প্রতিটি চরকে স্বতন্ত্রভাবে প্রতিস্থাপন করে স্ট্রিং বরাবর পুনরাবৃত্তি করুন।

বিকল্পভাবে আপনি findপদ্ধতিটি ব্যবহার করতে পারেন বা find_first_ofআপনার যা করা দরকার তা নির্ভর করে। এই সমাধানগুলির কোনওটিই একসাথে কাজটি করবে না, তবে কোডের কয়েকটি অতিরিক্ত লাইন দিয়ে আপনাকে তাদের জন্য কাজ করা উচিত। :-)


3
#include <iostream>
#include <string>
using namespace std;
// Replace function..
string replace(string word, string target, string replacement){
    int len, loop=0;
    string nword="", let;
    len=word.length();
    len--;
    while(loop<=len){
        let=word.substr(loop, 1);
        if(let==target){
            nword=nword+replacement;
        }else{
            nword=nword+let;
        }
        loop++;
    }
    return nword;

}
//Main..
int main() {
  string word;
  cout<<"Enter Word: ";
  cin>>word;
  cout<<replace(word, "x", "y")<<endl;
  return 0;
}

যদি wordদীর্ঘ হয় তবে ফাংশনটি কল করার সময় প্রচুর ওভারহেড থাকতে পারে। আপনি ক্ষণস্থায়ী দ্বারা এই নিখুত করতে word, targetএবং replacementconst-রেফারেন্স হিসাবে।
ট্রেডডজে

2

অ্যাবসিল স্ট্র্যাপ্লেসএল সম্পর্কে কী ? হেডার ফাইল থেকে:

// This file defines `absl::StrReplaceAll()`, a general-purpose string
// replacement function designed for large, arbitrary text substitutions,
// especially on strings which you are receiving from some other system for
// further processing (e.g. processing regular expressions, escaping HTML
// entities, etc.). `StrReplaceAll` is designed to be efficient even when only
// one substitution is being performed, or when substitution is rare.
//
// If the string being modified is known at compile-time, and the substitutions
// vary, `absl::Substitute()` may be a better choice.
//
// Example:
//
// std::string html_escaped = absl::StrReplaceAll(user_input, {
//                                                {"&", "&amp;"},
//                                                {"<", "&lt;"},
//                                                {">", "&gt;"},
//                                                {"\"", "&quot;"},
//                                                {"'", "&#39;"}});

1

পুরানো স্কুল :-)

std::string str = "H:/recursos/audio/youtube/libre/falta/"; 

for (int i = 0; i < str.size(); i++) {
    if (str[i] == '/') {
        str[i] = '\\';
    }
}

std::cout << str;

ফলাফল:

এইচ: \ recursos \ অডিও \ ইউটিউব \ ফ্রী \ ফলতা \


0

এইটা কাজ করে! আমি বইয়ের স্টোর অ্যাপ্লিকেশনটির জন্য এর অনুরূপ কিছু ব্যবহার করেছি, যেখানে জায়টি কোনও সিএসভিতে সংরক্ষণ করা হয়েছিল (.ড্যাট ফাইলের মতো)। তবে একক চরের ক্ষেত্রে, যার অর্থ প্রতিস্থাপনকারী কেবল একটি একক চর, যেমন '|', এটি অবশ্যই ডাবল উদ্ধৃতিতে থাকতে হবে "|" যাতে কোনও অবৈধ রূপান্তর কনস্ট চারটি না ফেলে।

#include <iostream>
#include <string>

using namespace std;

int main()
{
    int count = 0;  // for the number of occurences.
    // final hold variable of corrected word up to the npos=j
    string holdWord = "";
    // a temp var in order to replace 0 to new npos
    string holdTemp = "";
    // a csv for a an entry in a book store
    string holdLetter = "Big Java 7th Ed,Horstman,978-1118431115,99.85";

    // j = npos
    for (int j = 0; j < holdLetter.length(); j++) {

        if (holdLetter[j] == ',') {

            if ( count == 0 ) 
            {           
                holdWord = holdLetter.replace(j, 1, " | ");      
            }
            else {

                string holdTemp1 = holdLetter.replace(j, 1, " | ");

                // since replacement is three positions in length,
                // must replace new replacement's 0 to npos-3, with
                // the 0 to npos - 3 of the old replacement 
                holdTemp = holdTemp1.replace(0, j-3, holdWord, 0, j-3); 

                holdWord = "";

                holdWord = holdTemp;

            }
            holdTemp = "";
            count++;
        }
    } 
    cout << holdWord << endl;
    return 0;
}

// result:
Big Java 7th Ed | Horstman | 978-1118431115 | 99.85

অবিরামভাবে আমি বর্তমানে সেন্টস ব্যবহার করছি, তাই আমার সংকলক সংস্করণটি নীচে is সি ++ সংস্করণ (জি ++), সি ++ 98 ডিফল্ট:

g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

0

আপনি যদি std::stringএস ব্যবহার করতে ইচ্ছুক হন তবে আপনি এই নমুনা-অ্যাপ্লিকেশনটির strsubফাংশনটি যেমন রয়েছে তেমন ব্যবহার করতে পারেন বা প্রায় একই লক্ষ্য অর্জনের জন্য কোনও ভিন্ন ধরণের বা প্যারামিটারের সেট নিতে চান তা আপডেট করতে পারেন। মূলত, এটি std::stringঅক্ষরের মিলের সেটটি দ্রুত মুছে ফেলার জন্য এবং এর মধ্যে পছন্দসই অক্ষরগুলি সরাসরি সন্নিবেশ করানোর বৈশিষ্ট্য এবং কার্যকারিতা ব্যবহার করে std::string। প্রতিবার এটি এই প্রতিস্থাপন অপারেশনটি করে, অফসেট আপডেট করে যদি এটি এখনও প্রতিস্থাপনের জন্য মিলে যাওয়া অক্ষরগুলি খুঁজে পেতে পারে এবং যদি এটি প্রতিস্থাপনের মতো আরও কিছু না করতে পারে তবে এটি সর্বশেষ আপডেট থেকে তার রাজ্যে স্ট্রিংটি ফিরিয়ে দেয়।

#include <iostream>
#include <string>

std::string strsub(std::string stringToModify,
                   std::string charsToReplace,
                   std::string replacementChars);

int main()
{
    std::string silly_typos = "annoiiyyyng syyyllii tiipos.";

    std::cout << "Look at these " << silly_typos << std::endl;
    silly_typos = strsub(silly_typos, "yyy", "i");
    std::cout << "After a little elbow-grease, a few less " << silly_typos << std::endl;
    silly_typos = strsub(silly_typos, "ii", "y");

    std::cout << "There, no more " << silly_typos << std::endl;
    return 0;
}

std::string strsub(std::string stringToModify,
                   std::string charsToReplace,
                   std::string replacementChars)
{
    std::string this_string = stringToModify;

    std::size_t this_occurrence = this_string.find(charsToReplace);
    while (this_occurrence != std::string::npos)
    {
        this_string.erase(this_occurrence, charsToReplace.size());
        this_string.insert(this_occurrence, replacementChars);
        this_occurrence = this_string.find(charsToReplace,
                                           this_occurrence + replacementChars.size());
    }

    return this_string;
}

আপনি যদি std::stringনিজের প্যারামিটার হিসাবে s ব্যবহার করার উপর নির্ভর করতে না চান তবে আপনি পরিবর্তে সি-স্টাইলের স্ট্রিংগুলিতে যেতে পারেন, আপনি নীচের আপডেট হওয়া নমুনাটি দেখতে পারেন:

#include <iostream>
#include <string>

std::string strsub(const char * stringToModify,
                   const char * charsToReplace,
                   const char * replacementChars,
                   uint64_t sizeOfCharsToReplace,
                   uint64_t sizeOfReplacementChars);

int main()
{
    std::string silly_typos = "annoiiyyyng syyyllii tiipos.";

    std::cout << "Look at these " << silly_typos << std::endl;
    silly_typos = strsub(silly_typos.c_str(), "yyy", "i", 3, 1);
    std::cout << "After a little elbow-grease, a few less " << silly_typos << std::endl;
    silly_typos = strsub(silly_typos.c_str(), "ii", "y", 2, 1);

    std::cout << "There, no more " << silly_typos << std::endl;
    return 0;
}

std::string strsub(const char * stringToModify,
                   const char * charsToReplace,
                   const char * replacementChars,
                   uint64_t sizeOfCharsToReplace,
                   uint64_t sizeOfReplacementChars)
{
    std::string this_string = stringToModify;

    std::size_t this_occurrence = this_string.find(charsToReplace);
    while (this_occurrence != std::string::npos)
    {
        this_string.erase(this_occurrence, sizeOfCharsToReplace);
        this_string.insert(this_occurrence, replacementChars);
        this_occurrence = this_string.find(charsToReplace,
            this_occurrence + sizeOfReplacementChars);
    }

    return this_string;
}

0

সাধারণ পরিস্থিতিতে এটি স্ট্যান্ড :: স্ট্রিং (যা ইতিমধ্যে ব্যবহৃত) ব্যবহার করে অন্য কোনও লাইব্রেরি ব্যবহার না করে বেশ ভাল কাজ করে।

চরিত্রের সব occurences প্রতিস্থাপন একটি অক্ষর দিয়ে মধ্যে some_string :

for (size_t i = 0; i < some_string.size(); ++i) {
    if (some_string[i] == 'a') {
        some_string.replace(i, 1, "b");
    }
}

যদি স্ট্রিংটি বড় হয় বা একাধিক কল প্রতিস্থাপনের সমস্যা হয় তবে আপনি এই উত্তরে উল্লিখিত কৌশলটি প্রয়োগ করতে পারেন: https://stackoverflow.com/a/29752943/3622300


0

সর্বাধিক ডিআরআই স্পিরিটে আমি ঘূর্ণিত সমাধানটি এখানে দিই। এটি sHaystack এ sNeedle অনুসন্ধান করবে এবং sReplace দ্বারা এটি প্রতিস্থাপন করবে, nTimes যদি 0 না হয়, অন্যথায় সমস্ত sNeedle উপস্থিতি। এটি প্রতিস্থাপিত পাঠ্যে আবার অনুসন্ধান করবে না।

std::string str_replace(
    std::string sHaystack, std::string sNeedle, std::string sReplace, 
    size_t nTimes=0)
{
    size_t found = 0, pos = 0, c = 0;
    size_t len = sNeedle.size();
    size_t replen = sReplace.size();
    std::string input(sHaystack);

    do {
        found = input.find(sNeedle, pos);
        if (found == std::string::npos) {
            break;
        }
        input.replace(found, len, sReplace);
        pos = found + replen;
        ++c;
    } while(!nTimes || c < nTimes);

    return input;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.