Ontleden (splitsen) een tekenreeks in C++ met behulp van tekenreeksscheidingsteken (standaard C++)

Ik ontleed een string in C++ met het volgende:

using namespace std;
string parsed,input="text to be parsed";
stringstream input_stringstream(input);
if (getline(input_stringstream,parsed,' '))
{
     // do some processing.
}

Het ontleden met een enkel tekenscheidingsteken is prima. Maar wat als ik een string als scheidingsteken wil gebruiken.

Voorbeeld: ik wil splitsen:

scott>=tiger

met >= als scheidingsteken zodat ik scott en tiger kan krijgen.

Antwoord 1, autoriteit 100%

Je kunt de std::string::find() functie om de positie van uw tekenreeksscheidingsteken te vinden, gebruik dan std::string::substr() om een ​​token te krijgen.

Voorbeeld:

std::string s = "scott>=tiger";
std::string delimiter = ">=";
std::string token = s.substr(0, s.find(delimiter)); // token is "scott"
  • De functie find(const string& str, size_t pos = 0) retourneert de positie van het eerste voorkomen van str in de tekenreeks, of npos als de string niet wordt gevonden.

  • De functie substr(size_t pos = 0, size_t n = npos) retourneert een substring van het object, beginnend op positie pos en van lengte npos.


Als je meerdere scheidingstekens hebt, kun je, nadat je één token hebt geëxtraheerd, deze verwijderen (inclusief scheidingsteken) om door te gaan met volgende extracties (als je de originele tekenreeks wilt behouden, gebruik je gewoon s = s.substr(pos + delimiter.length());):

s.erase(0, s.find(delimiter) + delimiter.length());

Op deze manier kun je gemakkelijk een lus maken om elk token te krijgen.

Volledig voorbeeld

std::string s = "scott>=tiger>=mushroom";
std::string delimiter = ">=";
size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos) {
    token = s.substr(0, pos);
    std::cout << token << std::endl;
    s.erase(0, pos + delimiter.length());
}
std::cout << s << std::endl;

Uitvoer:

scott
tiger
mushroom

Antwoord 2, autoriteit 13%

Deze methode gebruikt std::string::find zonder de originele string te muteren door het begin en einde van de vorige substring-token te onthouden.

#include <iostream>
#include <string>
int main()
{
    std::string s = "scott>=tiger";
    std::string delim = ">=";
    auto start = 0U;
    auto end = s.find(delim);
    while (end != std::string::npos)
    {
        std::cout << s.substr(start, end - start) << std::endl;
        start = end + delim.length();
        end = s.find(delim, start);
    }
    std::cout << s.substr(start, end);
}

Antwoord 3, autoriteit 8%

Voor tekenreeksscheidingsteken

Tekenreeks splitsen op basis van een tekenreeksscheidingsteken. Zoals het splitsen van tekenreeks "adsf-+qwret-+nvfkbdsj-+orthdfjgh-+dfjrleih" op basis van tekenreeksscheidingsteken "-+", zal de uitvoer {"adsf", "qwret", "nvfkbdsj", "orthdfjgh", "dfjrleih"}

#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
// for string delimiter
vector<string> split (string s, string delimiter) {
    size_t pos_start = 0, pos_end, delim_len = delimiter.length();
    string token;
    vector<string> res;
    while ((pos_end = s.find (delimiter, pos_start)) != string::npos) {
        token = s.substr (pos_start, pos_end - pos_start);
        pos_start = pos_end + delim_len;
        res.push_back (token);
    }
    res.push_back (s.substr (pos_start));
    return res;
}
int main() {
    string str = "adsf-+qwret-+nvfkbdsj-+orthdfjgh-+dfjrleih";
    string delimiter = "-+";
    vector<string> v = split (str, delimiter);
    for (auto i : v) cout << i << endl;
    return 0;
}

Uitvoer

advertenties
qwret
nvfkbdsj
orthdfjgh
dfjrleih

Voor scheidingsteken van één teken

