Rust Cookbook(译):让我们再次进行系统编程(第一章)

在本章中,我们将介绍以下配方:

  • 在Linux和macOS中设置Rust
  • 在Windows中设置Rust
  • 创建你的第一个Rust程序
  • 定义变量赋值
  • 设置布尔值和字符类型
  • 控制小数点,数字格式和命名参数
  • 执行算术运算
  • 定义可变变量
  • 声明并执行字符串操作
  • 在Rust中声明数组并使用切片
  • 在Rust中声明向量
  • 在Rust中声明元组
  • 对两个数字执行计算

介绍

本章的重点是在设置Rust和使用它进行编程方面为您带来行为方面的改变。 本章的目的是让你意识到为什么在有许多其他编程语言解决不同垂直方面的各种问题时应该使用Rust - 为什么还需要另一种编程语言?

这些是他们在学习新语言时会想到的基本问题,Rust是一种运行速度极快,防止段错误并保证线程安全的系统编程语言。 正如定义所提到的,Rust专注于消除各种类型的系统编程错误和错误,这些错误在一天结束时有助于制作安全,快速和开箱即用的生产级应用程序。
本章深入介绍Rust中的各种赋值操作及其功能,数据类型和数据结构。

在Linux和macOS中设置Rust

在Windows中设置Rust

此内容介绍了如何在Windows系统上设置Rust。

做好准备

为此,我们需要一台Windows机器。

怎么做…

在Windows上安装它非常容易:

1.从https://win.rustup.rs下载并运行.exe文件。

2.单击下载的可执行文件; 这将在命令提示符中开始安装。

3.在“命令提示符”中选择选项1以进行常规安装,建议使用此选项。

怎么运行的…

它类似于Linux和macOS; 我们必须下载可执行文件并运行它,弹出安装开始的命令提示符。 这里,Rust团队不是使用shell脚本,而是为Windows提供可执行文件。 可执行文件在主机系统上下载Rust编译器和Cargo依赖项。

扫描二维码关注公众号,回复: 3326820 查看本文章

创建你的第一个Rust程序

此内容旨在帮助您确保编译器正常工作,并创建一个工作区,您可以在其中试用所有这些内容。

做好准备

我们将要求主机系统上的Rust编译器设置进行编程; 我建议你下载一个你选择的文本编辑器。 在本书中,我们使用Sublime Text编辑器进行代码开发过程。

怎么做…

1.在您的用户空间中创建一个文件夹,您将在其中存储该书的所有程序:

mkdir /home/viki/rust_cookbook

2.此命令将在您的用户空间中为您创建一个目录:

cd /home/viki/rust_cookbook

上述命令将把我们带到特定目录

3.现在,创建一个名为sample.rs的文件; .rs扩展名表明它是一个Rust脚本。
4.在文本编辑器中打开脚本,然后输入以下代码:

fn main() {
println!("Welcome to Rust Cookbook");
}

5.保存文件并转到终端。
6.使用Rust编译器编译代码,Rust编译器将创建可执行文件并在没有Rust的系统中运行:
在这里插入图片描述

怎么运行的…

让我们简要介绍一下代码,了解它是如何执行的。 Rust编译器查找main函数,它是代码流的起始部分。 我们有一个打印声明和要显示的对话。 当我们编译代码时,会创建一个可执行文件,在执行时会打印对话框。

Rust文件总是以.rs扩展名结尾。 如果你必须在文件名中使用多个单词来表示你的项目,建议使用下划线来分隔它们,例如,我们使用my_program.rs而不是myprogram.rs,这有助于提高可读性。

关键字fn定义了Rust中的一个函数。 主要功能是每个Rust程序的开始。 在这个程序中,我们有一个main函数,它不接受任何输入参数并返回任何类型。 如果有任何参数,它将放在括号(和)中。 函数体用大括号{和}包裹。 Rust需要围绕所有函数体。

将开口花括号放在与函数声明相同的行上是一种很好的风格,中间有一个空格。

Rust 中 std的println!宏用于创建和使用换行符打印到标准输出。 它位于main函数体内,并打印字符串Welcome to Rust Cookbook。 该行以分号(;)结尾。 Rust是一种面向表达式的语言,这意味着大多数事物都是表达式而不是语句。 分号(;)表示此表达式已结束,下一个表达式已准备好开始。

