web-dev-qa-db-fra.com

Suppression des espaces de début et de fin d'une chaîne

Comment supprimer des espaces d'un objet chaîne en C++.
Par exemple, comment supprimer les espaces de début et de fin de l'objet string ci-dessous. 

//Original string: "         This is a sample string                    "
//Desired string: "This is a sample string"

Autant que je sache, la classe string ne fournit aucune méthode pour supprimer les espaces de début et de fin. 

Pour ajouter au problème, comment étendre cette mise en forme pour traiter des espaces supplémentaires entre les mots de la chaîne. Par exemple,

// Original string: "          This       is         a sample   string    " 
// Desired string:  "This is a sample string"  

En utilisant les méthodes de chaîne mentionnées dans la solution, je peux penser à effectuer ces opérations en deux étapes.

  1. Supprimer les espaces de début et de fin.
  2. Utilisez find_first_of, find_last_of, find_first_not_of, find_last_not_of et substr , à plusieurs reprises aux limites de Word pour obtenir le formatage souhaité.
68
Ankur

Ceci s'appelle le rognage. Si vous pouvez utiliser Boost , je le recommanderais.

Sinon, utilisez find_first_not_of pour obtenir l'index du premier caractère autre qu'un espace, puis find_last_not_of pour obtenir l'index de la fin qui n'est pas un espace. Avec ceux-ci, utilisez substr pour obtenir la sous-chaîne sans espace blanc.

En réponse à votre modification, je ne connais pas le terme mais je suppose que quelque chose s'apparente à "réduire", c'est ce que j'ai appelé cela. :) (Remarque, j'ai modifié l'espace blanc en paramètre, pour plus de flexibilité)

#include <iostream>
#include <string>

std::string trim(const std::string& str,
                 const std::string& whitespace = " \t")
{
    const auto strBegin = str.find_first_not_of(whitespace);
    if (strBegin == std::string::npos)
        return ""; // no content

    const auto strEnd = str.find_last_not_of(whitespace);
    const auto strRange = strEnd - strBegin + 1;

    return str.substr(strBegin, strRange);
}

std::string reduce(const std::string& str,
                   const std::string& fill = " ",
                   const std::string& whitespace = " \t")
{
    // trim first
    auto result = trim(str, whitespace);

    // replace sub ranges
    auto beginSpace = result.find_first_of(whitespace);
    while (beginSpace != std::string::npos)
    {
        const auto endSpace = result.find_first_not_of(whitespace, beginSpace);
        const auto range = endSpace - beginSpace;

        result.replace(beginSpace, range, fill);

        const auto newStart = beginSpace + fill.length();
        beginSpace = result.find_first_of(whitespace, newStart);
    }

    return result;
}

int main(void)
{
    const std::string foo = "    too much\t   \tspace\t\t\t  ";
    const std::string bar = "one\ntwo";

    std::cout << "[" << trim(foo) << "]" << std::endl;
    std::cout << "[" << reduce(foo) << "]" << std::endl;
    std::cout << "[" << reduce(foo, "-") << "]" << std::endl;

    std::cout << "[" << trim(bar) << "]" << std::endl;
}

Résultat:

[too much               space]  
[too much space]  
[too-much-space]  
[one  
two]  
112
GManNickG

Suppression facile des espaces de début, de fin et extra de std :: string en une seule ligne

value = std::regex_replace(value, std::regex("^ +| +$|( ) +"), "$1");

supprimer uniquement les espaces de début

value.erase(value.begin(), std::find_if(value.begin(), value.end(), std::bind1st(std::not_equal_to<char>(), ' ')));

ou

value = std::regex_replace(value, std::regex("^ +"), "");

supprimer uniquement les espaces de fin

value.erase(std::find_if(value.rbegin(), value.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), value.end());

ou

value = std::regex_replace(value, std::regex(" +$"), "");

supprimer uniquement les espaces supplémentaires

value = regex_replace(value, std::regex(" +"), " ");
41
Evgeny Karpov

J'utilise actuellement ces fonctions:

// trim from left
inline std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v")
{
    s.erase(0, s.find_first_not_of(t));
    return s;
}

// trim from right
inline std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v")
{
    s.erase(s.find_last_not_of(t) + 1);
    return s;
}

// trim from left & right
inline std::string& trim(std::string& s, const char* t = " \t\n\r\f\v")
{
    return ltrim(rtrim(s, t), t);
}

// copying versions

inline std::string ltrim_copy(std::string s, const char* t = " \t\n\r\f\v")
{
    return ltrim(s, t);
}

inline std::string rtrim_copy(std::string s, const char* t = " \t\n\r\f\v")
{
    return rtrim(s, t);
}

inline std::string trim_copy(std::string s, const char* t = " \t\n\r\f\v")
{
    return trim(s, t);
}
28
Galik

Algorithme Boost String Trim

#include <boost/algorithm/string/trim.hpp>

[...]

std::string msg = "   some text  with spaces  ";
boost::algorithm::trim(msg);
19
jon-hanson

C'est ma solution pour éliminer les espaces de début et de fin ...

