2009-09-28 22 views

risposta

78
#include <algorithm> 
#include <string> 

std::string str; 

str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); 

Il comportamento di std :: remove potrebbe non essere del tutto ciò che vi aspettereste. Vedere una spiegazione di esso here.

+3

Se c'è qualche possibilità di newline da altre piattaforme, forse cancella anche i caratteri '\ r'. Una seconda chiamata per cancellare e std :: remove etc non rappresenta un grosso vantaggio per quanto riguarda le prestazioni. Le alternative, come l'uso di std :: remove_if con una funzione di predicato, saranno probabilmente più lente. – Steve314

+0

Se i tuoi dati sono stati originariamente caricati da un file aperto in modalità testo (ascii, non binario) credo che converta automaticamente tutte le convenzioni di nuova riga in un semplice '\ n'. Sto cercando un riferimento definitivo a corroborare. – luke

+0

http://msdn.microsoft.com/en-us/library/kt0etdcs%28VS.71%29.aspx - thats per fread(), ma credo che iostream letture e scritture abbiano lo stesso comportamento. – luke

0

Se è ovunque nella stringa di quanto tu non possa fare meglio di O (n).

E l'unico modo è cercare '\ n' nella stringa e cancellarlo.

for(int i=0;i<s.length();i++) if(s[i]=='\n') s.erase(s.begin()+i); 

Per maggiori ritorni a capo di:

int n=0; 
for(int i=0;i<s.length();i++){ 
    if(s[i]=='\n'){ 
     n++;//we increase the number of newlines we have found so far 
    }else{ 
     s[i-n]=s[i]; 
    } 
} 
s.resize(s.length()-n);//to delete only once the last n elements witch are now newlines 

cancella tutti i ritorni a capo una volta.

+1

Questa implementazione non gestirà correttamente i newline consecutivi, poiché 'i' viene incrementato indipendentemente dal fatto che un elemento sia cancellato. –

+0

Ho appena notato, modifico questa – csiz

5

Se la nuova linea dovrebbe essere alla fine della stringa, quindi:

if (!s.empty() && s[s.length()-1] == '\n') { 
    s.erase(s.length()-1); 
} 

Se la stringa può contenere molti ritorni a capo in qualsiasi punto della stringa:

std::string::size_type i = 0; 
while (i < s.length()) { 
    i = s.find('\n', i); 
    if (i == std::string:npos) { 
     break; 
    } 
    s.erase(i); 
} 
+2

Prima versione perfetta. Seconda versione sarebbe più facile da usare std :: erase (std :: removr (XXX)) –

+0

Non mi sono mai sentito molto a mio agio con la semantica di remove() e devo sempre cercare perché non è ovvio. La mia implementazione sopra è semplice e diretta, ma non la più efficiente. Se l'efficienza è importante, è necessaria una soluzione leggermente diversa. –

+1

la domanda era "qual è il modo più efficiente ...", quindi immagino che l'efficienza sia importante;) – Pieter

6

si dovrebbe usare il erase-remove idiom, cercando '\n'. Questo funzionerà per qualsiasi contenitore di sequenze standard; non solo string.

1
s.erase(std::remove(s.begin(), s.end(), '\n'), s.end()); 
1

Il codice rimuove tutte newline dalla stringa str.

O (N) implementazione migliore senza commenti su SO e con commenti in produzione.

unsigned shift=0; 
for (unsigned i=0; i<length(str); ++i){ 
    if (str[i] == '\n') { 
     ++shift; 
    }else{ 
     str[i-shift] = str[i]; 
    } 
} 
str.resize(str.length() - shift); 
0
std::string some_str = SOME_VAL; 
if (some_str.size() > 0 && some_str[some_str.length()-1] == '\n') 
    some_str.resize(some_str.length()-1); 

o (rimuove diverse a capo alla fine)

some_str.resize(some_str.find_last_not_of(L"\n")+1); 
-1

Tutte queste risposte sembrano un po 'pesante per me.

Se togli semplicemente il "\ n" e sposta tutto il resto in un punto, è probabile che alcuni personaggi vengano sbattuti insieme in un modo strano. Quindi, perché non fare la semplice (e più efficiente) cosa: Sostituisci tutti \ n con gli spazi?

for (int i = 0; i < str.length();i++) { 
    if (str[i] == '\n') { 
     str[i] = ' '; 
    } 
} 

Ci possono essere modi per migliorare la velocità di questo ai bordi, ma sarà modo più veloce di muoversi intere porzioni della stringa intorno in memoria.

4

Ecco uno per DOS o Unix nuova linea:

void chomp(string &s) 
    { 
      int pos; 
      if((pos=s.find('\n')) != string::npos) 
        s.erase(pos); 
    } 
+1

Cambia il ciclo' if' in un 'while' e hai una soluzione piuttosto buona. – CaptainBli

1

Un altro modo per farlo nel ciclo for

void rm_nl(string &s) { 
    for (int p = s.find("\n"); p != (int) string::npos; p = s.find("\n")) 
    s.erase(p,1); 
} 

Usage:

string data = "\naaa\nbbb\nccc\nddd\n"; 
rm_nl(data); 
cout << data; // data = aaabbbcccddd 
0

su RISPOSTA 3 rimuovendo solo l'ultimo \ n codice stringa off:

if (!s.empty() && s[s.length()-1] == '\n') { 
    s.erase(s.length()-1); 
} 

La condizione if non fallirà se la stringa è veramente vuota?

Non è meglio fare:

if (!s.empty()) 
{ 
    if (s[s.length()-1] == '\n') 
     s.erase(s.length()-1); 
} 
Problemi correlati