From c95f29e478e5f848388aba1576c56d34d9d8e5e9 Mon Sep 17 00:00:00 2001 From: WangMengabc <98640292+WangMengabc@users.noreply.github.com> Date: Mon, 15 Apr 2024 06:08:18 +0000 Subject: [PATCH] print.md synchronizes official documents (#190) * print.md synchronizes official documents * Modified format without translation * Update print.md * Update src/hello/print.md --------- Co-authored-by: YangFong --- english/src/hello/print.md | 91 +++++++++++++++++++++++--------------- src/hello/print.md | 64 ++++++++++++++++++--------- 2 files changed, 99 insertions(+), 56 deletions(-) diff --git a/english/src/hello/print.md b/english/src/hello/print.md index 89d2aa0d..abc26d4b 100644 --- a/english/src/hello/print.md +++ b/english/src/hello/print.md @@ -1,13 +1,15 @@ # Formatted print -Printing is handled by a series of [`macros`][macros] defined in [`std::fmt`][fmt] -some of which include: +Printing is handled by a series of [`macros`][macros] defined in +[`std::fmt`][fmt] some of which include: * `format!`: write formatted text to [`String`][string] -* `print!`: same as `format!` but the text is printed to the console (io::stdout). +* `print!`: same as `format!` but the text is printed to the console + (io::stdout). * `println!`: same as `print!` but a newline is appended. -* `eprint!`: same as `format!` but the text is printed to the standard error (io::stderr). -* `eprintln!`: same as `eprint!`but a newline is appended. +* `eprint!`: same as `print!` but the text is printed to the standard error + (io::stderr). +* `eprintln!`: same as `eprint!` but a newline is appended. All parse text in the same fashion. As a plus, Rust checks formatting correctness at compile time. @@ -18,11 +20,9 @@ fn main() { // arguments. These will be stringified. println!("{} days", 31); - // Without a suffix, 31 becomes an i32. You can change what type 31 is - // by providing a suffix. The number 31i64 for example has the type i64. - - // There are various optional patterns this works with. Positional - // arguments can be used. + // Positional arguments can be used. Specifying an integer inside `{}` + // determines which additional argument will be replaced. Arguments start + // at 0 immediately after the format string. println!("{0}, this is {1}. {1}, this is {0}", "Alice", "Bob"); // As can named arguments. @@ -31,29 +31,46 @@ fn main() { subject="the quick brown fox", verb="jumps over"); - // Special formatting can be specified after a `:`. - println!("{} of {:b} people know binary, the other half doesn't", 1, 2); + // Different formatting can be invoked by specifying the format character + // after a `:`. + println!("Base 10: {}", 69420); // 69420 + println!("Base 2 (binary): {:b}", 69420); // 10000111100101100 + println!("Base 8 (octal): {:o}", 69420); // 207454 + println!("Base 16 (hexadecimal): {:x}", 69420); // 10f2c + + // You can right-justify text with a specified width. This will + // output " 1". (Four white spaces and a "1", for a total width of 5.) + println!("{number:>5}", number=1); - // You can right-align text with a specified width. This will output - // " 1". 5 white spaces and a "1". - println!("{number:>width$}", number=1, width=6); + // You can pad numbers with extra zeroes, + println!("{number:0>5}", number=1); // 00001 + // and left-adjust by flipping the sign. This will output "10000". + println!("{number:0<5}", number=1); // 10000 - // You can pad numbers with extra zeroes. This will output "000001". - println!("{number:0>width$}", number=1, width=6); + // You can use named arguments in the format specifier by appending a `$`. + println!("{number:0>width$}", number=1, width=5); - // Rust even checks to make sure the correct number of arguments are - // used. + // Rust even checks to make sure the correct number of arguments are used. println!("My name is {0}, {1} {0}", "Bond"); // FIXME ^ Add the missing argument: "James" - // Create a structure named `Structure` which contains an `i32`. - #[allow(dead_code)] + // Only types that implement fmt::Display can be formatted with `{}`. User- + // defined types do not implement fmt::Display by default. + + #[allow(dead_code)] // disable `dead_code` which warn against unused module struct Structure(i32); - // However, custom types such as this structure require more complicated - // handling. This will not work. - println!("This struct `{}` won't print...", Structure(3)); - // FIXME ^ Comment out this line. + // This will not compile because `Structure` does not implement + // fmt::Display. + // println!("This struct `{}` won't print...", Structure(3)); + // TODO ^ Try uncommenting this line + + // For Rust 1.58 and above, you can directly capture the argument from a + // surrounding variable. Just like the above, this will output + // " 1", 4 white spaces and a "1". + let number: f64 = 1.0; + let width: usize = 5; + println!("{number:>width$}"); } ``` @@ -62,7 +79,7 @@ of text. The base form of two important ones are listed below: * `fmt::Debug`: Uses the `{:?}` marker. Format text for debugging purposes. * `fmt::Display`: Uses the `{}` marker. Format text in a more elegant, user -friendly fashion. + friendly fashion. Here, we used `fmt::Display` because the std library provides implementations for these types. To print text for custom types, more steps are required. @@ -70,20 +87,22 @@ for these types. To print text for custom types, more steps are required. Implementing the `fmt::Display` trait automatically implements the [`ToString`] trait which allows us to [convert] the type to [`String`][string]. +In *line 43*, `#[allow(dead_code)]` is an [attribute] which only applies to the module after it. + ### Activities - * Fix the two issues in the above code (see FIXME) so that it runs without - error. - * Add a `println!` macro that prints: `Pi is roughly 3.142` by controlling - the number of decimal places shown. For the purposes of this exercise, - use `let pi = 3.141592` as an estimate for pi. (Hint: you may need to - check the [`std::fmt`][fmt] documentation for setting the number of - decimals to display) +* Fix the issue in the above code (see FIXME) so that it runs without + error. +* Try uncommenting the line that attempts to format the `Structure` struct + (see TODO) +* Add a `println!` macro call that prints: `Pi is roughly 3.142` by controlling + the number of decimal places shown. For the purposes of this exercise, use + `let pi = 3.141592` as an estimate for pi. (Hint: you may need to check the + [`std::fmt`][fmt] documentation for setting the number of decimals to display) ### See also: -[`std::fmt`][fmt], [`macros`][macros], [`struct`][structs], -and [`traits`][traits] +[`std::fmt`][fmt], [`macros`][macros], [`struct`][structs], [`traits`][traits], and [`dead_code`][dead_code] [fmt]: https://doc.rust-lang.org/std/fmt/ [macros]: ../macros.md @@ -92,3 +111,5 @@ and [`traits`][traits] [traits]: https://doc.rust-lang.org/std/fmt/#formatting-traits [`ToString`]: https://doc.rust-lang.org/std/string/trait.ToString.html [convert]: ../conversion/string.md +[attribute]: ../attribute.md +[dead_code]: ../attribute/unused.md diff --git a/src/hello/print.md b/src/hello/print.md index d02ab02e..5734a694 100644 --- a/src/hello/print.md +++ b/src/hello/print.md @@ -16,11 +16,9 @@ fn main() { // 变量内容会转化成字符串。 println!("{} days", 31); - // 不加后缀的话,31 就自动成为 i32 类型。 - // 你可以添加后缀来改变 31 的类型(例如使用 31i64 声明 31 为 i64 类型)。 - - // 用变量替换字符串有多种写法。 - // 比如可以使用位置参数。 + // 可以使用位置参数。 + // 在 `{}` 中指定一个整数确定将替换哪个附加参数。 + // 参数从紧接在格式字符串之后的 0 开始。 println!("{0}, this is {1}. {1}, this is {0}", "Alice", "Bob"); // 可以使用命名参数。 @@ -29,49 +27,73 @@ fn main() { subject="the quick brown fox", verb="jumps over"); - // 可以在 `:` 后面指定特殊的格式。 - println!("{} of {:b} people know binary, the other half don't", 1, 2); + // 通过在 `:` 后面指定格式字符,可以调用不同的格式。 + println!("Base 10: {}", 69420); // 69420 + println!("Base 2 (binary): {:b}", 69420); // 10000111100101100 + println!("Base 8 (octal): {:o}", 69420); // 207454 + println!("Base 16 (hexadecimal): {:x}", 69420); // 10f2c + + // 可以用指定的宽度对文本进行右对齐。 + // 这将输出“ 1”。(四个空格和一个“1”,总宽度为5) + println!("{number:>5}", number=1); - // 你可以按指定宽度来右对齐文本。 - // 下面语句输出 " 1",5 个空格后面连着 1。 - println!("{number:>width$}", number=1, width=6); + // 你可以在数字左边补 0, + println!("{number:0>5}", number=1); // 00001 + // 在数字右边补零,下面语句输出 "000001"。 + println!("{number:0<5}", number=1); // 10000 - // 你可以在数字左边补 0。下面语句输出 "000001"。 - println!("{number:>0width$}", number=1, width=6); + // 可以通过添加 `$` 在格式说明符中使用命名参数。 + println!("{number:0>width$}", number=1, width=5); // println! 会检查使用到的参数数量是否正确。 println!("My name is {0}, {1} {0}", "Bond"); - // 改正 ^ 补上漏掉的参数:"James" + // FIXME ^ 补上漏掉的参数:"James" - // 创建一个包含单个 `i32` 的结构体(structure)。命名为 `Structure`。 - #[allow(dead_code)] + // 只有实现了fmt::Display的类型才能使用'{}'进行格式化。 + // 默认情况下,用户定义的类型不实现fmt::Display。 + #[allow(dead_code)] // 禁用对未使用模块发出警告的' dead_code ' struct Structure(i32); - // 但是像结构体这样的自定义类型需要更复杂的方式来处理。 + // 这将不会编译,因为 `Structure` 没有实现 // 下面语句无法运行。 - println!("This struct `{}` won't print...", Structure(3)); - // 改正 ^ 注释掉此行。 + // println!("This struct `{}` won't print...", Structure(3)); + // TODO ^ 注释掉此行。 + + // 对于 Rust 1.58 及更高版本,你可以直接从周围变量捕获参数。 + // 就像上面一样,这将输出“ 1”,4 个空格和 1 个“1”。 + let number: f64 = 1.0; + let width: usize = 5; + println!("{number:>width$}"); } ``` -[`std::fmt`][fmt] 包含多种 [`trait`][traits](特质)来控制文字显示,其中重要的两种 trait 的基本形式如下: +[`std::fmt`][fmt] 包含多种 [`traits`][traits](特质)来控制文字显示,其中重要的两种 trait 的基本形式如下: - `fmt::Debug`:使用 `{:?}` 标记。格式化文本以供调试使用。 - `fmt::Display`:使用 `{}` 标记。以更优雅和友好的风格来格式化文本。 上例使用了 `fmt::Display`,因为标准库提供了那些类型的实现。若要打印自定义类型的文本,需要更多的步骤。 +实现 `fmt::Display` 特性会自动实现 [`ToString`] 特征,它允许我们将类型 [convert] 为 [`String`][string]。 + +在*第 43 行*中,`#[allow(dead_code)]` 是一个 [attribute],只适用于它后面的模块。 + ### 动手试一试 -- 改正上面代码中的两个错误(见 “改正”),使它可以没有错误地运行。 +- 改正上面代码中的错误(见 FIXME),使它可以没有错误地运行。 +- 尝试取消注释,输出结构体内容(见 TODO)。 - 再用一个 `println!` 宏,通过控制显示的小数位数来打印:`Pi is roughly 3.142`(Pi 约等于 3.142)。为了达到练习目的,使用 `let pi = 3.141592` 作为 Pi 的近似值(提示:设置小数位的显示格式可以参考文档 [`std::fmt`][fmt])。 ### 参见: -[`std::fmt`][fmt], [`macros`][macros], [`struct`][structs] 和 [`trait`][traits] +[`std::fmt`][fmt], [`macros`][macros], [`struct`][structs], [`traits`][traits] 和 [`dead_code`][dead_code] [fmt]: https://rustwiki.org/zh-CN/std/fmt/ [macros]: ../macros.md [string]: ../std/str.md [structs]: ../custom_types/structs.md [traits]: ../trait.md +[`ToString`]: https://doc.rust-lang.org/std/string/trait.ToString.html +[convert]: ../conversion/string.md +[attribute]: ../attribute.md +[dead_code]: ../attribute/unused.md