Tekenreeks splitsen op basis van een tekenscheidingsteken. Zoals het splitsen van string "adsf+qwer+poui+fdgh" met scheidingsteken "+" zal {"adsf", "qwer", "poui", "fdg"h}

#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
vector<string> split (const string &s, char delim) {
    vector<string> result;
    stringstream ss (s);
    string item;
    while (getline (ss, item, delim)) {
        result.push_back (item);
    }
    return result;
}
int main() {
    string str = "adsf+qwer+poui+fdgh";
    vector<string> v = split (str, '+');
    for (auto i : v) cout << i << endl;
    return 0;
}

Uitvoer

advertenties
qwer
poui
fdgh

Antwoord 4, autoriteit 7%

Je kunt de volgende functie gebruiken om een ​​string te splitsen:

vector<string> split(const string& str, const string& delim)
{
    vector<string> tokens;
    size_t prev = 0, pos = 0;
    do
    {
        pos = str.find(delim, prev);
        if (pos == string::npos) pos = str.length();
        string token = str.substr(prev, pos-prev);
        if (!token.empty()) tokens.push_back(token);
        prev = pos + delim.length();
    }
    while (pos < str.length() && prev < str.length());
    return tokens;
}

Antwoord 5, autoriteit 3%

Je kunt hiervoor ook regex gebruiken:

std::vector<std::string> split(const std::string str, const std::string regex_str)
{
    std::regex regexz(regex_str);
    std::vector<std::string> list(std::sregex_token_iterator(str.begin(), str.end(), regexz, -1),
                                  std::sregex_token_iterator());
    return list;
}

wat gelijk is aan :

std::vector<std::string> split(const std::string str, const std::string regex_str)
{
    std::sregex_token_iterator token_iter(str.begin(), str.end(), regexz, -1);
    std::sregex_token_iterator end;
    std::vector<std::string> list;
    while (token_iter != end)
    {
        list.emplace_back(*token_iter++);
    }
    return list;
}

en gebruik het als volgt:

#include <iostream>
#include <string>
#include <regex>
std::vector<std::string> split(const std::string str, const std::string regex_str)
{   // a yet more concise form!
    return { std::sregex_token_iterator(str.begin(), str.end(), std::regex(regex_str), -1), std::sregex_token_iterator() };
}
int main()
{
    std::string input_str = "lets split this";
    std::string regex_str = " "; 
    auto tokens = split(input_str, regex_str);
    for (auto& item: tokens)
    {
        std::cout<<item <<std::endl;
    }
}

speel er online mee! http://cpp.sh/9sumb

je kunt gewoon substrings, karakters, enz. gebruiken zoals normaal, of echte reguliere expressies gebruiken om de splitsing uit te voeren.
het is ook beknopt en C++11!

Antwoord 6, autoriteit 3%

Deze code splitst regels van tekst en voegt iedereen toe aan een vector.

vector<string> split(char *phrase, string delimiter){
    vector<string> list;
    string s = string(phrase);
    size_t pos = 0;
    string token;
    while ((pos = s.find(delimiter)) != string::npos) {
        token = s.substr(0, pos);
        list.push_back(token);
        s.erase(0, pos + delimiter.length());
    }
    list.push_back(s);
    return list;
}

Geroepen door:

vector<string> listFilesMax = split(buffer, "\n");

Antwoord 7, autoriteit 2%

strtok stelt je in staat meerdere tekens als scheidingstekens door te geven. Ik wed dat als je “>=” doorgeeft, je voorbeeldstring correct zou worden gesplitst (ook al worden de > en = als afzonderlijke scheidingstekens geteld).

EDIT als u c_str() niet wilt gebruiken om van string naar char* te converteren, kunt u substr en find_first_of om te tokeniseren.

string token, mystring("scott>=tiger");
while(token != mystring){
  token = mystring.substr(0,mystring.find_first_of(">="));
  mystring = mystring.substr(mystring.find_first_of(">=") + 1);
  printf("%s ",token.c_str());
}

Antwoord 8

