119 votes

Suppression des espaces avant et arrière d'une chaîne de caractères

Comment supprimer les espaces d'un objet chaîne de caractères en C++.
Par exemple, comment supprimer les espaces avant et arrière de l'objet chaîne ci-dessous.

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

La classe des chaînes de caractères, pour autant que je sache, ne fournit aucune méthode pour supprimer les espaces avant et après.

Pour ajouter au problème, comment étendre ce formatage pour traiter les 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înes de caractères mentionnées dans la solution, je peux penser à faire ces opérations en deux étapes.

  1. Supprimez les espaces avant et après.
  2. Utilice find_first_of, find_last_of, find_first_not_of, find_last_not_of et substr à plusieurs reprises aux limites des mots pour obtenir le formatage souhaité.

144voto

GManNickG Points 155079

C'est ce qu'on appelle l'élagage. Si vous pouvez utiliser Boost je le recommande.

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

En réponse à votre modification, je ne connais pas le terme, mais je pense qu'il s'agit de quelque chose du genre "réduire", c'est pourquoi je l'ai appelé ainsi :) (Note, j'ai changé 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]

0 votes

Je suppose que vous vouliez dire 'size_t'. et vous avez un off-by-one sur la sous-chaîne, cela devrait être substr(beginStr, endStr - beginStr + 1) ;

0 votes

Devrait site_t être size_t ? Et je pense que là où vous avez le commentaire no whitespace signifie que la chaîne est entièrement composée d'espaces ou qu'elle est vide.

0 votes

Merci, j'ai corrigé le size_t typo et off-by-one dans l'édition, mais je n'avais pas remarqué que mon commentaire était inversé, merci.

61voto

Evgeny Karpov Points 132

Suppression facile des espaces de tête, de queue et supplémentaires d'une chaîne std::string en une ligne

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

en supprimant uniquement les espaces de tête

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

o

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

en supprimant uniquement les espaces de fin de ligne

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

o

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

en supprimant uniquement les espaces supplémentaires

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

5 votes

Joli coup. Il serait utile de fournir quelques informations sur ce qui se passe ici, car il est difficile de comprendre ces codes.

0 votes

Ne fonctionne que dans C++11, cependant.

9 votes

Il ne supprime pas les onglets, mais cela peut être corrigé. Ce qui ne peut pas être corrigé, c'est qu'il est terriblement lent (~100 fois plus lent que les réponses avec le logiciel substr o erase ).

28voto

jon-hanson Points 3912

Améliorer l'algorithme de coupe de la ficelle

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

[...]

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

5voto

Murphy78 Points 11
/// 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 la fonction isspace() depuis "ctype.h" si vous le souhaitez.

0voto

Amarghosh Points 33957
    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);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X