2012-11-15 15 views
6

Sto usandoSplit una stringa utilizzando C++ boost :: spaccatura senza scissione all'interno testo citato

boost::split(strs, r_strCommandLine, boost::is_any_of("\t ")); 

di sputare una stringa in token per l'analisi di un semplice script. Fin qui tutto bene. Tuttavia, per la seguente stringa

command_name first_argument "Second argument which is a quoted string." 

Vorrei che il mio token di essere

strs[0] = command_name 
strs[1] = first_argument 
strs[2] = "Second argument which is a quoted string." 

Naturalmente, potrei cercare virgolette all'inizio e alla fine di gettoni e la fusione con "" delimitatori i gettoni tra l'occorrenza di un token che inizia con una citazione e un token che termina con una citazione per ricreare la stringa quotata, ma mi chiedo se esiste un modo più efficiente/elegante per farlo. Qualche idea?

+0

Escaped '\" 's pure? – Yakk

+0

Benvenuti in Stack Overflow! Sono confuso dalla tua domanda.Il primo paragrafo di questa domanda è in qualche modo collegato al resto della domanda? –

+2

[' boost :: tokenizer '] (http://www.boost.org/doc/libs/1_51_0/libs/tokenizer/introduc.htm) potrebbe avere la funzionalità richiesta. – hmjd

risposta

13

Esempio con boost::tokenizer:

#include <string> 
#include <iostream> 
using std::cout; 
using std::string; 

#include <boost/tokenizer.hpp> 
using boost::tokenizer; 
using boost::escaped_list_separator; 

typedef tokenizer<escaped_list_separator<char> > so_tokenizer; 

int main() 
{ 
    string s("command_name first_argument " 
      "\"Second argument which is a quoted string.\""); 

    so_tokenizer tok(s, escaped_list_separator<char>('\\', ' ', '\"')); 
    for(so_tokenizer::iterator beg=tok.begin(); beg!=tok.end(); ++beg) 
    { 
     cout << *beg << "\n"; 
    } 

    return 0; 
} 

uscita:

 
command_name 
first_argument 
Second argument which is a quoted string. 

See demo https://ideone.com/gwCpug.

+0

Funziona perfettamente. Grazie! –

+0

C'è un modo per preservare le virgolette?Ho bisogno che l'output sia come: 'command_name' ' first_argument' '" Secondo argomento che è una stringa quotata. "' –

0

Non sono sicuro che questa soluzione sia portatile (violiamo la condizione const per bool operator() (char ch) const), ma funziona.

Questa soluzione è interessante in teoria, non la userei in un progetto reale.

#include <boost/algorithm/string/split.hpp> 
#include <string> 
#include <vector> 
#include <iostream> 

class split_q { 
public: 
    split_q() : in_q(false) {} 
    bool operator() (char ch) const 
    { 
     if (ch == '\"') in_q = !in_q; 
     return !in_q && ch == ' '; 
    } 

private: 
    mutable bool in_q; 

}; 

int main(int argc, char* argv[]) 
{ 
    std::string in = "command_name first_argument \"Second argument which is a quoted string.\" additional_argument"; 
    std::vector<std::string> res; 
    boost::algorithm::split(res, in, split_q()); 

    for (size_t i = 0; i < res.size(); ++i) 
     std::cout << res[i] << std::endl; 

    return 0; 
} 

Risultato:

command_name 
first_argument 
"Second argument which is a quoted string." 
additional_argument 
+0

Puoi risolvere 'const 'rompendo questo memorizzando' bool * in_q' invece di un 'mutabile'' in_q'. E uno stato di escape backslash dovrebbe essere facile da aggiungere. – Yakk

+0

La mia preoccupazione è di non usare la parola chiave mutabile, ma la vera e propria violazione dell'immutabilità – pogorskiy

+2

Non c'è alcuna violazione di immutabilità se si è memorizzato un puntatore nel functor. Il grosso problema con la mutazione del functor è che si dipende dall'algoritmo per utilizzare esattamente un'istanza del proprio functor, e non fare una copia - se ciò accade, si incontrano dei problemi. L'unico problema che posso vedere con la versione del puntatore è che l'algoritmo potrebbe eseguirlo fuori ordine. – Yakk