আমি কীভাবে স্ট্যান্ডার্ড স্ট্রিংয়ে অনুসন্ধান / সন্ধান এবং প্রতিস্থাপন করব?


95

একটি স্ট্রিংয়ের সমস্ত উপস্থিতিগুলিকে অন্য স্ট্রিংয়ের সাথে প্রতিস্থাপন করার কোনও উপায় আছে কি std::string?

এই ক্ষেত্রে:

void SomeFunction(std::string& str)
{
   str = str.replace("hello", "world"); //< I'm looking for something nice like this
}

উত্তর:


75

আপনার নিজস্ব প্রতিস্থাপন বাস্তবায়ন করছেন না কেন?

void myReplace(std::string& str,
               const std::string& oldStr,
               const std::string& newStr)
{
  std::string::size_type pos = 0u;
  while((pos = str.find(oldStr, pos)) != std::string::npos){
     str.replace(pos, oldStr.length(), newStr);
     pos += newStr.length();
  }
}

4
"প্রতিস্থাপন" করার জন্য সমস্ত কল দিয়ে আপনি এখানে মেমরির সাথে কিছুটা গোলমাল করছেন: আপনি "ooooooo ... o" থেকে "ও" সরিয়ে ফেললে জটিলতা নেই। আমি অনুমান করি যে কেউ আরও ভাল করতে পারে তবে এই সমাধানটিতে বোঝা সহজ হওয়ার যোগ্যতা রয়েছে।
জোনকো

4
এটি লুপের জন্য অস্পষ্ট পরিবর্তে লুপের জন্য কেন সত্য নয়?
শিরিক

আমি 'সর্বনিম্ন আশ্চর্য' নীতিটি প্রয়োগ করতে ব্যবহৃত হয়েছি। লুপগুলির জন্য বেশিরভাগ সময় সরল সূচক বৃদ্ধির ব্যবহারের জন্য। এখানে, আমার মতে, কিছুক্ষণের জন্য লুপটি আরও পরিষ্কার হয়।
yves বাউমস

4
@ অ্যালডো একটি সাধারণ নিয়ম হিসাবে জটিলতা এড়ানো ভাল এবং উদাহরণস্বরূপ, অন্যান্য জবাবগুলিতে উল্লিখিত হিসাবে রেজেক্স ব্যবহার করুন। তবে আপনার প্রয়োজনের উপর নির্ভর করে আপনি আপনার প্রকল্পের নির্ভরতা নিয়ন্ত্রণ করতে চাইতে পারেন। একটি ছোট কোড স্নিপেট যা আপনার যা প্রয়োজন ঠিক তা করে, আর কখনও না better
yves বাউমস

159
#include <boost/algorithm/string.hpp> // include Boost, a C++ library
...
std::string target("Would you like a foo of chocolate. Two foos of chocolate?");
boost::replace_all(target, "foo", "bar");

এখানে প্রতিস্থাপন_এর সরকারী ডকুমেন্টেশন রয়েছে।


4
নোট করুন যে আপনাকে প্যাটার্ন এবং প্রতিস্থাপনের জন্য স্পষ্টভাবে std :: স্ট্রিং তৈরি করতে হবে না: বুস্ট :: রিপ্লেস_ল (টার্গেট, "ফু", "বার");
অ্যালেক্সিস উইলক

4
+1, একটি সতর্কতার সাথে: replace_allকোনও সংস্করণের জন্য সান স্টুডিওতে>> 1.43 এর সংস্করণে সেগফল্ট করবে <12.3
ব্রায়ান ভ্যানডেনবার্গ

4
boostএম্বেড থাকা ডিভাইসগুলিতে যথেষ্ট সংকলন সময় বৃদ্ধি করে। এমনকি এআরএমভি 7 কোয়াড কোর 100 লাইন কোড 2 মিনিটের মধ্যে 2 মিনিটের মধ্যেই কমপাইল করে, 2 সেকেন্ডে।
পাইওটর কুলা

4
@ পিপমকিন: এর অর্থ আপনার সংকলক (বা বিল্ড সেটআপ, বা যাই হোক না কেন) সফল হয়, লক্ষ্য আর্কিটেকচার নয়, যার কোনও যোগসূত্র নেই।
ড্যানিয়েল কামিল কোজার

যদি আপনার সংকলক প্রাক-সংকলিত শিরোলেখকে সমর্থন করে তবে বুস্টটি ব্যবহার করার সময় এটি ব্যবহারের জন্য অত্যন্ত সুপারিশ করা হয়। এটি সত্যই সময় সাশ্রয় করে।
আলেক্সি ওমেলচেঙ্কো

33

সি ++ 11 এ আপনি কল করার মাধ্যমে ওয়ান-লাইনার হিসাবে এটি করতে পারেন regex_replace:

#include <string>
#include <regex>

using std::string;

