본문 바로가기

반복문과 게임 완성하기

추리 게임에 반복문을 추가하고 정답과 잘못된 입력을 처리하여 최종 프로그램을 완성합니다.

추리 게임에서 만든 프로그램은 한 번만 추리하고 끝나며, 숫자가 아닌 것을 입력하면 프로그램이 멈춥니다. 이 글에서는 반복문으로 여러 번 추리하게 하고, 정답을 맞히면 반복을 끝내며, 숫자가 아닌 입력은 버리고 다시 받도록 고쳐 게임을 완성합니다.

반복문으로 여러 번 추리하기

loop 키워드는 끝없이 되풀이하는 반복문을 만듭니다. 입력 안내부터 비교까지를 loop 안으로 옮겨 여러 번 추리할 수 있게 합니다.

src/main.rs
use std::cmp::Ordering;
use std::io;

use rand::prelude::*;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::rng().random_range(1..=100);

    println!("The secret number is: {secret_number}");

    loop {
        println!("Please input your guess.");

        let mut guess = String::new();

        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");

        let guess: u32 = guess.trim().parse().expect("Please type a number!");

        println!("You guessed: {guess}");

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => println!("You win!"),
        }
    }
}

loop 안의 코드는 네 칸씩 더 들여썼습니다. 비밀 숫자는 loop 밖에서 한 번만 고르므로 한 게임 동안 그대로이고, 입력을 담을 String은 반복할 때마다 새로 만들므로 이전 회차의 입력이 쌓이지 않습니다. 실행하면 여러 번 추리할 수 있지만, 이번에는 다른 문제가 생깁니다. 프로그램이 끝나지 않습니다.

Ctrl+C를 누르면 언제든 프로그램을 멈출 수 있지만, 그 밖에도 빠져나갈 방법이 하나 있습니다. 앞 글에서 보았듯이 숫자가 아닌 것을 입력하면 parse가 실패해 프로그램이 멈추므로, quit처럼 숫자가 아닌 글자를 입력하면 됩니다. 비밀 숫자가 59였던 실행의 예입니다.

Guess the number!
The secret number is: 59
Please input your guess.
45
You guessed: 45
Too small!
Please input your guess.
60
You guessed: 60
Too big!
Please input your guess.
59
You guessed: 59
You win!
Please input your guess.
quit

thread 'main' (6017887) panicked at src/main.rs:22:47:
Please type a number!: ParseIntError { kind: InvalidDigit }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

정답을 맞혀 You win!이 나온 뒤에도 다시 입력을 요청합니다. 첫 줄의 괄호 안 숫자는 패닉이 난 스레드의 ID로 실행할 때마다 다릅니다. quit을 입력하자 22번째 줄 47번째 열, 곧 expect를 부른 곳에서 패닉이 났고, expect에 넘긴 메시지 뒤에 parse가 실패한 까닭인 ParseIntError { kind: InvalidDigit }(숫자가 아닌 글자가 있음)이 붙어 나옵니다. 마지막 줄은 환경 변수 RUST_BACKTRACE=1을 주고 실행하면 패닉에 이른 함수 호출의 경로인 백트레이스를 볼 수 있다는 안내입니다. 이렇게 끝나는 것은 의도한 동작이 아니므로, 정답을 맞혔을 때 끝나도록 고칩니다.

정답을 맞힌 후 종료하기

You win! 다음에 break를 넣어, 정답을 맞히면 반복문을 빠져나가게 합니다. 아래는 main 전체가 아니라 loop 안의 match 부분만 보인 것이며, 바뀐 곳은 Ordering::Equal 갈래뿐입니다.

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }

Ordering::Equal 갈래에서 두 문장을 실행해야 하므로, 갈래의 코드를 중괄호로 묶은 블록으로 바꾸었습니다. break는 지금 실행 중인 반복문을 끝내며, 이 loop가 main의 마지막 부분이므로 반복이 끝나면 프로그램도 끝납니다.

잘못된 입력값 처리하기

