Start learning free

LESSON 70 OF 414 · STRINGS I

Uppercase and Lowercase in Rust

Lesson Read the full explanation

In Rust, you can convert a string to uppercase or lowercase using the built-in .to_uppercase() and .to_lowercase() methods:

let s = "Hello World";

let upper = s.to_uppercase();
// upper == "HELLO WORLD"

let lower = s.to_lowercase();
// lower == "hello world"

.to_uppercase() converts every character to its uppercase form, and .to_lowercase() converts every character to its lowercase form. Both methods return a new String and do not modify the original.


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


Hint
Use .to_uppercase() for uppercase and .to_lowercase() for lowercase.

STEP 1 OF 2
    Ctrl + Enter to check

    RUST · STRINGS I

    String Upper Lower in Rust, explained

    Changing the case of a string

    Two methods on str change the case of every character in a string: to_uppercase() and to_lowercase().

    let s = "Hello World";
    
    let upper = s.to_uppercase();
    let lower = s.to_lowercase();
    
    println!("{}", upper);
    println!("{}", lower);
    println!("{}", s);
    
    HELLO WORLD
    hello world
    Hello World
    

    Both methods return a new, owned String. The original is a &str that can't be modified through those methods, and as the last line shows, it keeps its original case. If you want to keep the changed version, store the return value.

    Where case conversion is useful

    The most common use is comparing text without caring about case. Converting both sides to the same case makes "Yes", "YES" and "yes" equal:

    let answer = "YES";
    if answer.to_lowercase() == "yes" {
        println!("confirmed");
    }
    

    It is also used for normalising input before storing or counting it, and for formatting output such as headings.

    Unicode behaviour

    Rust strings are Unicode, and to_uppercase() and to_lowercase() follow Unicode rules. That means they handle letters beyond English, and a conversion can even change the length of the text. The German letter ß has no single-character uppercase form, so:

    println!("{}", "straße".to_uppercase());
    
    STRASSE
    

    That is one reason the methods return a new String instead of editing in place: the result may need a different amount of memory.

    ASCII-only alternatives

    When you know the text is plain ASCII, or you want only the ASCII letters changed, there are cheaper variants:

    • to_ascii_uppercase() and to_ascii_lowercase() return a new String and change only the letters A to Z.
    • eq_ignore_ascii_case(other) compares two strings ignoring ASCII case, without building any new string: "abc".eq_ignore_ascii_case("ABC") is true.

    Comparing without allocating

    Each to_lowercase() call allocates a new String. That is fine for a few comparisons. In a loop over a large amount of text, eq_ignore_ascii_case is cheaper because it compares character by character and builds nothing. The trade-off is that it only understands ASCII case rules, so "É" and "é" would be considered different by it, while to_lowercase() treats them as a matching pair.

    Gotchas

    • Calling the method without using the result. word.to_uppercase(); by itself builds a string and throws it away.
    • Mixing up types. The result is a String, not a &str. Comparing it with a literal works (upper == "HELLO WORLD"), but passing it to a function that expects &str needs a borrow: &upper.
    • Non-letters are untouched. Digits, spaces and punctuation stay as they are.
    • Only the first letter. Rust has no single method for capitalising a word. To change just one character, work with chars() on the string.

    Working with single characters

    The same ideas exist for one char. c.to_ascii_uppercase() returns a char. c.to_uppercase() returns an iterator, because one character can turn into several (ß becomes SS). Collect it into a String, or print it directly, since the iterator implements Display.

    To test a character before converting it, use c.is_uppercase(), c.is_lowercase() or c.is_alphabetic(). Together with chars() these let you build conversions the standard library doesn't have, such as capitalising only the first letter of each word.

    Case conversion also pairs well with the other string methods in this chapter. For example, text.trim().to_lowercase() removes surrounding whitespace and then lowercases the result, which gives a clean value to compare against.

    Choosing a method

    Use to_lowercase() for general text, particularly user-facing text that may contain non-English letters. Use the ASCII variants for identifiers, file extensions and protocol keywords, where only A to Z can occur and speed matters more than language coverage.

    The exercise

    The lesson has two steps.

    1. Declare word with let, holding "Hello World". Then declare upper and assign it word.to_uppercase().
    2. Declare lower and assign it word.to_lowercase().
            let word = "Hello World";
            let upper = word.to_uppercase();
            let lower = word.to_lowercase();
    

    After this, upper is "HELLO WORLD", lower is "hello world", and word is unchanged. Both calls read from word, which is possible because each method only borrows the string.

    Key takeaways

    • to_uppercase() and to_lowercase() convert every character and return a new String.
    • The original string is never modified.
    • They follow Unicode rules, so the result can be longer than the input.
    • Use the _ascii_ variants and eq_ignore_ascii_case when only ASCII matters.
    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free