Я получил строку и хочу удалить все знаки препинания. Как я могу это сделать? Я провел некоторое исследование и обнаружил, что люди используют функцию ispunct () (я пытался это сделать), но я не могу заставить ее работать в моем коде. У кого-нибудь есть идеи?
#include <string>
int main() {
string text = "this. is my string. it's here."
if (ispunct(text))
text.erase();
return 0;
}
Используя алгоритм remove_copy_if
: —
string text,result;
std::remove_copy_if(text.begin(), text.end(),
std::back_inserter(result), //Store output
std::ptr_fun<int, int>(&std::ispunct)
);
У POW уже есть хороший ответ, если вам нужен результат в виде новой строки. Этот ответ — как с этим справиться, если вы хотите обновить на месте.
Первая часть рецепта std::remove_if
, который может эффективно удалить пунктуацию, упаковывая все знаки препинания по ходу дела.
std::remove_if (text.begin (), text.end (), ispunct)
К несчастью, std::remove_if
не сокращает строку до нового размера. Не может, потому что не имеет доступа к самому контейнеру. Следовательно, после упакованного результата в строке остаются ненужные символы.
Чтобы справиться с этим, std::remove_if
возвращает итератор, который указывает часть строки, которая все еще необходима. Это можно использовать со строками erase
метод, приводящий к следующей идиоме …
text.erase (std::remove_if (text.begin (), text.end (), ispunct), text.end ());
Я называю это идиомой, потому что это распространенная техника, которая работает во многих ситуациях. Другие типы, чем string
предоставить подходящий erase
методы и std::remove
(и, возможно, некоторые другие функции библиотеки алгоритмов, которые я забыл на данный момент) используют такой подход, чтобы закрыть пробелы для удаляемых элементов, но оставить изменение размера контейнера для вызывающей стороны.
#include <string>
#include <iostream>
#include <cctype>
int main() {
std::string text = "this. is my string. it's here.";
for (int i = 0, len = text.size(); i < len; i++)
{
if (ispunct(text[i]))
{
text.erase(i--, 1);
len = text.size();
}
}
std::cout << text;
return 0;
}
Выход
this is my string its here
Когда вы удаляете символ, размер строки изменяется. Он должен обновляться всякий раз, когда происходит удаление. И вы удалили текущий символ, поэтому следующий символ становится текущим. Если вы не уменьшите счетчик цикла, символ рядом с символом пунктуации проверяться не будет.
ispunct
занимает char
значение не строка.
ты можешь делать как
for (auto c : string)
if (ispunct(c)) text.erase(text.find_first_of(c));
Это будет работать, но это медленный алгоритм.
Проблема в том, что ispunct () принимает один аргумент, являющийся символом, в то время как вы пытаетесь отправить строку. Вы должны перебрать элементы строки и стереть каждый символ, если это пунктуация, как здесь:
for(size_t i = 0; i<text.length(); ++i)
if(ispunct(text[i]))
text.erase(i--, 1);
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string str = "this. is my string. it's here.";
transform(str.begin(), str.end(), str.begin(), [](char ch)
{
if( ispunct(ch) )
return '\0';
return ch;
});
}
Другой способ сделать это будет следующим:
#include <ctype.h> //needed for ispunct()
string onlyLetters(string str){
string retStr = "";
for(int i = 0; i < str.length(); i++){
if(!ispunct(str[i])){
retStr += str[i];
}
}
return retStr;
В результате создается новая строка вместо фактического стирания символов из старой строки, но это немного проще, чем использовать некоторые из более сложных встроенных функций.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;//string is defined here.
cout << "Please enter a string with punctuation's: " << endl;//Asking for users input
getline(cin, s);//reads in a single string one line at a time
/* ERROR Check: The loop didn't run at first because a semi-colon was placed at the end
of the statement. Remember not to add it for loops. */
for(auto &c : s) //loop checks every character
{
if (ispunct(c)) //to see if its a punctuation
{
c=' '; //if so it replaces it with a blank space.(delete)
}
}
cout << s << endl;system("pause");
return 0;
}