在运行Rust程序之前,我们必须编译它,我们可以使用可执行文件来运行程序并在终端中打印字符串。 Rust编译器通过输入rustc命令并将其传递给源文件的名称将创建可执行文件,例如,rustc main.rs将创建一个可执行文件./main。 在同一目录中。

定义变量赋值

我们将深入研究本节中的各种赋值运算符和函数。

做好准备

我们需要Rust编译器和任何文本编辑器进行编码,并在项目工作区中创建名为assignment.rs的文件。

怎么做…

1.首先在assignment.rs脚本中声明我们将用于此配方的不同库:

// Primitive libraries in rust
use std::{i8,i16,i32,i64,u8,u16,u32,u64,f32,f64,isize,usize};
use std::io::stdin;

use语句告诉编译器程序将使用库的以下属性。 std是一个内置的库,它随Rust编译器一起提供,不需要外部下载。 i8和i16是将在程序中使用的变量的不同数据类型,stdin帮助我们接受来自用户的用户输入:

fn main() {
println!("Understanding assignment");
// Compiler will automatically figure out the data type if
not mentioned
// Cannot change the value
let num =10;
println!("Num is {}", num);
}

2.上述脚本的输出如下:
在这里插入图片描述

3.使用下面的代码片段替换assignment.rs文件中前面脚本的main函数:

fn main(){
let age: i32 =40;
println!("Age is {}", age);
// Prints the max and min value of 32bit integer
println!("Max i32 {}",i32::MAX);
println!("Max i32 {}",i32::MIN);
}

在这里插入图片描述

4.在前面的代码片段中,我们声明了一个名为age的变量,并明确告诉编译器它是一个32位整数类型数据,并且我们正在打印32位int数据类型的最大值和最小值。 现在,下一段代码:

// Another way of variable assigning
let(f_name,l_name)=("viki","d");
println!("First name {0} and last name {1}",f_name,l_name);

在这里,我们使用方括号()在f_name和l_name中声明了两个变量。 这是一种在Rust中的单个语句中声明多个变量的方法。 类似地,在打印它们时,我们可以对变量的位置进行编号,以确定必须首先打印哪个变量。

怎么运行的…

在上一节中,我们从执行开始的地方声明了main函数。 在这里,我们声明一个名为num的变量并将其赋值为10. let语句使您能够声明变量并将它们赋值给一个值。 我们没有明确告诉num变量是什么类型的数据类型,但是在编译期间,它将被自动确定并且将基于此分配内存。

num值是不可变的,这意味着它的值在程序期间不能更改,并且一旦超出main函数的范围,它将从内存中删除。 要打印数字的值,我们必须使用大括号; 我们将在下一节详细介绍更多内容。

设置布尔值和字符类型

布尔运算符对程序员进行状态识别和检查有很大帮助。 在本文中,您将了解字符类型变量的分配。

做好准备

我们需要Rust编译器和任何文本编辑器进行编码。

怎么做…

1.创建一个名为boolean.rs的文件并编译以下代码:

fn main(){
//Setting boolean and character types
let bool_val: bool = true;
let x_char: char = 'a';
// Printing the character
println!("x char is {}", x_char);
println!("Bool value is {}", bool_val);
}

2.在前面的代码片段中,我们在Rust中分配一个布尔类型变量和字符值。

3.输出如下:
在这里插入图片描述

怎么运行的…

在前面的代码片段中,我们声明了main函数,我们在其中定义了两个变量:bool_val和x_char。 我们使用let语句为它们分配了布尔和字符值。 我们通过打印它们来跟进它。

控制小数点,数字格式和命名参数

本文重点介绍如何操作打印宏以在数据中执行各种控制操作。

做好准备

我们需要Rust编译器和任何文本编辑器进行编码。

怎么做…

1.在名为decimal.rs的Rust脚本中输入以下代码并编译它们:

fn main(){
// Prints the first 2 numbers after the decimal points
println!("{:.2}",1.2345 );
println!("================");
// print the binary hex and octal format
println!("B: {:b} H: {:x} O: {:o}",10,10,10 );
println!("================");
// Shifts
println!("{ten:>ws$}",ten=10, ws=5 );
println!("{ten:>0ws$}",ten=10, ws=5 );
}

2.代码输出如下:
在这里插入图片描述

怎么运行的…

在第一个print语句中,我们控制了终端中显示的小数点数。 在前面的代码片段中,我们在print语句中的冒号(:)之后将值设置为2,这告诉编译器只打印运行时变量的前两个小数点。

下一个print语句显示了Rust的内置功能,可以将要打印的值转换为不同的数字格式。 我们打印了十进制值10的二进制,十六进制和八进制值。要执行此活动,我们在print语句中的冒号后面特别提到了该参数。 Rust编译器可以理解这一点。 在运行时,Rust会自动将十进制类型转换为上面提到的数字格式,其中b代表二进制,x代表十六进制,o代表八进制。 这必须在以下内容之后给出:在print语句中。

接下来,print语句命名为arguments,我们定义了我们想要的空格(ws)类型。 我们这里有两个论点:十和ws。 我们控制了我们想要打印数据的方式以及我们希望用什么类型的值来填充ws。 在第一个打印声明中,我们用空格填充它。 在第二个印刷声明中,我们明确提到了零,这就是我们想要填补的空白。 我们在print语句的花括号内声明了命名参数,并为其分配了数据值。

执行算术运算

此配方展示了Rust中不同类型的算术运算。

做好准备

我们需要Rust编译器和任何文本编辑器进行编码。

怎么做…

1.在工作空间中创建名为arithmetic.rs的文件,并编译以下代码:

fn main(){
// Arithmetic Operations
println!("5 + 4 = {}", 5+4 );
println!("5 - 4 = {}", 5-4 );
println!("5 * 4 = {}", 5*4 );
println!("5 / 4 = {}", 5/4 );
println!("5 % 4 = {}", 5%4 );
// Assigning data types and mathematical Operations
let neg_4 = -4i32;
println!("abs(-4) = {}", neg_4.abs() );
println!("abs(-4) = {}", neg_4.pow(2) );
println!("round(1.2345) = {}", 1.2354f64.round() );
println!("ceil(1.2345) = {}", 1.2345f64.ceil() );
print!("sin 3.14 = {}", 3.14f64.sin() );
}

2.我们将获得以下输出:
在这里插入图片描述

怎么运行的…

在第一组打印语句中,我们在运行时期间对数据集执行了不同类型的算术运算。 与每个操作关联的括号中的以下符号用于执行算术运算:

  • 加(+)
  • 减法( - )
  • 乘法(x)
  • 除(/)
  • 模数(%)
    在下一组打印语句中,我们执行了各种数学运算,这些运算都是使用Rust编译器构建的。 我们声明了一个名为neg_4的变量,并为其赋值4i32,它是一个负32位整数,值为4.我们通过使用变量name variable.function调用abs()函数来设置变量的绝对值。 类似地,我们执行了其他数学运算,例如pow(value),它计算并将功率值应用于数据。 round()函数将数据查找到最接近的较低值。 ceil()函数返回大于或等于该数字的最小整数。 并且,sin()函数返回正弦值。

定义可变变量

Rust拥有所有权和借用的独特功能,使其能够克服段错误和数据争用。 这是通过Rust的可变性来实现的。

做好准备

我们需要Rust编译器和任何文本编辑器进行编码。

怎么做…

1.创建一个名为mutuable.rs的文件并编译以下代码:

fn main(){
let mut sample_var = 10;
println!(“Value of the sample variable is {}”,sample_var);
let sample_var = 20;
println!(“New Value of the sample variable is {}”,sample_var);
}

2.您应该得到以下输出:

在这里插入图片描述

怎么运行的…

由于我们已声明变量类型为mutable,因此Rust编译器允许开发人员更改在函数范围内分配的任意次数的数据值。

在前面的程序中,我们创建了一个名为sample_var的变量,并在赋值期间将其明确标记为可变类型。 由于此操作,Rust编译器允许为变量分配不同的值。

声明并执行字符串操作

