草庐IT

【一起学Rust | 基础篇】Rust基础——变量和数据类型

广龙宇 2023-04-11 原文

 

目录

前言

一、定义变量

二、Rust变量的可变性

​编辑

三、Rust基本数据类型

1.数值类型

整型

浮点型

2.字符类型

3.布尔类型

四、复合类型

元组

数组

五、常量

总结

作业

变量只有初始化了才可以使用

使用 mut 将变量标记为可变

变量解构


前言

经过前面几期的学习,大家应该对Rust已经有了个初步的了解。现在我们将从Rust的基础开始学习。

变量是一个编程语言必要的内容,学习任何一门编程语言都离不开变量,而是基础中的基础,学习Rust也是这样的。本期我们将从Rust变量的概念开始讲起,同时搭配编程案例,辅以作业,帮助大家学习和理解Rust的变量基础概念。


一、定义变量

Rust定义变量需要使用关键词let,这点和Javascript是一致的,如果你有JS开发的经验,那你应该很熟悉。现在我们定义几个变量

let x = 5;
let y = 5.0;
let str = String::from("Hello");

以上的几个变量都是没有问题的,定义了三个变量,x是整数型的,y是浮点型的,z是字符串型的。除此以外,Rust还支持指定变量类型来定义变量

let x: i32 = 5;
let y: f64 = 5.0;
let str: String = String::from("Hello");

其实我们并不是一定得指定类型,因为Rust可以自动推断你使用的是哪种类型。 

二、Rust变量的可变性

在Rust中,变量默认是不可变的。如果你写了如下代码,就会报错

fn main() {
    let x = 5;
    println!("The value of x is: {x}");
    x = 6;
    println!("The value of x is: {x}");
}

报错如下

现在我们分析一下这个报错,首先看红色的报错,翻译过来的意思是,不可变的变量不可以赋值两次。意思就是不可变的变量不能再次赋值。

然后我们看蓝色的部分,第一次给x分配值,帮助:考虑使x变得可变,`mut x`。可以看出,蓝色的部分是帮助我们修改这个错误的,这也是Rust比较强大的地方之一。按照这个提示,我们应该这么改,

    let mut x: i32 = 5;
    print!("The value of x is: {}", x);
    x = 6;
    print!("The value of x is: {}", x);

 此时我们继续运行看看,

因此我们得出结论,Rust的变量默认是不可变的,只有添加mut关键字以后才会变得可变。 

三、Rust基本数据类型

1.数值类型

数值类型又分为整数型、浮点数、序列类型

整型

长度有符号无符号
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

其中,每个长度都有有符号和无符号两种,有符号表示这个数分正数和负数,无符号则表示这个数据类型只有正数。

有符号的整型取值范围是

 其中n是长度。

另外,isize 和 usize 类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的, 32 位架构上它们是 32 位的。

同时也支持用不同的形式表示不同进制的字面量。

数字字面值例子
Decimal (十进制)98_222
Hex (十六进制)0xff
Octal (八进制)0o77
Binary (二进制)0b1111_0000
Byte (单字节字符)(仅限于u8)b'A'

浮点型

Rust 也有两个原生的 浮点数 类型,它们是带小数点的数字。Rust 的浮点数类型是 f32 和 f64,分别占 32 位和 64 位。浮点数采用 IEEE-754 标准表示。f32 是单精度浮点数,f64 是双精度浮点数。默认类型是 f64,因为在现代 CPU 中,它与 f32 速度几乎一样,不过精度更高。所有的浮点型都是有符号的。以下是使用浮点型的实例。

fn main() {
    let x = 2.0; // f64

    let y: f32 = 3.0; // f32
}

2.字符类型

和C语言一样,char也是Rust的原生类型。但是与之不同的是,Rust的char类型是Unicode的,支持更多的字符,以下是使用字符类型的例子,(如果你能复制到梵文,连梵文也能编码了。)

fn main() {
    let c = 'z';
    let z: char = 'ℤ'; // 指定变量类型
    let heart_eyed_cat = '😻';
}

要注意分清楚字符和字符串,字符使用的是单引号,字符串使用的是双引号。 

3.布尔类型

Rust 中的布尔类型有两个可能的值:true 和 false。Rust 中的布尔类型使用 bool 表示。例如:

fn main() {
    let t = true;

    let f: bool = false; // 指定变量类型
}

四、复合类型

