Richtiger Weg, um einen std :: string in einen Vektor <string> aufzuteilen

74

Mögliches Duplikat: Wie teile ich
einen String?

Was ist der richtige Weg, um einen String in einen Vektor von Strings aufzuteilen? Trennzeichen ist Leerzeichen oder Komma.

Software
quelle
Eine Aufteilung, bei der Kommas und Leerzeichen Begrenzer sind, oder eine Funktion, die je nach Parameter entweder auf Leerzeichen oder auf Komma aufgeteilt wird?
Steve Jessop
Einige der Antworten auf stackoverflow.com/questions/236129/how-to-split-a-string können problemlos für die Arbeit mit mehreren Trennzeichen angepasst werden.
Gareth McCaughan

Antworten:

93

Für durch Leerzeichen getrennte Zeichenfolgen können Sie Folgendes tun:

std::string s = "What is the right way to split a string into a vector of strings";
std::stringstream ss(s);
std::istream_iterator<std::string> begin(ss);
std::istream_iterator<std::string> end;
std::vector<std::string> vstrings(begin, end);
std::copy(vstrings.begin(), vstrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

Ausgabe:

What
is
the
right
way
to
split
a
string
into
a
vector
of
strings

Zeichenfolge, die sowohl Komma als auch Leerzeichen enthält

struct tokens: std::ctype<char> 
{
    tokens(): std::ctype<char>(get_table()) {}
 
    static std::ctype_base::mask const* get_table()
    {
        typedef std::ctype<char> cctype;
        static const cctype::mask *const_rc= cctype::classic_table();
 
        static cctype::mask rc[cctype::table_size];
        std::memcpy(rc, const_rc, cctype::table_size * sizeof(cctype::mask));
 
        rc[','] = std::ctype_base::space; 
        rc[' '] = std::ctype_base::space; 
        return &rc[0];
    }
};
 
std::string s = "right way, wrong way, correct way";
std::stringstream ss(s);
ss.imbue(std::locale(std::locale(), new tokens()));
std::istream_iterator<std::string> begin(ss);
std::istream_iterator<std::string> end;
std::vector<std::string> vstrings(begin, end);
std::copy(vstrings.begin(), vstrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

Ausgabe:

right
way
wrong
way
correct
way
Nawaz
quelle
std::vector<std::string> vstrings(begin, end);wäre schöner IMO, aber ich nehme an, wir wissen nicht, ob der Fragesteller den Vektor konstruiert oder hofft, einen bereits vorhandenen Vektor zu füllen.
Steve Jessop
Schön, aber falsch. Das OP war insofern spezifisch, als sowohl Leerzeichen als auch Komma Trennzeichen sind. Und Sie können in diesem Fall nicht den gleichen Trick machen, oder?
Armen Tsirunyan
1
Dies ist eine erstaunliche Antwort und muss irgendwie hervorgehoben werden.
Samveen
2
+1 Sehr schön. Aber müssen Sie nicht die ss.imbue(std::locale(std::locale(), new tokens()))irgendwo erstellte Token-Struktur löschen ?
Kafman
1
@ Ja, ich dachte, das Lesen wird das tun. Verwenden Sie auto loc = std::make_shared<tokens>()und dann übergeben ss.imbue(..., loc.get()));. Das sollte funktionieren.
Nawaz
129

Ein bequemer Weg wäre die String-Algorithmus-Bibliothek von Boost .

#include <boost/algorithm/string/classification.hpp> // Include boost::for is_any_of
#include <boost/algorithm/string/split.hpp> // Include for boost::split
// ...

std::vector<std::string> words;
std::string s;
boost::split(words, s, boost::is_any_of(", "), boost::token_compress_on);
Onkel Bens
quelle
13
vector<string> split(string str, string token){
    vector<string>result;
    while(str.size()){
        int index = str.find(token);
        if(index!=string::npos){
            result.push_back(str.substr(0,index));
            str = str.substr(index+token.size());
            if(str.size()==0)result.push_back(str);
        }else{
            result.push_back(str);
            str = "";
        }
    }
    return result;
}

split ("1,2,3", ",") ==> ["1", "2", "3"]

split ("1,2,", ",") ==> ["1", "2", ""]

split ("1token2token3", "token") ==> ["1", "2", "3"]

Shiqi Ai
quelle
12

Sie können getline mit Trennzeichen verwenden:

string s, tmp; 
stringstream ss(s);
vector<string> words;

while(getline(ss, tmp, ',')){
    words.push_back(tmp);
    .....
}
James LT
quelle
9

Wenn die Zeichenfolge sowohl Leerzeichen als auch Kommas enthält, können Sie die Zeichenfolgenklassenfunktion verwenden

found_index = myString.find_first_of(delims_str, begin_index) 

in einer Schleife. Nach! = Npos suchen und in einen Vektor einfügen. Wenn Sie alte Schule bevorzugen, können Sie auch Cs verwenden

strtok() 

Methode.

Tod
quelle
2

Optimierte Version von Techie Delight :

#include <string>
#include <vector>

std::vector<std::string> split(const std::string& str, char delim) {
    std::vector<std::string> strings;
    size_t start;
    size_t end = 0;
    while ((start = str.find_first_not_of(delim, end)) != std::string::npos) {
        end = str.find(delim, start);
        strings.push_back(str.substr(start, end - start));
    }
    return strings;
}
wcochran
quelle
0

Ich habe diese benutzerdefinierte Funktion gemacht, die die Linie in Vektor konvertiert

#include <iostream>
#include <vector>
#include <ctime>
#include <string>

using namespace std;

int main(){

    string line;
    getline(cin, line);
    int len = line.length();
    vector<string> subArray;

    for (int j = 0, k = 0; j < len; j++) {
        if (line[j] == ' ') {
            string ch = line.substr(k, j - k);
            k = j+1;
            subArray.push_back(ch);
        }
        if (j == len - 1) {
            string ch = line.substr(k, j - k+1);
            subArray.push_back(ch);
        }
    }

    return 0;
}
Ankit Baid
quelle
0
std::vector<std::string> split(std::string text, char delim) {
    std::string line;
    std::vector<std::string> vec;
    std::stringstream ss(text);
    while(std::getline(ss, line, delim)) {
        vec.push_back(line);
    }
    return vec;
}

split("String will be split", ' ') -> {"String", "will", "be", "split"}

split("Hello, how are you?", ',') -> {"Hello", "how are you?"}

Plötze
quelle
-1

Ich schreibe diese benutzerdefinierte Funktion, die Ihnen helfen wird. Aber diskutieren Sie über die zeitliche Komplexität.

std::vector<std::string> words;
std::string s;
std::string separator = ",";

while(s.find(separator) != std::string::npos){
   separatorIndex = s.find(separator)
   vtags.push_back(s.substr(0, separatorIndex ));
   words= s.substr(separatorIndex + 1, s.length());
}

words.push_back(s);

Sajeevan Vinayakavaseerakan
quelle