Я пишу часть программного обеспечения, и мне требуется обработать данные, которые я получаю с веб-страницы с помощью libcurl. Когда я получаю данные, по какой-то причине в нем есть дополнительные разрывы строк. Мне нужно выяснить способ разрешить только буквы, цифры и пробелы. И удалите все остальное, включая разрывы строк. Есть ли простой способ сделать это? Спасибо.
Как удалить все не буквенно-цифровые символы из строки в С++?
Ответ 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());