이제 숫자가 아닌 것을 입력했을 때 프로그램이 멈추지 않고 그 입력만 버린 뒤 다시 묻게 합니다. 아래 그림처럼 입력을 읽는 데 실패하는 경우는 그대로 expect로 멈추고, 숫자로 바꾸지 못한 경우만 이번 회차를 건너뜁니다.

잘못된 입력은 버리고 정답은 반복을 끝낸다

새 회차 입력→parse 실패 continue 또는 숫자 비교→Less/Greater 재시도/Equal break의 실제 반복 상태이다. 같은 secret과 새 String을 구분한다.

추리 게임의 전체 반복 흐름. read_line의 I/O 실패는 expect로 처리합니다. parse가 실패하면 현재 입력을 조용히 버리고 다음 회차로 이동합니다. 숫자 변환에 성공하면 cmp 결과를 검사하고, Less와 Greater는 다시 입력받으며 Equal은 break로 반복을 끝냅니다.

Rust · loop · Result · Ordering

잘못된 입력은 이번 회차만 버리고, 정답은 루프를 끝낸다

두 오류 정책을 구분하세요. read_line(...).expect(...)는 I/O 실패 시 그대로 종료하지만, parse의 Err(_)는 메시지 없이 현재 문자열만 버리고 continue합니다.

잘못된 숫자 입력의 재시도와 정답의 루프 종료원완성코드의8노드9관계다.회차→readline→parse에서Err는continue로다음회차로재진입,Ok는cmp로향한다.Less/Greater는안내후다음회차,Equal만break터미널이다.재진입은secret재생성이아니라새String/새입력이다.I/OErr는기존expect정책이며EOF정상종료추가버전과섞지않는다.새 loop 회차새 String · 입력 안내입력 읽기read_line().expect(...)정수 변환parse::<u32>()Err(_)continue · 현재 회차 끝비밀 숫자와 비교cmp → OrderingLess / GreaterToo small! / Too big!EqualYou win! · break다음 회차같은 비밀 숫자새 String · 새 입력ErrOk재시도EqualI/O Err는 expect 종료 유지EOF 종료는 본문의 별도 실습
추리 게임의 입력, 변환, 비교, 재시도, 종료 흐름 새 loop 회차에서 입력을 읽습니다. parse 결과가 Err이면 현재 입력을 버리고 다음 회차로 돌아갑니다. Ok이면 비밀 숫자와 비교합니다. Less 또는 Greater이면 안내를 출력한 뒤 다음 회차로 돌아가고, Equal이면 승리 메시지를 출력하고 break합니다. ErrOk재시도Equal다음 회차새 loop 회차Please input your guess.새 String 준비String에 입력 읽기read_line(...).expect(...) 유지정수 변환 결과parse::<u32>()Err(_)continue현재 문자열을 버림비밀 숫자와 비교cmp → OrderingLess / GreaterToo small!Too big!EqualYou win!break · loop 종료다음 회차로 이동새 String · 새 입력
input

1. 입력 I/O 정책은 그대로

read_line(&mut guess).expect(...)가 남아 있으므로 실제 I/O 실패는 종료됩니다.

parse

2. 숫자가 아니면 조용히 재시도

Err(_) => continue는 오류 메시지를 출력하지 않고 현재 문자열만 버린 뒤 새 회차로 이동합니다.

compare

3. 숫자만 cmp로 이동

Ok(num)가 만든 u32를 비밀 숫자와 비교합니다.

retry

4. Less · Greater는 다시 입력

Too small! 또는 Too big!을 출력한 뒤 루프 끝에서 다음 회차로 이어집니다.

break

5. Equal만 루프 종료

You win!을 출력하고 break가 반복을 끝냅니다.

expect를 모두 없앤 것이 아니다

바뀐 부분은 parse().expect(...)뿐입니다. read_line의 I/O 오류와 잘못된 숫자 입력은 서로 다른 실패입니다.

재시도와 종료의 경계

continue는 지금 회차를 중단하고, break는 loop 전체를 중단합니다. Less와 Greater는 회차 끝까지 간 뒤 자연스럽게 반복됩니다.

