Trimming characters at start / end

suggest change

This example requires the headers <algorithm>, <locale>, and <utility>.

To trim a sequence or string means to remove all leading and trailing elements (or characters) matching a certain predicate. We first trim the trailing elements, because it doesn’t involve moving any elements, and then trim the leading elements. Note that the generalizations below work for all types of std::basic_string (e.g. std::string and std::wstring), and accidentally also for sequence containers (e.g. std::vector and std::list).

template <typename Sequence, // any basic_string, vector, list etc.
          typename Pred>     // a predicate on the element (character) type
Sequence& trim(Sequence& seq, Pred pred) {
    return trim_start(trim_end(seq, pred), pred);
}

Trimming the trailing elements involves finding the last element not matching the predicate, and erasing from there on:

template <typename Sequence, typename Pred>
Sequence& trim_end(Sequence& seq, Pred pred) {
    auto last = std::find_if_not(seq.rbegin(),
                                 seq.rend(),
                                 pred);
    seq.erase(last.base(), seq.end());
    return seq;
}

Trimming the leading elements involves finding the first element not matching the predicate and erasing up to there:

template <typename Sequence, typename Pred>
Sequence& trim_start(Sequence& seq, Pred pred) {
    auto first = std::find_if_not(seq.begin(),
                                  seq.end(),
                                  pred);
    seq.erase(seq.begin(), first);
    return seq;
}

To specialize the above for trimming whitespace in a std::string we can use the std::isspace() function as a predicate:

std::string& trim(std::string& str, const std::locale& loc = std::locale()) {
    return trim(str, [&loc](const char c){ return std::isspace(c, loc); });
}

std::string& trim_start(std::string& str, const std::locale& loc = std::locale()) {
    return trim_start(str, [&loc](const char c){ return std::isspace(c, loc); });
}

std::string& trim_end(std::string& str, const std::locale& loc = std::locale()) {
    return trim_end(str, [&loc](const char c){ return std::isspace(c, loc); });
}

Similarly, we can use the std::iswspace() function for std::wstring etc.

If you wish to create a new sequence that is a trimmed copy, then you can use a separate function:

template <typename Sequence, typename Pred>
Sequence trim_copy(Sequence seq, Pred pred) { // NOTE: passing seq by value
    trim(seq, pred);
    return seq;
}

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:


std::string:
* Trimming characters at start / end

Table Of Contents
8 Arrays
11 Loops
20 std::string
39 Streams
51 Unions
56 Lambdas
60 SFINAE
62 RAII
67 Sorting
84 RTTI
87 Scopes
104 Profiling
107 Recursion
117 Iteration
125 Alignment
134 Semaphore
136 Debugging
139 Mutexes
142 decltype