Как удалить определенные символы из строки в C ++?

Например, у меня есть пользователь, который вводит номер телефона.

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

Я хочу удалить символы "(", ")" и "-" из строки. Я посмотрел на строку удалить, найти и заменить функции, но я вижу только, что они работают на основе позиции.

Есть ли строковая функция, которую я могу использовать для передачи символа, например, "(", и могу ли она удалить все экземпляры в строке?

88 голосов | спросил SD. 5 Mayam11 2011, 05:08:55

11 ответов


0
  

Я хочу удалить "(", ")" и "-"   символы из строки.

Вы можете использовать алгоритм 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
}

Вы можете указать, какие символы удалять, используя строку "()- ". В приведенном выше примере я добавил пробел для удаления пробелов, а также скобок и тире.

ответил In silico 5 Mayam11 2011, 05:27:14
0

remove_if () уже упоминалось. Но в C ++ 0x вы можете указать для него предикат с помощью лямбды.

Ниже приведен пример этого с 3 различными способами фильтрации. «копии» версий функций также включены для случаев, когда вы работаете с const или не хотите изменять оригинал.

#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;
}
ответил Shadow2531 5 Mayam11 2011, 08:49:47
0

Вот другое решение для всех, кто заинтересован. Он использует новый диапазон For в c ++ 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;
ответил ashwin911 7 Maypm13 2013, 19:21:46
0

Боюсь, что для 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;
}

РЕДАКТИРОВАТЬ: прочитав ответ ниже, я понял, что он более общий, а не только для определения цифры. Приведенное выше решение будет пропускать каждый символ, переданный во второй строке аргумента. Например:

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

приведет к

99999876543.87
ответил StormByte 5 Mayam11 2011, 05:23:38
0
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

ответил Oleg Svechkarenko 28 Maypm13 2013, 20:26:34
0

boost::is_any_of один вкладыш для удаления всех символов из данной строки:

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

std::string str = "a_bc0_d";
str.erase(boost::remove_if(str, boost::is_any_of("_0")), str.end());
assert((str == "abcd"));
ответил Ciro Santilli 新疆改造中心 六四事件 法轮功 2 AMpWed, 02 Apr 2014 01:34:47 +040034Wednesday 2014, 01:34:47
0

Если у вас есть доступ к компилятору, который поддерживает шаблоны переменных, вы можете использовать его:

#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;
}
ответил Timesquare 5 Mayam11 2011, 07:07:13
0

Вот еще одна альтернатива:

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

ответил Jem 16 32011vEurope/Moscow11bEurope/MoscowWed, 16 Nov 2011 06:34:39 +0400 2011, 06:34:39
0

Я новичок, но некоторые из приведенных выше ответов безумно сложны, так что вот альтернатива.

ПРИМЕЧАНИЕ. Пока 0-9 являются смежными (что должно быть в соответствии со стандартом), это должно отфильтровывать все другие символы, кроме цифр и ''. Знание 0-9 должно быть смежным, а тип char - целочисленным, мы можем сделать следующее.

РЕДАКТИРОВАТЬ: я не заметил, что плакат также хотел пробелы, поэтому я изменил его ...

#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;
}
ответил JustTired 12 FebruaryEurope/MoscowbTue, 12 Feb 2013 09:56:53 +0400000000amTue, 12 Feb 2013 09:56:53 +040013 2013, 09:56:53
0

Использование std :: wstring и wchar_t (требуется заголовок Юникод ):

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

... причудливый инициализатор статического диапазона next; не нужно настраивать 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"

ответил Darrin 9 Jpm1000000pmThu, 09 Jan 2014 21:23:43 +040014 2014, 21:23:43
0

Для тех из вас, кто предпочитает более лаконичный и легкий для чтения стиль лямбда-кодирования ...

В этом примере удаляются все не алфавитно-цифровые и пробельные символы из широкой строки. Вы можете смешать его с любыми другими ctype.h вспомогательными функциями для удаления сложных на вид символьные тесты.

(Я не уверен, как эти функции будут обрабатывать языки CJK, так что иди спокойно.)

    // 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 ++ для /итератора:

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 ) в одну лямбда1 (вторая for_each ), если вы уже установили, какие символы являются "badChars".

ответил Darrin 9 Jpm1000000pmThu, 09 Jan 2014 21:23:43 +040014 2014, 21:23:43

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132