완성 코드의 비밀 숫자는 rand 0.10.2 API인 rand::random_range(1..=100)로 한 번 생성되며, 반복되는 것은 사용자 입력과 판정입니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
관계도의 보충 설명
원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명원 완성 코드의 8노드 9관계다. 회차→readline→parse에서 Err는 continue로 다음 회차로 재진입하고, Ok는 cmp로 향한다. Less/Greater는 안내 후 다음 회차로, Equal만 break 종료점으로 이어진다. 재진입은 secret 재생성이 아니라 새 String/새 입력이다. I/O Err는 기존 expect 정책이며 EOF 정상 종료 추가 버전과 섞지 않는다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
회차 입력

같은 secret에 새 String 입력을 받는다.

  • secret: 회차 간 유지
  • 입력: 새 String
  • 반복 입력이 이전 문자열 뒤에 누적되지 않게 회차별로 준비한다.
파싱 분기

실패는 continue, 성공은 비교로 진행한다.

  • parse Err: 다음 회차
  • parse Ok: 숫자 비교
  • 유효한 숫자가 없는 경로에서는 cmp를 수행하지 않는다.
재시도·종료

Less/Greater는 반복하고 Equal은 break한다.

  • Less/Greater: 새 입력
  • Equal: 반복 종료
  • 비교 결과가 반복을 계속할지 결정한다.

잘못된 입력은 버리고 정답은 반복을 끝낸다

새 회차 입력→parse 실패 continue 또는 숫자 비교→Less/Greater 재시도/Equal break의 실제 반복 상태이다. 같은 secret과 새 String을 구분한다.

추리 게임의 전체 반복 흐름. read_line의 I/O 실패는 expect로 처리합니다. parse가 실패하면 현재 입력을 조용히 버리고 다음 회차로 이동합니다. 숫자 변환에 성공하면 cmp 결과를 검사하고, Less와 Greater는 다시 입력받으며 Equal은 break로 반복을 끝냅니다.

Rust · loop · Result · Ordering

잘못된 입력은 이번 회차만 버리고, 정답은 루프를 끝낸다

두 오류 정책을 구분하세요. read_line(...).expect(...)는 I/O 실패 시 그대로 종료하지만, parse의 Err(_)는 메시지 없이 현재 문자열만 버리고 continue합니다.

잘못된 숫자 입력의 재시도와 정답의 루프 종료원완성코드의8노드9관계다.회차→readline→parse에서Err는continue로다음회차로재진입,Ok는cmp로향한다.Less/Greater는안내후다음회차,Equal만break터미널이다.재진입은secret재생성이아니라새String/새입력이다.I/OErr는기존expect정책이며EOF정상종료추가버전과섞지않는다.새 loop 회차새 String · 입력 안내입력 읽기read_line().expect(...)정수 변환parse::<u32>()Err(_)continue · 현재 회차 끝비밀 숫자와 비교cmp → OrderingLess / GreaterToo small! / Too big!EqualYou win! · break다음 회차같은 비밀 숫자새 String · 새 입력ErrOk재시도EqualI/O Err는 expect 종료 유지EOF 종료는 본문의 별도 실습
추리 게임의 입력, 변환, 비교, 재시도, 종료 흐름 새 loop 회차에서 입력을 읽습니다. parse 결과가 Err이면 현재 입력을 버리고 다음 회차로 돌아갑니다. Ok이면 비밀 숫자와 비교합니다. Less 또는 Greater이면 안내를 출력한 뒤 다음 회차로 돌아가고, Equal이면 승리 메시지를 출력하고 break합니다. ErrOk재시도Equal다음 회차새 loop 회차Please input your guess.새 String 준비String에 입력 읽기read_line(...).expect(...) 유지정수 변환 결과parse::<u32>()Err(_)continue현재 문자열을 버림비밀 숫자와 비교cmp → OrderingLess / GreaterToo small!Too big!EqualYou win!break · loop 종료다음 회차로 이동새 String · 새 입력
input

