---
title: "1.6 Reading input: a first look"
description: "Reading user input in Rust with stdin and read_line, why the input keeps its newline, and what trim does."
url: "https://learnrust.net/chapter-1/reading-input/"
last_updated: "2026-06-11"
---

# 1.6 Reading input: a first look

A program that only prints is a fireworks display: nice to watch, but the conversation is one-way. This lesson adds input, so your programs can ask questions and use the answers. It's also the first lesson where you'll write code containing pieces we *can't fully explain yet*. That's on purpose, and we'll be honest about exactly which pieces and when each gets paid off.

## A program that listens

Here's a program that asks for your name and greets you:

```rust
use std::io;

fn main() {
    println!("What's your name?");

    let mut name = String::new();
    io::stdin()
        .read_line(&mut name)
        .expect("failed to read input");

    println!("Hello, {name}!");
}
```

Run it, type `Ada`, press Enter, and:

```
What's your name?
Ada
Hello, Ada
!
```

It works! Almost. The exclamation mark has fallen off the line, and that small wreck is this lesson's most useful teaching: we'll come back to it in a moment. First, the tour.

Line 1: `use std::io;` brings the standard library's input/output tools into the program. Treat `use` lines as the ingredient list at the top of a recipe; chapter 13 explains the pantry system.

`let mut name = String::new();` creates a `String`: an empty, growable container for text. It must be `mut`, because reading input is going to change it. Why text comes in two flavors (this one, and the string literals you've been printing) is a chapter 5 story.

The three-line statement is the actual read. `io::stdin()` is a handle to **standard input**, the stream of whatever the user types into the terminal. `.read_line(&mut name)` waits for the user to type a line and press Enter, then puts what they typed into `name`. And `.expect("failed to read input")` deals with the possibility that reading itself failed: if so, the program stops and prints that message.

> **What you're taking on credit**
>
> Two pieces of that statement are IOUs, and this box is the receipt. The `&mut` in `read_line(&mut name)` lends the function permission to *modify* `name` without giving the variable away; that's a reference, the star of chapter 9 (lesson 9.2 pays this off exactly). And `.expect(...)` is the bluntest tool from Rust's error-handling kit, chapter 12 (lesson 12.2). Until those chapters: write the recipe as shown, every time, and don't worry about it. There is no version of this course where you understand everything in week one; there's just the version where we admit it.

> **Tip**
>
> We print the question with `println!`, on its own line, rather than `print!("What's your name? ")` on the same line as the typing. That's the 1.5 wrinkle at work: a partial line can sit invisible in the terminal's buffer, leaving the user staring at nothing. Full-line prompts sidestep the problem until chapter 20 hands us the proper fix.

## The case of the fallen exclamation mark

So why did `!` end up on its own line? Because of a precise and easily-forgotten fact: **`read_line` keeps the Enter**. When the user types `Ada` and presses Enter, the line that arrives is `"Ada\n"`, newline included, and that's what lands in `name`. Our greeting then prints `Hello, ` + `Ada\n` + `!`, and the `\n` in the middle breaks the line before the `!` gets its turn.

The standard cleanup is `.trim()`, which produces the text with any leading and trailing whitespace (spaces, tabs, and that newline) removed:

```rust
use std::io;

fn main() {
    println!("What's your name?");

    let mut name = String::new();
    io::stdin()
        .read_line(&mut name)
        .expect("failed to read input");

    let trimmed = name.trim();
    println!("Hello, {trimmed}!");
}
```

```
What's your name?
Ada
Hello, Ada!
```

(Putting the trimmed text in a second variable works fine; lesson 5.2 shows the tidier idiom Rust programmers actually use here.)

Two behavioral details to file away, both quiz bait and both real-program bait. First, `read_line` *appends* to the string you give it; if `name` already had text, the new input is added to the end, which is why examples always hand it a fresh `String::new()`. Second, trimming only removes whitespace at the *edges*. `"  Ada Lovelace  \n"` trims to `"Ada Lovelace"`, inner space intact.

## Quiz time

**Question #1**

The user runs your program and, at the prompt, types two spaces, then `42`, then presses Enter. After `read_line(&mut input)` completes, exactly what text is inside `input`?

<details class="solution">
<summary>Show solution</summary>

`"  42\n"`: both leading spaces *and* the trailing newline. `read_line` delivers the line exactly as typed, Enter included; nothing is cleaned up unless you clean it.

</details>

**Question #2**

A classmate deletes the `.trim()` step because "it worked without it." What two characters of explanation does their next greeting carry, and why?

<details class="solution">
<summary>Show solution</summary>

Their greeting will break before the closing punctuation (like our fallen `!`), because the stored input ends with `\n`. The newline the user's Enter key produced is part of the string until something removes it.

</details>

**Question #3**

Write a program that asks "What's your favorite color?" and replies with `<color> is a great choice.` on a single line, regardless of any stray spaces the user types around their answer.

<details class="solution">
<summary>Show solution</summary>

```rust
use std::io;

fn main() {
    println!("What's your favorite color?");

    let mut color = String::new();
    io::stdin()
        .read_line(&mut color)
        .expect("failed to read input");

    let trimmed = color.trim();
    println!("{trimmed} is a great choice.");
}
```

`trim` handles both the newline and any accidental spaces, which is exactly the "regardless of stray spaces" requirement.

</details>

You can now read text in. Reading *numbers* in (so you can do math with them) takes one more tool, and it arrives in lesson 5.6. Before any of that: when your growing programs go wrong, the compiler will tell you, at length. The next lesson teaches you to read what it says.

## Sitemap

See the full [sitemap](https://learnrust.net/sitemap.md) for all pages.
