首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >StrSplit模板

StrSplit模板
EN

Stack Overflow用户
提问于 2022-08-28 05:36:23
回答 2查看 69关注 0票数 0

我试图将此函数转换为模板:

代码语言:javascript
复制
std::vector<std::string> StrSplit(const std::string& i_str, const std::string& i_delim)
{
    std::vector<std::string> result;

    size_t found = i_str.find(i_delim);
    size_t startIndex = 0;

    while (found != std::string::npos)
    {
        result.emplace_back(std::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.emplace_back(std::string(i_str.begin() + startIndex, i_str.end()));
    return result;
}

目标是让它支持我尝试过的stringwstring

代码语言:javascript
复制
template <typename T, typename T2>
std::vector<T> StrSplit(T& i_str, T2& i_delim)
{
    std::vector<T> result;

    size_t found = i_str.find(i_delim);
    size_t startIndex = 0;

    while (found != T::npos)
    {
        result.emplace_back(T(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.emplace_back(T(i_str.begin() + startIndex, i_str.end()));
    return result;
}

我得到了一个错误:binary '=': no operator found which takes a right-hand operand of type 'T' (or there is no acceptable conversion)

我对模板知之甚少,这条错误信息也没有多大帮助。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-28 05:58:54

您似乎对Tstd::string还是std::vector<std::string>感到有点困惑。您的一些代码将其视为第一个代码,一些代码将其视为第二个代码。

这是我的努力。我保留了const (为什么要删除这些),并且只有一个模板参数,因为我看不出您希望在一个函数调用中混合不同的字符串类型。

我还删除了显式的T构造函数调用。在此代码中或在原始代码中使用emplace_back时,这是不必要的。

代码语言:javascript
复制
template <typename T>
std::vector<T> StrSplit(const T& i_str, const T& i_delim)
{
    std::vector<T> result;

    size_t found = i_str.find(i_delim);
    size_t startIndex = 0;

    while (found != T::npos)
    {
        result.emplace_back(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.emplace_back(i_str.begin() + startIndex, i_str.end());
    return result;
}

由于这段代码确实依赖于字符串的参数,所以另一种方法是对字符类型进行模板,而不是字符串类型。像这样

代码语言:javascript
复制
template <typename T>
std::vector<std::basic_string<T>> StrSplit(const std::basic_string<T>& i_str, const std::basic_string<T>& i_delim)
{
    std::vector<std::basic_string<T>> result;

    size_t found = i_str.find(i_delim);
    size_t startIndex = 0;

    while (found != std::basic_string<T>::npos)
    {
        result.emplace_back(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.emplace_back(i_str.begin() + startIndex, i_str.end());
    return result;
}
票数 1
EN

Stack Overflow用户

发布于 2022-08-28 09:13:07

除了已经回答和注释过的显而易见的情况外,您还可以使用更短的形式来拆分字符串。C++在这方面有一个专门的功能。

std::regex_token_iterator。请读这里关于这件事。它存在于C++11之后,由于正则表达式的性质,它具有很强的通用性和强大性。(不过,也许对于某些用例来说太慢了)。

使用这个迭代器,您基本上可以遍历字符串中的模式。或者,将分隔符指定为模式。

结合std::vector范围构造函数(5),结果通常是用于拆分字符串的一行。

例如,见:

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <vector>
#include <regex>
#include <iterator>
using namespace std::string_literals;

template <typename C>
std::vector<std::basic_string<C>> split(const std::basic_string<C>& s, const std::basic_string<C>& delimiter) {
    const std::basic_regex<C> re{ delimiter };
    return { std::regex_token_iterator<std::basic_string<C>::const_iterator, C>( s.begin(), s.end(), re, -1),{} };
}

int main() {
    for (const auto& s : split("aXXbXXcXXd"s, "XX"s)) std::cout << s << ' ';
    for (const auto& ws : split(L"aaXXbbXXccXXdd"s, L"XX"s)) std::wcout << ws << ' ';
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73516265

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档