Rimuovi gli spazi da std :: string in C ++


222

Qual è il modo preferito per rimuovere gli spazi da una stringa in C ++? Potrei scorrere tutti i personaggi e creare una nuova stringa, ma c'è un modo migliore?

Risposte:


257

La cosa migliore da fare è usare l'algoritmo remove_ife isspace:

remove_if(str.begin(), str.end(), isspace);

Ora l'algoritmo stesso non può cambiare il contenitore (modifica solo i valori), quindi mescola i valori e restituisce un puntatore al punto in cui dovrebbe essere la fine. Quindi dobbiamo chiamare string :: erase per modificare effettivamente la lunghezza del contenitore:

str.erase(remove_if(str.begin(), str.end(), isspace), str.end());

Dobbiamo anche notare che remove_if eseguirà al massimo una copia dei dati. Ecco un'implementazione di esempio:

template<typename T, typename P>
T remove_if(T beg, T end, P pred)
{
    T dest = beg;
    for (T itr = beg;itr != end; ++itr)
        if (!pred(*itr))
            *(dest++) = *itr;
    return dest;
}

54
Poiché "isspace" presenta sovraccarichi, sarà probabilmente necessario qualificare il codice generico per utilizzare :: isspace (l'implementazione C che non accetta impostazioni locali) o essere accolto con errori di istanza del modello criptico.
Bklyn,

4
Tutti - diffidare del metodo sopra (Le due linee singole, non la versione basata su modelli, sebbene possa avere lo stesso problema). L'ho usato in un progetto senza rendermi conto che non è sempre corretto. Ad esempio, se le passi la stringa "1 + 1" restituisce "1 + 11". Sono passato al metodo di @rupello di seguito e ha funzionato bene in questo caso. Buona programmazione!
Joe B

6
@Joe La risposta menziona esplicitamente che è necessario chiamare in eraseseguito. Ciò restituirà il risultato corretto.
Konrad Rudolph,

31
-1 questo uso di isspaceè UB per tutti i set di caratteri tranne ASCII originale a 7 bit. C99 §7.4 / 1. che non sorprende me che è stato upvoted per la somma di 71 voti, ormai, nonostante sia molto un cattivo consiglio.
Saluti e hth. - Alf

16
Giusto per ripetere, il codice in questa risposta passa valori negativi (diversi da EOF) a isspace, per tutti i caratteri non ASCII, con la scelta predefinita di firma per char. Quindi ha un comportamento indefinito . Lo ripeto perché sospetto un tentativo deliberato di annegare questo fatto nel rumore.
Saluti e hth. - Alf,

100
std::string::iterator end_pos = std::remove(str.begin(), str.end(), ' ');
str.erase(end_pos, str.end());

31
Il mio voto per il canonico cancella / rimuovi idioma. Può essere trasformato in una riga: str.erase (std :: remove (str.begin (), str.end (), ''), str.end ());
Bklyn,

11
Nota: è necessario includere <algorithm>per farlo funzionare.
Tara,

37

Da gamedev

string.erase(std::remove_if(string.begin(), string.end(), std::isspace), string.end());

22
Questo non verrà compilato su implementazioni conformi agli standard a causa dei sovraccarichi di std :: isspace che richiedono le impostazioni locali. Dovrai usare :: isspace o eseguire alcune macchinazioni illeggibili con std :: bind2nd. Il codice generico non è bello?
Bklyn,

Si noti inoltre che se uno qualsiasi dei caratteri è negativo (ad esempio un carattere UTF8 quando il carattere è firmato), l'uso di ::isspaceè UB.
Martin Bonner supporta Monica il

30

Puoi usare Boost String Algo? http://www.boost.org/doc/libs/1_35_0/doc/html/string_algo/usage.html#id1290573

erase_all(str, " "); 

3
È più lento di remove_if(str.begin(), str.end(), isspace);quello menzionato da Matt Price. Non so perché. In realtà, tutte le cose boost, che hanno alternative STL, sono più lente di quelle corrispondenti gcc (tutte quelle che ho testato). Alcuni di loro sono immensamente più lenti! (fino a 5 volte negli inserti unordered_map) Forse è a causa della cache della CPU dell'ambiente condiviso o qualcosa del genere.
Etherealone,

16

Per tagliare, utilizzare gli algoritmi di stringa di boost :

#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;

// ...

string str1(" hello world! ");
trim(str1);      // str1 == "hello world!"

15

È possibile utilizzare questa soluzione per rimuovere un carattere:

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

str.erase(remove(str.begin(), str.end(), char_to_remove), str.end());

1
#include <string.h> usando namespace std;
slackmart,

Questa soluzione è corretta per me. Quello in alto non lo è.
Jason Liu,

1
l'uso dello spazio dei nomi std dovrebbe essere evitato. stackoverflow.com/questions/1452721/…
infinitezero

12

Ciao, puoi fare qualcosa del genere. Questa funzione cancella tutti gli spazi.

string delSpaces(string &str) 
{
   str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
   return str;
}

Ho fatto un'altra funzione, che cancella tutti gli spazi non necessari.

string delUnnecessary(string &str)
{
    int size = str.length();
    for(int j = 0; j<=size; j++)
    {
        for(int i = 0; i <=j; i++)
        {
            if(str[i] == ' ' && str[i+1] == ' ')
            {
                str.erase(str.begin() + i);
            }
            else if(str[0]== ' ')
            {
                str.erase(str.begin());
            }
            else if(str[i] == '\0' && str[i-1]== ' ')
            {
                str.erase(str.end() - 1);
            }
        }
    }
    return str;
}

8
string replaceinString(std::string str, std::string tofind, std::string toreplace)
{
        size_t position = 0;
        for ( position = str.find(tofind); position != std::string::npos; position = str.find(tofind,position) )
        {
                str.replace(position ,1, toreplace);
        }
        return(str);
}

usalo:

string replace = replaceinString(thisstring, " ", "%20");
string replace2 = replaceinString(thisstring, " ", "-");
string replace3 = replaceinString(thisstring, " ", "+");

7

Se vuoi farlo con una macro semplice, eccone una:

#define REMOVE_SPACES(x) x.erase(std::remove(x.begin(), x.end(), ' '), x.end())

Questo presuppone che tu l'abbia fatto #include <string>ovviamente.

Chiamalo così:

std::string sName = " Example Name ";
REMOVE_SPACES(sName);
printf("%s",sName.c_str()); // requires #include <stdio.h>

5
perché dovresti usare una macro per questo?
dani,

1
Meno digitazioni da tastiera per un'attività comune.
Volomike,

3
Altrettanto abbreviato per il sito di chiamata sta chiamando una funzione che prende un riferimento lvalue a una stringa. Le macro possono avere comportamenti sorprendenti interagendo con i loro argomenti (specialmente con effetti collaterali), ma peggio ancora, se sono coinvolti in un errore, i loro nomi non vengono visualizzati nei messaggi del compilatore, la loro implementazione sì.
Chris Uzdavinis,

2

Ho usato a lungo il lavoro di seguito - non sono sicuro della sua complessità.

s.erase(std::unique(s.begin(),s.end(),[](char s,char f){return (f==' '||s==' ');}),s.end());

quando vuoi rimuovere il personaggio ' 'e alcuni ad esempio lo - usano

s.erase(std::unique(s.begin(),s.end(),[](char s,char f){return ((f==' '||s==' ')||(f=='-'||s=='-'));}),s.end());

allo stesso modo aumenta solo il ||numero di caratteri che vuoi rimuovere non è 1

ma, come detto da altri, anche la cancellazione rimuove il linguaggio sembra a posto.


1
string removeSpaces(string word) {
    string newWord;
    for (int i = 0; i < word.length(); i++) {
        if (word[i] != ' ') {
            newWord += word[i];
        }
    }

    return newWord;
}

Questo codice fondamentalmente prende una stringa e scorre attraverso ogni carattere in essa contenuto. Quindi controlla se quella stringa è uno spazio bianco, in caso contrario il carattere viene aggiunto a una nuova stringa.


1
   #include <algorithm>
   using namespace std;

   int main() {
       .
       .
       s.erase( remove( s.begin(), s.end(), ' ' ), s.end() );
       .
       .
   }

Fonte:

Riferimento tratto da questo forum.


1
Questo in realtà non aggiunge altro che questa risposta già. C'è più spiegazione o dettaglio che potresti aggiungere per rendere la tua risposta di qualità più alta e vale la pena continuare con questa domanda?
Das_Geek,

Penso che sia più semplice , perché fa la stessa cosa in una frase.
Giovanni,

2
Grande! Quindi inserisci questo ragionamento come una spiegazione direttamente nella tua risposta . La domanda originale ha più di undici anni e senza una giustificazione la tua risposta potrebbe essere vista come un rumore rispetto alle altre risposte accettate e ben votate. Avere quella spiegazione ti aiuterà a non rimuovere la tua risposta.
Das_Geek,

Sarebbe bene , ma non ho potuto ottenere che come dovrei mettere che nella mia risposta ... che la mia risposta è meglio di questa risposta . ? Sarebbe un grande piacere se potessi modificare la mia risposta.
Giovanni,

2
Sfortunatamente, modificare la tua risposta per aggiungere quel contenuto da solo andrebbe contro le linee guida di modifica e la mia modifica verrebbe probabilmente rifiutata o annullata in seguito. Puoi utilizzare il primo link in questo commento per modificare tu stesso la risposta. È del tutto accettabile affermare che ritieni che la tua risposta sia migliore di qualcun altro e fornirti una giustificazione. La community deciderà se hai ragione votando o ridimensionando.
Das_Geek,

0

In C ++ 20 puoi usare la funzione gratuita std :: erase

std::string str = " Hello World  !";
std::erase(str, ' ');

Esempio completo:

#include<string>
#include<iostream>

int main() {
    std::string str = " Hello World  !";
    std::erase(str, ' ');
    std::cout << "|" << str <<"|";
}

Stampo | quindi è ovvio che anche lo spazio all'inizio è rimosso.

nota: questo rimuove solo lo spazio, non tutti gli altri possibili caratteri che possono essere considerati spazi bianchi, vedere https://en.cppreference.com/w/cpp/string/byte/isspace


0

Rimuove tutti i caratteri di spazi bianchi come schede e interruzioni di riga (C ++ 11):

string str = " \n AB cd \t efg\v\n";
str = regex_replace(str,regex("\\s"),"");

Perché consiglieresti questo approccio rispetto alla risposta accettata di @ Matt-Price di oltre un decennio fa?
Jeremy Caney,

Lascia che tutte le soluzioni siano presentate qui. Forse qualcuno avrà bisogno di questa soluzione.
AnselmRu,

Non sto discutendo contro questo. Sto dicendo che è più facile per le persone valutare diversi approcci spiegando le differenze e gli scenari per i quali potrebbero essere più adatti.
Jeremy Caney,

1
Probabilmente questa soluzione non è la più economica, ma ti consente di sbarazzarti di tutti i caratteri degli spazi bianchi , non solo degli spazi.
AnselmRu,

0
  string str = "2C F4 32 3C B9 DE";
  str.erase(remove(str.begin(),str.end(),' '),str.end());
  cout << str << endl;

uscita: 2CF4323CB9DE


-1
string removespace(string str)
{    
    int m = str.length();
    int i=0;
    while(i<m)
    {
        while(str[i] == 32)
        str.erase(i,1);
        i++;
    }    
}

3
In genere si preferisce aggiungere una breve spiegazione alle risposte del codice.
arcyqwerty,

1
@test: length()restituisce a size_t, non an int. erase()prende un size_type, non un int. La funzione probabilmente fallirà se si incontrano due spazi consecutivi poiché l'indice è sempre incrementato. Se uno spazio viene rimosso, il ciclo leggerà oltre i limiti della stringa. Probabilmente dovresti eliminare questa risposta poiché ha bisogno di molto aiuto.
jww

-3

Temo sia la migliore soluzione che mi venga in mente. Ma puoi usare reserve () per pre-allocare la memoria minima richiesta in anticipo per velocizzare un po 'le cose. Ti ritroverai con una nuova stringa che sarà probabilmente più corta ma che occuperà la stessa quantità di memoria, ma eviterai le riallocazioni.

MODIFICA: A seconda della situazione, ciò potrebbe comportare meno costi generali dei personaggi confusi.

Dovresti provare approcci diversi e vedere cosa è meglio per te: potresti non avere alcun problema di prestazioni.


remove_if crea al massimo una copia di ciascun valore. Quindi non c'è davvero molto overhead rispetto a ciò che deve essere fatto.
Matt Price,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.