3 常见编程概念
本章我们会介绍一些其他高级语言都会有的编程概念,以及它们如何在rust中工作的。具体来说我们将会了解变量、基本类型、函数、注释和控制流
3.1 变量与可变性
不可变变量
Rust中,默认的变量是不可变的,如下,不能将已绑定到某个值的不可变变量再次赋值
fn main() {
let x = 5;
x = 6;//cannot assign twice to immutable variable
println!("{}",x)
}
可变变量
在声明变量时,在变量名前面加上mut,使得变量成为可变变量,如下列语句可以通过编译并且能正常打印
fn main() {
let mut x = 5;
x = 6;
println!("{}",x)
}
变量和常量的区别
常量声明用关键字const而不用let,而且必须注明类型
常量不使用mut
常量可以在任何作用域中声明,并且会在整个生命周期中发挥作用
常量通常用大写加下滑线来声明,例如:
fn main() {
const THREE_HOURS_IN_SECONDS:u32 = 60*60*3;
println!("{}",THREE_HOURS_IN_SECONDS)//10800
}
隐藏(shadowing)
Rust这个shadowing的特性我们之前讲过,这里再复习一下:声明两个同名变量,后面的变量会覆盖前面的变量
并且他们的类型是可以不同的,如下:
fn main() {
let x = 5;
let x = 6;
let spaces = " ";
let spaces= spaces.len();//Rsut 中变量调用函数是通过.在后面加上函数施加的
println!("{},{}",x,spaces)//6,9
}
3.2 数据类型
Rust是静态类型语言,即在编译时就需知道所有变量的类型
一般情况下,根据值及其使用方式,编译器通常能够推断出类型
但是当多种类型均可能时,我们需要显示注解类型
let guess:i32 = "42".parse().expect("Not a number!");
3.2.1 标量类型
标量类型代表单独的值,包括:整型、浮点型、布尔型、字符型
整型
整型分为无符号和有符号,i代表有符号,u代表无符号
Rust中的整型的长度有:8/16/32/64/128-bit以及arch
其中arch长度色isize和usize类型依赖运行计算机架构,64位架构它们就是64位的,32位架构就是32位的
对于整型的选择,如果拿不定主意,Rust默认类型是不错的起点,数字类型是i32,isize和usize主要作为某些集合的索引
浮点型
两种f32 和 f64
小结:数值类型的都支持四则运算和取余,整数一般向下取整
let sum = 5+10;
let difference = 95.5-4.3;
let product =4*30;
let floored = 2/3;
let reminder = 43%5;
println!("{},{},{},{},{}",sum,difference,product,floored,reminder);//15,91.2,120,0,3
布尔型
Rust布尔类型有两个值:True/false
let t = true;
let f:bool =false;
println!("{},{}",t,f);//true,false
字符型
Rust的char类型是语言中最原生的字母类型,它不仅可以表示汉字、英文字母,甚至可以表示表情
let c = 'Z';
let heart_eyed_cat = '🐱';
println!("{},{}",c,heart_eyed_cat);//Z,🐱
3.2.2 符合类型
可以将多个值组合成一个类型。Rust有两个原生的复合类型,Tuple和Array
元组类型(tuple)
一旦声明,长度就固定,并且元组无法直接打印出来
let tup1:(i32,f64,u8) = (500,6.4,1);//注释类型
let tup2 = (600,6.4,2);//不注释类型
访问元组中的值,两种方式:
(1)使用模式匹配来解构元组的值
let tup2 = (600,6.4,2);
let (x,y,z) = tup2;
println!("{}",z);//2
(2)使用点号(.)后值的索引来直接访问
let tup1:(i32,f64,u8) = (500,6.4,1);
println!("{}",tup1.1);//6.4
元组的第一个索引值是0,没有任何值的元组是一种特殊类型,只有一个值,写成()
数组类型
数组中元素类型相同,但是它也是一旦声明长度就会固定,与之相对应的是vector,是一种可变数组
let a = [1,2,3,4,5];
let first = a[0];
let second = a[1];
println!("{},{}",first,second);1,2
3.3 函数
main函数是很多程序的入口
Rust语言中的函数和变量名使用snake case规范风格。在snake case中,所有字母都是小写并且用下划线分隔单词,如下:
fn main() {
println!("Hello World!");
another_function();
}
fn another_function() {
println!("Another function.");
}
函数参数
函数可以拥有参数,参数是特殊变量,是函数签名的一部分
fn main() {
another_function(10);
}
fn another_function(x: i32) {
println!("The value is: {}.", x);
}
多个参数用逗号分隔开
fn main() {
another_function(10,'y',true);//Values are: 10,y,true
}
fn another_function(x: i32,y:char,z:bool) {
println!("Values are: {},{},{}", x,y,z);
}
包含语句和表达式的函数体
语句是执行一些指令但不返回值,表达式是计算出一个结果,表达式可以作为语句的一部分,韩素函数、宏调用、{}都是表达式
fn main() {
let x = 5;
let y ={
let x = 3;//语句
x+1//表达式
};
println!("The value of y is: {},{}", y,x);//4,5
}
具有返回值的函数
函数可以向调用它的代码返回值,我们并不对返回值命名,但要在箭头(->)后声明它的类型。Rust语言中默认返回函数体中最后一个表达式的值,使用return可以提前返回
fn main() {
let x = five();
println!("{}",x)
}
fn five()->i32{
5
}
3.4 注释
注释用//开头,可以在语句、代码块之前和之后
//hello world
fn main() {
let lucky_number = 7; // I’m feeling lucky today
}
3.5 控制流
3.5.1 if表达式
if表达式允许根据条件执行不同的代码分支,条件必须是bool类型
fn main() {
let number = 5;
if number <5{
println!("condition was true")
}else {
println!("condition was false")
}
}
使用else if 处理多重条件
fn main() {
let number = 6;
if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else if number % 2 == 0 {
println!("number is divisible by 2");
} else {
println!("number is not divisible by 4, 3, or 2");
}
}
在let中使用if
fn main() {
let condition = true;
let number = if condition {
5
} else {
6
};
println!("The value of number is: {}", number);
}
3.5.2 使用循环重复执行
Rust有三种循环 while,for,loop
loop
fn main() {
loop {
println!("again!");
}
}
使用break和continue
fn main() {
let mut count = 0;
'counting_up: loop {
println!("count = {}", count);
let mut remaining = 10;
loop {
println!("remaining = {}", remaining);
if remaining == 9 {
break;
}
if count == 2 {
break 'counting_up;
}
remaining -= 1;
}
count += 1;
}
println!("End count = {}", count);
}
while
当条件为真,执行循环。当条件不再为真,调用 break
停止循环,好处是不用使用loop等嵌套
fn main() {
let mut number = 3;
while number != 0 {
println!("{}!", number);
number = number - 1;
}
println!("LIFTOFF!!!");
}
for 遍历集合
while 遍历
fn main() {
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("the value is: {}", a[index]);
index = index + 1;
}
}
for 遍历
对于遍历集合中的元素来说,for循环是一中更简洁的方式
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("the value is: {}", element);
}
}
fn main() {
for number in (1..4).rev() {
println!("{}!", number);
}
println!("LIFTOFF!!!");
}