Как убрать все не алфавитно-цифровые символы из строки в C ++? - PullRequest
22 голосов
/ 12 июня 2011

Я пишу часть программного обеспечения, и она требует от меня обработки данных, полученных с веб-страницы с помощью libcurlКогда я получаю данные, по какой-то причине в них появляются дополнительные разрывы строк.Мне нужно найти способ разрешить только буквы, цифры и пробелы.И удалите все остальное, включая разрывы строк.Есть ли простой способ сделать это?Спасибо.

Ответы [ 10 ]

43 голосов
/ 12 июня 2011

Напишите функцию, которая принимает char и возвращает true, если вы хотите удалить этот символ, или false, если вы хотите сохранить его:

bool my_predicate(char c);

Затем используйте алгоритм std::remove_if для удаления нежелательных символов из строки:

std::string s = "my data";
s.erase(std::remove_if(s.begin(), s.end(), my_predicate), s.end());

В зависимости от ваших требований вы можете использовать один из предикатов стандартной библиотеки, например std::isalnum, вместо написания своего собственного предиката (вы сказали, что вам необходимо сопоставлять буквенно-цифровые символы и пробелы, поэтому, возможно, это точно подходит то, что вам нужно).

Если вы хотите использовать функцию std::isalnum Стандартной библиотеки, вам понадобится приведение для устранения неоднозначности между функцией std::isalnum в заголовке стандартной библиотеки С <cctype> (той, которую вы хотите использовать) и std::isalnum в заголовке стандартной библиотеки C ++ <locale> (это не тот файл, который вы хотите использовать, если только вы не хотите выполнять обработку строк, зависящую от локали):

s.erase(std::remove_if(s.begin(), s.end(), (int(*)(int))std::isalnum), s.end());

Это одинаково хорошо работает с любым из контейнеров последовательности (включая std::string, std::vector и std::deque). Эта идиома обычно упоминается как идиома «стереть / удалить». Алгоритм std::remove_if также будет работать с обычными массивами. std::remove_if делает только один проход по последовательности, поэтому он имеет линейную сложность по времени.

8 голосов
/ 05 августа 2017

Предыдущее использование std::isalnum не будет компилироваться с std::ptr_fun без передачи аргумента унарный . Требуется, следовательно, это решение с лямбда-функцией должно содержать правильный ответ:

s.erase(std::remove_if(s.begin(), s.end(), 
[]( auto const& c ) -> bool { return !std::isalnum(c); } ), s.end());
4 голосов
/ 12 июня 2011

Вы всегда можете выполнить цикл и просто erase все не алфавитно-цифровые символы, если вы используете string.

#include <cctype>

size_t i = 0;
size_t len = str.length();
while(i < len){
    if (!isalnum(str[i]) || str[i] == ' '){
        str.erase(i,1);
        len--;
    }else
        i++;
}

Кто-то лучше со стандартной библиотекой, вероятно, может сделать это без цикла.

Если вы используете только буфер char, вы можете циклически проходить и, если символ не является буквенно-цифровым, сдвинуть все символы после него назад на один (чтобы перезаписать нарушающий символ):

#include <cctype>

size_t buflen = something;
for (size_t i = 0; i < buflen; ++i)
    if (!isalnum(buf[i]) || buf[i] != ' ')
        memcpy(buf[i], buf[i + 1], --buflen - i);
2 голосов
/ 30 августа 2015
#include <cctype>
#include <string>
#include <functional>

std::string s = "Hello World!";
s.erase(std::remove_if(s.begin(), s.end(),
    std::not1(std::ptr_fun(std::isalnum)), s.end()), s.end());
std::cout << s << std::endl;

Результат:

"HelloWorld"

Вы используете isalnum, чтобы определить, является ли каждый символ буквенно-цифровым, а затем ptr_fun, чтобы передать функцию в not1, которая НЕ возвращает возвращаемое значение, оставляя вам только те буквенно-цифровые символы, которые вам нужны.

2 голосов
/ 12 июня 2011

Стандартный алгоритм remove_copy_if очень подходит для вашего случая.

1 голос
/ 23 сентября 2018

Ниже код должен работать нормально для данной строки s.Он использует библиотеки <algorithm> и <locale>.

std::string s("He!!llo  Wo,@rld! 12 453");
s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return !std::isalnum(c); }), s.end());
1 голос
/ 28 декабря 2016

Просто немного расширив код Джеймса Макнеллиса. Его функция заключается в удалении буквенных символов вместо обычных.

Чтобы удалить не строковые символы из строки. (буквенное обозначение = алфавитный или цифровой)

  • Объявление функции (isalnum возвращает 0, если переданный символ не является alnum)

    bool isNotAlnum(char c) {
        return isalnum(c) == 0;
    }
    
  • А потом напиши это

    s.erase(remove_if(s.begin(), s.end(), isNotAlnum), s.end());
    

тогда ваша строка состоит только из буквенных символов.

1 голос
/ 16 октября 2014

Вы можете использовать алгоритм удаления-стирания таким образом -

// Removes all punctuation       
s.erase( std::remove_if(s.begin(), s.end(), &ispunct), s.end());
0 голосов
/ 28 ноября 2016
void remove_spaces(string data)
{ int i=0,j=0;
    while(i<data.length())
    {
        if (isalpha(data[i]))
        {
        data[i]=data[i];
        i++;
        }
        else
            {
            data.erase(i,1);}
    }
    cout<<data;
}
0 голосов
/ 07 июня 2016

У меня работает следующее.

str.erase(std::remove_if(str.begin(), str.end(), &ispunct), str.end());
str.erase(std::remove_if(str.begin(), str.end(), &isspace), str.end());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...