Start learning free

LESSON 63 OF 343 · STRINGS I

String Trim in C++: Stripping Leading and Trailing Spaces

Lesson Read the full explanation

In C++, there is no built-in string trim function, but we can write one using find_first_not_of and find_last_not_of. For this lesson, a trim() helper function has been provided for you:

// trim() removes leading and trailing spaces
string s = "  hello  ";
string result = trim(s);
// result == "hello"

Here is how a trim function works internally:

string trim(const string& s) {
    int start = 0, end = s.size() - 1;
    while (start <= end && s[start] == ' ') start++;
    while (end >= start && s[end] == ' ') end--;
    return s.substr(start, end - start + 1);
}

Assignment
Follow the Coding Tutorial and use the trim() helper to strip whitespace from s!


Hint
Use trim(s) and assign the result to result.

STEP 1 OF 1
    Ctrl + Enter to check

    C++ · STRINGS I

    String Strip in C++, explained

    What trimming means

    Trimming removes unwanted space from both ends of a string and leaves everything in the middle alone. " hello " becomes "hello", while a string like " hello world " keeps the space between the words. Programs trim text all the time, for instance before comparing a typed answer with an expected one.

    Other languages build this into the string (strip() or trim()). The C++ std::string has no such member, so you write a small function or use one provided for you. In this lesson, trim() is already available. You call it with the string as an argument.

    Using the helper

    string s = "  hello  ";
    string result = trim(s);
    // result is "hello"
    

    trim is a free function. It takes the string and returns a new one, and the original s is unchanged. Writing s.trim() does not compile.

    How the helper works

    Here is a version of it:

    string trim(const string& s) {
        int start = 0, end = s.size() - 1;
        while (start <= end && s[start] == ' ') start++;
        while (end >= start && s[end] == ' ') end--;
        return s.substr(start, end - start + 1);
    }
    

    It uses two indexes, start at the front and end at the back:

    1. Start with the whole string. start is 0 and end is the index of the last character.
    2. Move start forward while it points at a space. The check start <= end keeps it from running past the end of an all-space string.
    3. Move end backward while it points at a space, never going below start.
    4. Return the slice between them. substr(start, length) takes a starting index and a count of characters, so the count is end - start + 1.

    For " hello " the string has nine characters. start stops at index 2 (the "h") and end stops at index 6 (the "o"). The slice is 6 - 2 + 1, five characters long.

    The indexes are stored as int on purpose. s.size() returns an unsigned type, and for an empty string s.size() - 1 would wrap around to a huge number. Converting the result to int gives -1 on the usual compilers, and then both loops are skipped and substr(0, 0) returns an empty string. An all-space string like " " also gives an empty result.

    The built-in way: find_first_not_of

    The standard library offers a shorter route using two member functions. find_first_not_of(chars) returns the index of the first character that is not in the given set, and find_last_not_of(chars) does the same from the right. Both return string::npos when every character is in the set:

    string trimmed(const string& s) {
        size_t first = s.find_first_not_of(" \t\n");
        if (first == string::npos) return "";
        size_t last = s.find_last_not_of(" \t\n");
        return s.substr(first, last - first + 1);
    }
    

    This version also removes tabs and newlines, because the set is passed as an argument. The helper shown earlier removes only the plain space character, so a string like "\thi\t" comes back unchanged. Know which characters your trim covers before you rely on it.

    Trimming a string in place

    The helper returns a new string, which is the safest design, but sometimes you want to change the variable itself. Combine the same two searches with erase. First cut off everything after the last non-space character, then everything before the first one:

    void trimInPlace(string& s) {
        s.erase(s.find_last_not_of(" \t\n") + 1);
        s.erase(0, s.find_first_not_of(" \t\n"));
    }
    

    The parameter is a non-const reference here, so changes reach the caller's variable. When the string is all whitespace, find_last_not_of returns npos, and adding 1 to it wraps around to 0, so the first erase removes everything. The second call then has nothing left to do. That wrap-around is intentional, but it is the kind of trick that deserves a comment in real code.

    The exercise, step by step

    The editor starts with string s = " hello ";.

    1. Declare a new string named result.
    2. Assign it trim(s). The helper strips the spaces at both ends and returns the cleaned copy.
    string s = "  hello  ";
    
    string result = trim(s);
    

    The value of result is "hello", five characters, with no spaces. The variable s still holds the original nine characters, because trim works on a copy.

    Common mistakes

    • Calling it like a member function. It is trim(s), not s.trim().
    • Expecting the original to change. The function returns the trimmed text, so store it, as result does here.
    • Expecting the middle to change. Spaces between words stay.
    • Using size_t indexes in the two-pointer version. With an unsigned end, the loop end-- past 0 wraps around instead of going negative.

    Key takeaways

    • std::string has no trim member. A helper function does the job.
    • The helper moves two indexes inward from the ends and takes a substr of what remains.
    • find_first_not_of and find_last_not_of give a shorter version, and let you choose which characters count as whitespace.
    Keep going with C++About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free