此配方深入研究各种内置字符串操作和函数,使开发人员可以拆分和修改字符串数据。

做好准备

我们需要Rust编译器和任何文本编辑器进行编码。

怎么做…

1.创建一个名为string.rs的脚本并编译以下代码:

fn main() {
// declaring a random string
let rand_string = "I love Rust cookbook <3";
// printing the length of the string
println!("length of the string is {}",rand_string.len() );

2.在这里,您将创建一个名为rand_string的不可变变量,并使用字符串值赋值。 您还使用字符串数据类型的len()函数来打印句子的长度,这也将计算空白:

// Splits in string
let (first,second) = rand_string.split_at(7);
println!("First part : {0} Second part : {1}",first,second);
  1. split_at(value)函数将句子分为两部分,并将它们分配为两个变量:第一个和第二个。 然后我们打印出来:
// Count using iterator count
let count = rand_string.chars().count();
print!("count {}",count );

4.我们在这里使用两个函数,即字符和计数,其中字符标识所有字符,计数给出聚合的字符数:

println!("__________________________");
// printing all chars
let mut chars = rand_string.chars();
let mut indiv_chars = chars.next();
loop {
// Its like switch in c++
match indiv_chars {
Some(x) => println!("{}",x ),
None => break
} i
ndiv_chars = chars.next();
}

5.在前面的代码中,我们创建了一个名为chars的变量,它包含句子的所有字符。 然后,在下一步中,我们创建了另一个名为indiv_chars的变量,该变量包含chars变量的第一个字符。 我们使用next()函数将值赋给indiv_chars。

6.在循环函数中,打印chars变量的所有值,直到它变为null:

println!("__________________________");
// iterate over whitespace
let mut iter = rand_string.split_whitespace();
let mut indiv_word = iter.next();
loop {
// Its like switch in c++
match indiv_word {
Some(x) => println!("{}",x ),
None => break
}i
ndiv_word = iter.next();
}

7.在代码的这一部分中,我们将使用内置的split_whitespace()函数进行迭代。 本节将打印完整的单词:

println!("__________________________");
// iterate over next line
let rand_string2 = "I love \n everything about \n Rust <3";
let mut iter_line = rand_string2.lines();
let mut indiv_sent = iter_line.next();
loop {
// Its like switch in c++
match indiv_sent {
Some(x) => println!("{}",x ),
None => break
}i
ndiv_sent = iter_line.next();
}}

8.在代码的这一部分中,我们将使用内置的lines()函数迭代下一行。 本节将打印完整的句子。

9.您应该得到以下结果:
在这里插入图片描述

怎么运行的…

在这个配方中,我们分配一个名为rand_string的变量,其字符串值为I love Rust cookbook,我们在其中执行一组字符串操作。

在第一个print语句中,我们通过调用rand_string.len()来显示str类型的len()方法的字符串长度,相应地在下一个print语句中我们使用split_at()方法,该方法需要输入参数 将字符串拆分为传递的参数的值,在我们的例子中,我们调用rand_string.split_at(7)在字符串的索引7处拆分并将其分配给名为first和second的两个变量,这里space占用索引值。

在第三个print语句中,我们使用chars()和count()方法打印出现的字符数,我们使用以下语法rand_string.chars()。count(),其中chars()遍历字符和 count()用于计算元素数量。

循环是一个迭代语句,一直运行直到调用break键。 我们使用匹配功能,类似于其他语言的切换。 我们为它创建了不同的条件来检查和执行某些操作。

在匹配语句中,我们有两个条件:Some(x)和None。 在这两种情况下,我们执行如下的独特操作:

  • 在Some(x)的情况下,它基本上表示x是一个存在的值并且具有类型T,因此我们可以使用x变量进行进一步的操作,在这种情况下,我们打印值
  • 在None的情况下,它指的是一个值不存在的情况,理想情况下是字符串的结尾,我们在这些情况下执行的操作是打破循环

我们迭代三种类型的条件:

  • 第一组是个别情况,我们打印字符串的所有字符,由chars()和next()函数执行前面的匹配语句
  • 第二组是我们通过在空格的位置分割来打印字符串的所有不同单词的地方,并由split_whitespace()和next()函数与前面的匹配语句执行
  • 最后一个我们通过在下一行的位置分割来打印字符串的所有不同行,并由lines()和next()函数执行前面的匹配语句

