Pythonerが、ゼロからRustで、Printとinputを使いたいの巻


概要

  • Python しかわからねえマンが
  • さっき始めたばかりの Rust を使って
  • 入出力をキメる

材料を調達

  • 確認用のprintinを見ながら文字列を学ぶ
  • 文字を入力させたいので、Pythonで言うところのinputができるようにしたい

Print の仕組みから学ぼう

とりあえず前回の記事でHello Worldはできたので、

今回はPrintを取り扱っていきます。

とにかく変数を文字列として Print する

title
fn main() {
    let text = "aaaa";
    println!("{}", text);
}

// aaaa
  • let ~で変数を宣言
  • "{}", ~という書き方。
    • 出力したいところに{}を置く。
    • それをあとから~で置き換えるイメージ

「一般的に {}はどんな引数であろうと自動的に置き換えられます。」

フォーマットしてプリント - Rust By Example 日本語版

文字列を改行したい

  • 改行したい場合は開改行を差し込めば改行される。
title
fn main() {
    let text = "aa
aa";
    println!("{}", text);
}

// -----出力
// aa
// aa
// -----出力

  • "";の間であれば、実際に改行していても認識されるらしい。
  • この場合、インデントになっているスペースも文字列に含まれるので取扱に注意が必要。
title
fn main() {
    let text = "aa
    aa
aa";
    println!("{}", text);
}

// -----出力
// aa
//     aa
// aa
// -----出力

input の初歩

Python の場合、こういう記述で一発で input ができます。

便利ですね。

main.py
s = input('文字列を入力してください >>>> ')

Rust ではどう書くか

ところが、Rust では input が一発でできないみたいです。

調べたらマクロ?というものを組む必要があるらしいんですが、

初学者が手つけたら死ぬなと思ったので、おとなしく諸々を書いていきます。

main.rs
fn main() {
  println!("フォルダの名前は?
>>>> ");
  let mut title = String::new();
  // 入力機構
  stdin().read_line(&mut title).ok().expect("Error");
  // 改行コードを抹消
  title = title.trim().to_string();
  println!("'{}'", title);
}
// -----出力
// フォルダの名前は?
// >>>>
// test(と入力)
// 'test'
// -----出力

  • ミュータブルな変数を宣言して
  • std::io::stdin().read_lineを呼び出す前菜のようなものですかね
  • .read_line(&mut title)で入力
  • それをtitleにそれを書き込んで
  • ok()で指差し確認、ヨシ!
  • expect()で万が一だめなときでも、ヨシ!
  • このままだと末端に改行コードが挿入されてしまう
  • のでtrim()してto_string()で整える(?)

…ってところでしょうか、あんまり良くわかっていません。

マクロを書く書き方が主流みたいなので、

慣れたらそっちのほうが良さげです。

わかりやすくするために見た目を整えよう

ただ、このままだと

>>>>
test
'test'

という風に出力されてしまいます。
Python ライクに扱いたいので…

>>>> test
'test'

と出力したい…なにか方法ないのかな…

…あるじゃん。

main.rs
use std::io::Write;

fn main() {
  print!("フォルダの名前は?
>>>> ");
  std::io::stdout().flush().unwrap();
  let mut title = String::new();
  std::io::stdin().read_line(&mut title).ok().expect("Error");
  title = title.trim().to_string();
  println!("'{}'", title);
}
  • use std::io::Write; は Python で言うところのimport ~
  • とにかくWriteの中にflush()というものがあるということでよろしく
  • print!を使うと改行コードが末尾に付加されずに済む
  • ただflush()を使わないと順番通りにいかないとのことなので入れておく(※)

flush()がどういうものなのか、

公式ドキュメント読んでもよくわからなかったので

有志の方いたらコメントください…

これで理想通り

>>>> test
'test'

と出力されるようになりました。

関数

出力はうまくいきましたが、問題はこれを何度も書かなきゃいけないことです。
めんどくさいね…fn main()使ってるくらいだから関数化しちゃおうか。

ということでできました。

main.rs
use std::io;
use std::io::Write;

// inputを扱う関数、引数はない
fn input() -> String {
  print!(">>>> ");
  std::io::stdout().flush().unwrap();
  let mut word = String::new();
  io::stdin().read_line(&mut word).ok();
  return word.trim().to_string();
}

fn main() {
  println!("1?");
  let a = input();

  println!("2?");
  let b = input();

  println!("結果");
  println!("'{}'", a);
  println!("'{}'", b);

}

関数の考え方は Python と同じで良いようです。

title=出力
1?
>>>> aaaa
2?
>>>> bbbb
結果
'aaaa'
'bbbb'

参考