C ++ स्ट्रिंग में चार की सभी घटनाओं को कैसे हटाएं


98

मैं निम्नलिखित का उपयोग कर रहा हूं:

replace (str1.begin(), str1.end(), 'a' , '')

लेकिन यह संकलन त्रुटि दे रहा है।


8
''वास्तव में एक चरित्र नहीं है।
एन। 'सर्वनाम' मी।

4
खैर, यह निश्चित रूप से उस त्रुटि को जानने में मदद करेगा जो आपको मिल रही है।
SBI

3
अच्छा हो, वहाँ बहुत सारे संदर्भ हैं जहां प्रतिस्थापित करना एक उचित विचार है, बस यह नहीं है।
रिचर्डप्लंकेट

जवाबों:


171

मूल रूप से, replaceएक चरित्र को दूसरे के साथ बदलता है और ''एक चरित्र नहीं है। तुम जो खोज रहे हो erase

इस सवाल को देखें जो एक ही समस्या का जवाब देता है। आपके मामले में:

#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());

या उपयोग करें boostयदि यह आपके लिए एक विकल्प है, जैसे:

#include <boost/algorithm/string.hpp>
boost::erase_all(str, "a");

यह सब संदर्भ वेबसाइटों पर अच्छी तरह से प्रलेखित है । लेकिन अगर आपको इन कार्यों की जानकारी नहीं है, तो आप इस तरह की चीजों को आसानी से कर सकते हैं:

std::string output;
output.reserve(str.size()); // optional, avoids buffer reallocations in the loop
for(size_t i = 0; i < str.size(); ++i)
  if(str[i] != 'a') output += str[i];

2
आपके द्वारा प्रदान किया गया एल्गोरिथम नहीं है O(n^2)?
5

@jww: मुझे लगता है कि आप अंतिम कोड नमूने के बारे में बात कर रहे हैं और nमूल स्ट्रिंग लंबाई है। प्रत्येक इनपुट चरित्र के लिए, मैं 1 वर्ण परीक्षण करता हूं O(1), और 0 या 1 वर्ण परिशिष्ट। चरित्र परिशिष्ट O(1)पर्याप्त मेमोरी आरक्षित है, या O(current_length)यदि एक नया बफर आवंटित किया गया है। यदि आप output.reserve(str.size())लूप से पहले ऐसा करते हैं तो ऐसा कभी नहीं होता है और आपके पास एक वैश्विक O(n)लागत है। अन्यथा asymptotically, मुझे लगता है कि लागत O(n . log(n) )STL कंटेनर reallocation रणनीति के कारण है।
एंटोनी

5
मुझे #include <कलन विधि>
S मीडन

अच्छा उत्तर। यह हमेशा अच्छा होता है यदि उत्तर में कई समाधान होते हैं। मेरे लिए, इसके साथ समाधान forसबसे उपयुक्त है।
दिमित्री निकिपोरेंको

@DmitryNichiporenko के लिए जवाब सबसे उपयुक्त नहीं हो सकता है। यदि आपके पास एक विधेय या एक गैर-रिक्त आउटपुट है, तो मैं इस पर विचार करूंगा: output.reserve (str.size () + output.size ()); std :: copy_if (str.begin (), str.end (), std :: back_inserter (आउटपुट), [] (char c) {वापसी विधेय (c);});
जिमीफिकी

10

एल्गोरिथ्म एक दिए गए अनुक्रम पर प्रति तत्वstd::replace काम करता है (इसलिए यह विभिन्न तत्वों के साथ तत्वों को बदलता है, और इसे कुछ भी नहीं बदल सकता है )। लेकिन कोई खाली चरित्र नहीं है । यदि आप तत्वों को अनुक्रम से हटाना चाहते हैं, तो निम्नलिखित तत्वों को स्थानांतरित करना होगा , और इस तरह से काम नहीं करना चाहिए।std::replace

आप इसे प्राप्त करने के लिए std::remove( साथ मेंstd::erase ) उपयोग करने का प्रयास कर सकते हैं ।

str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());

8

का उपयोग कर copy_if:

#include <string>
#include <iostream>
#include <algorithm>
int main() {
    std::string s1 = "a1a2b3c4a5";
    char s2[256];
    std::copy_if(s1.begin(), s1.end(), s2, [](char c){return c!='a';});
    std::cout << s2 << std::endl;
    return 0;
}

3
string RemoveChar(string str, char c) 
{
   string result;
   for (size_t i = 0; i < str.size(); i++) 
   {
          char currentChar = str[i];
          if (currentChar != c)
              result += currentChar;
   }
       return result;
}

मैंने इस तरह से इसे किया।

या आप एंटोनी का उल्लेख कर सकते हैं:

इस सवाल को देखें जो एक ही समस्या का जवाब देता है। आपके मामले में:

#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());

1

यह कोड चेंजर्स की पुनरावृत्ति को हटा देता है अर्थात यदि इनपुट एएबीबीसी है तो आउटपुट एबीसी होगा।

cin >> s;
ans = "";
ans += s[0];
for(int i = 1;i < s.length();++i)
if(s[i] != s[i-1])
    ans += s[i];
cout << ans << endl;

1

यदि आपके पास फ़िल्टर्ड स्ट्रिंग के साथ भरने के लिए एक predicateऔर / या एक गैर खाली outputहै, तो मैं विचार करूंगा:

output.reserve(str.size() + output.size());  
std::copy_if(str.cbegin(), 
             str.cend(), 
             std::back_inserter(output), 
             predicate});

मूल प्रश्न में विधेय है [](char c){return c != 'a';}


0

अन्य उत्तरों के आधार पर, यहां एक और उदाहरण दिया गया है जहां मैंने दिए गए स्ट्रिंग में सभी विशेष वर्ण हटा दिए हैं:

#include <iostream>
#include <string>
#include <algorithm>

std::string chars(".,?!.:;_,!'\"-");

int main(int argc, char const *argv){

  std::string input("oi?");
  std::string output = eraseSpecialChars(input);   

 return 0;
}




std::string eraseSpecialChars(std::string str){

std::string newStr;
    newStr.assign(str);  

    for(int i = 0; i < str.length(); i++){
        for(int  j = 0; j < chars.length(); j++ ){
            if(str.at(i) == chars.at(j)){
                char c = str.at(i);
                newStr.erase(std::remove(newStr.begin(), newStr.end(), c), newStr.end());
            }
        }

    }      

return newStr; 
}

इनपुट बनाम आउटपुट:

Input:ra,..pha
Output:rapha

Input:ovo,
Output:ovo

Input:a.vo
Output:avo

Input:oi?
Output:oi

-1

मुझे लगता है कि विधि एसटीडी: कामों को हटा दें, लेकिन इसमें कुछ संगतता मुद्दे भी शामिल थे, इसलिए मैंने इस छोटे से कार्य को लिखना समाप्त कर दिया:

string removeCharsFromString(const string str, char* charsToRemove )
{
    char c[str.length()+1]; // + terminating char
    const char *p = str.c_str();
    unsigned int z=0, size = str.length();
    unsigned int x;
    bool rem=false;

    for(x=0; x<size; x++)
    {
        rem = false;
        for (unsigned int i = 0; charsToRemove[i] != 0; i++)
        {
            if (charsToRemove[i] == p[x])
            {
                rem = true;
                break;
            }
        }
        if (rem == false) c[z++] = p[x];
    }

    c[z] = '\0';
    return string(c);
}

बस के रूप में उपयोग करें

myString = removeCharsFromString (myString, "abc \ r");

और यह दी गई सूची की सभी घटनाओं को हटा देगा।

यह थोड़ा और अधिक कुशल हो सकता है क्योंकि पहले मैच के बाद लूप रिटर्न होता है, इसलिए हम वास्तव में कम तुलना करते हैं।


1
आप सही अनुमान लगाते हैं। अपना खुद का लिखने के बजाय, यह पता लगाएं कि आप मानक C ++ हेडर का उपयोग क्यों नहीं कर सकते हैं।
xtofl

वैसे यह एक व्यक्तिगत राय है xtofl, यह हमेशा 3 कोड का उपयोग करने के लिए अच्छा नहीं है जिसे आप वास्तव में नहीं जानते कि यह क्या करता है और न ही प्रदर्शन जो आपको विशेष रूप से लिखने की बजाय।
डेमियन

1
मैं समझता हूं तुम्हारा क्या मतलब है। यह विनम्रता है, जो मुझे अपने स्वयं के बजाय पेशेवर पूर्णकालिक पुस्तकालय लेखकों द्वारा अनुकूलित किए गए संस्करण की समीक्षा करने, परीक्षण करने के लिए चुनती है। मानक इसकी क्रम जटिलता अपने कार्यों के साथ-साथ: पुस्तकालय आवश्यक ज्ञान के रूप में माना जा सकता है।
xtofl

एक तरफ तार, यह एक सी + + समस्या का हल है। मुझे नहीं लगता कि इसे नीचे वोट दिया जाना चाहिए था।
उल्लू

-1

यह मेरा इसे करने का तरीका है:

std::string removeAll(std::string str, char c) {
    size_t offset = 0;
    size_t size = str.size();

    size_t i = 0;
    while (i < size - offset) {
        if (str[i + offset] == c) {
            offset++;
        }

        if (offset != 0) {
            str[i] = str[i + offset];
        }

        i++;
    }

    str.resize(size - offset);
    return str;
}

मूल रूप से जब भी मुझे कोई चार्ट मिलता है, तो मैं ऑफसेट को अग्रिम करता हूं और सही इंडेक्स पर चार्ट को स्थानांतरित करता हूं। मुझे नहीं पता कि यह सही है या कुशल, मैं C ++ में (अभी तक फिर से) शुरू कर रहा हूं और मुझे उस पर कोई इनपुट पसंद आएगा।


4
4 महीने बाद इस सवाल का जवाब देते हुए, मुझे वास्तव में नहीं पता कि मैंने std :: erase या std :: प्रतिस्थापन का उपयोग क्यों नहीं किया।
रिकार्डो पीपर

-3
#include <string>
#include <algorithm>
std::string str = "YourString";
char chars[] = {'Y', 'S'};
str.erase (std::remove(str.begin(), str.end(), chars[i]), str.end());

"वाईट्रिंग" को छोड़ते हुए, पूंजी वाई और एस को हटा देगा।

ध्यान दें कि removeएक एल्गोरिथ्म है और <algorithm>इसमें हेडर शामिल है।


हाँ, मुझे लगता है कि hte array chars पर एक निहित लूप है जो उसने छोड़ दिया है
RichardPlunkett
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.