在Rust中声明数组并使用切片

数组是具有相同数据类型的对象的集合,并存储在连续的内存中。 数组总是使用方括号[]创建,它们的大小在编译时是已知的。 这是他们类型的一部分:[T; size]。

切片类似于数组,但它们的大小在编译时是未知的。 第一个标记是数据的指针值; 第二个标记是用户根据应用程序选择的切片长度。 切片通常用于借用数组的一部分并具有类型签名和[T]。

做好准备

我们需要Rust编译器和任何文本编辑器进行编码。

怎么做…

1.创建一个名为array.rs的文件并编译以下代码:

fn main() {
// Defining an array
let rand_array = [1,2,3];
println!("random array {:?}",rand_array );
// indexing starts with 0
println!("random array 1st element {}",rand_array[0] );
println!("random array length {}",rand_array.len() );
// last two elements
println!("random array {:?}",&rand_array[1..3] );
}

2.我们将获得以下输出:
在这里插入图片描述

怎么运行的…

在这里,我们声明了一个名为rand_array的变量,并将其分配给一个在方括号内有三个元素的数组:1,2和3。 在第一个print语句中,我们在冒号(:)之后有一个问号(?),它向print语句指示它将打印数组的所有元素。

我们可以通过索引(指向数组数据元素的位置)来处理数组的每个元素。 在Rust中,定位从零开始。 因此,当我们打印rand_array [0]时,它将打印第一个元素。 在第三个print语句中,我们使用len()函数来获取数组中元素的长度或数量; 我们通过调用rand_var.len()来使用length函数。
在第四版中,我们有了一个名为slice的新概念。 数组被借作切片,我们在签名中提到指针的起始值和长度。 切片基本上引用数组元素的连续序列而不是整个元素。

我们通过print&rand_var打印完整的数组,这将打印整个数组。 我们还使用&rand_var [1…3]借用了一段数组,我们在方括号中提到了切片的大小。 这里,从一开始,我们打印数字的所有部分,直到三个上限,其中一个和三个是在终端中被解除引用并打印的数组的索引值。

在Rust中声明向量

向量是编程中非常重要的概念,人们常常在数组和向量之间混淆。 让我们揭开这个概念的神秘面纱。 向量是一个动态数组,这意味着它的数据分配可以在运行时增加或减少,我们将看到如何通过一个简单的内置函数来完成。 向量在Rust中实现为标准库类型,即Vec 。 这里,T意味着我们可以拥有任何数据类型的向量; 向量总是在堆上分配它们的数据,我们可以用vec宏创建它们!。

做好准备

我们需要Rust编译器和任何文本编辑器进行编码。

怎么做…

1.创建一个名为vector.rs的文件并编译以下代码:

fn main() {
// declaring a vector
let mut vec1 = vec![1,2,3,4,5];

2.使用五个元素声明一个可变向量vec1:

// printing element 3 in vector
println!("Item 3 : {}", vec1[2]);


这里,为了打印向量的第三个元素,我们可以通过它的位置来引用堆中向量的特定数据。

3.如果有n个数据值,则位置的值从零开始,一直到n-1:

// iterating in a vector
for i in &vec1 {
println!("{}",i )
}

4.在上一步中,我们通过引用向量并打印其所有元素来迭代向量:

// push an element to vector
vec1.push(6);
println!("vector after push {:?}", vec1 );
// pop an element from vector
vec1.pop();
println!("vector after pop {:?}", vec1 );
}

5.添加和删除矢量中的值。
6.您应该得到以下输出:
在这里插入图片描述

怎么运行的…

如果我们通过获取向量的所有权进行迭代,并且为了多次重复向量,我们不能再次使用向量,我们必须引用向量。

使用pop和push,我们可以在存储矢量数据的内存分配堆中添加/删除元素。 此功能允许矢量是动态的。 ush向顶部添加一个新元素,这是索引的最后一个元素,pop会删除与索引相关的第一个值和最后一个元素。

在Rust中声明元组