std::string stripString = "  Plamen     ";
while(!stripString.empty() && std::isspace(*stripString.begin()))
    stripString.erase(stripString.begin());

while(!stripString.empty() && std::isspace(*stripString.rbegin()))
    stripString.erase(stripString.length()-1);

Le résultat est "Plamen"

7
Plamen Stoyanov

Voici comment vous pouvez le faire:

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 it2 =  std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
  str.erase( str.begin() , it2);
  return str;   
}

std::string & rtrim(std::string & str)
{
  auto it1 =  std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
  str.erase( it1.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));
}

Essaye ça

7
gjha

Exemple de réduction des espaces de début et de fin suivant la suggestion de jon-hanson d’utiliser le boost (ne supprime que les espaces de fin et en attente):

#include <boost/algorithm/string/trim.hpp>

std::string str = "   t e s t    ";

boost::algorithm::trim ( str );

Résultats en "t e s t"

Il y a aussi 

  • trim_left résulte en "t e s t "
  • trim_right résulte en " t e s t"
7
Semjon Mössinger
/// strip a string, remove leading and trailing spaces
void strip(const string& in, string& out)
{
    string::const_iterator b = in.begin(), e = in.end();

    // skipping leading spaces
    while (isSpace(*b)){
        ++b;
    }

    if (b != e){
        // skipping trailing spaces
        while (isSpace(*(e-1))){
            --e;
        }
    }

    out.assign(b, e);
}

Dans le code ci-dessus, la fonction isSpace () est une fonction booléenne qui indique si un caractère est un espace blanc, vous pouvez implémenter cette fonction pour refléter vos besoins ou simplement appeler isspace () depuis "ctype.h" si vous le souhaitez. .

4
Murphy78

L'utilisation de la bibliothèque standard présente de nombreux avantages, mais vous devez être conscient de certains cas particuliers qui provoquent des exceptions. Par exemple, aucune des réponses ne couvre le cas où une chaîne C++ contient des caractères Unicode. Dans ce cas, si vous utilisez la fonction isspace , une exception sera levée.

J'ai utilisé le code suivant pour couper les chaînes et d'autres opérations qui pourraient s'avérer utiles. Les principaux avantages de ce code sont les suivants: il est très rapide (plus rapide que tout code que j'ai jamais testé), il utilise uniquement la bibliothèque standard et ne provoque jamais d'exception:

#include <string>
#include <algorithm>
#include <functional>
#include <locale>
#include <iostream>

typedef unsigned char BYTE;

std::string strTrim(std::string s, char option = 0)
{
    // convert all whitespace characters to a standard space
    std::replace_if(s.begin(), s.end(), (std::function<int(BYTE)>)::isspace, ' ');

    // remove leading and trailing spaces
    size_t f = s.find_first_not_of(' ');
    if (f == std::string::npos) return "";
    s = s.substr(f, s.find_last_not_of(' ') - f + 1);

    // remove consecutive spaces
    s = std::string(s.begin(), std::unique(s.begin(), s.end(),
        [](BYTE l, BYTE r){ return l == ' ' && r == ' '; }));

    switch (option)
    {
    case 'l':  // convert to lowercase
        std::transform(s.begin(), s.end(), s.begin(), ::tolower);
        return s;
    case 'U':  // convert to uppercase
        std::transform(s.begin(), s.end(), s.begin(), ::toupper);
        return s;
    case 'n':  // remove all spaces
        s.erase(std::remove(s.begin(), s.end(), ' '), s.end());
        return s;
    default: // just trim
        return s;
    }
}
3
polfosol ఠ_ఠ

Exemple de réduction des espaces de début et de fin 

std::string aString("    This is a string to be trimmed   ");
auto start = aString.find_first_not_of(' ');
auto end = aString.find_last_not_of(' ');
std::string trimmedString;
trimmedString = aString.substr(start, (end - start) + 1);

OU 

trimmedSring = aString.substr(aString.find_first_not_of(' '), (aString.find_last_not_of(' ') - aString.find_first_not_of(' ')) + 1);
2
Thinkal VB

J'ai testé cela, tout fonctionne. Donc, cette méthode processInput demandera simplement à l'utilisateur de taper quelque chose. Elle retournera une chaîne qui ne contient aucun espace supplémentaire en interne, ni d'espace supplémentaire au début ou à la fin. J'espère que cela t'aides. (mettez également un tas de commentaires pour le rendre simple à comprendre).

vous pouvez voir comment l'implémenter dans main () en bas

#include <string>
#include <iostream>

