我在c++中使用以下方法解析字符串:
using namespace std;
string parsed,input="text to be parsed";
stringstream input_stringstream(input);
if (getline(input_stringstream,parsed,' '))
{
// do some processing.
}
使用单个字符分隔符进行解析是可以的。但是如果我想使用字符串作为分隔符呢?
例子:我想拆分:
scott>=tiger
用>=作为分隔符,这样我就可以得到斯科特和老虎。
一种非常简单/幼稚的方法:
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;
}
或者你可以使用boost库拆分函数:
vector<string> result;
boost::split(result, input, boost::is_any_of("\t"));
或者你可以尝试TOKEN或strtok:
char str[] = "DELIMIT-ME-C++";
char *token = strtok(str, "-");
while (token)
{
cout<<token;
token = strtok(NULL, "-");
}
或者你可以这样做:
char split_with=' ';
vector<string> words;
string token;
stringstream ss(our_string);
while(getline(ss , token , split_with)) words.push_back(token);
这段代码从文本中分离行,并将每个行添加到一个向量中。
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;
}
调用:
vector<string> listFilesMax = split(buffer, "\n");
我查看了答案,没有看到一个基于迭代器的方法可以被送入范围循环,所以我做了一个。
这使用了c++ 17 string_views,所以它不应该分配字符串的副本。
struct StringSplit
{
struct Iterator
{
size_t tokenStart_ = 0;
size_t tokenEnd_ = 0;
std::string str_;
std::string_view view_;
std::string delimiter_;
bool done_ = false;
Iterator()
{
// End iterator.
done_ = true;
}
Iterator(std::string str, std::string delimiter)
: str_{std::move(str)}, view_{str_}, delimiter_{
std::move(delimiter)}
{
tokenEnd_ = view_.find(delimiter_, tokenStart_);
}
std::string_view operator*()
{
return view_.substr(tokenStart_, tokenEnd_ - tokenStart_);
}
Iterator &operator++()
{
if (tokenEnd_ == std::string::npos)
{
done_ = true;
return *this;
}
tokenStart_ = tokenEnd_ + delimiter_.size();
tokenEnd_ = view_.find(delimiter_, tokenStart_);
return *this;
}
bool operator!=(Iterator &other)
{
// We only check if both points to the end.
if (done_ && other.done_)
{
return false;
}
return true;
}
};
Iterator beginIter_;
StringSplit(std::string str, std::string delim)
: beginIter_{std::move(str), std::move(delim)}
{
}
Iterator begin()
{
return beginIter_;
}
Iterator end()
{
return Iterator{};
}
};
示例用法如下:
int main()
{
for (auto token : StringSplit{"<>foo<>bar<><>bar<><>baz<><>", "<>"})
{
std::cout << "TOKEN: '" << token << "'" << std::endl;
}
}
打印:
TOKEN: ''
TOKEN: 'foo'
TOKEN: 'bar'
TOKEN: ''
TOKEN: 'bar'
TOKEN: ''
TOKEN: 'baz'
TOKEN: ''
TOKEN: ''
它正确地处理字符串开头和结尾的空项。
你也可以使用regex:
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;
}
这相当于:
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;
}
像这样使用它:
#include <iostream>
#include <string>
#include <regex>
std::vector<std::string> split(const std::string str,
const std::string regex_str) {
std::regex regexz(regex_str);
return {std::sregex_token_iterator(str.begin(), str.end(), regexz, -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;
}
}
在网上玩!
您可以简单地使用子字符串、字符等,或者使用实际的正则表达式来进行分割。
它也是简洁的c++ 11!