Подтвердить что ты не робот

Как удалить все не буквенно-цифровые символы из строки в С++?

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

4b9b3361

Ответ 1

Напишите функцию, которая принимает 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 в заголовке стандартной библиотеки C <cctype> (именно тот, который вы хотите использовать), и std::isalnum в заголовке стандартной библиотеки С++ <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 делает только один проход по последовательности, поэтому он имеет линейную временную сложность.

Ответ 2

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

s.erase(std::remove_if(s.begin(), s.end(), 
[]( auto const& c ) -> bool { return !std::isalnum(c); } ), s.end());

Ответ 3

Вы можете всегда прокручивать и просто 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++;
}

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

Если вы используете только буфер 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);

Ответ 4

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

Ответ 5

#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, которая НЕ возвращает возвращаемое значение, оставляя вам только буквенно-цифровой текст, который вы хотите.

Ответ 6

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

// Removes all punctuation       
s.erase( std::remove_if(s.begin(), s.end(), &ispunct), s.end());

Ответ 7

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

Удаление ненулевых символов из строки. (alnum = алфавитный или числовой)

  • Объявить функцию (isalnum возвращает 0, если прошло char не alnum)

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

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

то ваша строка будет только с символами alnum.

Ответ 8

Приведенный ниже код должен работать нормально для данной строки 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());

Ответ 9

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

str.erase(std::remove_if(str.begin(), str.end(), &ispunct), str.end());
str.erase(std::remove_if(str.begin(), str.end(), &isspace), str.end());

Ответ 10

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

Ответ 11

Упомянутое решение

s.erase( std::remove_if(s.begin(), s.end(), &std::ispunct), s.end());

очень хорошо, но, к сожалению, не работает с такими символами, как 'С' в Visual Studio (режим отладки), из-за этой строки:

_ASSERTE((unsigned)(c + 1) <= 256)

в isctype.c

Итак, я бы порекомендовал что-то вроде этого:

inline int my_ispunct( int ch )
{
    return std::ispunct(unsigned char(ch));
}
...
s.erase( std::remove_if(s.begin(), s.end(), &my_ispunct), s.end());