C ++ में स्ट्रिंग से कुछ अक्षर कैसे निकालें?


96

उदाहरण के लिए मेरे पास एक उपयोगकर्ता इनपुट एक फोन नंबर है।

cout << "Enter phone number: ";
INPUT: (555) 555-5555
cin >> phone;

मैं स्ट्रिंग से "(", ")", और "-" अक्षर निकालना चाहता हूं। मैंने स्ट्रिंग हटाने पर ध्यान दिया है, फ़ंक्शंस खोजें और प्रतिस्थापित करें हालांकि मैं केवल यह देखता हूं कि वे स्थिति के आधार पर काम करते हैं।

क्या कोई स्ट्रिंग फ़ंक्शन है जिसे मैं एक चरित्र पास करने के लिए उपयोग कर सकता हूं, "(" उदाहरण के लिए, और क्या यह एक स्ट्रिंग के भीतर सभी उदाहरणों को हटा सकता है?

जवाबों:


140
   string str("(555) 555-5555");

   char chars[] = "()-";

   for (unsigned int i = 0; i < strlen(chars); ++i)
   {
      // you need include <algorithm> to use general algorithms like std::remove()
      str.erase (std::remove(str.begin(), str.end(), chars[i]), str.end());
   }

   // output: 555 5555555
   cout << str << endl;

फ़ंक्शन के रूप में उपयोग करने के लिए :

void removeCharsFromString( string &str, char* charsToRemove ) {
   for ( unsigned int i = 0; i < strlen(charsToRemove); ++i ) {
      str.erase( remove(str.begin(), str.end(), charsToRemove[i]), str.end() );
   }
}
//example of usage:
removeCharsFromString( str, "()-" );

4
यह कैसे काम करता है? क्या यह मिटा और हटाने का उपयोग करने के लिए एक डबल नकारात्मक नहीं है? मेरे लिए यह पढ़ता है: "उन वर्णों को मिटा दें जो स्थिति में हैं () - नहीं हैं।" और जब से प्रत्येक एक समय में किया जाता है, क्या उसे सभी वर्णों को नहीं हटाना चाहिए? मैंने दोनों कार्यों पर प्रलेखन पढ़ा है, और इससे मुझे कोई मतलब नहीं है। cplusplus.com/reference/algorithm/remove cplusplus.com/reference/string/string/erase
ब्रेंट

@Bent std :: remove () स्ट्रिंग से किसी भी मान्य वर्ण को नहीं निकालेगा, यह केवल मान्य वर्णों को एक साथ ले जाता है।
lk_vc

20
@ बेंट और भविष्य के पाठक, यह इरेज़ -हटा मुहावरा है । संक्षेप में, std::removeगैर-हटाए गए आइटम को वेक्टर के सामने ले जाता है और पिछले अपरिवर्तित आइटम से परे इंगित करते हुए एक पुनरावृत्ति देता है। फिर std::eraseवेक्टर को उस पुनरावृत्त से अंत तक विभाजित करता है।
chwarr

1
वास्तव में C ++ संस्करण के लिए मुझे लगता है कि हमें उपयोग करना चाहिए string chars("()-");और फिर वर्णों .length()तक पहुंचने के लिए लंबाई और .at(i)विधि प्राप्त करने के लिए विधि का उपयोग करना चाहिए :) फ़ंक्शन किए गए फ़ाइडल
ideone.com/tAZt5I

2
के रूप में उपयोग करने के लिए : समारोह ideone.com/XOROjq का उपयोग करता है -<iostream> <algorithm> <cstring>
jave.web

36

मैं स्ट्रिंग से "(", ")", और "-" अक्षर निकालना चाहता हूं।

आप अपने द्वारा std::remove_if()निर्दिष्ट वर्णों को हटाने के लिए एल्गोरिथ्म का उपयोग कर सकते हैं:

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

bool IsParenthesesOrDash(char c)
{
    switch(c)
    {
    case '(':
    case ')':
    case '-':
        return true;
    default:
        return false;
    }
}

