2013-10-02 14 views
10

Mam ciąg znaków i chcę usunąć z niego wszystkie znaki interpunkcyjne. Jak mogę to zrobić? Zrobiłem trochę badań i odkryłem, że ludzie używają funkcji ispunct(), próbowałem tego, ale nie mogę tego zmusić do działania w moim kodzie. Czy ktoś ma jakieś pomysły?C++ Usuń interpunkcję z ciągu znaków

#include <string> 

int main() { 

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

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

return 0; 
} 
+0

Powinieneś sprawdzić wszystkie znaki jeden po drugim. –

Odpowiedz

-3

mam go.

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

Spowoduje to tylko usunięcie pierwszej instancji ".", Nie usunie całej interpunkcji, a nie wszystkich wystąpień ".". – pippin1289

+0

ale z pętlą for działa – NewFile

+0

powinieneś edytować swoje odpowiedzi, aby nie wprowadzać w błąd innych. Ale także usuwa tylko "." Nie wszystkie znaki interpunkcyjne. – pippin1289

5

ispunct zajmuje char wartość nie ciąg.

można zrobić jak

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

to będzie działać, ale jest to powolny algorytm.

+3

text.erase()? Jesteś pewny? –

+1

Masz mnie. 'text.erase()' nie działa. –

1

Problem polega na tym, że ispunct() przyjmuje jeden argument będący postacią, podczas gdy próbujesz wysłać ciąg znaków. Zalecana pętlę nad elementami łańcucha i wymazać każdy znak jeśli jest interpunkcja jak tutaj:

for(size_t i = 0; i<text.length(); ++i) 
    if(ispunct(text[i])) 
    text.erase(i--, 1); 
4
#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; 
} 

Wyjście

this is my string its here 

Po usunięciu charakter, rozmiar ciąg zmienia się. Musi być aktualizowany po każdym usunięciu. Usunąłeś obecny znak, aby następna postać stała się bieżącą postacią. Jeśli nie zmniejszysz licznika pętli, znak obok znaku interpunkcyjnego nie zostanie zaznaczony.

+0

Nie mogę dostać ispunct do kompilacji. Zawarłem wszystkie nagłówki, które zrobiłeś. – NewFile

+1

Musisz dołączyć '' lub ''. – thefourtheye

19

Stosując algorytm 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) 
         ); 
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; 
    }); 
} 
8

POW ma już dobrą odpowiedź jeśli trzeba wynik jako nowy ciąg znaków. Ta odpowiedź brzmi, jak sobie z tym poradzić, jeśli chcesz przeprowadzić aktualizację w miejscu.

Pierwsza część przepisu to std::remove_if, dzięki czemu można skutecznie usunąć interpunkcję, pakując wszystkie nie-interpunkcje w toku.

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

Niestety, std::remove_if nie zmniejsza łańcucha do nowego rozmiaru. Nie może, ponieważ nie ma dostępu do samego kontenera. Dlatego w wyniku po spakowanych wynikach pozostały niepotrzebne znaki.

Aby obsłużyć to, std::remove_if zwraca iterator, który wskazuje część ciąg, który jest nadal potrzebny. To może być używany z ciągów erase metody, prowadzące do następnego idiomu ...

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

[EDIT - Nie mogę uwierzyć, że ja właśnie tak - że iteratorów dla erase powinno wskazywać zakres usunąć , a nie zakres do zachowania.]

Ja nazywam to idiomem, ponieważ jest to powszechna technika, która działa w wielu sytuacjach.Inne typy niż string zapewniają odpowiednie metody erase i std::remove (i prawdopodobnie niektóre inne funkcje biblioteki algorytmów, o których zapomniałem w tej chwili) przyjmują takie podejście do zamykania przerw na elementy, które usuwają, ale pozostawiają zmianę rozmiaru kontenera dla osoby dzwoniącej.

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

Innym sposobem można to zrobić będzie w następujący sposób:

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

ta kończy się tworząc nowy ciąg zamiast faktycznie kasowanie znaków ze starego łańcucha, ale to jest trochę łatwiej owijaj głowę, zamiast korzystać z bardziej złożonych wbudowanych funkcji.

0

Spróbuj użyć tego, usunie wszystkie znaki interpunkcyjne na łańcuchu w pliku tekstowym oky. str.erase (remove_if (str.begin(), str .end(), :: ispunct), str.end());

Proszę wysłać komentarz, jeśli są pomocne