2009-09-28 7 views

Répondre

78
#include <algorithm> 
#include <string> 

std::string str; 

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

Le comportement de std :: remove ne peut pas être tout à fait ce que vous attendez. Voir une explication here.

+3

S'il y a une chance de nouvelles lignes d'autres plates-formes, peut-être supprimer les caractères '\ r' aussi. Un deuxième appel à effacer et std :: remove etc n'est pas un gros problème de performance. Les alternatives, telles que l'utilisation de std :: remove_if avec une fonction de prédicat, seront probablement plus lentes. – Steve314

+0

Si vos données ont été chargées à partir d'un fichier ouvert en mode texte (ascii, non-binaire), je crois qu'il convertit automatiquement toutes les conventions de nouvelle ligne en un simple «\ n». Je cherche une référence définitive pour corroborer. – luke

+0

http://msdn.microsoft.com/en-us/library/kt0etdcs%28VS.71%29.aspx - c'est pour fread(), mais je crois que les lectures et les écritures d'iostream ont le même comportement. – luke

0

Si c'est n'importe où dans la chaîne que vous ne pouvez pas faire mieux que O (n).

Et le seul moyen est de rechercher '\ n' dans la chaîne et de l'effacer.

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

Pour plus que les nouvelles lignes:

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 

Il efface tous les sauts de ligne une fois.

+1

Cette implémentation ne gérera pas correctement les retours à la ligne consécutifs, puisque 'i' est incrémenté indépendamment du fait qu'un élément soit effacé. –

+0

Je viens de remarquer, je vais éditer ce – csiz

5

Si la nouvelle ligne devrait être à la fin de la chaîne, puis:

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

Si la chaîne peut contenir plusieurs sauts de ligne ne importe où dans la chaîne:

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

Première version parfaite. La deuxième version serait plus facile à utiliser std :: erase (std :: removr (XXX)) –

+0

Je n'ai jamais été très à l'aise avec la sémantique de remove() et je dois toujours la rechercher parce que ce n'est pas évident. Ma mise en œuvre ci-dessus est simple et directe, mais pas la plus efficace. Si l'efficacité est importante, une solution légèrement différente est nécessaire. –

+1

la question était, "quel est le moyen le plus efficace ...", donc je suppose que l'efficacité est importante;) – Pieter

6

Vous devez utiliser la erase-remove idiom, à la recherche de '\n'. Cela fonctionnera pour n'importe quel conteneur de séquence standard; pas seulement string.

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

Le code supprime tous la chaîne de nouvelles lignes str.

O (N) implémentation mieux servi sans commentaires sur SO et avec commentaires en production.

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

ou (supprime plusieurs sauts de ligne à la fin)

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

Toutes ces réponses semblent un peu lourd pour moi.

Si vous supprimez simplement le '\ n' et déplacez tout le reste, vous risquez d'avoir des personnages claqués ensemble d'une manière bizarre. Alors pourquoi ne pas simplement faire la chose la plus simple (et la plus efficace): Remplacer tous les \ n par des espaces?

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

Il peut y avoir des moyens d'améliorer la vitesse de ce sur les bords, mais il sera beaucoup plus rapide que des morceaux entiers de déplacer la chaîne autour de la mémoire.

4

Voici un pour la nouvelle ligne DOS ou Unix:

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

Changez le' if' en boucle while et vous avez une bonne solution. – CaptainBli

1

Une autre façon de le faire dans la boucle

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

Utilisation:

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

A propos de réponse 3 supprimant uniquement le dernier code de chaîne \ n:

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

Est-ce que la condition if n'échoue pas si la chaîne est vraiment vide?

est-il pas mieux à faire:

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