int main()
{
    std::string str("(555) 555-5555");
    str.erase(std::remove_if(str.begin(), str.end(), &IsParenthesesOrDash), str.end());
    std::cout << str << std::endl; // Expected output: 555 5555555
}

std::remove_if()एल्गोरिथ्म कुछ एक विधेय कहा जाता है, जो ऊपर टुकड़ा की तरह एक समारोह सूचक हो सकता है की आवश्यकता है।

आप एक फ़ंक्शन ऑब्जेक्ट (एक ऑब्जेक्ट जो फ़ंक्शन कॉल ()ऑपरेटर को ओवरलोड करता है ) भी पास कर सकता है । यह हमें और भी सामान्य समाधान बनाने की अनुमति देता है:

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

class IsChars
{
public:
    IsChars(const char* charsToRemove) : chars(charsToRemove) {};

    bool operator()(char c)
    {
        for(const char* testChar = chars; *testChar != 0; ++testChar)
        {
            if(*testChar == c) { return true; }
        }
        return false;
    }

private:
    const char* chars;
};

int main()
{
    std::string str("(555) 555-5555");
    str.erase(std::remove_if(str.begin(), str.end(), IsChars("()- ")), str.end());
    std::cout << str << std::endl; // Expected output: 5555555555
}

आप निर्दिष्ट कर सकते हैं कि किन वर्णों को "()- "स्ट्रिंग से निकालना है । ऊपर के उदाहरण में मैंने एक स्थान जोड़ा है ताकि रिक्त स्थान के साथ-साथ कोष्ठक और डैश भी हट जाएँ।


आप भी उपयोग कर सकते हैंispunct(int c)
MSalters

बहुत बढ़िया कार्यान्वयन। इस पद्धति ने त्रुटिपूर्ण रूप से काम किया और आगे की गतिशीलता के लिए बहुत जगह है। जवाब देने के लिए धन्यवाद। MSalters, मैं भी ispunct (int c) फ़ंक्शन को देखूंगा और अपने कामकाज पर वापस रिपोर्ट करूंगा।
एस.डी.

12

remove_if () पहले ही उल्लेख किया गया है। लेकिन, C ++ 0x के साथ, आप इसके लिए लैम्बडा के साथ विधेय को निर्दिष्ट कर सकते हैं।

नीचे फ़िल्टरिंग करने के 3 अलग-अलग तरीकों के साथ इसका एक उदाहरण है। फ़ंक्शंस के "कॉपी" संस्करण उन मामलों के लिए भी शामिल किए जाते हैं जब आप एक कास्ट के साथ काम कर रहे होते हैं या मूल को संशोधित नहीं करना चाहते हैं।

#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;

string& remove_chars(string& s, const string& chars) {
    s.erase(remove_if(s.begin(), s.end(), [&chars](const char& c) {
        return chars.find(c) != string::npos;
    }), s.end());
    return s;
}
string remove_chars_copy(string s, const string& chars) {
    return remove_chars(s, chars);
}

string& remove_nondigit(string& s) {
    s.erase(remove_if(s.begin(), s.end(), [](const char& c) {
        return !isdigit(c);
    }), s.end());
    return s;
}
string remove_nondigit_copy(string s) {
    return remove_nondigit(s);
}

string& remove_chars_if_not(string& s, const string& allowed) {
    s.erase(remove_if(s.begin(), s.end(), [&allowed](const char& c) {
        return allowed.find(c) == string::npos;
    }), s.end());
    return s;
}
string remove_chars_if_not_copy(string s, const string& allowed) {
    return remove_chars_if_not(s, allowed);
}

int main() {
    const string test1("(555) 555-5555");
    string test2(test1);
    string test3(test1);
    string test4(test1);
    cout << remove_chars_copy(test1, "()- ") << endl;
    cout << remove_chars(test2, "()- ") << endl;
    cout << remove_nondigit_copy(test1) << endl;
    cout << remove_nondigit(test3) << endl;
    cout << remove_chars_if_not_copy(test1, "0123456789") << endl;
    cout << remove_chars_if_not(test4, "0123456789") << endl;
}

