J'utilise actuellement le code suivant pour couper à droite tous les std::strings
programmes:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
Cela fonctionne bien, mais je me demande s'il y a des cas finaux où cela pourrait échouer?
Bien sûr, les réponses avec des alternatives élégantes et une solution de garniture gauche sont les bienvenues.
std::string
classe, alors que ce sont des fonctions comme celles-ci qui rendent les autres langages si agréables à utiliser (Python par exemple).Réponses:
EDIT Depuis c ++ 17, certaines parties de la bibliothèque standard ont été supprimées. Heureusement, à partir de c ++ 11, nous avons des lambdas qui sont une solution supérieure.
Merci à https://stackoverflow.com/a/44973498/524503 pour avoir mis en place la solution moderne.
Réponse originale:
J'ai tendance à utiliser l'un de ces 3 pour mes besoins de coupe:
Ils sont assez explicites et fonctionnent très bien.
EDIT : BTW, j'ai
std::ptr_fun
là pour aider à lever l'ambiguïtéstd::isspace
car il existe en fait une deuxième définition qui prend en charge les paramètres régionaux. Cela aurait pu être un casting tout de même, mais j'ai tendance à aimer ça mieux.EDIT : Pour répondre à certains commentaires concernant l'acceptation d'un paramètre par référence, sa modification et son retour. Je suis d'accord. Une implémentation que je préférerais probablement serait deux ensembles de fonctions, une pour en place et une qui fait une copie. Un meilleur ensemble d'exemples serait:
Je garde cependant la réponse originale ci-dessus pour le contexte et dans l'intérêt de garder la réponse à vote élevé toujours disponible.
la source
boost::trim
pour résoudre le problème.L'utilisation des algorithmes de chaîne de Boost serait plus simple:
str
est maintenant"hello world!"
. Il y a aussitrim_left
ettrim
, qui coupe les deux côtés.Si vous ajoutez un
_copy
suffixe à l'un des noms de fonction ci-dessustrim_copy
, par exemple , la fonction renverra une copie tronquée de la chaîne au lieu de la modifier via une référence.Si vous ajoutez un
_if
suffixe à l'un des noms de fonctions ci-dessustrim_copy_if
, par exemple , vous pouvez supprimer tous les caractères satisfaisant votre prédicat personnalisé, par opposition aux seuls espaces blancs.la source
Utilisez le code suivant pour couper les espaces et les tabulations à droite de
std::strings
( ideone ):Et juste pour équilibrer les choses, je vais aussi inclure le code de garniture gauche ( ideone ):
la source
str.substr(...).swap(str)
est mieux. Enregistrez une affectation.basic_string& operator= (basic_string&& str) noexcept;
?Ce que vous faites est bien et robuste. J'utilise la même méthode depuis longtemps et je n'ai pas encore trouvé de méthode plus rapide:
En fournissant les caractères à rogner, vous avez la possibilité de rogner les caractères non blancs et l'efficacité de rogner uniquement les caractères que vous souhaitez rogner.
la source
trim
, c'est- à -dire que vous la rendezrtrim(ltrim(s, t), t)
un peu plus efficaceUn peu tard pour la fête, mais tant pis. Maintenant C ++ 11 est là, nous avons des lambdas et des variables automatiques. Donc, ma version, qui gère également les espaces vides et les chaînes vides, est la suivante:
Nous pourrions créer un itérateur inversé à partir de
wsfront
et l'utiliser comme condition de terminaison dans le second,find_if_not
mais cela n'est utile que dans le cas d'une chaîne entièrement blanche, et gcc 4.8 au moins n'est pas assez intelligent pour déduire le type de l'itérateur inversé (std::string::const_reverse_iterator
) avecauto
. Je ne sais pas combien coûte la construction d'un itérateur inversé, alors YMMV ici. Avec cette modification, le code ressemble à ceci:la source
std::isspace
:auto wsfront=std::find_if_not(s.begin(),s.end(),std::isspace);
candidate template ignored: couldn't infer template argument '_Predicate' find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred)
Essayez ça, ça marche pour moi.
la source
str.find_last_not_of(x)
renvoie la position du premier caractère différent de x. Il ne renvoie npos que si aucun caractère ne correspond à x. Dans l'exemple, s'il n'y a pas d'espace suffixant, il retournera l'équivalent destr.length() - 1
, ce qui donnera essentiellementstr.erase((str.length() - 1) + 1).
C'est-à-dire, sauf si je me trompe terriblement.std::string&
.J'aime la solution de tzaman, le seul problème est qu'elle ne coupe pas une chaîne contenant uniquement des espaces.
Pour corriger ce défaut, ajoutez un str.clear () entre les 2 lignes de coupe
la source
ltrim
ourtrim
comme ça.std::stringstream
.http://ideone.com/nFVtEo
la source
it
) et inverse: position du caractère après laquelle il n'y a que des espaces (rit
) - après cela, il retourne une chaîne nouvellement créée == une copie de la partie de la chaîne d'origine - une partie basée sur ces itérateurs ...Dans le cas d'une chaîne vide, votre code suppose que l'ajout de 1 à
string::npos
0 donnestring::npos
est de typestring::size_type
, qui n'est pas signé. Ainsi, vous comptez sur le comportement de dépassement de l'addition.la source
1
àstd::string::npos
doit donner0
selon leC++ Standard
. C'est donc une bonne hypothèse sur laquelle on peut absolument compter.Piraté de Cplusplus.com
Cela fonctionne également pour le cas nul. :-)
la source
rtrim
, pasltrim
Avec C ++ 17, vous pouvez utiliser basic_string_view :: remove_prefix et basic_string_view :: remove_suffix :
Une belle alternative:
la source
Ma solution basée sur la réponse de @Bill the Lizard .
Notez que ces fonctions renverront la chaîne vide si la chaîne d'entrée ne contient que des espaces.
la source
Ma réponse est une amélioration par rapport à la première réponse de ce post qui coupe les caractères de contrôle ainsi que les espaces (0-32 et 127 sur la table ASCII ).
std::isgraph
détermine si un caractère a une représentation graphique, vous pouvez donc l'utiliser pour modifier la réponse d'Evan pour supprimer tout caractère qui n'a pas de représentation graphique de chaque côté d'une chaîne. Le résultat est une solution beaucoup plus élégante:Remarque: Alternativement, vous devriez pouvoir utiliser
std::iswgraph
si vous avez besoin de prise en charge des caractères larges, mais vous devrez également modifier ce code pour permettre lastd::wstring
manipulation, ce que je n'ai pas testé (voir la page de référence pourstd::basic_string
explorer cette option) .la source
Avec C ++ 11 est également venu un module d' expression régulière , qui peut bien sûr être utilisé pour couper les espaces de début ou de fin.
Peut-être quelque chose comme ça:
la source
C'est ce que j'utilise. Continuez à retirer de l'espace à l'avant, puis, s'il reste quelque chose, faites de même à l'arrière.
la source
la source
Pour ce que ça vaut, voici une implémentation de finition avec un œil sur les performances. C'est beaucoup plus rapide que beaucoup d'autres routines de trim que j'ai vues. Au lieu d'utiliser des itérateurs et std :: find, il utilise des chaînes et des index C bruts. Il optimise les cas spéciaux suivants: chaîne de taille 0 (ne rien faire), chaîne sans espace à découper (ne rien faire), chaîne avec uniquement des espaces à droite à découper (juste redimensionner la chaîne), chaîne entièrement blanche (simplement effacer la chaîne) . Et enfin, dans le pire des cas (chaîne avec espace blanc de tête), il fait de son mieux pour effectuer une construction de copie efficace, en effectuant une seule copie, puis en déplaçant cette copie à la place de la chaîne d'origine.
la source
Une manière élégante de le faire peut être comme
Et les fonctions de support sont implémentées comme:
Et une fois que tout cela est en place, vous pouvez également écrire ceci:
la source
Mettre en œuvre l'implémentation C ++ 11:
la source
Je suppose que si vous commencez à demander la "meilleure façon" de couper une chaîne, je dirais qu'une bonne implémentation serait celle qui:
De toute évidence, il existe trop de façons différentes d'aborder cela et cela dépend certainement de ce dont vous avez réellement besoin. Cependant, la bibliothèque standard C a encore quelques fonctions très utiles dans <string.h>, comme memchr. Il y a une raison pour laquelle C est toujours considéré comme le meilleur langage pour IO - son stdlib est une pure efficacité.
la source
Je ne sais pas si votre environnement est le même, mais dans le mien, le cas de chaîne vide entraînera l'abandon du programme. J'envelopperais cet appel d'effacement avec un if (! S.empty ()) ou j'utiliserais Boost comme déjà mentionné.
la source
Voici ce que j'ai trouvé:
L'extraction de flux élimine automatiquement les espaces blancs, donc cela fonctionne comme un charme.
Assez propre et élégant aussi, si je le dis moi-même. ;)
la source
Contribuer ma solution au bruit.
trim
par défaut, la création d'une nouvelle chaîne et le retour de la chaîne modifiée tout entrim_in_place
modifient la chaîne qui lui est transmise. Latrim
fonction prend en charge la sémantique de déplacement c ++ 11.la source
Cela peut être fait plus simplement en C ++ 11 grâce à l'ajout de
back()
etpop_back()
.la source
Voici ma version:
la source
Les méthodes ci-dessus sont excellentes, mais vous souhaitez parfois utiliser une combinaison de fonctions pour ce que votre routine considère comme un espace. Dans ce cas, l'utilisation de foncteurs pour combiner des opérations peut devenir compliquée, je préfère donc une boucle simple que je peux modifier pour le trim. Voici une fonction de trim légèrement modifiée copiée de la version C ici sur SO. Dans cet exemple, je coupe des caractères non alphanumériques.
la source
Voici une implémentation simple. Pour une opération aussi simple, vous ne devriez probablement pas utiliser de constructions spéciales. La fonction intégrée isspace () prend en charge diverses formes de caractères blancs, nous devons donc en profiter. Vous devez également prendre en compte des cas particuliers où la chaîne est vide ou simplement un tas d'espaces. Le trim à gauche ou à droite peut être dérivé du code suivant.
la source
Voici une solution facile à comprendre pour les débutants qui n'ont pas l'habitude d'écrire
std::
partout et qui ne sont pas encore familiarisés avecconst
-correctness,iterator
s, STLalgorithm
s, etc ...J'espère que cela aide...
la source
Cette version réduit les espaces internes et les caractères non alphanumériques:
la source
Encore une autre option - supprime un ou plusieurs caractères des deux extrémités.
la source