1. 입력 I/O 정책은 그대로

read_line(&mut guess).expect(...)가 남아 있으므로 실제 I/O 실패는 종료됩니다.

parse

2. 숫자가 아니면 조용히 재시도

Err(_) => continue는 오류 메시지를 출력하지 않고 현재 문자열만 버린 뒤 새 회차로 이동합니다.

compare

3. 숫자만 cmp로 이동

Ok(num)가 만든 u32를 비밀 숫자와 비교합니다.

retry

4. Less · Greater는 다시 입력

Too small! 또는 Too big!을 출력한 뒤 루프 끝에서 다음 회차로 이어집니다.

break

5. Equal만 루프 종료

You win!을 출력하고 break가 반복을 끝냅니다.

expect를 모두 없앤 것이 아니다

바뀐 부분은 parse().expect(...)뿐입니다. read_line의 I/O 오류와 잘못된 숫자 입력은 서로 다른 실패입니다.

재시도와 종료의 경계

continue는 지금 회차를 중단하고, break는 loop 전체를 중단합니다. Less와 Greater는 회차 끝까지 간 뒤 자연스럽게 반복됩니다.

완성 코드의 비밀 숫자는 rand 0.10.2 API인 rand::random_range(1..=100)로 한 번 생성되며, 반복되는 것은 사용자 입력과 판정입니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.

관계도의 보충 설명

원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명원 완성 코드의 8노드 9관계다. 회차→readline→parse에서 Err는 continue로 다음 회차로 재진입하고, Ok는 cmp로 향한다. Less/Greater는 안내 후 다음 회차로, Equal만 break 종료점으로 이어진다. 재진입은 secret 재생성이 아니라 새 String/새 입력이다. I/O Err는 기존 expect 정책이며 EOF 정상 종료 추가 버전과 섞지 않는다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
회차 입력

같은 secret에 새 String 입력을 받는다.

  • secret: 회차 간 유지
  • 입력: 새 String
  • 반복 입력이 이전 문자열 뒤에 누적되지 않게 회차별로 준비한다.
파싱 분기

실패는 continue, 성공은 비교로 진행한다.

  • parse Err: 다음 회차
  • parse Ok: 숫자 비교
  • 유효한 숫자가 없는 경로에서는 cmp를 수행하지 않는다.
재시도·종료

Less/Greater는 반복하고 Equal은 break한다.

  • Less/Greater: 새 입력
  • Equal: 반복 종료
  • 비교 결과가 반복을 계속할지 결정한다.

guess를 String에서 u32로 바꾸는 줄을 다음과 같이 고칩니다.

        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

expect를 match 식으로 바꾸어, 오류가 나면 멈추는 대신 오류를 처리합니다. parse는 Ok와 Err 배리언트를 가진 Result를 돌려주므로, cmp가 돌려준 Ordering을 다룰 때처럼 match로 각 배리언트에 맞는 일을 정할 수 있습니다.

parse가 문자열을 숫자로 바꾸는 데 성공하면 그 숫자를 담은 Ok를 돌려줍니다. 이 값은 첫 갈래의 패턴 Ok(num)에 맞으며, Ok 안의 숫자가 num이라는 이름에 묶여 갈래의 코드인 num이 그 값을 돌려주므로, 그 숫자가 새로 만든 guess에 들어갑니다. 실패하면 오류 정보를 담은 Err를 돌려주는데, 이 값은 Ok(num)에는 맞지 않고 둘째 갈래의 Err(_)에 맞습니다. 밑줄 _는 어떤 값이든 받아들이는 패턴이므로 Err(_)는 안에 어떤 정보가 있든 모든 Err에 맞으며, 갈래의 코드인 continue는 반복문의 다음 회차로 넘어가 다시 입력을 받습니다.

이번에는 비밀 숫자가 61이었던 실행에서 foo를 입력해 봅니다.

Guess the number!
The secret number is: 61
Please input your guess.
10
You guessed: 10
Too small!
Please input your guess.
99
You guessed: 99
Too big!
Please input your guess.
foo
Please input your guess.
61
You guessed: 61
You win!