string do_replace( string const & in, string const & from, string const & to )
{
  return std::regex_replace( in, std::regex(from), to );
}

string test = "Remove all spaces";
std::cout << do_replace(test, " ", "") << std::endl;

আউটপুট:

Removeallspaces

ধন্যবাদ, ব্যবহার এবং মনে রাখা খুব সহজ!
জুলিয়ান ডিক্লেয়ারক্ক

এটিও লক্ষ্য করুন যে fromএটি একটি নিয়মিত প্রকাশ হতে পারে - তাই আপনার প্রয়োজনের সাথে আপনি আরও পরিশীলিত মিলের মানদণ্ড ব্যবহার করতে পারেন। আমি কি দেখতে না কিভাবে এই কাজ করতে হয় ছাড়া পরিবর্তে শুধুমাত্র সরাসরি ব্যাখ্যা ব্যবহার করে - রেগুলার এক্সপ্রেশন পার্স কিছু ফর্ম আবেদন fromঅক্ষর।
ব্রেন্ট ব্র্যাডবার্ন

এর জন্য একটি আপ-টু-ডেট সংকলক লাগতে পারে। এটি জিসিসি 5.0 দিয়ে কাজ করেছিল, তবে জিসিসি 4.8.4 নিয়ে আমার কিছুটা সমস্যা হয়েছিল।
ব্রেন্ট ব্র্যাডবার্ন

@ নোবার, হ্যাঁ, আমি যদি সঠিকভাবে মনে রাখি তবে 4.8.x এ রেগেক্স সমর্থনটি সম্পূর্ণ ছিল না। এছাড়াও আপনি আরও পরিশীলিত অনুসন্ধানগুলি পেতে পারেন, তবে সময় অনুসারে আপনি শাস্তি পেয়ে যাবেন ... এটি অন্য আরও সোজা ফরোয়ার্ড অনুসন্ধানের চেয়ে ধীর হতে চলেছে এবং ফাংশনগুলি প্রতিস্থাপন করবে।
অ্যালেক্সিস উইলক :17 ই

4
দয়া করে মনে রাখবেন এটি স্ট্রিংয়ের ধরণের উপর নির্ভর করে প্রচুর প্রিপ্রোসেসিং না করে কেবল খুব মৌলিক বর্ণানুক্রমিক অক্ষরের জন্য এবং অন্য কিছুই জন্য কাজ করবে না। আমি এখনও কোনও সাধারণ উদ্দেশ্য রেজেক্স ভিত্তিক স্ট্রিং প্রতিস্থাপন পাই নি।
পীযূষ সোনি

17

কেন একটি পরিবর্তিত স্ট্রিং ফিরে না?

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 changed: " 
          << 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

6

আমার টেম্পলেটাইজড ইনলাইন ইন-প্লেস-এ-সন্ধান এবং প্রতিস্থাপন:

template<class T>
int inline findAndReplace(T& source, const T& find, const T& replace)
{
    int num=0;
    typename T::size_t fLen = find.size();
    typename T::size_t rLen = replace.size();
    for (T::size_t pos=0; (pos=source.find(find, pos))!=T::npos; pos+=rLen)
    {
        num++;
        source.replace(pos, fLen, replace);
    }
    return num;
}

এটি প্রতিস্থাপিত আইটেমগুলির সংখ্যার একটি গণনা প্রদান করে (আপনি যদি ধারাবাহিকভাবে এটি চালাতে চান তবে ব্যবহারের জন্য)। এটি ব্যবহার করতে:

std::string str = "one two three";
int n = findAndReplace(str, "one", "1");

4
আমি জিসিসির অধীনে এই নমুনাটি চেষ্টা করেছি কিন্তু এটি সংকলন করবে না - এটি টি :: আকার_টি ব্যবহার পছন্দ করে নি। টি :: আকার_t এর পরিবর্তে টাইপনাম টি :: আকার_প্রকার সমস্যাটি সমাধান করে।
অ্যান্ড্রু ওয়াইট

3

সবচেয়ে সহজ উপায় (আপনি যা লিখেছেন তার কাছে কিছু সরবরাহ করা) বুস্ট.আরেজেক্স , বিশেষত regex_replace ব্যবহার করা ।

std :: স্ট্রিং () এবং () পদ্ধতিগুলি প্রতিস্থাপনে তৈরি করেছে তবে সূচকগুলি এবং স্ট্রিংয়ের দৈর্ঘ্যের সাথে ডিলিংয়ের প্রয়োজন হওয়ায় এগুলি কাজ করা আরও জটিল।


4
রিপ্লেস_ল সহ (বুজে স্ট্রিং অ্যালগরিদমগুলিও রয়েছে) (রেগেক্স এমন সাধারণ বিকল্পের জন্য কিছুটা ভারী ওজন হতে পারে) be
আঙ্কেলবেন্স

3

আমি বিশ্বাস করি এটি কার্যকর হবে। এটি প্যারামিটার হিসাবে কনস্টের চর * লাগে।