Const char & c के बजाय, मुझे वास्तव में const string :: value_type & का उपयोग करना चाहिए था। लेकिन, इस मामले में यह कोई बड़ी बात नहीं है।
शैडो २५३१

1
यह बहुत गहन कार्यान्वयन है। मैं इसकी सराहना करता हूं और इस कार्यान्वयन का उपयोग भी करूंगा।
एस.डी.

8

यहाँ रुचि रखने वाले के लिए एक अलग समाधान है। यह c ++ 11 में नए For रेंज का उपयोग करता है

string str("(555) 555-5555");
string str2="";

for (const auto c: str){

    if(!ispunct(c)){

        str2.push_back(c);
    }
}

str = str2;
//output: 555 5555555
cout<<str<<endl;

1
(1) str2आरंभीकरण की आवश्यकता नहीं है। (२) str = std::move(str2)अधिक कुशल होगा।
अजय

6

मुझे डर है कि std :: string के लिए ऐसा कोई सदस्य नहीं है, लेकिन आप आसानी से उस तरह के कार्य कर सकते हैं। यह सबसे तेज़ समाधान नहीं हो सकता है लेकिन यह पर्याप्त होगा:

std::string RemoveChars(const std::string& source, const std::string& chars) {
   std::string result="";
   for (unsigned int i=0; i<source.length(); i++) {
      bool foundany=false;
      for (unsigned int j=0; j<chars.length() && !foundany; j++) {
         foundany=(source[i]==chars[j]);
      }
      if (!foundany) {
         result+=source[i];
      }
   }
   return result;
}

EDIT: नीचे दिए गए उत्तर को पढ़कर, मैंने इसे अधिक सामान्य समझा, न कि केवल अंकों का पता लगाने के लिए। उपरोक्त समाधान दूसरे तर्क स्ट्रिंग में पारित प्रत्येक वर्ण को छोड़ देगा। उदाहरण के लिए:

std::string result=RemoveChars("(999)99-8765-43.87", "()-");

में परिणाम होगा

99999876543.87

3
using namespace std;


// c++03
string s = "(555) 555-5555";
s.erase(remove_if(s.begin(), s.end(), not1(ptr_fun(::isdigit))), s.end());

// c++11
s.erase(remove_if(s.begin(), s.end(), ptr_fun(::ispunct)), s.end());

नोट: यह पॉसिबल है आपको ptr_fun<int, int>सरल के बजाय लिखने की आवश्यकता हैptr_fun


यह चयनित उत्तर कैसे नहीं है?
user3240688

@ user3240688 ध्यान दें कि std :: ptr_fun C ++ 11 में पदावनत है और इसे C ++ 17 में हटा दिया जाएगा और std :: not1 को C ++ 17 में पदावनत कर दिया जाएगा । आप std::crefया std::function(या लंबोदर) का उपयोग कर सकते हैं ।
रूई दंतों

3

हां, आप अंकों के लिए जांच करने के लिए isdigit () फ़ंक्शन का उपयोग कर सकते हैं :)

हेयर यू गो:

#include <iostream>
#include <cctype>
#include <string.h>

using namespace std;

int main(){

  char *str = "(555) 555-5555";
  int len = strlen(str);

  for (int i=0; i<len; i++){
      if (isdigit(*(str+i))){
        cout << *(str+i);
      }
  }

  cout << endl;


return 0;   
}

आशा करता हूँ की ये काम करेगा :)


यह उस तत्व को हटाने के लिए संशोधित किया जा सकता है जो गलत रिटर्न देता है। धन्यवाद।
एस.डी.

3

boost::is_any_of

एक स्ट्रिंग से सभी वर्णों के लिए पट्टी जो दूसरे दिए गए स्ट्रिंग में दिखाई देते हैं:

#include <cassert>

#include <boost/range/algorithm/remove_if.hpp>
#include <boost/algorithm/string/classification.hpp>

int main() {
    std::string str = "a_bc0_d";
    str.erase(boost::remove_if(str, boost::is_any_of("_0")), str.end());
    assert((str == "abcd"));
}

उबंटू 16.04, बूस्ट 1.58 में परीक्षण किया गया।


2

यदि आपके पास ऐसे कंपाइलर की पहुंच है जो वैरिएड टेम्प्लेट का समर्थन करता है, तो आप इसका उपयोग कर सकते हैं:

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

template<char ... CharacterList>
inline bool check_characters(char c) {
    char match_characters[sizeof...(CharacterList)] = { CharacterList... };
    for(int i = 0; i < sizeof...(CharacterList); ++i) {
        if(c == match_characters[i]) {
            return true;
        }
    }
    return false;
}

template<char ... CharacterList>
inline void strip_characters(std::string & str) {
    str.erase(std::remove_if(str.begin(), str.end(), &check_characters<CharacterList...>), str.end());
}

int main()
{
    std::string str("(555) 555-5555");
    strip_characters< '(',')','-' >(str);
    std::cout << str << std::endl;
}

1

यहाँ अभी तक एक और विकल्प है:

template<typename T>
void Remove( std::basic_string<T> & Str, const T * CharsToRemove )
{
    std::basic_string<T>::size_type pos = 0;
    while (( pos = Str.find_first_of( CharsToRemove, pos )) != std::basic_string<T>::npos )
    {
        Str.erase( pos, 1 ); 
    }
}

std::string a ("(555) 555-5555");
Remove( a, "()-");

Std :: string और std :: wstring के साथ काम करता है


1

मैं नया हूं, लेकिन ऊपर दिए गए कुछ उत्तर बेहद जटिल हैं, इसलिए यहां एक विकल्प है।

नोट: जब तक 0-9 सन्निहित हैं (जो उन्हें मानक के अनुसार होना चाहिए), यह अन्य सभी वर्ण लेकिन संख्या और '' को फ़िल्टर करना चाहिए। 0-9 को जानना संक्रामक होना चाहिए और एक चर वास्तव में एक इंट है, हम नीचे कर सकते हैं।

संपादित करें: मैंने पोस्टर को रिक्त स्थान नहीं चाहा, इसलिए मैंने इसे बदल दिया ...

#include <cstdio>
#include <cstring>

void numfilter(char * buff, const char * string)
{
  do
  { // According to standard, 0-9 should be contiguous in system int value.
    if ( (*string >= '0' && *string <= '9') || *string == ' ')
      *buff++ = *string;
  } while ( *++string );
  *buff++ = '\0'; // Null terminate
}

int main()
{
  const char *string = "(555) 555-5555";
  char buff[ strlen(string) + 1 ];

  numfilter(buff, string);
  printf("%s\n", buff);

return 0;
}

नीचे दिए गए वर्णों को फ़िल्टर करना है।

#include <cstdio>
#include <cstring>

void cfilter(char * buff, const char * string, const char * toks)
{
  const char * tmp;  // So we can keep toks pointer addr.
  do
  {
    tmp = toks;
    *buff++ = *string; // Assume it's correct and place it.
    do                 // I can't think of a faster way.
    {
      if (*string == *tmp)
      {
        buff--;  // Not correct, pull back and move on.
        break;
      }
    }while (*++tmp);
  }while (*++string);

  *buff++ = '\0';  // Null terminate
}

int main()
{
  char * string = "(555) 555-5555";
  char * toks = "()-";
  char buff[ strlen(string) + 1 ];

  cfilter(buff, string, toks);
  printf("%s\n", buff);

  return 0;
}

ओपी जो चाहता था वह नहीं करता है; यह रिक्त स्थान भी हटा देता है।
एंड्रयू बार्बर