元组是一种独特的数据结构,并且在日常开发中被许多开发人员广泛用于处理不同数据类型的值。

通常,元组由括号()构成,每个元组都有一个类型签名,例如T1,T2,…,其中T1和T2是其成员值的类型。

当我们想要返回多种数据类型时,元组在Rust中非常方便。 我们可以使用Rust将它们打包成单个数据结构。

做好准备

我们需要Rust编译器和任何文本编辑器进行编码。

怎么做…

1.创建一个名为tuple.rs的文件并编译以下代码:

use std::{i8};
fn main() {
// Declaring a tuple
let rand_tuple = ("Rust", 2017);
let rand_tuple2 : (&str, i8) = ("Viki",4);
// tuple operations
println!(" Name : {}", rand_tuple2.0);
println!(" Lucky no : {}", rand_tuple2.1);
}

2.您应该得到以下输出:
在这里插入图片描述

怎么运行的…

在上一节中,我们以两种不同的方式声明了两个元组。 在第一种方法中,Rust编译器自动定位数据类型。 在第二种方法中,我们明确提到了数据类型和元组允许我们创建不同的数据类型。

在元组操作部分中,我们使用元组索引从元组中提取值,这是通过打印tuple_variable.index_value来执行的。

对两个数字执行计算

这个食谱涵盖了我们从其他食谱中学到的所有方面。 我们执行各种操作,例如从终端输入两个值以被用户接受为标准输入,转换整数可接受的字符串,以及执行算术运算。

做好准备

我们需要Rust编译器和任何文本编辑器进行编码。

怎么做…

1.创建一个名为calculator.rs的文件并编译以下代码:

// Libraries in rust
use std::io;
use std::{i32};
  1. io功能帮助我们接受终端中的用户输入:
// Main Functions
fn main() {
// Request for entering number 1
println!("Enter First number ? ");
let mut input1 = String::new();
io::stdin().read_line(&mut input1).expect("Failed to read
line");
// Request for entering number 2
println!("Enter second number ? ");
let mut input2 = String::new();
io::stdin().read_line(&mut input2).expect("Failed to read
line");
// Converting string to integer
let aint: i32 = input1.trim().parse().ok().expect("Program
only
processes numbers, Enter number");
let bint: i32 = input2.trim().parse().ok().expect("Program
only
processes numbers, Enter number");
// Output of basic operations
println!("sum is: {}", aint + bint);
println!("difference is: {}", aint - bint);
println!("Multiply is: {}", aint * bint);
println!("division is: {}", aint / bint);
}

3.您应该得到以下输出:
在这里插入图片描述

怎么运行的…

std :: io模块包含许多您需要的常见内容。 该模块的核心部分是读写特性。

我们从std :: io模块调用了read_line()方法。 read_line()方法不将String作为参数; 它需要一个&mut String。 Rust有一个名为references的功能,它允许您对一个数据进行多次引用,这可以减少复制。 read_line的工作是将用户键入的内容作为标准输入并将其放入字符串中。 所以它将该字符串作为参数,并且为了添加输入,它需要是可变的。 在这种情况下,io :: Result有一个expect()方法,它接受了一个被调用的值; 如果这不成功,我们的程序将崩溃,显示一条消息。 如果我们不调用expect(),我们的程序将编译,但我们会收到警告。

为了将字符串转换为整数,我们使用了trim和parse方法。 字符串上的trim()方法消除了数据开头和结尾的任何ws。 这意味着如果我们输入5并点击返回,猜猜它看起来像这样:5 \ n。 \ n表示换行符,输入键引发的换行符将被trim()方法删除,只留下数字5的字符串。

字符串数据上的parse()方法将字符串解析为某种数字格式,因为它可以解析各种数字,我们需要给Rust一个关于我们希望它转换的数字格式的确切类型的提示,即 我们有这个陈述的原因是让a_int:i32。 冒号(:)后告诉Rust我们要注释它的类型,i32是一个包含32位大小的整数。 我们使用expect()方法捕获错误情况下的崩溃。 脚本的最后一部分用于进行常规算术运算。

猜你喜欢

转载自blog.csdn.net/m0_37696990/article/details/82811329