web-dev-qa-db-fra.com

Couper les espaces d'une chaîne

Je sais qu'il y a plusieurs façons de faire cela en Java et en C qui sont sympas, mais en C++, il semble impossible de trouver un moyen d'implémenter facilement une fonction de coupe de chaîne.

C'est ce que j'ai actuellement:

string trim(string& str)
{
    size_t first = str.find_first_not_of(' ');
    size_t last = str.find_last_not_of(' ');
    return str.substr(first, (last-first+1));
}

mais chaque fois que j'essaie d'appeler 

trim(myString);

Je reçois l'erreur du compilateur 

/tmp/ccZZKSEq.o: In function `song::Read(std::basic_ifstream<char, 
std::char_traits<char> >&, std::basic_ifstream<char, std::char_traits<char> >&, char const*, char const*)':
song.cpp:(.text+0x31c): undefined reference to `song::trim(std::string&)'
collect2: error: ld returned 1 exit status

J'essaie de trouver un moyen simple et standard de couper les espaces de début et de fin d'une chaîne sans que celle-ci ne prenne 100 lignes de code. J'ai essayé d'utiliser regex, mais je ne pouvais pas que cela fonctionne aussi bien.

Je ne peux pas non plus utiliser Boost.

17
kf.

Votre code est bon. Ce que vous voyez est un problème de l'éditeur de liens.

Si vous mettez votre code dans un seul fichier comme ceci:

#include <iostream>
#include <string>

using namespace std;

string trim(const string& str)
{
    size_t first = str.find_first_not_of(' ');
    if (string::npos == first)
    {
        return str;
    }
    size_t last = str.find_last_not_of(' ');
    return str.substr(first, (last - first + 1));
}

int main() {
    string s = "abc ";
    cout << trim(s);

}

ensuite, faites g++ test.cc et exécutez a.out, vous verrez que cela fonctionne.

Vous devez vérifier si le fichier contenant la fonction trim est inclus dans l'étape de liaison de votre processus de compilation. 

36
Anthony Kong

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

19
gjha

Je pense que substr () lève une exception si str ne contient que les espaces. 

Je le modifierais dans le code suivant:

string trim(string& str)
{
    size_t first = str.find_first_not_of(' ');
    if (first == std::string::npos)
        return "";
    size_t last = str.find_last_not_of(' ');
    return str.substr(first, (last-first+1));
}
5
Martin

En plus de la réponse de @gjha:

inline std::string ltrim_copy(const std::string& str)
{
    auto it = std::find_if(str.cbegin(), str.cend(),
        [](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
    return std::string(it, str.cend());
}

inline std::string rtrim_copy(const std::string& str)
{
    auto it = std::find_if(str.crbegin(), str.crend(),
        [](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
    return it == str.crend() ? std::string() : std::string(str.cbegin(), ++it.base());
}

inline std::string trim_copy(const std::string& str)
{
    auto it1 = std::find_if(str.cbegin(), str.cend(),
        [](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
    if (it1 == str.cend()) {
        return std::string();
    }
    auto it2 = std::find_if(str.crbegin(), str.crend(),
        [](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
    return it2 == str.crend() ? std::string(it1, str.cend()) : std::string(it1, ++it2.base());
}
0
ivan.ukr
#include <vector>
#include <numeric>
#include <sstream>
#include <iterator>

void Trim(std::string& inputString)
{
    std::istringstream stringStream(inputString);
    std::vector<std::string> tokens((std::istream_iterator<std::string>(stringStream)), std::istream_iterator<std::string>());

    inputString = std::accumulate(std::next(tokens.begin()), tokens.end(),
                                 tokens[0], // start with first element
                                 [](std::string a, std::string b) { return a + " " + b; });
}
0
Will