Snij witruimte uit een string

Ik weet dat er verschillende manieren zijn om dit in Java en C te doen die leuk zijn, maar in C++ kan ik geen manier vinden om gemakkelijk een functie voor het trimmen van strings te implementeren.

Dit is wat ik momenteel heb:

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));
}

maar wanneer ik probeer te bellen

trim(myString);

Ik krijg de compilerfout

/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

Ik ben op zoek naar een eenvoudige en standaardmanier om voorloop- en volgspaties van een tekenreeks bij te snijden zonder dat het 100 regels code in beslag neemt, en ik heb geprobeerd regex te gebruiken, maar ik kreeg dat ook niet voor elkaar.

>

Ik kan Boost ook niet gebruiken.


Antwoord 1, autoriteit 100%

Je code is in orde. Wat u ziet, is een linkerprobleem.

Als u uw code als volgt in een enkel bestand plaatst:

#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);
}

Doe dan g++ test.ccen voer A.Out uit, u zult het werken.

U moet controleren of het bestand met de trim-functie is opgenomen in de koppelingsfase van uw compilatieproces.


Antwoord 2, Autoriteit 66%

Hier is hoe u het kunt doen:

std::string & trim(std::string & str)
{
   return ltrim(rtrim(str));
}

en de ondersteunende functies zijn geïmplementeerd als:

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;   
}

En zodra u al deze op zijn plaats bent, kunt u dit ook schrijven:

std::string trim_copy(std::string const & str)
{
   auto s = str;
   return ltrim(rtrim(s));
}

Probeer dit


Antwoord 3, Autoriteit 16%

Ik denk dat substr () een uitzondering gooit als STR alleen de witruimte bevat.

Ik zou het wijzigen in de volgende code:

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));
}

Antwoord 4, Autoriteit 7%

Een regex gebruiken

#include <regex>
#include <string>
string trim(string s) {
    regex e("^\\s+|\\s+$");   // remove leading and trailing spaces
    return regex_replace(s, e, "");
}
// if you prefer the namespaced version
std::string trim(std::string s) {
    std::regex e("^\\s+|\\s+$"); // remove leading and trailing spaces
    return std::regex_replace(s, e, "");
}

Credit to: https://www.regular-expressions.info/examples.html voor de regex


Antwoord 5

#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; });
}

Antwoord 6

Naast antwoord van @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());
}

Other episodes