1

Std :: wstring और wchar_t का उपयोग करना ( यूनिकोड हेडर की आवश्यकता है ):

//#include <tchar.h>
std::wstring phone(L"(555) 555-5555");

... फैंसी स्थिर रेंज इनिशियलाइज़र अगले; badChars2 को सेटअप करने के लिए आवश्यक नहीं यह ठीक उसी तरह है। यह ओवरकिल है; और कुछ की तुलना में अधिक अकादमिक:

const wchar_t *tmp = L"()-"; 
const std::set<wchar_t> badChars2(tmp,tmp + sizeof(tmp)-1);

सरल, संक्षिप्त मेमना:

  1. लैम्ब्डा कैप्चर सूची में फोन का उपयोग करता है।
  2. इरेज़-रिमूव मुहावरे का उपयोग करता है
  3. फोन से सभी खराब पात्रों को निकालता है

    for_each(badChars2.begin(), badChars2.end(), [&phone](wchar_t n){
         phone.erase(std::remove(phone.begin(), phone.end(), n), phone.end());
    });
    wcout << phone << endl;

आउटपुट: "555 5555555"


1

उन लोगों के लिए जो अधिक संक्षिप्त पसंद करते हैं, लंबोदर कोडिंग शैली पढ़ना आसान है ...

यह उदाहरण सभी गैर-अल्फ़ान्यूमेरिक और सफ़ेद अंतरिक्ष वर्णों को एक विस्तृत स्ट्रिंग से निकालता है। आप इसे किसी भी अन्य ctype.h सहायक कार्यों के साथ मिश्रित कर सकते हैं ताकि जटिल दिखने वाले चरित्र-आधारित परीक्षणों को हटाया जा सके।

(मुझे यकीन नहीं है कि ये फ़ंक्शन सीजेके भाषाओं को कैसे संभालेंगे, इसलिए वहां नरम तरीके से चलें।)

    // Boring C loops: 'for(int i=0;i<str.size();i++)' 
    // Boring C++ eqivalent: 'for(iterator iter=c.begin; iter != c.end; ++iter)'

देखें कि क्या आपको शोरगुल C / C ++ की तुलना में समझने में आसान नहीं है / iterator loops:

TSTRING label = _T("1.   Replen & Move  RPMV");
TSTRING newLabel = label;
set<TCHAR> badChars; // Use ispunct, isalpha, isdigit, et.al. (lambda version, with capture list parameter(s) example; handiest thing since sliced bread)
for_each(label.begin(), label.end(), [&badChars](TCHAR n){
    if (!isalpha(n) && !isdigit(n))
        badChars.insert(n);
});

for_each(badChars.begin(), badChars.end(), [&newLabel](TCHAR n){
    newLabel.erase(std::remove(newLabel.begin(), newLabel.end(), n), newLabel.end());
});

इस कोड को चलाने के बाद newLabel परिणाम: " 1ReplenMoveRPMV "

यह सिर्फ अकादमिक है, क्योंकि यह स्पष्ट रूप से अधिक सटीक, संक्षिप्त और कुशल होगा अगर 'lambda0 (पहले for_each ) से तर्क को एकल lambda1 (दूसरा for_each ) में जोड़ा जाए , यदि आपने पहले ही स्थापित कर लिया है कि कौन से अक्षर "badChars" हैं ।


आसान इरेज़-हटा मुहावरे का उल्लेख करने और उपयोग करने के लिए @Eric Z के उत्तर का श्रेय। en.wikipedia.org/wiki/Erase-remove_idiom
डारिन

0

अच्छे उत्तरों की संख्या, यहाँ संख्याओं की एक स्ट्रिंग को साफ करने का एक और तरीका है, वर्णों को हटाना नहीं है बल्कि संख्याओं को हटाकर।

string str("(555) 555-5555"), clean;
for (char c : str)
    if (c >= 48 and c <= 57)
        clean.push_back(c);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.