Het antwoord is er al, maar het geselecteerde antwoord gebruikt de wisfunctie die erg duur is, denk aan een hele grote reeks (in MB’s). Daarom gebruik ik onderstaande functie.

vector<string> split(const string& i_str, const string& i_delim)
{
    vector<string> result;
    size_t found = i_str.find(i_delim);
    size_t startIndex = 0;
    while(found != string::npos)
    {
        result.push_back(string(i_str.begin()+startIndex, i_str.begin()+found));
        startIndex = found + i_delim.size();
        found = i_str.find(i_delim, startIndex);
    }
    if(startIndex != i_str.size())
        result.push_back(string(i_str.begin()+startIndex, i_str.end()));
    return result;      
}

Antwoord 9

Ik zou boost::tokenizer gebruiken. Hier is documentatie waarin wordt uitgelegd hoe u een geschikte tokenizer-functie kunt maken: http:// www.boost.org/doc/libs/1_52_0/libs/tokenizer/tokenizerfunction.htm

Hier is er een die voor uw geval werkt.

struct my_tokenizer_func
{
    template<typename It>
    bool operator()(It& next, It end, std::string & tok)
    {
        if (next == end)
            return false;
        char const * del = ">=";
        auto pos = std::search(next, end, del, del + 2);
        tok.assign(next, pos);
        next = pos;
        if (next != end)
            std::advance(next, 2);
        return true;
    }
    void reset() {}
};
int main()
{
    std::string to_be_parsed = "1) one>=2) two>=3) three>=4) four";
    for (auto i : boost::tokenizer<my_tokenizer_func>(to_be_parsed))
        std::cout << i << '\n';
}

Antwoord 10

Hier is mijn mening hierover. Het behandelt de randgevallen en neemt een optionele parameter om lege vermeldingen uit de resultaten te verwijderen.

bool endsWith(const std::string& s, const std::string& suffix)
{
    return s.size() >= suffix.size() &&
           s.substr(s.size() - suffix.size()) == suffix;
}
std::vector<std::string> split(const std::string& s, const std::string& delimiter, const bool& removeEmptyEntries = false)
{
    std::vector<std::string> tokens;
    for (size_t start = 0, end; start < s.length(); start = end + delimiter.length())
    {
         size_t position = s.find(delimiter, start);
         end = position != string::npos ? position : s.length();
         std::string token = s.substr(start, end - start);
         if (!removeEmptyEntries || !token.empty())
         {
             tokens.push_back(token);
         }
    }
    if (!removeEmptyEntries &&
        (s.empty() || endsWith(s, delimiter)))
    {
        tokens.push_back("");
    }
    return tokens;
}

Voorbeelden

split("a-b-c", "-"); // [3]("a","b","c")
split("a--c", "-"); // [3]("a","","c")
split("-b-", "-"); // [3]("","b","")
split("--c--", "-"); // [5]("","","c","","")
split("--c--", "-", true); // [1]("c")
split("a", "-"); // [1]("a")
split("", "-"); // [1]("")
split("", "-", true); // [0]()

Antwoord 11

Dit zou perfect moeten werken voor scheidingstekens voor tekenreeksen (of enkele tekens). Vergeet niet om #include <sstream> op te nemen.

std::string input = "Alfa=,+Bravo=,+Charlie=,+Delta";
std::string delimiter = "=,+"; 
std::istringstream ss(input);
std::string token;
std::string::iterator it;
while(std::getline(ss, token, *(it = delimiter.begin()))) {
    std::cout << token << std::endl; // Token is extracted using '='
    it++;
    // Skip the rest of delimiter if exists ",+"
    while(it != delimiter.end() and ss.peek() == *(it)) { 
        it++; ss.get(); 
    }
}

De eerste while-lus extraheert een token met het eerste teken van het tekenreeksscheidingsteken. De tweede while-lus slaat de rest van het scheidingsteken over en stopt aan het begin van het volgende token.

Antwoord 12

Een manier om het te doen met C++20 :

