2012-11-15 3 views
6

Ich verwendeSplit ein String C++ boost :: Split ohne Spaltung innerhalb zitierten Text

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

einen String in Token zu spucken für ein einfaches Skript, das Parsen. So weit, ist es gut. Doch für die folgende Zeichenfolge

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

würde ich meine Jetons wie

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

Natürlich sein, ich für Anführungszeichen am Anfang suchen konnte und von Token zu beenden und die Token mit „“ Trennzeichen verschmelzenden zwischen dem Auftreten eines Tokens, das mit einem Zitat beginnt, und einem Token, das mit einem Zitat endet, um den String in Anführungszeichen neu zu erstellen, aber ich frage mich, ob es einen effizienteren/eleganteren Weg gibt, dies zu tun. Irgendwelche Ideen?

+0

Escaped '\" 's auch? – Yakk

+0

Willkommen zu Stack Overflow! Ich bin verwirrt durch Ihre Frage. Ist der erste Absatz dieser Frage in irgendeiner Weise auf den Rest der Frage bezogen? –

+2

[' Boost :: Tokenizer '] (http://www.boost.org/doc/libs/1_51_0/libs/tokenizer/introduc.htm) könnte die Funktionalität haben, die Sie benötigen – hmjd

Antwort

13

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

Ausgang:

 
command_name 
first_argument 
Second argument which is a quoted string. 

Siehe Demo auf https://ideone.com/gwCpug.

+0

Funktioniert perfekt. Vielen Dank! –

+0

Gibt es eine Möglichkeit, die Angebote zu erhalten?Ich brauche die Ausgabe, um wie zu sein: 'command_name' ' first_argument' '" Zweites Argument, das eine in Anführungszeichen gesetzte Zeichenkette ist. "' –

0

Ich bin nicht sicher, dass diese Lösung tragbar ist (wir verletzen die const-Bedingung für bool operator() (char ch) const), aber es funktioniert.

Diese Lösung ist in der Theorie interessant, ich würde es nicht in einem realen Projekt verwenden.

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

Ergebnis:

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

Sie können das 'const' reparieren, indem Sie' bool * in_q' anstelle von 'mutable'' in_q' speichern. Und ein Backslash-Escape-Status sollte einfach hinzuzufügen sein. – Yakk

+0

Mein Anliegen ist nicht die Verwendung des Mutable-Schlüsselworts, sondern die tatsächliche Verletzung der Unveränderlichkeit – pogorskiy

+2

Es gibt keine Verletzung der Unveränderlichkeit, wenn Sie einen Zeiger im Funktor gespeichert haben. Das große Problem bei der Mutation des Funktors besteht darin, dass Sie auf den Algorithmus angewiesen sind, um genau eine Instanz Ihres Funktors zu verwenden und keine Kopie zu erstellen - wenn das passiert, treten Probleme auf. Das einzige Problem, das ich mit der Zeigerversion sehen kann, ist, dass der Algorithmus es out-of-order ausführen könnte. – Yakk