С++ Удалить пунктуацию из строки

У меня есть строка, и я хочу удалить из нее все помехи. Как мне это сделать? Я провел некоторое исследование и обнаружил, что люди используют функцию ispunct() (я пробовал это), но я не могу заставить ее работать в моем коде. У кого-нибудь есть идеи?

#include <string>

int main() {

string text = "this. is my string. it here."

if (ispunct(text))
text.erase();

return 0;
}

Ответ 1

Я понял.

size_t found = text.find('.');
text.erase(found, 1);

Ответ 2

Использование алгоритма 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)  
                       );

Ответ 3

У 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 (и, возможно, некоторые другие функции библиотеки алгоритмов, которые я на данный момент забыл) используют этот подход, чтобы закрыть пробелы для удаляемых элементов, но оставляя изменение размера контейнера для вызывающий абонент.

Ответ 4

#include <string>
#include <iostream>
#include <cctype>

int main() {

    std::string text = "this. is my string. it 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

При удалении символа изменяется размер строки. Он должен обновляться при каждом удалении. И вы удалили текущий символ, поэтому следующий символ станет текущим символом. Если вы не уменьшаете счетчик циклов, символ рядом с символом пунктуации не будет проверяться.

Ответ 5

ispunct принимает значение char не строку.

вы можете сделать как

for (auto c : string)
     if (ispunct(c)) text.erase(text.find_first_of(c));

Это будет работать, но это медленный алгоритм.

Ответ 6

Проблема заключается в том, что ispunct() принимает один аргумент как символ, в то время как вы пытаетесь отправить строку. Вы должны перебирать элементы строки и стирать каждый символ, если это пунктуация, как здесь:

for(size_t i = 0; i<text.length(); ++i)
  if(ispunct(text[i]))
    text.erase(i--, 1);

Ответ 7

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

int main() {
    string str = "this. is my string. it here.";

    transform(str.begin(), str.end(), str.begin(), [](char ch)
    {
        if( ispunct(ch) )
            return '\0';
        return ch;
    });
}

Ответ 8

Довольно хороший ответ от Steve314. Я хотел бы добавить небольшое изменение:

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

Добавление :: before функция ispunct заботится о перегрузке.

Ответ 9

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

Ответ 10

Другим способом, который вы могли бы сделать это, было бы следующее:

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

Это приводит к созданию новой строки вместо фактического стирания символов из старой строки, но немного легче обернуть голову, чем использовать некоторые из более сложных встроенных функций.

Ответ 11

Попробуйте использовать этот, он удалит всю пунктуацию в строке в текстовом файле oky. str.erase(remove_if (str.begin(), str.end(),:: ispunct), str.end());

ответьте, если полезно

Ответ 12

Я пытался применить ответ @Steve314, но не смог заставить его работать, пока не наткнулся на эту заметку здесь на cppreference.com:

Заметки

Как и все другие функции из <cctype>, поведение std::ispunct не определено, если значение аргумента не может быть представлено как unsigned char и равно EOF. Чтобы безопасно использовать эти функции с простым char (или signed char), аргумент должен быть сначала преобразован в unsigned char.

Изучая приведенный пример, я могу заставить его работать так:

#include <string>
#include <iostream>
#include <cctype>
#include <algorithm>

int main()
{
    std::string text = "this. is my string. it here.";
    std::string result;
    text.erase(std::remove_if(text.begin(),
                              text.end(),
                              [](unsigned char c) { return std::ispunct(c); }),
               text.end());
    std::cout << text << std::endl;
}