#include <iostream>
#include <ranges>
#include <string_view>
int main()
{
    std::string hello = "text to be parsed";
    auto split = hello
        | std::ranges::views::split(' ')
        | std::ranges::views::transform([](auto&& str) { return std::string_view(&*str.begin(), std::ranges::distance(str)); });
    for (auto&& word : split)
    {
        std::cout << word << std::endl;
    }
}

Zie:
https://stackoverflow.com/a/48403210/10771848
https://en.cppreference.com/w/cpp/ranges/split_view

Antwoord 13

Dit is een complete methode die de string op een willekeurig scheidingsteken splitst en een vector van de opgedeelde strings retourneert.

Het is een bewerking van het antwoord van ryanbwork. Zijn controle op: if(token != mystring) geeft echter verkeerde resultaten als je herhalende elementen in je string hebt. Dit is mijn oplossing voor dat probleem.

vector<string> Split(string mystring, string delimiter)
{
    vector<string> subStringList;
    string token;
    while (true)
    {
        size_t findfirst = mystring.find_first_of(delimiter);
        if (findfirst == string::npos) //find_first_of returns npos if it couldn't find the delimiter anymore
        {
            subStringList.push_back(mystring); //push back the final piece of mystring
            return subStringList;
        }
        token = mystring.substr(0, mystring.find_first_of(delimiter));
        mystring = mystring.substr(mystring.find_first_of(delimiter) + 1);
        subStringList.push_back(token);
    }
    return subStringList;
}

Antwoord 14

Een zeer eenvoudige/naïeve benadering:

vector<string> words_seperate(string s){
    vector<string> ans;
    string w="";
    for(auto i:s){
        if(i==' '){
           ans.push_back(w);
           w="";
        }
        else{
           w+=i;
        }
    }
    ans.push_back(w);
    return ans;
}

Of u kunt de functie voor het splitsen van de bibliotheek gebruiken:

vector<string> result; 
boost::split(result, input, boost::is_any_of("\t"));

Of je kunt TOKEN of strtok proberen:

char str[] = "DELIMIT-ME-C++"; 
char *token = strtok(str, "-"); 
while (token) 
{ 
    cout<<token; 
    token = strtok(NULL, "-"); 
} 

Of u kunt dit doen:

char split_with=' ';
vector<string> words;
string token; 
stringstream ss(our_string);
while(getline(ss , token , split_with)) words.push_back(token);

Antwoord 15

Aangezien dit het best beoordeelde Stack Overflow Google-zoekresultaat is voor C++ split string of iets dergelijks, zal ik een compleet, door kopiëren/plakken uitvoerbaar voorbeeld plaatsen dat beide methoden laat zien.

splitString gebruikt stringstream (in de meeste gevallen waarschijnlijk de betere en gemakkelijkere optie)

splitString2 gebruikt find en substr (een meer handmatige benadering)

// SplitString.cpp
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
// function prototypes
std::vector<std::string> splitString(const std::string& str, char delim);
std::vector<std::string> splitString2(const std::string& str, char delim);
std::string getSubstring(const std::string& str, int leftIdx, int rightIdx);
int main(void)
{
  // Test cases - all will pass
  std::string str = "ab,cd,ef";
  //std::string str = "abcdef";
  //std::string str = "";
  //std::string str = ",cd,ef";
  //std::string str = "ab,cd,";   // behavior of splitString and splitString2 is different for this final case only, if this case matters to you choose which one you need as applicable
  std::vector<std::string> tokens = splitString(str, ',');
  std::cout << "tokens: " << "\n";
  if (tokens.empty())
  {
    std::cout << "(tokens is empty)" << "\n";
  }
  else
  {
    for (auto& token : tokens)
    {
      if (token == "") std::cout << "(empty string)" << "\n";
      else std::cout << token << "\n";
    }
  }
  return 0;
}
std::vector<std::string> splitString(const std::string& str, char delim)
{
  std::vector<std::string> tokens;
  if (str == "") return tokens;
  std::string currentToken;
  std::stringstream ss(str);
  while (std::getline(ss, currentToken, delim))
  {
    tokens.push_back(currentToken);
  }
  return tokens;
}
std::vector<std::string> splitString2(const std::string& str, char delim)
{
  std::vector<std::string> tokens;
  if (str == "") return tokens;
  int leftIdx = 0;
  int delimIdx = str.find(delim);
  int rightIdx;
  while (delimIdx != std::string::npos)
  {
    rightIdx = delimIdx - 1;
    std::string token = getSubstring(str, leftIdx, rightIdx);
    tokens.push_back(token);
    // prep for next time around
    leftIdx = delimIdx + 1;
    delimIdx = str.find(delim, delimIdx + 1);
  }
  rightIdx = str.size() - 1;
  std::string token = getSubstring(str, leftIdx, rightIdx);
  tokens.push_back(token);
  return tokens;
}
std::string getSubstring(const std::string& str, int leftIdx, int rightIdx)
{
  return str.substr(leftIdx, rightIdx - leftIdx + 1);
}

