标准输入输出

标准输入输出

输入输出是人机交互的一种方式。最常见的输入输出是标准输入输出和文件输入输出。

标准输入

标准输入也叫作控制台输入,是常见输入的一种。

use std::io;

fn read_input() -> io::Result<()> {
    let mut input = String::new();

    try!(io::stdin().read_line(&mut input));

    println!("You typed: {}", input.trim());

    Ok(())
}

fn main() {
    read_input();
}

use std::io;
fn main() {
    let mut input = String::new();

    io::stdin().read_line(&mut input).expect("WTF!");

    println!("You typed: {}", input.trim());
}

这里体现了常见的标准输入的处理方式。两个例子都是声明了一个可变的字符串来保存输入的数据。他们的不同之处在在于处理潜在输入异常的方式。

  1. 例子 1 使用了 try! 宏。这个宏会返回 Result<(), io::Error> 类型,io::Result<()> 就是这个类型的别名。所以例子 1 需要单独使用一个 read_input 函数来接收这个类型,而不是在 main 函数里面,因为 main 函数并没有接收 io::Result<()> 作为返回类型。
  2. 例子 2 使用了 Result<(), io::Error> 类型的 expect 方法来接收 io::stdin().read_line 的返回类型。并处理可能潜在的 io 异常。

标准输出

println! 是 Rust 中常用的打印变量的宏,添加 \n 将创建新行,而 \t 将创建制表符:

fn main() {
    // Note: this is print!, not println!
    print!("\t Start with a tab\nand move to a new line");
}

         Start with a tab
and move to a new line

换行

"" 中您可以毫无问题地写很多行,但要注意间距:

fn main() {
    // Note: After the first line you have to start on the far left.
    // If you write directly under println!, it will add the spaces
    println!("Inside quotes
you can write over
many lines
and it will print just fine.");

    println!("If you forget to write
    on the left side, the spaces
    will be added when you print.");
}

Inside quotes
you can write over
many lines
and it will print just fine.
If you forget to write
    on the left side, the spaces
    will be added when you print.

有时您在字符串中包含许多 " 和转义字符,并希望 Rust 忽略所有内容。为此,您可以在开头添加 r#,在结尾添加 #。如果需要打印#,则可以以 r# 开头#并以##结尾。如果您需要多个,则可以在每侧再添加一个#。

fn main() {

    let my_string = "'Ice to see you,' he said."; // single quotes
    let quote_string = r#""Ice to see you," he said."#; // double quotes
    let hashtag_string = r##"The hashtag #IceToSeeYou had become very popular."##; // Has one # so we need at least ##
    let many_hashtags = r####""You don't have to type ### to use a hashtag. You can just use #.""####; // Has three ### so we need at least ####

    println!("{}\n{}\n{}\n{}\n", my_string, quote_string, hashtag_string, many_hashtags);
}

'Ice to see you,' he said.
"Ice to see you," he said.
The hashtag #IceToSeeYou had become very popular.
"You don't have to type ### to use a hashtag. You can just use #."

r# 有另一种用途:可以将关键字用作变量名。

fn main() {
    let r#let = 6; // The variable's name is let
    let mut r#mut = 10; // This variable's name is mut

}

r# 也具有此功能,因为旧版本的 Rust 不具有与 Rust 现在相同的所有关键字。因此,使用 r# 可以更轻松地避免以前不是关键字的变量名出错。您可能不需要它,但是如果您确实需要为变量使用关键字,则可以使用 r#。

变量

Rust 中的简单变量可以在 println!中用 {} 打印。但是某些变量不能,您需要调试打印。调试打印是为程序员打印的,因为它通常会显示更多信息。调试有时看起来并不漂亮,因为它有更多信息可帮助您。您如何知道是否需要 {:?} 而不是 {}? 编译器会告诉您。例如:

fn main() {
    let doesnt_print = ();
    println!("This will not print: {}", doesnt_print); // ⚠️
}

error[E0277]: `()` doesn't implement `std::fmt::Display`
 --> src\main.rs:3:41
  |
3 |     println!("This will not print: {}", doesnt_print);
  |                                         ^^^^^^^^^^^^ `()` cannot be formatted with the default formatter
  |
  = help: the trait `std::fmt::Display` is not implemented for `()`
  = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
  = note: required by `std::fmt::Display::fmt`
  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

因此,Display 表示使用 {} 打印,而 Debug 表示使用 {:?} 打印。例如,如果您有引用,则可以使用{:p}打印指针地址。指针地址是指计算机内存中的位置。

fn main() {
    let number = 9;
    let number_ref = &number;
    println!("{:p}", number_ref);
}

这将打印 0xe2bc0ffcfc 或其他地址。每次都可能会有所不同,具体取决于计算机的存储位置。或者您可以打印二进制,十六进制和八进制:

fn main() {
    let number = 555;
    println!("Binary: {:b}, hexadecimal: {:x}, octal: {:o}", number, number, number);
}

您可以添加数字以更改顺序:

fn main() {
    let father_name = "Vlad";
    let son_name = "Adrian Fahrenheit";
    let family_name = "Țepeș";
    println!("This is {1} {2}, son of {0} {2}.", father_name, son_name, family_name);
}

This is Adrian Fahrenheit Țepeș, son of Vlad Țepeș.

也许您要打印一个非常复杂的字符串,并想在 {} 中添加名称。您可以这样做:

fn main() {
    println!("{city1} is in {country} and {city2} is also in {country},
but {city3} is not in {country}.", city1 = "Seoul", city2 = "Busan", city3 = "Tokyo", country = "Korea");
}

Rust 中不会使用太多复杂的打印。但是这是怎么做的:{variable:padding alignment minimum.maximum}

fn main() {
    let letter = "a";
    println!("{:ㅎ^11}", letter);
}

ㅎㅎㅎㅎㅎaㅎㅎㅎㅎㅎ

fn main() {
    let title = "TODAY'S NEWS";
    println!("{:-^30}", title); // no variable name, pad with -, put in centre, 30 characters long
    let bar = "|";
    println!("{: <15}{: >15}", bar, bar); // no variable name, pad with space, 15 characters each, one to the left, one to the right
    let a = "SEOUL";
    let b = "TOKYO";
    println!("{city1:-<15}{city2:->15}", city1 = a, city2 = b); // variable names city1 and city2, pad with -, one to the left, one to the right
}

---------TODAY'S NEWS---------
|                            |
SEOUL--------------------TOKYO

打印特殊字符

如果要打印 &str 或 char 的字节,可以在字符串之前写 b。这适用于所有 ASCII 字符。这些都是 ASCII 字符:

☺☻♥♦♣♠♫☼►◄↕‼¶§▬↨↑↓→∟↔▲▼123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

当我们打印如下字符串时,就能够得到字节:

fn main() {
    println!("{:?}", b"This will look like numbers");
}

[84, 104, 105, 115, 32, 119, 105, 108, 108, 32, 108, 111, 111, 107, 32, 108, 105, 107, 101, 32, 110, 117, 109, 98, 101, 114, 115]

对于 char,这称为字节,对于 &str,则称为字节字符串。还有一个 Unicode 转义符,可让您在字符串内打印任何 Unicode 字符:\u{}。{}内有一个十六进制数字以进行打印。这是一个简短的示例,说明如何获取 Unicode 编号以及如何再次打印它。

fn main() {
    println!("{:X}", '행' as u32); // Cast char as u32 to get the hexadecimal value
    println!("{:X}", 'H' as u32);
    println!("{:X}", '居' as u32);
    println!("{:X}", 'い' as u32);

    println!("\u{D589}, \u{48}, \u{5C45}, \u{3044}"); // Try printing them with unicode escape \u
}
下一页