复合类型可以将多个值组合成一个类型。Rust 有两个原生的复合类型:元组(tuple)和数组(array)。

元组

元组是一个将多个其他类型的值组合进一个复合类型的主要方式。可以将多个不同类型的值进行复合,但是元组长度固定:一旦声明,其长度不会增大或缩小。

fn main() {
    let tup1 = (500, 6.4, 1);
    let tup2: (i32, f64, u8) = (500, 6.4, 1); // 指定类型
}

同时元组也支持解构操作 

fn main() {
    let tup = (500, 6.4, 1);

    let (x, y, z) = tup;

    println!("y的值是: {y}");
}

访问元组的值是使用元素在元组中的索引来访问的,索引是从0开始的,与数组是一样的

fn main() {
    let x: (i32, f64, u8) = (500, 6.4, 1);

    let x1 = x.0;

    let x2 = x.1;

    let x3 = x.2;
}

数组

与元组不同,数组中的每个元素的类型必须相同。Rust 中的数组与一些其他语言中的数组不同,Rust中的数组长度是固定的。使用方式如下

fn main() {
    let a = [1, 2, 3, 4, 5];
    let months = ["January", "February", "March", "April", "May", "June", "July",
              "August", "September", "October", "November", "December"];
}

同时也可以指定元素类型

let a: [i32; 5] = [1, 2, 3, 4, 5];

如果初始化数组里面的值都是一样的,那么就有种简便的写法,如下,创建了一个数组a,其中有5个元素,这五个元素都是整数型3

let a = [3; 5];

 访问数组中的元素也是同其他编程语言一样

fn main() {
    let a = [1, 2, 3, 4, 5];

    let a1 = a[0];
    let a2 = a[1];
}

但是要注意,不要尝试越界访问数组元素,也就是说,要访问数组长度内的元素。 

五、常量

常量与不可变量是类似的,但是是不同的。常量(constants) 是绑定到一个名称的不允许改变的值。

  • 不可变量是默认不可变
  • 常量是总是不能变
  • 常量可以在任何作用域中声明
  • 常量只能被设置为常量表达式,而不可以是其他任何只能在运行时计算出的值

申明一个常量要用const


fn main() {
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
}

总结

以上就是本期所要讲述的内容了。本期主要讲了

  • 变量的定义
  • 变量的可变性
  • 基本变量类型
    • 整型
    • 布尔型
    • 字符型
  • 复合型
    • 数组
    • 元组
  • 常量

虽然很努力的组织内容了,但还是感觉不是很合理,在后期一定要调整,方便新手入门,让更多人能够学到Rust。

作业

完成以下作业是你学好rust的重要组成部分。以下题目摘自《Rust练习实践》

变量只有初始化了才可以使用


// 修复下面代码的错误并尽可能少的修改
fn main() {
    let x: i32; // 未初始化,但被使用
    let y: i32; // 未初始化,也未被使用
    println!("x is equal to {}", x); 
}

使用 mut 将变量标记为可变


// 完形填空,让代码编译
fn main() {
    let __ = 1;
    __ += 2; 
    
    println!("x = {}", x); 
}

变量解构


// 修复下面代码的错误并尽可能少的修改
fn main() {
    let (x, y) = (1, 2);
    x += 2;

    assert_eq!(x, 3);
    assert_eq!(y, 2);
}

有关【一起学Rust | 基础篇】Rust基础——变量和数据类型的更多相关文章

  1. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  4. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  5. ruby - Infinity 和 NaN 的类型是什么? - 2

    我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

  6. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  7. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  8. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  9. ruby-on-rails - 如果我将 ruby​​ 版本 2.5.1 与 rails 版本 2.3.18 一起使用会怎样? - 2

    如果我使用ruby​​版本2.5.1和Rails版本2.3.18会怎样?我有基于rails2.3.18和ruby​​1.9.2p320构建的rails应用程序,我只想升级ruby的版本,而不是rails,这可能吗?我必须面对哪些挑战? 最佳答案 GitHub维护apublicfork它有针对旧Rails版本的分支,有各种变化,它们一直在运行。有一段时间,他们在较新的Ruby版本上运行较旧的Rails版本,而不是最初支持的版本,因此您可能会发现一些关于需要向后移植的有用提示。不过,他们现在已经有几年没有使用2.3了,所以充其量只能让更

  10. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

随机推荐