Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
Rust Standard Library Cookbook

You're reading from   Rust Standard Library Cookbook Over 75 recipes to leverage the power of Rust

Arrow left icon
Product type Paperback
Published in Mar 2018
Publisher Packt
ISBN-13 9781788623926
Length 360 pages
Edition 1st Edition
Languages
Arrow right icon
Authors (2):
Arrow left icon
Jan Hohenheim Jan Hohenheim
Author Profile Icon Jan Hohenheim
Jan Hohenheim
Daniel Durante Daniel Durante
Author Profile Icon Daniel Durante
Daniel Durante
Arrow right icon
View More author details
Toc

Table of Contents (17) Chapters Close

Title Page
Copyright and Credits
Packt Upsell
Contributors
Preface
1. Learning the Basics FREE CHAPTER 2. Working with Collections 3. Handling Files and the Filesystem 4. Serialization 5. Advanced Data Structures 6. Handling Errors 7. Parallelism and Rayon 8. Working with Futures 9. Networking 10. Using Experimental Nightly Features 1. Other Books You May Enjoy Index

Reading from stdin


If you want to create an interactive application, it's easy to prototype your functionality with the command line. For CLI programs, this will be all the interaction you need.

How to do it...

  1. In the src/bin folder, create a file called stdin.rs

  2. Add the following code and run it with cargo run --bin stdin:

1   use std::io;
2   use std::io::prelude::*;
3
4   fn main() {
5     print_single_line("Please enter your forename: ");
6     let forename = read_line_iter();
7
8     print_single_line("Please enter your surname: ");
9     let surname = read_line_buffer();
10
11    print_single_line("Please enter your age: ");
12    let age = read_number();
13
14    println!(
15      "Hello, {} year old human named {} {}!",
16      age, forename, surname
17    );
18  }
19
20  fn print_single_line(text: &str) {
21    // We can print lines without adding a newline
22    print!("{}", text);
23    // However, we need to flush stdout afterwards
24    // in order to guarantee that the data actually displays
25    io::stdout().flush().expect("Failed to flush stdout");
26  }
27
28  fn read_line_iter() -> String {
29    let stdin = io::stdin();
30    // Read one line of input iterator-style
31    let input = stdin.lock().lines().next();
32    input
33      .expect("No lines in buffer")
34      .expect("Failed to read line")
35      .trim()
36      .to_string()
37  }
38
39  fn read_line_buffer() -> String {
40    // Read one line of input buffer-style
41    let mut input = String::new();
42    io::stdin()
43      .read_line(&mut input)
44      .expect("Failed to read line");
45    input.trim().to_string()
46  }
47
48  fn read_number() -> i32 {
49    let stdin = io::stdin();
50    loop {
51      // Iterate over all lines that will be inputted
52      for line in stdin.lock().lines() {
53        let input = line.expect("Failed to read line");
54        // Try to convert a string into a number
55        match input.trim().parse::<i32>() {
56          Ok(num) => return num,
57            Err(e) => println!("Failed to read number: {}", e),
58        }
59      }
60    }
61  }

How it works...

In order to read from the standard console input, stdin, we first need to obtain a handle to it. We do this by calling io::stdin() [29]. Imagine the returned object as a reference to a global stdin object. This global buffer is managed by a Mutex, which means that only one thread can access it at a time (more on that later in the book, in the Parallelly accessing resources with Mutexes section inChapter 7,Parallelism and Rayon). We get this access by locking (usinglock()) the buffer, which returns a new handle [31]. After we have done this, we can call thelinesmethod on it, which returns an iterator over the lines the user will write [31 and 52]. More on iterators in the Accessing collections as Iterators section inChapter 2,Working with Collections.

Finally, we can iterate over as many submitted lines as we want until some kind of break condition is reached, otherwise the iteration would go on forever. In our example, we break the number-checking loop as soon as a valid number has been entered [56].

If we're not particularly picky about our input and just want the next line, we have two options:

  • We can continue using the infinite iterator provided by lines(), but simply call next on it in order to just take the first one. This comes with an additional error check as, generally speaking, we cannot guarantee that there is a next element.

  • We can use read_line in order to populate an existing buffer [43]. This doesn't require that we lock the handler first, as it is done implicitly.

Although they both result in the same end effect, you should choose the first option. It is more idiomatic as it uses iterators instead of a mutable state, which makes it more maintainable and readable.

On a side note, we are using print! instead of println! in some places in this recipe for aesthetic reasons [22]. If you prefer the look of newlines before user input, you can refrain from using them.

There's more...

This recipe is written with the assumption that you want to use stdin for live interaction over the cli. If you plan on instead piping some data into it (for example, cat foo.txt | stdin.rs on *nix), you can stop treating the iterator returned by lines() as infinite and retrieve the individual lines, not unlike how you retrieved the individual parameters in the last recipe.

There are various calls to trim() in our recipe [35, 45 and 55]. This method removes leading and trailing whitespace in order to enhance the user-friendliness of our program. We are going to look at it in detail in the Using a string section in Chapter 2, Working with Collections.

See also

  • Interacting with environment variables recipe inChapter 1, Learning the Basics
  • Using a string and Accessing collections as iterators recipe inChapter 2, Working with Collections
  • Parallelly accessing resources with Mutexes recipe inChapter 7, Parallelism and Rayon
You have been reading a chapter from
Rust Standard Library Cookbook
Published in: Mar 2018
Publisher: Packt
ISBN-13: 9781788623926
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at ₹800/month. Cancel anytime
Visually different images