Java有一个方便的分割方法:
String str = "The quick brown fox";
String[] results = str.split(" ");
在c++中有简单的方法来做到这一点吗?
Java有一个方便的分割方法:
String str = "The quick brown fox";
String[] results = str.split(" ");
在c++中有简单的方法来做到这一点吗?
当前回答
我认为这就是字符串流上的>>操作符的用途:
string word; sin >> word;
其他回答
我知道你想要一个c++的解决方案,但你可能会认为这是有帮助的:
Qt
#include <QString>
...
QString str = "The quick brown fox";
QStringList results = str.split(" ");
在这个例子中,与Boost相比的优势在于,它直接一对一地映射到你的文章代码。
详见Qt文档
我只是看了所有的答案,找不到下一个前提条件的解决方案:
没有动态内存分配 不使用boost 不使用正则表达式 c++17标准
这就是我的解
#include <iomanip>
#include <iostream>
#include <iterator>
#include <string_view>
#include <utility>
struct split_by_spaces
{
std::string_view text;
static constexpr char delim = ' ';
struct iterator
{
const std::string_view& text;
std::size_t cur_pos;
std::size_t end_pos;
std::string_view operator*() const
{
return { &text[cur_pos], end_pos - cur_pos };
}
bool operator==(const iterator& other) const
{
return cur_pos == other.cur_pos && end_pos == other.end_pos;
}
bool operator!=(const iterator& other) const
{
return !(*this == other);
}
iterator& operator++()
{
cur_pos = text.find_first_not_of(delim, end_pos);
if (cur_pos == std::string_view::npos)
{
cur_pos = text.size();
end_pos = cur_pos;
return *this;
}
end_pos = text.find(delim, cur_pos);
if (cur_pos == std::string_view::npos)
{
end_pos = text.size();
}
return *this;
}
};
[[nodiscard]] iterator begin() const
{
auto start = text.find_first_not_of(delim);
if (start == std::string_view::npos)
{
return iterator{ text, text.size(), text.size() };
}
auto end_word = text.find(delim, start);
if (end_word == std::string_view::npos)
{
end_word = text.size();
}
return iterator{ text, start, end_word };
}
[[nodiscard]] iterator end() const
{
return iterator{ text, text.size(), text.size() };
}
};
int main(int argc, char** argv)
{
using namespace std::literals;
auto str = " there should be no memory allocation during parsing"
" into words this line and you should'n create any"
" contaner for intermediate words "sv;
auto comma = "";
for (std::string_view word : split_by_spaces{ str })
{
std::cout << std::exchange(comma, ",") << std::quoted(word);
}
auto only_spaces = " "sv;
for (std::string_view word : split_by_spaces{ only_spaces })
{
std::cout << "you will not see this line in output" << std::endl;
}
}
简单的c++代码(标准c++ 98),接受多个分隔符(在std::string中指定),只使用向量、字符串和迭代器。
#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>
std::vector<std::string>
split(const std::string& str, const std::string& delim){
std::vector<std::string> result;
if (str.empty())
throw std::runtime_error("Can not tokenize an empty string!");
std::string::const_iterator begin, str_it;
begin = str_it = str.begin();
do {
while (delim.find(*str_it) == std::string::npos && str_it != str.end())
str_it++; // find the position of the first delimiter in str
std::string token = std::string(begin, str_it); // grab the token
if (!token.empty()) // empty token only when str starts with a delimiter
result.push_back(token); // push the token into a vector<string>
while (delim.find(*str_it) != std::string::npos && str_it != str.end())
str_it++; // ignore the additional consecutive delimiters
begin = str_it; // process the remaining tokens
} while (str_it != str.end());
return result;
}
int main() {
std::string test_string = ".this is.a.../.simple;;test;;;END";
std::string delim = "; ./"; // string containing the delimiters
std::vector<std::string> tokens = split(test_string, delim);
for (std::vector<std::string>::const_iterator it = tokens.begin();
it != tokens.end(); it++)
std::cout << *it << std::endl;
}
这里有许多过于复杂的建议。试试这个简单的std::string解决方案:
using namespace std;
string someText = ...
string::size_type tokenOff = 0, sepOff = tokenOff;
while (sepOff != string::npos)
{
sepOff = someText.find(' ', sepOff);
string::size_type tokenLen = (sepOff == string::npos) ? sepOff : sepOff++ - tokenOff;
string token = someText.substr(tokenOff, tokenLen);
if (!token.empty())
/* do something with token */;
tokenOff = sepOff;
}
c++标准库算法普遍基于迭代器,而不是具体的容器。不幸的是,这使得在c++标准库中很难提供类似java的split函数,尽管没有人认为这很方便。但是它的返回类型是什么呢?std::向量< std:: basic_string <…> >吗?也许吧,但这样我们就被迫执行(可能是冗余的和昂贵的)分配。
相反,c++提供了大量基于任意复杂的分隔符分割字符串的方法,但它们都没有像其他语言中那样封装得很好。各种各样的方法填满了整个博客文章。
在最简单的情况下,你可以使用std::string::find进行迭代,直到你击中std::string::npos,然后使用std::string::substr提取内容。
一个更流畅的(和惯用的,但基本的)版本在空格上拆分将使用std::istringstream:
auto iss = std::istringstream{"The quick brown fox"};
auto str = std::string{};
while (iss >> str) {
process(str);
}
使用std::istream_iterators,还可以使用vector的迭代器范围构造函数将string流的内容复制到vector中。
多个库(如Boost.Tokenizer)提供特定的标记器。
更高级的分裂需要正则表达式。c++特别为此提供了std::regex_token_iterator:
auto const str = "The quick brown fox"s;
auto const re = std::regex{R"(\s+)"};
auto const vec = std::vector<std::string>(
std::sregex_token_iterator{begin(str), end(str), re, -1},
std::sregex_token_iterator{}
);