Taking user input
Cara termudah untuk mendapatkan input dari user adalah dengan menggunakan std::io::stdin
. Ini berarti "standard in", yang mana itu adalah input yang masuk dari keyboard. Dengan stdin()
Anda bisa mengapatkan inputan dari user, tapi Anda ingin meletakkannya pada type &mut String
dengan method .read_line()
. Ini adalah contohnya. Programnya akan bekerja, namun tidak bekerja dengan semestinya:
use std::io; fn main() { println!("Please type something, or x to escape:"); let mut input_string = String::new(); while input_string != "x" { // Ini adalah bagian dimana programnya tidak bekerja dengan semestinya input_string.clear(); // Pertama kita clear Stringnya. Jika tidak, ia akan terus bertambah io::stdin().read_line(&mut input_string).unwrap(); // dapatkan stdin dari user, dan masukkan ke read_string println!("You wrote {}", input_string); } println!("See you later!"); }
Maka seperti inilah outputnya:
Please type something, or x to escape:
something
You wrote something
Something else
You wrote Something else
x
You wrote x
x
You wrote x
x
You wrote x
Ia mengambil input yang kita berikan dan mengembalikannya, dan ia pun tahu bahwa kita menuliskan x
. Hanya saja, ia tidak keluar dari programnya. Cara satu-satunya untuk keluar dari program tersebut adalah dengan menutup window dimana Terminalnya terbuka, atau menggunakan Ctrl+c. Mari kita ubah {}
menjadi {:?}
di println!
untuk mendapatkan informasi (atau Anda bisa menggunakan dbg!(&input_string)
jika Anda menyukai macro tersebut). Sekarang outputnya menjadi seperti ini:
Please type something, or x to escape:
something
You wrote "something\r\n"
Something else
You wrote "Something else\r\n"
x
You wrote "x\r\n"
x
You wrote "x\r\n"
Ini dikarenakan inputan dari keyboard sebenarnya tidak hanya mendapatkan tulisan something
. Ia sebenarnya mendapatkan tulisan something
dan juga Enter
. Ada method yang mudah digunakan yang berguna untuk memperbaiki hal ini, namanya adalah .trim()
, yang mana akan menghapus semua whitespace. Whitespace, adalah semua karakter yang terdaftar di sini:
U+0009 (horizontal tab, '\t')
U+000A (line feed, '\n')
U+000B (vertical tab)
U+000C (form feed)
U+000D (carriage return, '\r')
U+0020 (space, ' ')
U+0085 (next line)
U+200E (left-to-right mark)
U+200F (right-to-left mark)
U+2028 (line separator)
U+2029 (paragraph separator)
Sehingga ia akan mengubah x\r\n
menjadi hanya x
. Dengan itu, program kita sudah berjalan sebagaimana semestinya:
use std::io; fn main() { println!("Please type something, or x to escape:"); let mut input_string = String::new(); while input_string.trim() != "x" { input_string.clear(); io::stdin().read_line(&mut input_string).unwrap(); println!("You wrote {}", input_string); } println!("See you later!"); }
Inilah outputnya:
Please type something, or x to escape:
something
You wrote something
Something
You wrote Something
x
You wrote x
See you later!
Ada inputan user berjenis lain yang biasanya disebut std::env::Args
(env adalah environment). Args
adalah apa yang user tuliskan saat memulai program. Sebenarnya selalu ada setidaknya satu buah Arg
dalam sebuah program. Mari kita buat program yang hanya mencetak menggunakan std::env::args()
untuk melihat apa sebenarnya Args
ini.
fn main() { println!("{:?}", std::env::args()); }
Jika kita menjalankan cargo run
maka ia mencetak sesuatu seperti ini:
Args { inner: ["target\\debug\\rust_book.exe"] }
Mari kita berikan lebih banyak input dan melihat apa yang dilakukannya. Kita akan menuliskan cargo run but with some extra words
. Outputnya adalah seperti berikut:
Args { inner: ["target\\debug\\rust_book.exe", "but", "with", "some", "extra", "words"] }
Menarik. Dan saat kita melihat pada laman tentang Args, kita melihat bahwa ia mengimplementasikan IntoIterator
. Yang berarti kita bisa melakukan semua hal yang kita ketahui tentang iterator untuk membacanya dan juga mengubahnya. Mari kita coba:
use std::env::args; fn main() { let input = args(); for entry in input { println!("You entered: {}", entry); } }
Outputnya adalah:
You entered: target\debug\rust_book.exe
You entered: but
You entered: with
You entered: some
You entered: extra
You entered: words
Anda bisa melihat bahwa argument pertama selalu menuliskan nama programnya, sehingga Anda seringkali ingin mengabaikannya, seperti ini:
use std::env::args; fn main() { let input = args(); input.skip(1).for_each(|item| { println!("You wrote {}, which in capital letters is {}", item, item.to_uppercase()); }) }
Outputnya adalah seperti ini:
You wrote but, which in capital letters is BUT
You wrote with, which in capital letters is WITH
You wrote some, which in capital letters is SOME
You wrote extra, which in capital letters is EXTRA
You wrote words, which in capital letters is WORDS
Penggunaan paling umum dari Args
adalah untuk memasukkan setting dari user. Anda bisa memastikan bahwa user menuliskan input yang Anda butuhkan, dan hanya menjalankan programnya jika inputannya benar. Ini adalah program sederhana yang membuat outputnya menjadi huruf besar (capital) atau huruf kecil (lowercase):
use std::env::args; enum Letters { Capitalize, Lowercase, Nothing, } fn main() { let mut changes = Letters::Nothing; let input = args().collect::<Vec<_>>(); if input.len() > 2 { match input[1].as_str() { "capital" => changes = Letters::Capitalize, "lowercase" => changes = Letters::Lowercase, _ => {} } } for word in input.iter().skip(2) { match changes { Letters::Capitalize => println!("{}", word.to_uppercase()), Letters::Lowercase => println!("{}", word.to_lowercase()), _ => println!("{}", word) } } }
Berikut adalah beberapa contoh outputnya:
Input: cargo run please make capitals
:
make capitals
Input: cargo run capital
:
// Nothing here...
Input: cargo run capital I think I understand now
:
I
THINK
I
UNDERSTAND
NOW
Input: cargo run lowercase Does this work too
does
this
work
too
Selain Args
yang bisa mengambil inputan dari user melalui std::env::args()
, ada juga Vars
yang mana ia adalah system variable. Itu adalah setting dasar untuk program yang tidak diketikkan oleh pengguna. Anda bisa menggunakan std::env::vars()
untuk melihat semua setting tersebut sebagai (String, String)
. Dan ada banyak sekali. Contohnya:
fn main() { for item in std::env::vars() { println!("{:?}", item); } }
Dengan menuliskan code seperti di atas, Anda bisa melihat semua informasi tentang user session. Ia akan menampilkan informasi seperti ini:
("CARGO", "/playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/cargo")
("CARGO_HOME", "/playground/.cargo")
("CARGO_MANIFEST_DIR", "/playground")
("CARGO_PKG_AUTHORS", "The Rust Playground")
("CARGO_PKG_DESCRIPTION", "")
("CARGO_PKG_HOMEPAGE", "")
("CARGO_PKG_NAME", "playground")
("CARGO_PKG_REPOSITORY", "")
("CARGO_PKG_VERSION", "0.0.1")
("CARGO_PKG_VERSION_MAJOR", "0")
("CARGO_PKG_VERSION_MINOR", "0")
("CARGO_PKG_VERSION_PATCH", "1")
("CARGO_PKG_VERSION_PRE", "")
("DEBIAN_FRONTEND", "noninteractive")
("HOME", "/playground")
("HOSTNAME", "f94c15b8134b")
("LD_LIBRARY_PATH", "/playground/target/debug/build/backtrace-sys-3ec4c973f371c302/out:/playground/target/debug/build/libsqlite3-sys-fbddfbb9b241dacb/out:/playground/target/debug/build/ring-cadba5e583648abb/out:/playground/target/debug/deps:/playground/target/debug:/playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib:/playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib")
("PATH", "/playground/.cargo/bin:/playground/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
("PLAYGROUND_EDITION", "2018")
("PLAYGROUND_TIMEOUT", "10")
("PWD", "/playground")
("RUSTUP_HOME", "/playground/.rustup")
("RUSTUP_TOOLCHAIN", "stable-x86_64-unknown-linux-gnu")
("RUST_RECURSION_COUNT", "1")
("SHLVL", "1")
("SSL_CERT_DIR", "/usr/lib/ssl/certs")
("SSL_CERT_FILE", "/usr/lib/ssl/certs/ca-certificates.crt")
("USER", "playground")
("_", "/usr/bin/timeout")
Jadi jika Anda memerlukan informasi ini, Vars
adalah hal yang Anda perlukan.
Cara termudah untuk mendapatkan single information dari Var
adalah menggunakan macro env!
. Anda cukup memberikannya nama variabel, dan ia akan memberikan kembalian value yang berupa &str
. Ini tidak akan berfungsi jika variabelnya dituliskan dengan salah (typo) atau memang tidak ada, jadinya jika Anda tidak yakin maka gunakan option_env!
. Jika kita menuliskan seperti ini di Playground:
fn main() { println!("{}", env!("USER")); println!("{}", option_env!("ROOT").unwrap_or("Can't find ROOT")); println!("{}", option_env!("CARGO").unwrap_or("Can't find CARGO")); }
maka kita akan mendapatkan output:
playground
Can't find ROOT
/playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/cargo
Jadi, option_env!
akan selalu menjadi macro yang lebih aman untuk hal ini. env!
lebih baik digunakan jika sebenarnya Anda menginginkan programnya menjadi crash di saat Anda tidak bisa menemukan environment variablenya.