string processInput() {
  char inputChar[256];
  string output = "";
  int outputLength = 0;
  bool space = false;
  // user inputs a string.. well a char array
  cin.getline(inputChar,256);
  output = inputChar;
       string outputToLower = "";
  // put characters to lower and reduce spaces
  for(int i = 0; i < output.length(); i++){
    // if it's caps put it to lowercase
    output[i] = tolower(output[i]);
    // make sure we do not include tabs or line returns or weird symbol for null entry array thingy
    if (output[i] != '\t' && output[i] != '\n' && output[i] != 'Ì') {
      if (space) {
        // if the previous space was a space but this one is not, then space now is false and add char
        if (output[i] != ' ') {
          space = false;
          // add the char
          outputToLower+=output[i];
        }
      } else {
        // if space is false, make it true if the char is a space
        if (output[i] == ' ') {
          space = true;
        }
        // add the char
        outputToLower+=output[i];
      }
    }
  }
  // trim leading and tailing space
  string trimmedOutput = "";
  for(int i = 0; i < outputToLower.length(); i++){
    // if it's the last character and it's not a space, then add it
    // if it's the first character and it's not a space, then add it
    // if it's not the first or the last then add it
    if (i == outputToLower.length() - 1 && outputToLower[i] != ' ' || 
      i == 0 && outputToLower[i] != ' ' || 
      i > 0 && i < outputToLower.length() - 1) {
      trimmedOutput += outputToLower[i];
    } 
  }
  // return
  output = trimmedOutput;
  return output;
}

int main() {
  cout << "Username: ";
  string userName = processInput();
  cout << "\nModified Input = " << userName << endl;
}
2
Elipsis

Cela pourrait être le plus simple de tous.

Vous pouvez utiliser string::find et string::rfind pour trouver des espaces des deux côtés et réduire la chaîne.

void TrimWord(std::string& Word)
{
    if (Word.empty()) return;

    // Trim spaces from left side
    while (Word.find(" ") == 0)
    {
        Word.erase(0, 1);
    }

    // Trim spaces from right side
    size_t len = Word.size();
    while (Word.rfind(" ") == --len)
    {
        Word.erase(len, len + 1);
    }
}
2
user2983960

Pourquoi se compliquer?

std::string removeSpaces(std::string x){
    if(x[0] == ' '){ x.erase(0, 1); }
    if(x[x.length()-1] == ' '){ x.erase(x.length()-1, x.length()); }
    return x;
}

Cela fonctionne même si boost devait échouer, pas de regex, pas de choses étranges ni de bibliothèques.

1
Jack Of Blades
string trim(const string & sStr)
{
    int nSize = sStr.size();
    int nSPos = 0, nEPos = 1, i;
    for(i = 0; i< nSize; ++i) {
        if( !isspace( sStr[i] ) ) {
            nSPos = i ;
            break;
        }
    }
    for(i = nSize -1 ; i >= 0 ; --i) {
        if( !isspace( sStr[i] ) ) {
            nEPos = i;
            break;
        }
    }
    return string(sStr, nSPos, nEPos - nSPos + 1);
}
0
kjk

propre et net

 void trimLeftTrailingSpaces(string &input) {
        input.erase(input.begin(), find_if(input.begin(), input.end(), [](int ch) {
            return !isspace(ch);
        }));
    }

    void trimRightTrailingSpaces(string &input) {
        input.erase(find_if(input.rbegin(), input.rend(), [](int ch) {
            return !isspace(ch);
        }).base(), input.end());
    }
0
user1856722
void removeSpaces(string& str)
{
    /* remove multiple spaces */
    int k=0;
    for (int j=0; j<str.size(); ++j)
    {
            if ( (str[j] != ' ') || (str[j] == ' ' && str[j+1] != ' ' ))
            {
                    str [k] = str [j];
                    ++k;
            }

    }
    str.resize(k);

    /* remove space at the end */   
    if (str [k-1] == ' ')
            str.erase(str.end()-1);
    /* remove space at the begin */
    if (str [0] == ' ')
            str.erase(str.begin());
}
0
Devesh Agrawal

Pour les espaces de début et de fin, que diriez-vous:

string string_trim(const string& in) {

    stringstream ss;
    string out;
    ss << in;
    ss >> out;
    return out;

}

Ou pour une phrase:

string trim_words(const string& sentence) {
    stringstream ss;
    ss << sentence;
    string s;
    string out;

    while(ss >> s) {

        out+=(s+' ');
    }
    return out.substr(0, out.length()-1);
}
0
Iderwok

Non boost, pas regex, juste la bibliothèque string. C'est si simple.

string trim(const string s) { // removes whitespace characters from beginnig and end of string s
    string x = s;
    for(int i=0; i<(int)s.length(); i++) {
        const int l = (int)x.length()-1;
        if(x[l]==' '||x[l]=='\t'||x[l]=='\n'||x[l]=='\v'||x[l]=='\f'||x[l]=='\r'||x[l]=='\0') x.erase(l, 1);
        if(x[0]==' '||x[0]=='\t'||x[0]=='\n'||x[0]=='\v'||x[0]=='\f'||x[0]=='\r'||x[0]=='\0') x.erase(0, 1);
    }
    return x;
}
0
ProjectPhysX
    char *str = (char*) malloc(50 * sizeof(char));
    strcpy(str, "    some random string (<50 chars)  ");

    while(*str == ' ' || *str == '\t' || *str == '\n')
            str++;

    int len = strlen(str);

    while(len >= 0 && 
            (str[len - 1] == ' ' || str[len - 1] == '\t' || *str == '\n')
    {
            *(str + len - 1) = '\0';
            len--;
    }

    printf(":%s:\n", str);
0
Amarghosh