Antwoord 16

Als u de string niet wilt wijzigen (zoals in het antwoord van Vincenzo Pii) en ook het laatste token wilt uitvoeren, kunt u deze benadering gebruiken:

inline std::vector<std::string> splitString( const std::string &s, const std::string &delimiter ){
    std::vector<std::string> ret;
    size_t start = 0;
    size_t end = 0;
    size_t len = 0;
    std::string token;
    do{ end = s.find(delimiter,start); 
        len = end - start;
        token = s.substr(start, len);
        ret.emplace_back( token );
        start += len + delimiter.length();
        std::cout << token << std::endl;
    }while ( end != std::string::npos );
    return ret;
}

Antwoord 17

std::vector<std::string> parse(std::string str,std::string delim){
    std::vector<std::string> tokens;
    char *str_c = strdup(str.c_str()); 
    char* token = NULL;
    token = strtok(str_c, delim.c_str()); 
    while (token != NULL) { 
        tokens.push_back(std::string(token));  
        token = strtok(NULL, delim.c_str()); 
    }
    delete[] str_c;
    return tokens;
}

Antwoord 18

Nog een ander antwoord: hier gebruik ik de find_first_not_of tekenreeksfunctie die retourneert de positie van het eerste teken dat niet overeenkomt met een van de tekens gespecificeerd in het scheidingsteken.

size_t find_first_not_of(const string& delim, size_t pos = 0) const noexcept;

Voorbeeld:

int main()
{
    size_t start = 0, end = 0;
    std::string str = "scott>=tiger>=cat";
    std::string delim = ">=";
    while ((start = str.find_first_not_of(delim, end)) != std::string::npos)
    {
        end = str.find(delim, start); // finds the 'first' occurance from the 'start'
        std::cout << str.substr(start, end - start)<<std::endl; // extract substring
    }
    return 0;
}

Uitvoer:

    scott
    tiger
    cat

Antwoord 19

Ik maak deze oplossing. Het is heel eenvoudig, alle afdrukken/waarden zitten in de lus (het is niet nodig om na de lus te controleren).

#include <iostream>
#include <string>
using std::cout;
using std::string;
int main() {
    string s = "it-+is-+working!";
    string d = "-+";
    int firstFindI = 0;
    int secendFindI = s.find(d, 0); // find if have any at all
    while (secendFindI != string::npos)
    {
        secendFindI = s.find(d, firstFindI);
        cout << s.substr(firstFindI, secendFindI - firstFindI) << "\n"; // print sliced part
        firstFindI = secendFindI + d.size(); // add to the search index
    }
}

Het enige nadeel van deze oplossing is dat je in het begin twee keer moet zoeken.

Antwoord 20

#include<iostream>
#include<algorithm>
using namespace std;
int split_count(string str,char delimit){
return count(str.begin(),str.end(),delimit);
}
void split(string str,char delimit,string res[]){
int a=0,i=0;
while(a<str.size()){
res[i]=str.substr(a,str.find(delimit));
a+=res[i].size()+1;
i++;
}
}
int main(){
string a="abc.xyz.mno.def";
int x=split_count(a,'.')+1;
string res[x];
split(a,'.',res);
for(int i=0;i<x;i++)
cout<<res[i]<<endl;
  return 0;
}

