C++ 用多个分隔符将字符串拆分为单词

C++ 用多个分隔符将字符串拆分为单词,c++,string,token,delimiter,C++,String,Token,Delimiter,我有一些文本(有意义的文本或算术表达式),我想将其拆分为单词。 如果我只有一个分隔符,我会使用: std::stringstream stringStream(inputString); std::string word; while(std::getline(stringStream, word, delimiter)) { wordVector.push_back(word); } 如何将字符串拆分为带有多个分隔符的标记 假设其中一个分隔符是换行符,下面的代码将读取该行并用分隔符

我有一些文本(有意义的文本或算术表达式),我想将其拆分为单词。
如果我只有一个分隔符,我会使用:

std::stringstream stringStream(inputString);
std::string word;
while(std::getline(stringStream, word, delimiter)) 
{
    wordVector.push_back(word);
}

如何将字符串拆分为带有多个分隔符的标记

假设其中一个分隔符是换行符,下面的代码将读取该行并用分隔符将其进一步拆分。对于这个例子,我选择了分隔符空格、撇号和分号

std::stringstream stringStream(inputString);
std::string line;
while(std::getline(stringStream, line)) 
{
    std::size_t prev = 0, pos;
    while ((pos = line.find_first_of(" ';", prev)) != std::string::npos)
    {
        if (pos > prev)
            wordVector.push_back(line.substr(prev, pos-prev));
        prev = pos+1;
    }
    if (prev < line.length())
        wordVector.push_back(line.substr(prev, std::string::npos));
}
std::stringstream(inputString);
std::字符串行;
while(std::getline(stringStream,line))
{
标准::尺寸前=0,位置;
while((pos=line.find_first_of(“;”,prev))!=std::string::npos)
{
如果(位置>上一个)
wordVector.push_back(line.substr(prev,pos-prev));
上一个=位置+1;
}
如果(上一个
如果您有boost,您可以使用:

#include <boost/algorithm/string.hpp>
std::string inputString("One!Two,Three:Four");
std::string delimiters("|,:");
std::vector<std::string> parts;
boost::split(parts, inputString, boost::is_any_of(delimiters));
#包括
字符串输入字符串(“一!二,三:四”);
std::字符串分隔符(“|,:”);
向量部分;
boost::split(parts、inputString、boost::是(分隔符)的任意一个);

如果您对如何自己做而不使用boost感兴趣

假设分隔符字符串可能很长,比如说M,如果它是分隔符,那么检查字符串中的每个字符将花费O(M)个,因此在循环中检查原始字符串中的所有字符,比如长度N,是O(M*N)

我会使用一个字典(就像“delimiter”到“booleans”的映射,但这里我会使用一个简单的布尔数组,每个分隔符都有true in index=ascii值)

现在对字符串进行迭代,并检查字符是否是分隔符是O(1),这最终会给出O(N)

以下是我的示例代码:

const int dictSize = 256;    

vector<string> tokenizeMyString(const string &s, const string &del)
{
    static bool dict[dictSize] = { false};

    vector<string> res;
    for (int i = 0; i < del.size(); ++i) {      
        dict[del[i]] = true;
    }

    string token("");
    for (auto &i : s) {
        if (dict[i]) {
            if (!token.empty()) {
                res.push_back(token);
                token.clear();
            }           
        }
        else {
            token += i;
        }
    }
    if (!token.empty()) {
        res.push_back(token);
    }
    return res;
}


int main()
{
    string delString = "MyDog:Odie, MyCat:Garfield  MyNumber:1001001";
//the delimiters are " " (space) and "," (comma) 
    vector<string> res = tokenizeMyString(delString, " ,");

    for (auto &i : res) {

        cout << "token: " << i << endl;
    }
return 0;
}
const int dictSize=256;
向量标记系统(常量字符串&s、常量字符串&del)
{
静态bool dict[dictSize]={false};
向量res;
对于(inti=0;i我不知道为什么没有人指出手动方式,但这里是:

const std::string delims(";,:. \n\t");
inline bool isDelim(char c) {
    for (int i = 0; i < delims.size(); ++i)
        if (delims[i] == c)
            return true;
    return false;
}

通过这种方式,如果您愿意,您可以使用delims做一些有用的事情。

使用Eric Niebler的range-v3库:

#包括
#包括
#包括“range/v3/all.hpp”
int main()
{
std::string s=“user1:192.168.0.1 | user2:192.168.0.2 | user3:192.168.0.3”;
自动单词=s
|范围::视图::拆分(“|”)
|范围::视图::转换([](自动w){
返回w | ranges::view::split(“:”);
});
ranges::for_each(words,[](auto i){std::cout使用
std::regex
std::regex
可以在几行中进行字符串拆分:

std::regex re("[\\|,:]");
std::sregex_token_iterator first{input.begin(), input.end(), re, -1}, last;//the '-1' is what makes the regex split (-1 := what was not matched)
std::vector<std::string> tokens{first, last};
std::regex-re(“[\\\\,:]”);
std::sregex_token_迭代器first{input.begin(),input.end(),re,-1},last;//使正则表达式拆分的是“-1:=不匹配的内容)
向量标记{first,last};

Boost.StringAlgorithm或Boost.Tokenizer会有所帮助。或者,您可以从以下答案中获得一些想法:@K-ballo:根据问题,您不应该使用像Boost这样的外部库。@MasoudM.:Boost仍然算是外部库吗;)?就我而言,Boost就像我的标准库,它是内置的!@MatthieuM.:那么,Qt对我来说也不是外部库。你对我来说太快了:p如果换行符不是分隔符,那么只需选择一个“常规”分隔符(并将其从内部循环中删除)可以在循环中移动std::string word;和char c;,避免使用clear()…变量应该尽可能是局部的和短暂的。这就像让某人打开一罐泡菜,然后你拿出一把电锯。为什么这只有很少的投票。这真是太棒了!几行,不需要外部库和一些新奇的东西。非常感谢!@berkayberabi没问题-我想这是一个迟来的答案这就是为什么。如果你想,你可以发布一个悬赏来奖励现有的答案(这也会引起注意)。嗨,我没有那么高的声誉。但我还有一个问题。如果我也想根据括号拆分为delimeter([])如何传递括号。如果我只输入括号,它们将被解释为另一个正则表达式,而它不会work@berkayberabi通过
\\]
转义这个例子怎么样?text=“Windows.Apple”我只想看['Windows”,“Apple']。这个正则表达式给出[
Windows
,'',
Apple
],其中包含一个空格(“”)我不需要。这对多个分隔符如何工作?
#include <string>
#include <iostream>
#include "range/v3/all.hpp"

int main()
{
    std::string s = "user1:192.168.0.1|user2:192.168.0.2|user3:192.168.0.3";
    auto words = s  
        | ranges::view::split('|')
        | ranges::view::transform([](auto w){
            return w | ranges::view::split(':');
        });
      ranges::for_each(words, [](auto i){ std::cout << i  << "\n"; });
}
std::regex re("[\\|,:]");
std::sregex_token_iterator first{input.begin(), input.end(), re, -1}, last;//the '-1' is what makes the regex split (-1 := what was not matched)
std::vector<std::string> tokens{first, last};