变量和可变性
rust中声明变量是不可变的,比如:
let x = 5;
x = 6; // 报错
如果使用可变的,则需要添加mut
关键字:
let mut x = 5;
x = 6; // 正常执行
注意,rust的变量声明为不可变的,与其他语言(比如C++)的const
等关键字是有核心区别的。以C++为例,声明const int x = 3;
后,x
的值是永远不能被改变的,而在rust中,可以shadowing的概念:
fn main() {
let x= 5;
let x = x + 1;
let x = x * 2;
println!("x = {}", x);
}
输出:
x = 12
上面个的x
虽然是不可变的,但是可以让x
自己覆盖原来的值,这是与const
的核心区别,而且还可以进行类型转换,比如:
fn main() {
let x = "hello world!";
println!("x = {}", x);
let x = x.len();
println!("x length = {}", x);
}
函数输出:
x = hello world!
x length = 12
注意只有不可变的使用shadow才可以,下面这个做法是错误的!!!!!
let mut spaces = " ";
spaces = spaces.len(); // 错误的!!!!!!!!!!!
基本数据类型
rust是静态类型的语言,意味着rust必须在运行期间就要知道所有的变量类型!!!!!
标量
整型、浮点型、字符型和布尔型。
let x = 5;
let y: i64 = 100;
let a = 2.0;
let b: f32 = 3.14;
let remainder = 43 % 5; // mod
let t = true;
let f: bool = false;
let c = 'z'; // 使用unicode编码
复合类型
tuple
类型
tuple
类型之间的赋值使用复制的方式,tuple
每个元素的类型可以不一致。
直接给出代码实例:
fn main() {
let tup: (i32, f64, u8) = (500, 6.4 , 1); // 不可变tuple
let mut tup1 = tup; // 可变tuple,复制tup的值
let (x, y, z) = tup; // 不可变tuple
tup1.0 = 10; // 使用0索引第一个元素,以下同理,只有可变的才能这么做
tup1.1 = 3.14;
println!("tup.0 = {}, tup.1 = {}", tup.0, tup.1);
println!("tup1.0 = {}, tup1.1 = {}", tup1.0, tup1.1);
println!("x = {}, y = {}, z = {}", x, y, z);
}
数组类型
概念可以类比C++,数组的长度固定,而且每个元素的值都是固定的。
比如:
fn main() {
let arr = [1.1, 2, 3]; // f64的3个元素
let a: [i32; 5] = [1, 2, 3, 4, 5]; // 5个i32的元素
let b = [3; 2]; // [3, 3]
}
遍历元素可以通过下标的方式:
fn main() {
let a: [i32, 2] = [0, 1];
let x = a[0]; // 复制的方式
println!("a[0] = {}", x);
}
函数
函数的参数必须声明类型,函数只要定义了就能调用,不用管顺序,这点和C、C++是有区别的;函数的返回值需要后置类型:
fn main() {
let z= 'Z';
foo(1, 3.14, z);
println!("foo1(2) = {}", foo1(2));
}
fn foo (x: i32, y: f64, z: char) {
println!("x = {}, y = {}, z = {}", x, y, z);
}
fn foo1(x: i32) -> i32 { // 返回值后置
return x * x;
}
Statememts和Expression的区别:
statements
:一组没有返回值的指令集expression
:返回一个结果
rust是基于表达式的,需要注意下面几个地方:
fn main() {
let x = 6; // 这是一个statememt
}
形如let x = (let y = 6);
是错误的,因为let y = 6
是一个statement
,没有返回值。
expression
返回的是指令集中最后的结果,注意结尾没有分号:
fn main() {
let x = 5;
let y = { // 这是一个expression
let x = 3; // 变量的覆盖
x + 1 // 没有分号!!!
};
println!("x = {}, y = {}", x, y); // 5, 4
}
同样的,函数的内部也是可以包含expression
的,给出代码实例:
fn main() {
println!("foo(3) = {}", foo(3)); // 9
}
fn foo(x: i32) -> i32 {
x * x
}
控制流
if
条件控制
if
的条件中,必须是bool类型,否则会报错。基本格式如下:
if condition0 {
// do some operations...
} else if condition1 {
// do some operations...
} else {
// do some operations...
}
同时使用if
和let
:
fn main() {
let condition = true;
let number = if condition { // 注意这是`expression`
5
} else {
6
};
println!("number = {}", number);
}
注意一个地方,if
和let
的组合中,静态的数据必须是同样的类型的,比如这里5 & 6
都是i32
;若不是则会报错。
循环控制条件
loop
循环
这是一个死循环,除非使用break
跳出,或者直接return
。
代码实例:
fn main() {
let mut cnt = 0;
let result = loop { // 常用的表达式模式
cnt += 1;
if cnt == 10 {
break cnt * 2
}
};
println!("cnt = {}", result);
}
while
循环
这个和C的类似,简单例子:
fn main() {
let mut cnt = 0;
while cnt < 10 {
cnt += 1;
}
println!("cnt = {}", cnt);
}
for
循环
for
循环最主要的作用是便利数组等,代码实例:
fn main() {
let a = [1, 2, 3, 4, 5];
for elem in a.iter() {
println!("elem = {}", elem);
}
}
注意for
循环使用的是引用!!!