P.S: Werkt alleen als de lengtes van de strings na het splitsen gelijk zijn

Antwoord 21

Functie:

std::vector<std::string> WSJCppCore::split(const std::string& sWhat, const std::string& sDelim) {
    std::vector<std::string> vRet;
    size_t nPos = 0;
    size_t nLen = sWhat.length();
    size_t nDelimLen = sDelim.length();
    while (nPos < nLen) {
        std::size_t nFoundPos = sWhat.find(sDelim, nPos);
        if (nFoundPos != std::string::npos) {
            std::string sToken = sWhat.substr(nPos, nFoundPos - nPos);
            vRet.push_back(sToken);
            nPos = nFoundPos + nDelimLen;
            if (nFoundPos + nDelimLen == nLen) { // last delimiter
                vRet.push_back("");
            }
        } else {
            std::string sToken = sWhat.substr(nPos, nLen - nPos);
            vRet.push_back(sToken);
            break;
        }
    }
    return vRet;
}

Eenheidstests:

bool UnitTestSplit::run() {
bool bTestSuccess = true;
    struct LTest {
        LTest(
            const std::string &sStr,
            const std::string &sDelim,
            const std::vector<std::string> &vExpectedVector
        ) {
            this->sStr = sStr;
            this->sDelim = sDelim;
            this->vExpectedVector = vExpectedVector;
        };
        std::string sStr;
        std::string sDelim;
        std::vector<std::string> vExpectedVector;
    };
    std::vector<LTest> tests;
    tests.push_back(LTest("1 2 3 4 5", " ", {"1", "2", "3", "4", "5"}));
    tests.push_back(LTest("|1f|2п|3%^|44354|5kdasjfdre|2", "|", {"", "1f", "2п", "3%^", "44354", "5kdasjfdre", "2"}));
    tests.push_back(LTest("|1f|2п|3%^|44354|5kdasjfdre|", "|", {"", "1f", "2п", "3%^", "44354", "5kdasjfdre", ""}));
    tests.push_back(LTest("some1 => some2 => some3", "=>", {"some1 ", " some2 ", " some3"}));
    tests.push_back(LTest("some1 => some2 => some3 =>", "=>", {"some1 ", " some2 ", " some3 ", ""}));
    for (int i = 0; i < tests.size(); i++) {
        LTest test = tests[i];
        std::string sPrefix = "test" + std::to_string(i) + "(\"" + test.sStr + "\")";
        std::vector<std::string> vSplitted = WSJCppCore::split(test.sStr, test.sDelim);
        compareN(bTestSuccess, sPrefix + ": size", vSplitted.size(), test.vExpectedVector.size());
        int nMin = std::min(vSplitted.size(), test.vExpectedVector.size());
        for (int n = 0; n < nMin; n++) {
            compareS(bTestSuccess, sPrefix + ", element: " + std::to_string(n), vSplitted[n], test.vExpectedVector[n]);
        }
    }
    return bTestSuccess;
}

Antwoord 22

Als bonus is hier een codevoorbeeld van een splitfunctie en macro die gemakkelijk te gebruiken is en waar u het containertype kunt kiezen:

#include <iostream>
#include <vector>
#include <string>
#define split(str, delim, type) (split_fn<type<std::string>>(str, delim))
template <typename Container>
Container split_fn(const std::string& str, char delim = ' ') {
    Container cont{};
    std::size_t current, previous = 0;
    current = str.find(delim);
    while (current != std::string::npos) {
        cont.push_back(str.substr(previous, current - previous));
        previous = current + 1;
        current = str.find(delim, previous);
    }
    cont.push_back(str.substr(previous, current - previous));
    return cont;
}
int main() {
    auto test = std::string{"This is a great test"};
    auto res = split(test, ' ', std::vector);
    for(auto &i : res) {
        std::cout << i << ", "; // "this", "is", "a", "great", "test"
    }
    return 0;
}