//params find and replace cannot be NULL
void FindAndReplace( std::string& source, const char* find, const char* replace )
{
   //ASSERT(find != NULL);
   //ASSERT(replace != NULL);
   size_t findLen = strlen(find);
   size_t replaceLen = strlen(replace);
   size_t pos = 0;

   //search for the next occurrence of find within source
   while ((pos = source.find(find, pos)) != std::string::npos)
   {
      //replace the found string with the replacement
      source.replace( pos, findLen, replace );

      //the next line keeps you from searching your replace string, 
      //so your could replace "hello" with "hello world" 
      //and not have it blow chunks.
      pos += replaceLen; 
   }
}

size_typeস্ট্রিংয়ের জন্য এটি দেওয়া হয়েছে, লুপের অবস্থায় unsignedআপনার >=চেক সর্বদা থাকবে true। আপনি std::string::nposসেখানে ব্যবহার করতে হবে।
পাভেল মিনায়েভ

আকার_প্রকার স্বাক্ষরযুক্ত নয়। এটি অনেকগুলি প্ল্যাটফর্মে স্বাক্ষরবিহীন, তবে সমস্ত নয়।
অ্যালান

12
বিশ্বে কেন এটি স্টাডি :: স্ট্রিংয়ের অংশ নয়? প্রোগ্রামিংয়ের বিশ্বে আর কোনও গুরুতর স্ট্রিং ক্লাস রয়েছে যা 'অনুসন্ধান এবং প্রতিস্থাপন' অপারেশন প্রস্তাব করে না? অবশ্যই এটি দুটি পুনরুক্তি করা এবং তাদের মধ্যে পাঠ্যটি প্রতিস্থাপনের চেয়ে বেশি সাধারণ ?? কখনও কখনও স্টাড :: স্ট্রিংটি একটি সুরযুক্ত বর্ণালী উইন্ডশীল্ডযুক্ত গাড়ির মতো মনে হয় তবে চালকের উইন্ডোটি নিচে নামার কোনও উপায় নেই।
স্পাইক0xff

@ স্পাইকএক্সএফ বুস্টের রয়েছেroll_down_window
ta.speot.is

4
@ গুস্তাফর: আমার ভুল আমি এমন সিস্টেমে কাজ করেছি যেখানে পুরানো সংকলকগুলি মাপ_টাকে ভুলভাবে সংজ্ঞায়িত করে।
অ্যালান

2
#include <string>

using std::string;

void myReplace(string& str,
               const string& oldStr,
               const string& newStr) {
  if (oldStr.empty()) {
    return;
  }

  for (size_t pos = 0; (pos = str.find(oldStr, pos)) != string::npos;) {
    str.replace(pos, oldStr.length(), newStr);
    pos += newStr.length();
  }
}

OldStr খালি থাকার জন্য পরীক্ষা করা গুরুত্বপূর্ণ। যে কারণেই যদি সেই প্যারামিটারটি খালি থাকে তবে আপনি একটি অসীম লুপে আটকে যাবেন।

তবে হ্যাঁ আপনি যদি পারেন তবে পরীক্ষিত ও পরীক্ষিত সি ++ 11 বা বুস্ট সলিউশনটি ব্যবহার করুন।


1
// Replace all occurrences of searchStr in str with replacer
// Each match is replaced only once to prevent an infinite loop
// The algorithm iterates once over the input and only concatenates 
// to the output, so it should be reasonably efficient
std::string replace(const std::string& str, const std::string& searchStr, 
    const std::string& replacer)
{
    // Prevent an infinite loop if the input is empty
    if (searchStr == "") {
        return str;
    }

    std::string result = "";
    size_t pos = 0;
    size_t pos2 = str.find(searchStr, pos);

    while (pos2 != std::string::npos) {
        result += str.substr(pos, pos2-pos) + replacer;
        pos = pos2 + searchStr.length();
        pos2 = str.find(searchStr, pos);
    }

    result += str.substr(pos, str.length()-pos);
    return result;
}

4
আমাদের কেবল শেষ ম্যাচ থেকে নতুন ম্যাচগুলি অনুসন্ধান করা দরকার, এজন্যই আলগোরিদম সাবধানতার সাথে পোস্টে শেষ ম্যাচটি ট্র্যাক করে। পোজ 2 সর্বদা পরবর্তী ম্যাচটি সঞ্চয় করে, তাই আমরা ফলাফলের মধ্যে পোজ এবং পোস্ট 2 এর মধ্যে স্ট্রিংটি সংযুক্ত করি, তারপরে পোস্ট এবং পোস্ট 2 অগ্রিম করুন। যদি অন্য কোনও মিল খুঁজে পাওয়া যায় না, তবে ফলাফলের স্ট্রিংয়ের বাকী অংশগুলি আমরা সম্মতি জানাই।
বিজন গ্যানস্টার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.