সি ++ এর স্ট্রিং থেকে নির্দিষ্ট অক্ষরগুলি কীভাবে সরিয়ে নেওয়া যায়?


96

উদাহরণস্বরূপ আমার কাছে একটি ফোন নম্বর রয়েছে user

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/references/algorithm/remove cplusplus.com/references/string/string/erase
ব্রেন্ট

@ ব্রেন্ট স্টডি :: সরান () স্ট্রিং থেকে কোনও বৈধ অক্ষর মুছে ফেলবে না, এটি কেবল বৈধ অক্ষরকে একসাথে সরিয়ে দেয়।
lk_vc

21
@ ব্রেন্ট এবং ভবিষ্যতের পাঠক, এটি মুছে ফেলা আইডিয়ম । সংক্ষেপে, std::removeঅ-সরানো আইটেমগুলিকে ভেক্টরের সামনের দিকে সরানো হয় এবং সর্বশেষে অবিরত আইটেমের বাইরে নির্দেশক একটি পুনরাবৃত্তি প্রদান করে। তারপরে std::eraseসেই পুনরুদ্ধারকারী থেকে শেষ পর্যন্ত ভেক্টরটিকে ছাঁটাই।
chwarr

4
সত্যিকারের সি ++ সংস্করণের জন্য আমি মনে করি আমাদের অক্ষরটি অ্যাক্সেস করার জন্য দৈর্ঘ্য এবং পদ্ধতিটি অর্জনেরstring chars("()-"); জন্য .length()পদ্ধতিটি ব্যবহার করা উচিত এবং তারপরে ব্যবহার করা উচিত .at(i):)
ফাংশনাইজড

4
ফাংশন হিসাবে ব্যবহার করতে : 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, আমি ispunct (int গ) ফাংশন সন্ধান করব এবং আমার কাজ সম্পর্কে ফিরে রিপোর্ট করব।
এসডি

12

সরানো_এফ () ইতিমধ্যে উল্লেখ করা হয়েছে। তবে, 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;
}

কনস্ট চর ও সি পরিবর্তে আমার সত্যিকারের কনস্ট স্ট্রিং :: মান_প্রকার & ব্যবহার করা উচিত। তবে, এই ক্ষেত্রে এটি কোনও বড় বিষয় নয়।
শ্যাডো 2531

4
এটি একটি খুব সম্পূর্ণ বাস্তবায়ন। আমি এটির প্রশংসা করি এবং এই প্রয়োগটিও ব্যবহার করব।
এসডি

8

আগ্রহী প্রত্যেকের জন্য এখানে আলাদা সমাধান রয়েছে। এটি সি ++ 11 এ নতুন ফর রেঞ্জ ব্যবহার করে

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;

4
(1) str2আরম্ভের প্রয়োজন হয় না। (2) str = std::move(str2)আরও দক্ষ হবে।
অজয়

6

আমি আশঙ্কা করছি যে স্টাডি :: স্ট্রিংয়ের জন্য এমন কোনও সদস্য নেই তবে আপনি সহজেই এই জাতীয় ফাংশনটি প্রোগ্রাম করতে পারেন। এটি দ্রুততম সমাধান নাও হতে পারে তবে এটি যথেষ্ট হবে:

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;
}

সম্পাদনা: নীচের উত্তরটি পড়ে, আমি এটি আরও সাধারণ হিসাবে বুঝতে পেরেছি, কেবল অঙ্কটি সনাক্ত করতে নয়। উপরের সমাধানটি দ্বিতীয় আর্গুমেন্ট স্ট্রিংয়ে পাস হওয়া প্রতিটি চরিত্রকে বাদ দেবে। উদাহরণ স্বরূপ:

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


এটি কীভাবে নির্বাচিত উত্তর নয়?
ব্যবহারকারী 3240688

@ ব্যবহারকারীর 3240688 নোট করুন যে std :: ptr_fun সি ++ 11 এ অবনতি হয়েছে এবং সি ++ 17 এ সরানো হবে এবং স্ট্যান্ড :: নট 1 সি ++ 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, "()-");

স্ট্যান্ড :: স্ট্রিং এবং এসটিডি :: wstring এর সাথে কাজ করে


1

আমি নতুন, তবে উপরের উত্তরগুলির মধ্যে কয়েকটি অত্যন্ত জটিল, তাই এখানে একটি বিকল্প রয়েছে alternative

দ্রষ্টব্য: যতক্ষণ 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

ব্যবহার এসটিডি :: 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

আপনার মধ্যে যারা আরও সংক্ষিপ্ত, ল্যাম্বডা কোডিং স্টাইল পড়তে সহজ পছন্দ করেন তাদের জন্য ...

এই উদাহরণটি একটি বিস্তৃত স্ট্রিং থেকে সমস্ত অ-অক্ষর এবং সাদা স্থানের অক্ষর সরিয়ে দেয়। জটিল চেহারার চরিত্রভিত্তিক পরীক্ষাগুলি অপসারণ করতে আপনি এটি অন্য যে কোনও সিটিপিএইচ সহায়ক সহায়তার সাথে মিশ্রিত করতে পারেন ।

(আমি নিশ্চিত না যে এই ফাংশনগুলি কীভাবে সিজেকে ভাষাগুলি পরিচালনা করবে, সুতরাং সেখানে নরমভাবে চলুন।)

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

আপনি / পুনরুক্তিকারী লুপগুলির জন্য কোলাহলকারী সি / সি ++ এর চেয়ে বুঝতে এই সহজটি না খুঁজে পান কিনা দেখুন:

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());
});

এই কোডটি চালানোর পরে নতুন লেবেলের ফলাফল: " 1ReplenMoveRPMV "

এটি কেবল একাডেমিক, যেহেতু ল্যাম্বডা0 (প্রথম for_each ) থেকে 'যদি' যুক্তিটি একক ল্যাম্বডা 1 (দ্বিতীয় বারের_আচ ) এর সাথে একত্রিত করার জন্য এটি আরও স্পষ্ট, সংক্ষিপ্ত এবং দক্ষ হবে , যদি আপনি ইতিমধ্যে প্রতিষ্ঠিত করেন যে কোন চরিত্রগুলি "ব্যাডচার্স" ।


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