Trimming a string is a common operation in programming where you remove unnecessary whitespace from the beginning, end, or both sides of a string. In C++, several approaches can be taken to achieve this goal efficiently and effectively. This tutorial will guide you through different methods for trimming std::string
objects using standard library functions and other techniques.
Understanding String Trimming
String trimming is primarily used to clean up user input or data read from files where extraneous spaces may have been added unintentionally. There are three main types of string trimming:
- Left-trimming: Removes whitespace characters (spaces, tabs, newlines) from the beginning.
- Right-trimming: Removes whitespace characters from the end.
- Full trimming: Removes whitespace from both ends.
Using Standard Library Functions
C++11 Approach
C++11 introduced lambda functions and other modern constructs that simplify string manipulation. You can define inline functions to trim strings in place or return a modified copy:
#include <algorithm>
#include <cctype>
// Trim from start (in place)
inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}
// Trim from end (in place)
inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// Trim from both ends (in place)
inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
These functions use std::find_if
with lambda expressions to find the first non-whitespace character, efficiently removing whitespace.
C++03 Approach
Before C++11, developers relied on more verbose constructs. The following example demonstrates a similar approach without lambdas:
#include <algorithm>
#include <functional>
#include <cctype>
inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
std::not1(std::ptr_fun<int, int>(std::isspace))));
}
inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
}
Here, std::ptr_fun
is used to adapt the std::isspace
function for use with std::find_if
.
Boost Library
The Boost library provides convenient functions for string trimming:
#include <boost/algorithm/string.hpp>
// Using Boost's trim_right
std::string str = "hello world! ";
boost::trim_right(str); // str is now "hello world!"
// Trim both sides
boost::trim(str);
Boost functions can also create trimmed copies of strings or accept custom predicates for trimming, providing versatility.
Custom Trimming Functions
For those preferring standard library solutions without third-party dependencies, you can define your own trimming functions:
inline std::string& rtrim(std::string &s, const char* t = " \t\n\r\f\v") {
s.erase(s.find_last_not_of(t) + 1);
return s;
}
inline std::string& ltrim(std::string &s, const char* t = " \t\n\r\f\v") {
s.erase(0, s.find_first_not_of(t));
return s;
}
inline std::string& trim(std::string &s, const char* t = " \t\n\r\f\v") {
return ltrim(rtrim(s, t), t);
}
These functions use std::find_last_not_of
and std::find_first_not_of
to locate whitespace boundaries for trimming.
Conclusion
Trimming strings in C++ can be efficiently handled using various methods depending on your needs and constraints. Whether you prefer modern constructs introduced in C++11, the robustness of Boost libraries, or custom implementations with standard functions, there’s a suitable approach for every situation. By understanding these techniques, you can ensure your string manipulations are both efficient and maintainable.