STL split string function

Apr 8, 2007

4 min read

VC6

C++

Windows

Visual-Studio

STL

Dev

Advanced

Author picture

by David 'dex' Schwartz

Contributor

75k Views

Introduction

Splitting a string using a given delimiter is a very common operation.
Unfortunately the STL doesn't provide any direct way to achieve this.
This split implementation is templatised and uses type deduction to determine what kind of string and container are being passed as arguments, which must must be some form of basic_string<> and any container that implements the push_back() method.

You may either place this code directly into the file where it is used, or create a separate include file for it.

Note that the string type is not fully specified, allowing the traits and allocator to default.
In some situations this may not be what you want and some compilers might not like it.

Background

I wrote this when I found that the code written by Paul J. Weiss with the title STL Split String was more complex than I needed for this common simple case.

The most common case should be the easiest to write.

Source Code

template <typename E, typename C>
size_t split(std::basic_string<E> const& s,
             C &container,
             E const delimiter,
             bool keepBlankFields = true)
{
    size_t n = 0;
    std::basic_string<E>::const_iterator it = s.begin(), end = s.end(), first;
    for (first = it; it != end; ++it)
    {
        // Examine each character and if it matches the delimiter
        if (delimiter == *it)
        {
            if (keepBlankFields || first != it)
            {
                // extract the current field from the string and
                // append the current field to the given container
                container.push_back(std::basic_string<E>(first, it));
                ++n;
                
                // skip the delimiter
                first = it + 1;
            }
            else
            {
                ++first;
            }
        }
    }
    if (keepBlankFields || first != it)
    {
        // extract the last field from the string and
        // append the last field to the given container
        container.push_back(std::basic_string<E>(first, it));
        ++n;
    }
    return n;
}

Example Usage

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>

std::string tests[3] = {
    std::string(""),
    std::string("||three||five|"),
    std::string("|two|three||five|")
};

char* delimiter = "|";

for (int i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i)
{
    std::vector< std::basic_string<char> > x;
    size_t n = split(tests[i], x, delimiter[0], true);
    std::cout << n << "==" << x.size() << " fields" << std::endl;
    if (n)
    {
        std::copy(x.begin(), x.end(),
            std::ostream_iterator<std::string>(std::cout, delimiter));
        std::cout << std::endl;
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)