J'utilise actuellement le code suivant pour redimensionner à droite tout le std::strings
dans mes programmes:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
Cela fonctionne bien, mais je me demande s’il existe des cas où cela pourrait échouer.
Bien sûr, les réponses avec des alternatives élégantes ainsi qu'une solution à gauche sont les bienvenues.
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 constituent une solution supérieure.
#include <algorithm>
#include <cctype>
#include <locale>
// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
return !std::isspace(ch);
}));
}
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
// trim from start (copying)
static inline std::string ltrim_copy(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrim_copy(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trim_copy(std::string s) {
trim(s);
return s;
}
Merci à https://stackoverflow.com/a/44973498/524503 d’avoir mis en place la solution moderne.
J'ai tendance à utiliser l'un de ces 3 pour mes besoins de coupe:
#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>
// trim from start
static inline std::string <rim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// trim from end
static inline std::string &rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// trim from both ends
static inline std::string &trim(std::string &s) {
return ltrim(rtrim(s));
}
Ils sont assez explicites et fonctionnent très bien.
EDIT: En passant, j'ai std::ptr_fun
dedans pour aider à lever l'ambiguïté std::isspace
car il y a en fait une deuxième définition qui supporte les locales. Cela aurait pu être un casting de la même façon, mais j'ai tendance à aimer ça mieux.
EDIT: Pour adresser quelques commentaires sur l'acceptation d'un paramètre par référence, sa modification et son renvoi. Je suis d'accord. Une implémentation que je préférerais probablement serait deux ensembles de fonctions, l’une pour in situ et l’autre pour la copie. Un meilleur ensemble d'exemples serait:
#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>
// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
std::not1(std::ptr_fun<int, int>(std::isspace))));
}
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
// trim from start (copying)
static inline std::string ltrim_copy(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrim_copy(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trim_copy(std::string s) {
trim(s);
return s;
}
Je garde la réponse originale ci-dessus, bien que pour le contexte et dans l’intérêt de garder la réponse avec vote élevé encore disponible.
Utiliser les algorithmes de chaîne de Boost serait le plus simple:
#include <boost/algorithm/string.hpp>
std::string str("hello world! ");
boost::trim_right(str);
str
est maintenant "hello world!"
. Il y a aussi trim_left
et trim
, qui coupe les deux côtés.
Si vous ajoutez le suffixe _copy
à l’un des noms de fonction ci-dessus, par exemple: trim_copy
, la fonction retournera une copie découpée de la chaîne au lieu de la modifier via une référence.
Si vous ajoutez le suffixe _if
à l’un des noms de fonction ci-dessus, par exemple: trim_copy_if
, vous pouvez supprimer tous les caractères correspondant à votre prédicat personnalisé, par opposition aux espaces.
Utilisez le code suivant pour découper à droite les espaces et les caractères de tabulation à partir de std::strings
( ideone ):
// trim trailing spaces
size_t endpos = str.find_last_not_of(" \t");
size_t startpos = str.find_first_not_of(" \t");
if( std::string::npos != endpos )
{
str = str.substr( 0, endpos+1 );
str = str.substr( startpos );
}
else {
str.erase(std::remove(std::begin(str), std::end(str), ' '), std::end(str));
}
Et juste pour équilibrer les choses, j'inclurai aussi le code de rognage de gauche ( ideone ):
// trim leading spaces
size_t startpos = str.find_first_not_of(" \t");
if( string::npos != startpos )
{
str = str.substr( startpos );
}
Peu en retard à la fête, mais peu importe. Maintenant que C++ 11 est arrivé, nous avons lambdas et auto variables. Ainsi, ma version, qui gère également les chaînes entièrement blanches et vides, est la suivante:
#include <cctype>
#include <string>
#include <algorithm>
inline std::string trim(const std::string &s)
{
auto wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
auto wsback=std::find_if_not(s.rbegin(),s.rend(),[](int c){return std::isspace(c);}).base();
return (wsback<=wsfront ? std::string() : std::string(wsfront,wsback));
}
Nous pourrions créer un itérateur inverse à 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 contenant uniquement des espaces, et gcc 4.8 au moins n'est pas assez intelligent pour déduire le type de l'inverse. itérateur (std::string::const_reverse_iterator
) avec auto
. Je ne sais pas combien coûte la construction d'un itérateur inversé, donc YMMV ici. Avec cette modification, le code ressemble à ceci:
inline std::string trim(const std::string &s)
{
auto wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
return std::string(wsfront,std::find_if_not(s.rbegin(),std::string::const_reverse_iterator(wsfront),[](int c){return std::isspace(c);}).base());
}
Ce que vous faites est bien et robuste. J'ai utilisé la même méthode depuis longtemps et je n'ai pas encore trouvé de méthode plus rapide:
const char* ws = " \t\n\r\f\v";
// trim from end of string (right)
inline std::string& rtrim(std::string& s, const char* t = ws)
{
s.erase(s.find_last_not_of(t) + 1);
return s;
}
// trim from beginning of string (left)
inline std::string& ltrim(std::string& s, const char* t = ws)
{
s.erase(0, s.find_first_not_of(t));
return s;
}
// trim from both ends of string (right then left)
inline std::string& trim(std::string& s, const char* t = ws)
{
return ltrim(rtrim(s, t), t);
}
En fournissant les caractères à découper, vous avez la possibilité de supprimer les caractères non blancs et l'efficacité de supprimer uniquement les caractères souhaités.
Essayez ceci, ça marche pour moi.
inline std::string trim(std::string& str)
{
str.erase(0, str.find_first_not_of(' ')); //prefixing spaces
str.erase(str.find_last_not_of(' ')+1); //surfixing spaces
return str;
}
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 cette faille, ajoutez un str.clear () entre les 2 lignes de trimmer
std::stringstream trimmer;
trimmer << str;
str.clear();
trimmer >> str;
std::string trim(const std::string &s)
{
std::string::const_iterator it = s.begin();
while (it != s.end() && isspace(*it))
it++;
std::string::const_reverse_iterator rit = s.rbegin();
while (rit.base() != it && isspace(*rit))
rit++;
return std::string(it, rit.base());
}
Dans le cas d'une chaîne vide, votre code suppose que l'ajout de 1 à string::npos
donne 0. string::npos
est du type string::size_type
, qui n'est pas signé. Ainsi, vous vous appuyez sur le comportement de débordement de l'addition.
Caché de Cplusplus.com
std::string choppa(const std::string &t, const std::string &ws)
{
std::string str = t;
size_t found;
found = str.find_last_not_of(ws);
if (found != std::string::npos)
str.erase(found+1);
else
str.clear(); // str is all whitespace
return str;
}
Cela fonctionne aussi pour le cas nul. :-)
Ma solution basée sur le répondre par @Bill the Lizard .
Notez que ces fonctions renverront la chaîne vide si la chaîne d'entrée ne contient que des espaces.
const std::string StringUtils::WHITESPACE = " \n\r\t";
std::string StringUtils::Trim(const std::string& s)
{
return TrimRight(TrimLeft(s));
}
std::string StringUtils::TrimLeft(const std::string& s)
{
size_t startpos = s.find_first_not_of(StringUtils::WHITESPACE);
return (startpos == std::string::npos) ? "" : s.substr(startpos);
}
std::string StringUtils::TrimRight(const std::string& s)
{
size_t endpos = s.find_last_not_of(StringUtils::WHITESPACE);
return (endpos == std::string::npos) ? "" : s.substr(0, endpos+1);
}
Ma réponse est une amélioration par rapport à top answer pour ce message qui supprime 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 afin de supprimer tout caractère qui n'a pas de représentation graphique d'un côté ou de l'autre de la chaîne. Le résultat est une solution beaucoup plus élégante:
#include <algorithm>
#include <functional>
#include <string>
/**
* @brief Left Trim
*
* Trims whitespace from the left end of the provided std::string
*
* @param[out] s The std::string to trim
*
* @return The modified std::string&
*/
std::string& ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
std::ptr_fun<int, int>(std::isgraph)));
return s;
}
/**
* @brief Right Trim
*
* Trims whitespace from the right end of the provided std::string
*
* @param[out] s The std::string to trim
*
* @return The modified std::string&
*/
std::string& rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::ptr_fun<int, int>(std::isgraph)).base(), s.end());
return s;
}
/**
* @brief Trim
*
* Trims whitespace from both ends of the provided std::string
*
* @param[out] s The std::string to trim
*
* @return The modified std::string&
*/
std::string& trim(std::string& s) {
return ltrim(rtrim(s));
}
Remarque: Vous devriez également pouvoir utiliser std::iswgraph
si vous avez besoin de la prise en charge des caractères larges, mais vous devrez également éditer ce code pour activer la manipulation std::wstring
, ce que je n’ai pas encore testé voir la page de référence pour std::basic_string
pour explorer cette option).
C'est ce que j'utilise. Continuez simplement à supprimer l’espace à l’avant, puis, s’il reste quelque chose, faites de même à l’arrière.
void trim(string& s) {
while(s.compare(0,1," ")==0)
s.erase(s.begin()); // remove leading whitespaces
while(s.size()>0 && s.compare(s.size()-1,1," ")==0)
s.erase(s.end()-1); // remove trailing whitespaces
}
Pour ce que cela vaut, voici une mise en œuvre soignée orientée vers la performance. C'est beaucoup plus rapide que beaucoup d'autres routines de trim que j'ai vues autour de moi. Au lieu d'utiliser iterators et std :: find, il utilise des chaînes c et des index bruts. Il optimise les cas particuliers suivants: chaîne de taille 0 (ne rien faire), chaîne sans espace à couper (ne rien faire), chaîne avec uniquement des espaces de fin à couper (il suffit de redimensionner la chaîne), chaîne entièrement blanche (tout effacer) . Et enfin, dans le pire des cas (chaîne avec des espaces de début), 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.
void TrimString(std::string & str)
{
if(str.empty())
return;
const auto pStr = str.c_str();
size_t front = 0;
while(front < str.length() && std::isspace(int(pStr[front]))) {++front;}
size_t back = str.length();
while(back > front && std::isspace(int(pStr[back-1]))) {--back;}
if(0 == front)
{
if(back < str.length())
{
str.resize(back - front);
}
}
else if(back <= front)
{
str.clear();
}
else
{
str = std::move(std::string(str.begin()+front, str.begin()+back));
}
}
s.erase(0, s.find_first_not_of(" \n\r\t"));
s.erase(s.find_last_not_of(" \n\r\t")+1);
C++ 11 est également venu avec un module 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:
std::string ltrim(const std::string& s)
{
static const std::regex lws{"^[[:space:]]*", std::regex_constants::extended};
return std::regex_replace(s, lws, "");
}
std::string rtrim(const std::string& s)
{
static const std::regex tws{"[[:space:]]*$", std::regex_constants::extended};
return std::regex_replace(s, tws, "");
}
std::string trim(const std::string& s)
{
return ltrim(rtrim(s));
}
Une façon élégante de le faire peut être comme
std::string & trim(std::string & str)
{
return ltrim(rtrim(str));
}
Et les fonctions de support sont implémentées comme:
std::string & ltrim(std::string & str)
{
auto it = std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
str.erase( str.begin() , it);
return str;
}
std::string & rtrim(std::string & str)
{
auto it = std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
str.erase( it.base() , str.end() );
return str;
}
Et une fois que tous ces éléments sont en place, vous pouvez également écrire ceci:
std::string trim_copy(std::string const & str)
{
auto s = str;
return ltrim(rtrim(s));
}
Trim C++ 11 implémentation:
static void trim(std::string &s) {
s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), [](char c){ return std::isspace(c); }));
s.erase(std::find_if_not(s.rbegin(), s.rend(), [](char c){ return std::isspace(c); }).base(), s.end());
}
Je suppose que si vous commencez à demander le "meilleur moyen" de couper une chaîne, je dirais une bonne implémentation serait celle qui:
Évidemment, il y a trop de manières différentes d'aborder cela, et cela dépend de ce dont vous avez réellement besoin. Cependant, la bibliothèque standard C a encore des 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 - sa stdlib est une pure efficacité.
inline const char* trim_start(const char* str)
{
while (memchr(" \t\n\r", *str, 4)) ++str;
return str;
}
inline const char* trim_end(const char* end)
{
while (memchr(" \t\n\r", end[-1], 4)) --end;
return end;
}
inline std::string trim(const char* buffer, int len) // trim a buffer (input?)
{
return std::string(trim_start(buffer), trim_end(buffer + len));
}
inline void trim_inplace(std::string& str)
{
str.assign(trim_start(str.c_str()),
trim_end(str.c_str() + str.length()));
}
int main()
{
char str [] = "\t \nhello\r \t \n";
string trimmed = trim(str, strlen(str));
cout << "'" << trimmed << "'" << endl;
system("pause");
return 0;
}
Contribuer ma solution au bruit. trim
crée par défaut une nouvelle chaîne et renvoie la chaîne modifiée pendant que trim_in_place
modifie la chaîne. La fonction trim
prend en charge la sémantique de déplacement de c ++ 11.
#include <string>
// modifies input string, returns input
std::string& trim_left_in_place(std::string& str) {
size_t i = 0;
while(i < str.size() && isspace(str[i])) { ++i; };
return str.erase(0, i);
}
std::string& trim_right_in_place(std::string& str) {
size_t i = str.size();
while(i > 0 && isspace(str[i - 1])) { --i; };
return str.erase(i, str.size());
}
std::string& trim_in_place(std::string& str) {
return trim_left_in_place(trim_right_in_place(str));
}
// returns newly created strings
std::string trim_right(std::string str) {
return trim_right_in_place(str);
}
std::string trim_left(std::string str) {
return trim_left_in_place(str);
}
std::string trim(std::string str) {
return trim_left_in_place(trim_right_in_place(str));
}
#include <cassert>
int main() {
std::string s1(" \t\r\n ");
std::string s2(" \r\nc");
std::string s3("c \t");
std::string s4(" \rc ");
assert(trim(s1) == "");
assert(trim(s2) == "c");
assert(trim(s3) == "c");
assert(trim(s4) == "c");
assert(s1 == " \t\r\n ");
assert(s2 == " \r\nc");
assert(s3 == "c \t");
assert(s4 == " \rc ");
assert(trim_in_place(s1) == "");
assert(trim_in_place(s2) == "c");
assert(trim_in_place(s3) == "c");
assert(trim_in_place(s4) == "c");
assert(s1 == "");
assert(s2 == "c");
assert(s3 == "c");
assert(s4 == "c");
}
Je ne sais pas si votre environnement est le même, mais dans le mien, la casse de chaîne vide entraînera l'abandon du programme. Je voudrais soit envelopper cet appel d'effacement avec un if (! S.empty ()), soit utiliser Boost comme déjà mentionné.
Voici ce que je suis venu avec:
std::stringstream trimmer;
trimmer << str;
trimmer >> str;
L'extraction de flux élimine automatiquement les espaces, cela fonctionne donc comme un charme.
Assez propre et élégant aussi, si je le dis moi-même. ;)
Cela peut être fait plus simplement en C++ 11 grâce à l'ajout de back()
et pop_back()
.
while ( !s.empty() && isspace(s.back()) ) s.pop_back();
Voici ma version:
size_t beg = s.find_first_not_of(" \r\n");
return (beg == string::npos) ? "" : in.substr(beg, s.find_last_not_of(" \r\n") - beg);
Les méthodes ci-dessus sont excellentes, mais vous souhaitez parfois utiliser une combinaison de fonctions pour ce que votre routine considère comme des espaces. Dans ce cas, l’utilisation de foncteurs pour combiner des opérations peut devenir désordonnée, je préfère donc une boucle simple que je peux modifier pour le découpage. Voici une fonction de découpage légèrement modifiée copiée à partir de la version C ici sur SO. Dans cet exemple, je coupe les caractères non alphanumériques.
string trim(char const *str)
{
// Trim leading non-letters
while(!isalnum(*str)) str++;
// Trim trailing non-letters
end = str + strlen(str) - 1;
while(end > str && !isalnum(*end)) end--;
return string(str, end+1);
}
Cette version supprime les espaces internes et les caractères non alphanumériques:
static inline std::string &trimAll(std::string &s)
{
if(s.size() == 0)
{
return s;
}
int val = 0;
for (int cur = 0; cur < s.size(); cur++)
{
if(s[cur] != ' ' && std::isalnum(s[cur]))
{
s[val] = s[cur];
val++;
}
}
s.resize(val);
return s;
}
Encore une autre option - supprime un ou plusieurs caractères des deux côtés.
string strip(const string& s, const string& chars=" ") {
size_t begin = 0;
size_t end = s.size()-1;
for(; begin < s.size(); begin++)
if(chars.find_first_of(s[begin]) == string::npos)
break;
for(; end > begin; end--)
if(chars.find_first_of(s[end]) == string::npos)
break;
return s.substr(begin, end-begin+1);
}
Voici une solution facile à comprendre pour les débutants qui n’ont pas l'habitude d'écrire std::
partout et qui ne connaissent pas encore const
- exactitude, iterator
s, STL algorithm
s, etc ...
#include <string>
#include <cctype> // for isspace
using namespace std;
// Left trim the given string (" hello! " --> "hello! ")
string left_trim(string str) {
int numStartSpaces = 0;
for (int i = 0; i < str.length(); i++) {
if (!isspace(str[i])) break;
numStartSpaces++;
}
return str.substr(numStartSpaces);
}
// Right trim the given string (" hello! " --> " hello!")
string right_trim(string str) {
int numEndSpaces = 0;
for (int i = str.length() - 1; i >= 0; i--) {
if (!isspace(str[i])) break;
numEndSpaces++;
}
return str.substr(0, str.length() - numEndSpaces);
}
// Left and right trim the given string (" hello! " --> "hello!")
string trim(string str) {
return right_trim(left_trim(str));
}
J'espère que ça aide...
Comme je voulais mettre à jour mon ancienne fonction de découpage C++ avec une approche C++ 11, j'ai testé de nombreuses réponses postées à la question. Ma conclusion est que je conserve mon ancienne solution C++!
C’est le plus rapide au monde, même ajouter plus de caractères à vérifier (par exemple,\r\n je ne vois aucun cas d’utilisation pour\f\v) est toujours plus rapide que les solutions utilisant un algorithme.
std::string & trimMe (std::string & str)
{
// right trim
while (str.length () > 0 && (str [str.length ()-1] == ' ' || str [str.length ()-1] == '\t'))
str.erase (str.length ()-1, 1);
// left trim
while (str.length () > 0 && (str [0] == ' ' || str [0] == '\t'))
str.erase (0, 1);
return str;
}
Et ça...?
#include <iostream>
#include <string>
#include <regex>
std::string ltrim( std::string str ) {
return std::regex_replace( str, std::regex("^\\s+"), std::string("") );
}
std::string rtrim( std::string str ) {
return std::regex_replace( str, std::regex("\\s+$"), std::string("") );
}
std::string trim( std::string str ) {
return ltrim( rtrim( str ) );
}
int main() {
std::string str = " \t this is a test string \n ";
std::cout << "-" << trim( str ) << "-\n";
return 0;
}
Note: Je suis encore relativement nouveau en C++, alors pardonnez-moi si je me trompe de base.
Voici une implémentation simple. Pour une opération aussi simple, vous ne devriez probablement pas utiliser de constructions spéciales. La fonction isspace () intégrée prend en charge diverses formes de caractères blancs. Nous devrions donc en tirer parti. Vous devez également tenir compte des cas spéciaux où la chaîne est vide ou simplement un tas d'espaces. Couper à gauche ou à droite peut être dérivé du code suivant.
string trimSpace(const string &str) {
if (str.empty()) return str;
string::size_type i,j;
i=0;
while (i<str.size() && isspace(str[i])) ++i;
if (i == str.size())
return string(); // empty string
j = str.size() - 1;
//while (j>0 && isspace(str[j])) --j; // the j>0 check is not needed
while (isspace(str[j])) --j
return str.substr(i, j-i+1);
}
Avec C++ 17, vous pouvez utiliser basic_string_view :: remove_prefix et basic_string_view :: remove_suffix :
std::string_view trim(std::string_view s) const
{
s.remove_prefix(std::min(s.find_first_not_of(" \t\r\v\n"), s.size()));
s.remove_suffix((s.size() - 1) - std::min(s.find_last_not_of(" \t\r\v\n"), s.size() - 1));
return s;
}
Je sais que la question est très ancienne, mais j’ai ajouté quelques lignes de code à la vôtre et elle réduit les espaces des deux côtés.
void trim(std::string &line){
auto val = line.find_last_not_of(" \n\r\t") + 1;
if(val == line.size() || val == std::string::npos){
val = line.find_first_not_of(" \n\r\t");
line = line.substr(val);
}
else
line.erase(val);
}
c ++ 11:
int i{};
string s = " h e ll \t\n o";
string trim = " \n\t";
while ((i = s.find_first_of(trim)) != -1)
s.erase(i,1);
cout << s;
sortie:
hello
fonctionne bien aussi avec des chaînes vides
Ci-dessous, une solution (peut être deux passes). Il parcourt deux fois la partie espaces de la chaîne et une fois les espaces non blancs.
void trim(std::string& s) {
if (s.empty())
return;
int l = 0, r = s.size() - 1;
while (l < s.size() && std::isspace(s[l++])); // l points to first non-whitespace char.
while (r >= 0 && std::isspace(s[r--])); // r points to last non-whitespace char.
if (l > r)
s = "";
else {
l--;
r++;
int wi = 0;
while (l <= r)
s[wi++] = s[l++];
s.erase(wi);
}
return;
}
C'est bon? (Parce que ce message a absolument besoin d'une autre réponse :)
string trimBegin(string str)
{
string whites = "\t\r\n ";
int i = 0;
while (whites.find(str[i++]) != whites::npos);
str.erase(0, i);
return str;
}
Cas similaire pour le trimEnd, inversez simplement la polaire, les index.
J'utilise celui-ci:
void trim(string &str){
int i=0;
//left trim
while (isspace(str[i])!=0)
i++;
str = str.substr(i,str.length()-i);
//right trim
i=str.length()-1;
while (isspace(str[i])!=0)
i--;
str = str.substr(0,i+1);
}
std::string trim( std::string && str )
{
size_t end = str.find_last_not_of( " \n\r\t" );
if ( end != std::string::npos )
str.resize( end + 1 );
size_t start = str.find_first_not_of( " \n\r\t" );
if ( start != std::string::npos )
str = str.substr( start );
return std::move( str );
}