2014-09-14 21 views
13

So che ci sono diversi modi per farlo in Java e C che sono belli, ma in C++ non riesco a trovare un modo per implementare facilmente una funzione di taglio delle stringhe.Spazio vuoto ritagliato da una stringa

Questo è quello che ho attualmente:

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

ma ogni volta che provo e chiamo

trim(myString); 

ottengo l'errore del compilatore

/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 

Sto cercando di trovare una semplice e modo standard di tagliare gli spazi bianchi iniziali e finali da una stringa senza occupare 100 righe di codice e io ho provato a usare regex, ma non ho potuto farlo funzionare bene.

Inoltre non è possibile utilizzare Boost.

+0

è 'song' uno spazio dei nomi? È una lezione? –

+1

possibile duplicato di [Rimozione di spazi iniziali e finali da una stringa] (http://stackoverflow.com/questions/1798112/removing-leading-and-trailing-spaces-from-a-string) –

+3

Questa domanda non è proprio fare con il taglio, ma con l'errore di collegamento. Probabilmente ottieni lo stesso errore indipendentemente dalla definizione di assetto – Brandin

risposta

30

Il tuo codice è a posto. Quello che stai vedendo è un problema di linker.

Se mettete il vostro codice in un unico file in questo modo:

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

} 

poi fare g++ test.cc ed eseguire a.out, vedrete che funziona.

È necessario verificare se il file contenente la funzione trim è incluso nella fase di collegamento del processo di compilazione.

+3

Gestisce correttamente "" "o' "" '? – AlexD

+4

Ciò provoca arresti anomali sulla stringa vuota! –

+3

Aggiungi 'if (first == string :: npos) return "";' per evitare crash. Oltre a questo è una soluzione carina e semplice. Ho visto come le persone usano boost (!!!) per implementare queste cose. –

15

Ecco come si può fare:

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

E le funzioni di supporto sono implemeted come:

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

E una volta che hai tutti questi in luogo, è possibile scrivere anche questo :

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

Prova questa

+1

+1 per aver introdotto il locale che mi manca da tante altre risposte in giro. Non necessario quello corretto in quanto dipende dal caso di applicazione, ma è ancora un fattore importante quando si ha a che fare con le stringhe. – Rado

4

Penso che substr() generi un'eccezione se str contiene solo gli spazi bianchi.

vorrei modificarlo al seguente codice:

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

Questa dovrebbe essere la risposta giusta –

+0

Questo non funziona per tabulazioni o altri tipi di spazio bianco oltre agli spazi. – jocull

+0

@jocull - hai ragione, ma penso che sia ovvio cosa fare per specificare più spazi bianchi, find_first_not_of ("\ t \ n \ r \ v \ f") – Martin

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