Start learning free

LESSON 64 OF 343 · STRINGS I

Uppercase and Lowercase in C++: transform with toupper

Lesson Read the full explanation

In C++, there is no built-in method to convert an entire string to uppercase or lowercase. Instead, use std::transform with ::toupper or ::tolower from <algorithm>:

string s = "Hello World";

string upper = s;
transform(upper.begin(), upper.end(), upper.begin(), ::toupper);
// upper == "HELLO WORLD"

string lower = s;
transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
// lower == "hello world"

transform applies a function to each character. ::toupper converts a character to uppercase, and ::tolower converts it to lowercase.


Assignment
Follow the Coding Tutorial and create upper and lower versions of word!


Hint
Use transform with ::toupper for uppercase and ::tolower for lowercase.

STEP 1 OF 2
    Ctrl + Enter to check

    C++ · STRINGS I

    String Upper Lower in C++, explained

    Why there is no toupper for strings

    In many languages a string has a method such as upper() or toUpperCase(). The C++ std::string has no such member. What the standard library gives you instead is a function for a single character, toupper, with its partner tolower, and a general algorithm, transform, that applies a function to every element of a range. Together they convert a whole string.

    Single characters

    The two character functions live in <cctype>:

    char a = toupper('q');   // 'Q'
    char b = tolower('Q');   // 'q'
    char c = toupper('7');   // '7', unchanged
    

    Letters change case, and any other character comes back as it was. Despite the name, they take and return an int, a leftover from the C library, which is why you may see a cast when the result goes back into a char.

    Applying a function to a whole string

    transform comes from <algorithm> and takes four arguments:

    1. where to start reading, word.begin();
    2. where to stop, word.end();
    3. where to start writing the results;
    4. the function to apply to each element.

    If the output starts at the same place as the input, the string is overwritten in place. That is what the lesson does:

    string s = "Hello World";
    
    string upper = s;
    transform(upper.begin(), upper.end(), upper.begin(), ::toupper);
    // upper is "HELLO WORLD"
    
    string lower = s;
    transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
    // lower is "hello world"
    

    The leading :: in ::toupper tells the compiler to use the global function from the C library. It matters because the C++ library also has a two-argument toupper for locales in <locale>. A plain toupper can then be ambiguous when you pass the function to transform, and the compiler cannot tell which one you mean.

    Why the copy comes first

    transform writes into the string, so it changes whatever it is pointed at. If you transformed s directly, the original text would be lost. Copying first, as in string upper = s;, leaves s intact, and you can make both an uppercase and a lowercase version from it. Assigning one string to another copies the characters.

    A safer version for unusual text

    The character functions expect a value that fits in an unsigned char (or equals EOF). Plain char may be signed, and a character outside the ASCII range, such as part of an accented letter in UTF-8, can then be negative, which is undefined behaviour. For ASCII text such as the lesson's, ::toupper is fine. For text you do not control, wrap the call in a lambda that converts first:

    transform(s.begin(), s.end(), s.begin(),
              [](unsigned char c) { return toupper(c); });
    

    Keep in mind that these functions handle one byte at a time. They convert the English letters A to Z in the default "C" locale, but they cannot do proper case conversion for text in other alphabets.

    The exercise, step by step

    The editor starts with string word = "Hello World";. The task is to produce an uppercase and a lowercase version.

    1. Copy for the uppercase version. Declare a string named upper and initialize it from word.
    2. Uppercase it in place. Call transform over the whole of upper, writing the output back to upper.begin(), with ::toupper as the function.
    3. Copy again for the lowercase version. Declare lower from word. Start from word, not from upper, so that this copy has the original letters.
    4. Lowercase it the same way, with ::tolower.
    string word = "Hello World";
    
    string upper = word;
    transform(upper.begin(), upper.end(), upper.begin(), ::toupper);
    string lower = word;
    transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
    

    Afterwards upper is "HELLO WORLD", lower is "hello world", and word is still "Hello World". Spaces and any digits or punctuation pass through unchanged.

    Common mistakes

    • Calling word.toupper() or word.upper(). Strings have no such members.
    • Passing toupper() with parentheses. transform needs the function itself, not its result.
    • Transforming the original and then expecting to still have it.
    • Writing the output at the wrong place. The third argument must be where the results go. Using upper.end() there writes past the string.
    • Forgetting the headers. transform needs <algorithm> and the character functions need <cctype>.

    Key takeaways

    • Convert a string by applying toupper or tolower to every character with transform.
    • Copy the string first if you need the original.
    • For non-ASCII input, cast to unsigned char before calling the character functions.
    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