foo는 숫자로 바뀌지 않으므로 continue로 이번 회차를 건너뛰어, You guessed와 비교 결과 없이 바로 다음 입력 안내가 나왔습니다. 61을 맞히자 You win!과 함께 프로그램이 끝났습니다.

더 깊이: parse가 숫자로 받아들이는 문자열

u32로 바꾸는 parse가 받아들이는 형식은 표준 라이브러리 문서에 정해져 있습니다. 문자열은 선택적인 + 기호 하나와 그 뒤의 10진수 숫자로만 이루어져야 하며, 앞뒤의 공백을 포함해 숫자가 아닌 글자가 하나라도 있으면 오류입니다. 러스트 리터럴에서는 쓸 수 있는 1_000 같은 밑줄도 받아들이지 않습니다. 그래서 +42는 42가 되지만, trim을 거치지 않은 42\n이나 42는 실패합니다.

실패했을 때 돌려받는 ParseIntError는 kind 메서드로 실패한 까닭을 IntErrorKind 값으로 알려 줍니다. 빈 문자열이면 Empty, 숫자가 아닌 글자가 있거나 +, -가 잘못된 자리에 있으면 InvalidDigit, 값이 너무 커서 그 타입에 담을 수 없으면 PosOverflow입니다. 부호 없는 u32는 - 기호를 받지 않으므로 -5는 InvalidDigit이 되고, u32의 최댓값 4294967295를 넘는 5000000000은 PosOverflow가 됩니다. 이 게임은 Err(_)로 모든 실패를 똑같이 다루지만, 입력을 왜 받지 않았는지 사용자에게 알려 주고 싶다면 kind의 값에 따라 메시지를 나눌 수 있습니다.

완성한 코드

마지막으로, 아직 프로그램이 비밀 숫자를 출력하고 있다는 점을 떠올립니다. 만드는 동안 확인하는 데는 편했지만 게임을 망치므로, 비밀 숫자를 출력하던 println!을 지웁니다. 완성한 코드는 다음과 같습니다.

src/main.rs
use std::cmp::Ordering;
use std::io;

use rand::prelude::*;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::rng().random_range(1..=100);

    loop {
        println!("Please input your guess.");

        let mut guess = String::new();

        io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");

        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

        println!("You guessed: {guess}");

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}

이것으로 추리 게임이 완성되었습니다. 비밀 숫자는 1부터 100 사이에서 고르지만, 플레이어의 입력은 u32로 바뀌기만 하면 200처럼 그 범위 밖의 숫자도 받아들입니다. 입력을 1부터 100으로 제한하려면 따로 검사해야 하며, 그런 검사를 타입으로 만드는 방법은 panic! 사용 기준에서 다룹니다.

입력이 끝났을 때

완성한 코드는 사람이 터미널에서 계속 입력하는 경우를 생각한 것입니다. 그런데 입력을 파일에서 읽게 하거나, 한 프로그램의 출력을 다른 프로그램의 입력으로 잇는 파이프(pipe)로 넘겨 입력이 끝나는 EOF(end of file)에 이르면 문제가 생깁니다. EOF에서 read_line은 오류가 아니라 읽은 바이트 수가 0인 Ok(0)을 돌려주므로 expect를 그대로 통과하고, 빈 문자열은 숫자로 바뀌지 않아 continue로 다음 회차에 들어갑니다. 다음 회차에서도 다시 Ok(0)이 나오므로, 프로그램은 입력 안내를 끝없이 출력하며 멈추지 않습니다.

다음은 완성한 코드에서 입력을 읽는 부분만 바꾸어, EOF에 이르면 끝나도록 한 프로그램입니다. Cargo.toml은 그대로 씁니다.

src/main.rs
use std::cmp::Ordering;
use std::io;

use rand::prelude::*;

