如何使用c ++拆分字符串,然后选择字符串的最后一部分?

时间:2018-11-25 04:34:26

标签: c++ split

我想分割一个字符串,然后打印字符串的数量,并打印定界符内的最后一个字符串?

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

1 个答案:

答案 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。

DEMO is here.

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

DEMO is here.

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::stringstd::string_view提出了一个可移植的通用拆分函数。 使用std::stringstd::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

DEMO is here.

// 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);