我想分割一个字符串,然后打印字符串的数量,并打印定界符内的最后一个字符串?
std::string s = ">=scott>=tiger>=mushroom>=>=abcd>=";
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;
我想计算字符串的数量,并像这样打印此字符串的最后一部分,我需要打印: 3 abcd
答案 0 :(得分:1)
编辑:我添加了一个最小的解决方案。
最小解决方案
假设我正确地理解了问题,那么我要做的就是定义一个适当的拆分函数。 由于您在 split 的定义中似乎会忽略拆分空字符串,因此,我期望以下拆分功能可以解决当前问题。 此函数计算非空字符串的数量,最后创建最后一个非空字符串:
std::pair<std::size_t, std::string>
check(const std::string& str, const std::string& delimiter)
{
std::size_t count = 0;
auto begin = str.begin();
auto end = str.begin();
for(auto it = str.begin();
it != str.cend();
it += ((it == str.cend()) ? 0 : delimiter.length()) )
{
const auto preit = it;
it = std::search(preit, str.cend(), delimiter.cbegin(), delimiter.cend());
if(it != preit)
{
++count;
begin = preit;
end = it;
}
}
return { count, std::string(begin, end) };
}
使用以下拆分功能,我们可以获得所需的输出3 abcd。
std::string s = ">=scott>=tiger>=mushroom>=>=abcd>=";
std::string delimiter = ">=";
const auto result = check(s, delimiter);
if(result.first != 0){
std::cout << (result.first - 1) << " " << result.second << std::endl;
}
常规拆分功能
如果还需要其他非空的分割字符串,则希望实现更通用的分割功能。
另外,由于一般的拆分功能在其他问题上很有用,因此我认为这是一个很好的机会。
在上述函数check
的if-section中创建字符串,并将其包含在std::vector
中,我们得到了一个更通用的拆分函数:
std::vector<std::string>
split(const std::string& str, const std::string& delimiter)
{
std::vector<std::string> strings;
for(auto it = str.begin();
it != str.cend();
it += ((it == str.cend()) ? 0 : delimiter.length()) )
{
const auto preit = it;
it = std::search(preit, str.cend(), delimiter.cbegin(), delimiter.cend());
if(it != preit){
strings.emplace_back(preit, it);
}
}
return strings;
}
使用以下拆分功能,我们再次获得所需的输出3 abcd
。
std::string s = ">=scott>=tiger>=mushroom>=>=abcd>=";
std::string delimiter = ">=";
const auto strings = split(s, delimiter);
if(!strings.empty()){
std::cout << (strings.size() - 1) << " " << strings.back() << std::endl;
}
C ++ 17和std::string_view
此外,在C ++ 17及更高版本中,std::string_view
也可用。
创建std::string_view
时,无需复制数据,它将提供一种有效的方法。
因此,在这里我还为std::string
和std::string_view
提出了一个可移植的通用拆分函数。
使用std::string
和std::string_view
几乎相同的ctor,即
basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
和
constexpr basic_string_view(const charT* str, size_type len);
,并使用通用参考定义以下模板功能
template<typename C>
auto split(C&& str, const std::string& delimiter)
{
std::vector<typename std::remove_reference<C>::type> strings;
for (auto p = str.data(), end = p + str.length();
p != end;
p += ((p==end) ? 0 : delimiter.length()) )
{
const auto pre = p;
p = std::search(pre, end, delimiter.cbegin(), delimiter.cend());
if (p != pre)
{
strings.emplace_back(pre, p - pre);
}
}
return strings;
}
,我们可以通过以下各种方式将s
除以delimiter
。
// std::string_view
const auto strings = split<std::string_view>(s, delimiter);
// std::string(s: lvalue reference)
const auto strings = split(s, delimiter);
// std::string(s: rvalue)
const auto strings = split(std::move(s), delimiter);