標準入力
Rustの勉強を進めるなかで標準入力に躓きました。
標準入力の実装方法はわかったけれど、どういう意味を持ったコードかわからなかったので自分なりに調べたことを書いていきます。
同じく標準入力で困った人のお役に立てれば・・・
文字を受け取る
まずは、文字を受け取ってその文字を出力します。
use std::io;
fn main()
{
let mut word = String::new();
io::stdin().read_line(&mut word).expect("F");
println!("input word = {}", word.trim());
}
おそらく一番簡単な実装方法はこれです。
実行結果はこちら。
hello
input wprd = hello
use std::io;
use std::io;
標準ライブラリのioモジュールをインポートするためのおまじないです。
でstdライブラリを読み込んでいます。C言語でいうところの#include <stdio.h>
、Pythonでいうimport flet as ft
みたいなものですかね。
標準入力ではioモジュールを使用するため、このおまじないを書いておく必要があります。
let mut word = String::new();
let mut word = String::new();
これで空の文字列(Strin型)を準備しています。
この変数の箱に入力された文字を入れるので、let mut
を使って可変の変数にしておく必要性があります。
String::new()
でString型の空のオブジェクトを作成、これを変数word
に代入します。
io::stdin().read_line(&mut word).expect("F");
io::stdin().read_line(&mut word).expect("F");
Constructs a new handle to the standard input of the current process.
引用元: Rust Programing Language
とあるように、io::stdin()
というのは、標準入力のハンドルを構築します。つまり、io::stdin()
で標準入力の意味を表します。C言語でいうscanf関数
とほぼ似たような感じですね。
.read_line()
入力された1行をwordという変数の箱に入れてあげるためのものです。
&mut word
は、wordに文字列を書き込んでいいよ!!という可変参照を渡しています。
可変参照では、参照先の値を読み出し変更することができます。
最初にwordという変数を空の文字列で作っているので、そこを変更します。
.expect()
正しく入力ができなかった時にエラーを出してプログラムを終了させるためのものです。
この部分はなくても動きます。
これで最低限の標準入力の実装の完成です。
.trim()
.trim()
は改行を取り除くという意味を持ちます。
なので、 word に含まれる改行を消してくれます。
print!("input number= {}", word);
という書き方でも、最後の段に空の改行なしで出力されます。
入力前に文を表示
上のやり方で必要最低限の標準入力の実装は可能です。
hello
input wprd = hello
しかし表示のされ方がすこしわかりにくいですね。
なので文字の入力を受け取る前に、文を表示しておきます。
use std::io;
use std::io::Write;
fn main()
{
print!("input word: ");
io::stdout().flush().unwrap();
let mut word = String::new();
io::stdin().read_line(&mut word).expect("F");
println!("input wprd = {}", word.trim());
}
input word: hello
input wprd = hello
わかりやすくなりましたね。
では、それぞれ何をしているのかについて書いていきます。
use std:: io::Write;
ioと両サイドの::で国旗に変換されちゃう;;
これは、ioモジュールの中にあるWriteという機能を使えるようにするおまじないです。
後述の.flush()
を使うために必要になります。
文字の出力を細かく管理したりするために必要なルールがまとまっています。
io::stdout().flush().unwrap();
io::stdout()
Constructs a new handle to the standard output of the current process.
Rust Programing Language
io::stdin()
は標準入力のハンドルを構築していましたが、io::stdout()
では標準出力のハンドルを構築しています。
.flush()
これはため込んでいる出力データを一気に外に出すための命令です。
print!
などの書き込みはすぐに出力されません。そのため、.flush()をもちいて、print!
で出力させた文をすぐに表示させています。
.unwrap()
これは、成功していればそのままプログラムを実行、失敗していればプログラムを終了させるためのものです。
では、io::stdout().flush().unwrap()
がないとどのように表示されるのでしょうか。
hello
input word: input wprd = hello
このようにinput word
が標準入力を受け取った後に表示されてしまします。
ちなみに、prinln!の場合、io::stdout().flush().unwrap()
がなくてもinput word
が標準入力の前に表示できます。
input word:
hello
input wprd = hello
このようにinput word
の後に改行が含まれます。println!
には、改行の要素が含まれているため.flush()
が自動的に行われます。
数値を受け取る
今までは文字列を受け取り、文字列を出力してきました。
数字を入力してその数字が奇数か偶数か判断するといった問題をみたことがある人も多いと思います。
Rsutでの数値の入力の仕方を書いていきます。
use std::io;
use std::io::Write;
fn main()
{
print!("input number: ");
io::stdout().flush().unwrap();
let mut word = String::new();
io::stdin().read_line(&mut word).expect("F");
let num: i32 = word.trim().parse().expect("F");
if num % 2 == 0 {
println!("偶数");
}else {
println!("奇数");
}
}
input number: 6
偶数
let num: i32 = word.trim().parse().expect("F");
文字列を数値に変換して変数に入れるという作業をしています。
Rustは静的型付け言語なので、変数の型を変換してあげる必要があります。
word.trim()
入力された文字列が入っている変数word
には改行も含まれています。その改行をなくすためのものです。
trim()
の部分が改行の削除に当たります。
.parse()
これは、文字列を別の型に変換しています。
変数word
はString型の文字列なのでこれをi32型(数値型)の数字に変換します。
数値に変換しなければ、大きさを比べたり四則演算ができないので必要な処理です。
(ChatGPT君によれば、内部のエラーチェックもしてくれているらしい。parseに解析
という意味があるから納得)
let num: i32
上記の処理が正常に終了し、型変換に成功したら、i32型の変数num
に格納します。i32
とはC言語でいうint
のようなものです。細かな違いはありますが両方整数のみを受け取るという点で共通しています。
.parse()
を用いた場合は変換先の変数の型を明示する必要があるので、ここで変数の型をしっかり指定しておきましょう。
数値型の変数num
をもちいて、奇数偶数の判定を行っていきます。
参考