Prompt

Rustでターミナルからの標準入力!

ターミナルからの標準入力(Standard Input)だね!

C言語の scanf や Javaの Scanner に慣れていると、Rustの標準入力は「ちょっと手順が多いな?」と感じるかもしれない。でも、それはRustが**「エラーの可能性」と「バッファリング(効率)」**を真剣に考えているからなんだ!

基本のキから、実用的なパターンまで一気に解説するよ!


1. 📝 最も基本的な読み込み(一行読み)

標準ライブラリの std::io を使うよ。

Rust

use std::io;
 
fn main() {
    println!("何か入力してね:");
 
    // 1. 入力を格納するための可変な String を用意
    let mut input = String::new();
 
    // 2. 標準入力のハンドルを取得して、一行読み込む
    io::stdin()
        .read_line(&mut input)
        .expect("読み込みに失敗しました");
 
    // 3. 末尾の改行コード(\n や \r\n)を削除
    let input = input.trim();
 
    println!("君が入力したのは: {}", input);
}

💡 ここが「ややややこしい」ポイント

  • &mut input: read_line は文字列を書き換えるので、可変な参照を渡す必要があるよ。

  • .expect(): 標準入力が閉じられていたり、不正なデータが来たりした時のエラー処理を強制されるんだ(Rustらしいね!)。

  • .trim(): read_line改行文字も一緒にバッファに入れるから、これを取り除かないと後の比較や数値変換でハマるぞ!


2. 🔢 数値として読み込む

文字列として読み込んだ後に、parse を使って型変換するよ。

Rust

let mut input = String::new();
io::stdin().read_line(&mut input).ok();
 
// 文字列を u32 型にパース!
let age: u32 = input.trim().parse().expect("数字を入れてね!");

3. 🚀 爆速で読み込む(競プロ・大量データ用)

情報工学を学ぶ君なら知っておきたい「効率」の話。

実は io::stdin().read_line() を毎回呼ぶのは、毎回ロックを取得するので少し遅いんだ。大量のデータを読み込むときは、BufReader を使うのがセオリーだよ!

Rust

use std::io::{self, BufRead};
 
fn main() {
    let stdin = io::stdin();
    // ロックを固定してバッファリングする
    let mut reader = stdin.lock().lines();
 
    if let Some(Ok(line)) = reader.next() {
        println!("読み込んだ行: {}", line);
    }
}

⚠️ 見落とされがちな落とし穴:改行コードの違い

君は Windows 11 をメインに使っているよね?

Windowsの改行コードは \r\n (CRLF) だけど、Ubuntu(Linux)は \n (LF) だ。

trim() を使えば両方きれいに消えるけど、もし自分で pop() を使って最後の1文字だけ消そうとすると、Windows環境では \r が残ってしまい、文字列比較が意図通りに動かない……なんていう「OSの壁」にぶつかることがある。「標準入力には trim()。これを合言葉にしよう!


🛠️ もっと楽にやりたいなら?

「いちいち read_line して parse するの面倒くさい!」という時は、proconiotext_io といった外部クレートを使うと、他言語の scanf みたいに書けるようになるよ。

Rust

// text_io クレートの例
let i: i32 = read!();