Catalyst

Rust 笔记(一)基础

📔 简约我流语法笔记

常规

  • 没有 i++ 之类。
  • 没有三目运算符。
  • 代码命名规范使用 snake case ,全小写并使用 _ 作分隔。
  • 没有用到却要留在代码里的变量加前缀 _ ,例: _member

类型

名称标志备注
布尔bool
字符char定义用单引号
整形i*(带符号),u*(无符号)*可以是 8,16,32,64,128,size(依赖于运行程序的电脑架构)
浮点f**为 32 或 64
元组(<类型>,<类型>)组合不同类型的变量
数组[<类型>;<个数>]可以使用 [<值>;<个数>] 来初始化数组

关于字符串:通常创建的硬编码字符串属于&str,而创建可变字符串需要使用String

String是以字节向量 (Vec<u8>) 的方法存储的,始终是有效的 UTF-8 序列,分配在堆上,长度可变且不以 null 结尾。str是始终指向有效的 UTF-8 序列的片段 (&[u8])。

特殊字符使用\转义,需要\时则使用\\

let a = "string";
let b = String::from("string");

Raw String : 原始字符串,不处理文本里的任何转义。以r开头,后面可以跟着一个或多个#"

let a = r"foo"; //foo
let b = r#""foo""#; // "foo"

元组

元组是将多种类型的多个值组合为一个复合类型的一般方法。它的长度是固定的。

fn main(){
	let tup:(i32,String) = (12, "abc");
}

取出元组中的物品需要解构或者用.取值。

fn main() {
    let tup: (i32, &str) = (12, "abc");
    let (x, y) = tup;
    let z = tup.0;
    println!("first value:{} {}", x, z);
    //first value:12 12
}

数组

Rust 中的数组是定长的,不定长的使用向量。建立数组可以用通常的方括号法:

let arr: [i32; 3] = [1,2,3];

或者用同一值初始化:

let arr = [1;3]; //[1, 1, 1]

用于循环的快速索引:

for i in 0..4 {
        println!("{}", i); //0 1 2 3
    }

数组取值方法:

fn main() {
   let arr: [i32; 3] = [1,2,3];
   let first = arr[0];
}

基础类型转换

数字类型:

let a:f32 = 1.2345;
let b:i32  = a as i32; // b = 1
//如果想要其他的转换方式:
let b2: i32 = a.ceil() as i32; //b2 = 2
方法作用输入 1.45输入 -1.45
round四舍五入1-1
trunc返回数字的整数部分1-1
ceil返回大于自身的最小整数2-1
floor返回小于自身的最大整数1-2

数字与字符串互转:

let a: f32 = -1.45;
let s: String = a.to_string();
let a2: f32 = s.parse::<f32>().unwrap();

String&str互转:

let s1: &str = "str";
let s2: String = s1.to_string();
let s3: &str = s2.as_str();

基础语法

变量和常量

变量使用 let 定义。默认不可变,如果需要可变则加上mut标志。 用let定义同名变量将覆盖原先变量(这和可变变量不一样)。

let x = 2;
let mut y = 3;

let x = 3; //x 最终等于 3,let 不能丢
y = 5;

常量使用const定义,并必须声明类型。常量一定是不可变的,所以不用mut

const c:u32 = 99

函数

函数用fn关键字定义。

fn main(){
    let result = add(1,3);
    println!("value:{}",result);
}

fn add(a:i64,b:i64) -> i64{
    a+b
}

函数的返回值与大括号内最后的表达式同值。注意,表达式最后不带分号,带分号的属于声明(statement)。

借用使用&<变量>。可变借用使用&mut <变量>同时使用的借用变量只能有一个可变借用或者多个不变借用。

注释

单行注释 //,多行注释 /**/

流程

条件

使用 if <exp> {<then>} else if <exp> {<then>} else {<then>}

Rust 在碰到第一个满足条件的块就执行并返回,不检查后面的内容。

循环

三种循环方法:loopwhilefor

fn main(){
    let lo = loop {
      println!("loop!");
      break "loop"; //通过 break 终止循环并返回 "loop"
    };
    println!("loop:{}",lo);

    let mut n = 3;
    while n > 0 {
      println!("while:{}",n);
      n -= 1;
    }

    let list = ["a","b","c","d"];

    for i in list.iter(){ //iter()
        println!("for:{}",i);
    }

    for i in 1..6 {
        println!("for:{}",i); //打印出的是 1-5
    }

}

切片

数组和字符串的分割都是其一部分的引用,示例如下:

//数组
let a = [1, 2, 3, 4, 5];
let slice = &a[1..4]; //[2, 3, 4]

切片的数字是从 开始结束 +1 。如果是从第一个索引开始,0 可以省略 ([..2])。

字符串切片:对于字符串位置的引用(所以没有对应的所有权概念)

let str = String::from("Hello");
let he = &str[0..2];
println!("{}",he);//He
//or
let he = &str[..2]; //开始为 0 可以忽略
println!("{}",he);//He
let lo = &str[3..]; //结尾为最后也可以忽略
println!("{}",lo);//lo

结构体

struct Person{
    name:String,
    age: u64,
}

struct Member{
    id: u64,
    ..Person //使用 person 内的定义
}

struct Point(i32,i32) //元组结构

初始化

let p = Person {
        name: String::from("Robert"),
        age: 8,
    };

let pt = Point(33,33);

//如果需要一个新结构体和现存的某个结构体一样,但修改部分数据

let p1 = Person {
	name: String::from("Alice"),
	..p
};

定义用于结构体的方法:往往在定义结构体的上下文,用self指代结构体。

fn main(){
    struct Point(i32,i32);

    impl Point{
        fn print(&self){
            let Point(x,y) = self;
            println!("(x:{},y:{})",x,y)
        }
    }

    let pt = Point(33,33);
    pt.print();
}

impl代表 implementations , 用于定义类型的实现。

参考资料