fn main() {
    println!("Guess the number!");

    let secret_number = rand::rng().random_range(1..=100);

    loop {
        println!("Please input your guess.");

        let mut guess = String::new();

        let bytes_read = io::stdin()
            .read_line(&mut guess)
            .expect("Failed to read line");

        if bytes_read == 0 {
            println!("Input ended.");
            break;
        }

        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };

        println!("You guessed: {guess}");

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}

expect가 꺼내 준 읽은 바이트 수를 bytes_read에 받아 두고, 0이면 Input ended.를 출력한 뒤 반복을 끝냅니다. 입력을 읽는 데 실패한 경우는 여전히 expect로 멈춥니다. 빈 줄을 입력한 것은 EOF와 다르다는 점에 주의합니다. 빈 줄에도 줄바꿈 문자가 있어 읽은 바이트 수가 1 이상이므로, 이 경우는 숫자로 바뀌지 않는 입력으로 처리되어 다시 묻습니다.

정리

  • loop는 끝없이 되풀이하는 반복문을 만들고, break는 반복문을 끝내며, continue는 이번 회차를 건너뛰고 다음 회차로 넘어갑니다.
  • 비밀 숫자는 loop 밖에서 한 번 고르고, 입력을 담을 String은 회차마다 새로 만듭니다.
  • match 갈래에서 여러 문장을 실행하려면 중괄호로 블록을 만듭니다.
  • expect 대신 match로 Result를 다루면, Ok(num)으로 값을 꺼내고 Err(_)로 실패를 처리할 수 있습니다.
  • 패닉 메시지는 패닉이 난 파일과 줄, 열, 그리고 expect의 메시지와 오류의 내용을 보여 줍니다.
  • EOF에서 read_line은 Ok(0)을 돌려주므로, 입력이 끝났는지는 읽은 바이트 수로 확인합니다.

연습 문제

1. 정답을 고정하고 따라가기

완성한 코드의 사본에서 비밀 숫자를 고르는 줄만 let secret_number = 42_u32;로 바꾸었습니다. 이 프로그램에 foo, 0, 50, 42를 한 줄씩 차례로 입력하면, 입력 안내와 You guessed는 각각 몇 번 출력되고 비교 결과는 무엇인가요?

해설 보기

foo는 숫자로 바뀌지 않아 continue하므로 You guessed와 비교 결과를 건너뜁니다. 0은 Too small!, 50은 Too big!, 42는 You win!을 출력하고 break로 끝납니다. 입력 안내는 네 번, You guessed는 세 번 출력됩니다. 또 rand를 더 이상 쓰지 않으므로, 컴파일러가 use rand::prelude::*;를 쓰지 않는다는 경고를 냅니다.

2. continue와 break

완성한 코드에서 Err(_) => continue를 Err(_) => break로 바꾸면, 앞의 foo를 입력한 실행은 어떻게 달라지나요?

해설 보기

continue는 이번 회차만 건너뛰지만 break는 반복문 전체를 끝냅니다. 그래서 foo를 입력하는 순간 반복이 끝나고, 아무 메시지 없이 프로그램이 끝납니다. 정답을 맞히지 않았는데도 게임이 끝나므로 의도와 다른 동작입니다.

3. 파이프로 입력하기

EOF 처리를 더한 프로그램에 한 줄 50만 담긴 입력을 파이프로 넘겼고, 비밀 숫자는 73이었습니다. 출력은 어떻게 되나요?

해설 보기

Guess the number!, Please input your guess., You guessed: 50, Too small!이 차례로 나온 뒤, 다음 회차의 Please input your guess.가 나옵니다. 그 회차에서는 더 읽을 입력이 없어 read_line이 Ok(0)을 돌려주므로 Input ended.를 출력하고 끝납니다. EOF 처리가 없는 완성 코드였다면 이 지점에서 입력 안내를 끝없이 출력했을 것입니다.

이것으로 1장을 마칩니다. 추리 게임에서 let, match, 메서드, 연관 함수, 외부 크레이트를 처음 써 보았으며, 다음 장의 변수와 가변성부터는 변수와 데이터 타입, 함수 같은 기본 개념을 하나씩 자세히 살펴봅니다.