Как удалить определенные символы из строки в С++?
Например, у меня есть пользовательский номер телефона.
cout << "Enter phone number: ";
INPUT: (555) 555-5555
cin >> phone;
Я хочу удалить символы "(", ")" и "-" из строки. Я посмотрел на строку remove, find и replace functions, но я вижу только, что они работают в зависимости от положения.
Есть ли строковая функция, которую я могу использовать для передачи символа "(например, и удалить все экземпляры в строке?
Ответы
Ответ 1
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, "()-" );
Ответ 2
Я хочу удалить "(", ")" и "-" символов из строки.
Вы можете использовать алгоритм 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
}
Вы можете указать, какие символы удалить с помощью строки "()- "
. В приведенном выше примере я добавил пробел, чтобы удалить пробелы, а также круглые скобки и тире.
Ответ 3
remove_if() уже упоминалось. Но с С++ 0x вы можете указать предикат для него с помощью лямбды.
Ниже приведен пример этого с тремя различными способами фильтрации. "Копировать" версии функций также включены для случаев, когда вы работаете с константой или не хотите изменять оригинал.
#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;
}
Ответ 4
Вот другое решение для всех заинтересованных. Он использует новый диапазон для диапазона в С++ 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;
Ответ 5
Я боюсь, что такого члена для 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
Ответ 6
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
Ответ 7
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"));
}
Протестировано в Ubuntu 16.04, Boost 1.58.
Ответ 8
Да, вы можете использовать функцию 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;
}
Надеюсь, это поможет:)
Ответ 9
Если у вас есть доступ к компилятору, поддерживающему вариационные шаблоны, вы можете использовать это:
#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;
}
Ответ 10
Здесь еще одна альтернатива:
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
Ответ 11
Я новичок, но некоторые из вышеперечисленных ответов безумно сложны, так что вот альтернатива.
ПРИМЕЧАНИЕ. Пока 0-9 смежны (они должны соответствовать стандарту), это должно отфильтровывать все остальные символы, кроме цифр, и ''. Знание 0-9 должно быть смежным, а char действительно является int, мы можем сделать следующее.
ИЗМЕНИТЬ: Я тоже не заметил, что плакаты тоже нужны, поэтому я изменил его...
#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 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;
}
Ответ 12
Для тех из вас, кто предпочитает более сжатый, более легкий для чтения стиль лямбда-кодирования...
В этом примере удаляются все символы, отличные от буквенно-цифровых и пробелов, из широкой строки. Вы можете смешать его с любым из других 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/С++ для/итератора:
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".
Ответ 13
Использование std:: wstring и wchar_t (требуется заголовок Unicode):
//#include <tchar.h>
std::wstring phone(L"(555) 555-5555");
... fancy static initial initializer next; не нужно настраивать badChars2 точно так же. Это излишне; больше академического, чем что-либо еще:
const wchar_t *tmp = L"()-";
const std::set<wchar_t> badChars2(tmp,tmp + sizeof(tmp)-1);
Простая, краткая лямбда:
- Использует телефон в списке захвата лямбда.
- Использует Стереть удаление идиомы
-
Удаляет все плохие символы из телефона
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"
Ответ 14
string s="(555) 555-5555";
for(int i=0;i<s.length();i++){
if(ispunct(s[i])){
char c=s[i];
s.erase(std::remove(s.begin(), s.end(), c), s.end());
}
}
cout<<s; // output: 555 5555555