std::io::stdin() / stdout()
| 対応: | Rust 1.0(2015) |
|---|
Rustの標準入出力は『std::io::stdin()』と『std::io::stdout()』で扱います。キーボードからの入力は『read_line()』で1行ずつ読み込み、出力は『println!()』マクロや『write!()』マクロで行います。
構文
use std::io::{self, BufRead, Write};
// 標準入力から1行読み込みます。
let mut input = String::new();
io::stdin().read_line(&mut input)?;
let trimmed = input.trim(); // 末尾の改行を除去します。
// stdin をロックして効率化します(複数行読み込む場合)。
let stdin = io::stdin();
for line in stdin.lock().lines() {
let line = line?;
println!("{}", line);
}
// 標準出力に書き込みます。
print!("入力してください: ");
io::stdout().flush()?; // バッファを即座に出力します。
// 標準エラー出力に書き込みます。
eprintln!("エラー: {}", msg);
writeln!(io::stderr(), "エラー詳細: {}")?;
メソッド一覧
| メソッド/関数 | 概要 |
|---|---|
| io::stdin() | 標準入力(Stdin 構造体)を返します。 |
| stdin.read_line(&mut s) | 1行(改行文字を含む)を String に読み込みます。Result<usize> を返します。 |
| stdin.lock().lines() | 標準入力をロックして行イテレータを取得します。複数行の読み込みに効率的です。 |
| io::stdout() | 標準出力(Stdout 構造体)を返します。 |
| stdout.flush() | 出力バッファを即座に書き出します。改行なし出力の後に必要です。 |
| io::stderr() | 標準エラー出力(Stderr 構造体)を返します。 |
| input.trim() | 先頭と末尾の空白・改行を除去します。read_line 後に必ず呼びます。 |
| s.parse::<T>() | 文字列を数値など別の型に変換します。 |
サンプルコード
標準入力(『stdin』)と標準出力(『stdout』)の基本的な使い方を確認するサンプルコードです。
sample_main.rs
use std::io::{self, Write};
fn main() {
// --- 基本的な入力 ---
print!("名前を入力してください: ");
io::stdout().flush().unwrap(); // プロンプトを即座に表示します。
let mut name = String::new();
io::stdin().read_line(&mut name).unwrap();
let name = name.trim(); // 末尾の改行を除去します。
println!("こんにちは、{}さん!", name);
// --- 数値の入力 ---
print!("年齢を入力してください: ");
io::stdout().flush().unwrap();
let mut age_str = String::new();
io::stdin().read_line(&mut age_str).unwrap();
let age: u32 = age_str.trim().parse().unwrap_or(0);
println!("来年は{}歳ですね", age + 1);
// --- エラーハンドリング付きの入力 ---
let num = loop {
print!("1〜10の整数を入力: ");
io::stdout().flush().unwrap();
let mut buf = String::new();
io::stdin().read_line(&mut buf).unwrap();
match buf.trim().parse::<u32>() {
Ok(n) if n >= 1 && n <= 10 => break n,
Ok(_) => eprintln!("1〜10の範囲で入力してください"),
Err(_) => eprintln!("整数を入力してください"),
}
};
println!("入力値: {}", num);
}
よくあるミス
よくあるミス1: trim()忘れで改行が残る
read_line()は末尾に改行文字('\n')を含んだまま文字列に追記します。trim()を忘れると比較や変換で予期しない動作になります。
stdin_mistake1.rs
use std::io;
fn main() {
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
// trim()を忘れると末尾に\nが残ります。
println!("入力値: '{}'", input); // 'hello\n' のようになります。
println!("長さ: {}", input.len()); // 改行文字分1バイト多い
// trimした場合との比較です。
println!("trim後: '{}'", input.trim());
println!("trim後長さ: {}", input.trim().len());
}
コンパイルして実行すると次のように出力されます。
rustc stdin_mistake1.rs echo "hello" | ./stdin_mistake1 入力値: 'hello ' 長さ: 6 trim後: 'hello' trim後長さ: 5
よくあるミス2: flush()忘れでプロンプトが表示されない
print!()(改行なし出力)の後にflush()を呼ばないと、バッファに残ってプロンプトが表示されないまま入力待ちになる場合があります。
stdin_flush.rs
use std::io::{self, Write};
fn main() {
// flush()なしの場合、プロンプトが表示されないことがあります。
// print!("名前を入力: ");
// io::stdin().read_line(&mut String::new()).unwrap();
// flush()を呼んでバッファを即座に出力します。
print!("名前を入力: ");
io::stdout().flush().unwrap();
let mut name = String::new();
io::stdin().read_line(&mut name).unwrap();
println!("こんにちは、{}!", name.trim());
}
rustc stdin_flush.rs echo "Gojo" | ./stdin_flush 名前を入力: こんにちは、Gojo!
概要
『read_line()』は末尾の改行文字('\n' または '\r\n')を含んだまま文字列に追記します。そのため必ず『trim()』で末尾の空白・改行を除去してから使ってください。
『print!()』で改行なし出力した後にプロンプトを即座に表示するには『io::stdout().flush()』が必要です。Rustの標準出力はバッファリングされているため、改行がないとバッファに残ったままになります。
ファイルの読み書きについてはFile::open() / File::create()を、フォーマット出力の詳細はprintln!() / print!() / format!()を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。