Antwoord 23

ik gebruik pointer-rekenkunde. inner while voor string delimeter als je satify met char delim verwijder gewoon inner while. ik hoop dat het klopt. als je een fout of verbetering opmerkt, laat dan een reactie achter.

std::vector<std::string> split(std::string s, std::string delim)
{
    char *p = &s[0];
    char *d = &delim[0];
    std::vector<std::string> res = {""};
    do
    {
        bool is_delim = true;
        char *pp = p;
        char *dd = d;
        while (*dd && is_delim == true)
            if (*pp++ != *dd++)
                is_delim = false;
        if (is_delim)
        {
            p = pp - 1;
            res.push_back("");
        }
        else
            *(res.rbegin()) += *p;
    } while (*p++);
    return res;
}

Antwoord 24

template<typename C, typename T>
auto insert_in_container(C& c, T&& t) -> decltype(c.push_back(std::forward<T>(t)), void()) {
    c.push_back(std::forward<T>(t));
}
template<typename C, typename T>
auto insert_in_container(C& c, T&& t) -> decltype(c.insert(std::forward<T>(t)), void()) {
    c.insert(std::forward<T>(t));
}
template<typename Container>
Container splitR(const std::string& input, const std::string& delims) {
    Container out;
    size_t delims_len = delims.size();
    auto begIdx = 0u;
    auto endIdx = input.find(delims, begIdx);
    if (endIdx == std::string::npos && input.size() != 0u) {
        insert_in_container(out, input);
    }
    else {
        size_t w = 0;
        while (endIdx != std::string::npos) {
            w = endIdx - begIdx;
            if (w != 0) insert_in_container(out, input.substr(begIdx, w));
            begIdx = endIdx + delims_len;
            endIdx = input.find(delims, begIdx);
        }
        w = input.length() - begIdx;
        if (w != 0) insert_in_container(out, input.substr(begIdx, w));
    }
    return out;
}

Antwoord 25

Hier is een beknopte split-functie. Ik heb besloten om scheidingstekens van achteren naar voren te laten komen als een lege tekenreeks, maar je kunt dat eenvoudig controleren als de subtekenreeks leeg is en deze niet aan de vector toevoegen als dat zo is.

#include <vector>
#include <string>
using namespace std;
vector<string> split(string to_split, string delimiter) {
    size_t pos = 0;
    vector<string> matches{};
    do {
        pos = to_split.find(delimiter);
        int change_end;
        if (pos == string::npos) {
            pos = to_split.length() - 1;
            change_end = 1;
        }
        else {
            change_end = 0;
        }
        matches.push_back(to_split.substr(0, pos+change_end));
        to_split.erase(0, pos+1);
    }
    while (!to_split.empty());
    return matches;
}

Antwoord 26

Sinds C++11 kan het als volgt:

std::vector<std::string> splitString(const std::string& str,
                                     const std::regex& regex)
{
  return {std::sregex_token_iterator{str.begin(), str.end(), regex, -1}, 
          std::sregex_token_iterator() };
} 
// usually we have a predefined set of regular expressions: then
// let's build those only once and re-use them multiple times
static const std::regex regex1(R"some-reg-exp1", std::regex::optimize);
static const std::regex regex2(R"some-reg-exp2", std::regex::optimize);
static const std::regex regex3(R"some-reg-exp3", std::regex::optimize);
string str = "some string to split";
std::vector<std::string> tokens( splitString(str, regex1) ); 

Opmerkingen:

Antwoord 27

std::vector<std::string> split(const std::string& s, char c) {
  std::vector<std::string> v;
  unsigned int ii = 0;
  unsigned int j = s.find(c);
  while (j < s.length()) {
    v.push_back(s.substr(i, j - i));
    i = ++j;
    j = s.find(c, j);
    if (j >= s.length()) {
      v.push_back(s.substr(i, s,length()));
      break;
    }
  }
  return v;
}

LEAVE A REPLY

Please enter your comment!
Please enter your name here

nine − one =

Other episodes