Rust基础学习笔记(零):复习基本知识

由于一个学期没有碰Rust,相关知识殆已忘尽。最近各课逐渐停授,余出时间来从基础重温这些知识,也算是对没有写的基础知识的补充。另外这次复习主要参照了Youtube上的Crush Course视频,两个小时的视频一气看下来还是很累的啊。原视频链接

下载Rust,并在VSCode环境下使用

首先打开Rust官网,点击Get Started,下载对应的64位版本。运行下载程序并启用默认设置就可以。我的电脑里已经有旧版本,故只进行了更新操作。然后找到下载的bin文件夹路径添加环境变量即可,这个路径一般在users/YourName/.cargo/bin

然后在VSCode的插件里搜索Rust,安装列表第一个插件即可。下面运行第一个小程序。

  1. 打开任意文件夹,创建一个文件Hello.rs,在里面输入如下代码:
fn main(){
      println!("Hello, World!");
}
  1. 在终端中输入rustc "Hello.rs",正常编译后会在相同路径下出现对应的Hello.exe,运行时即在终端输出
> Hello, World!

删除这些文件,在一个空文件夹里新建一个空工程。在终端输入如下指令:cargo init

Rust会为你自动生成一个完备的工程文件,包含一个Hello World程序。编译正常运行,到此基本配置已经结束。接下来就是Rust的一些基础使用方法。不过要指出的是这些内容并没有涉及到Rust的核心,也就是说几乎只是一个套皮的C、Python、Java或者其他语言的另一种写法。关于Rust的独到之处,还要进一步复习。在此只是记录备忘。

基本输出

把内容和参数打印到屏幕上可能是学习每门语言最先接触的东西了。Rust输出参数的时候会用到{},是在哪里见过呢……

    //原始形态
    println!("Hello, world!");
    //参数用{}标记
    println!("Number: {}",1+2);
    //{}中可加入指示位置的数字
    println!("{1},{0},{2},{0}",
                "Alice","Bob","Eve");
    //{}中可加入参数名,不过要在参数列表处加以说明
    println!("{name} stands by {num}",
            name = "Bob",num = 1);
    //格式化输出
    println!("Binary:{:b} Hex:{:x} Oct:{:o}",10,10,10);
    //{:?}可以输出元组,准确的说可以打印任何类型的具体信息。好像可以用来debug?
    println!("{:?}",(12,true,"Hello"));
    //参数列表可以进行简单的数学运算,这一点与C/C++等多数语言相同,不再赘述

定义变量

Rust中定义变量一般不需指明类型,而且默认是不可以改变其中的值的。要想改变需要额外添加mut字段。

    let name = "Brad";
    let age_1 = 20;
    //age_1 = 21;                 //这里会报错,因为默认age_1是不可以改变的
    let mut age = 20;
    println!("I am {}",age);      //输出20
    age = 21;
    println!("I am now {}", age); //输出21
    println!("My name is {}", name);
    //也可以定义常量
    const ID:i32 = 001;           //在变量名后面添加 :类型名 来指定类型
    println!("My ID: {}",ID);
    //可以一次定义多个变量
    let (my_name, my_age) = ("Bob", 20);
    println!("{} is {}", my_name, my_age);

基本类型

Rust中的一些基本类型见下:

  • 整形用i/u + 数字(8/16/32/64/128) 表示 如u8,i64
  • 浮点型有f32和f64两个类型
  • 布尔型 bool
  • 字符类型 Char
  • Tuples和Arrays
    //普通整型默认为 "i32"类型
    let x = 1;
    //普通浮点数默认为"f64"类型
    let y = 1.2;
    //显式定义类型
    let y:i64 = 123456789;
    //显示Max size
    println!("Max i32: {}", std::i32::MAX);
    println!("Max i64: {}", std::i64::MAX);
    //定义布尔值
    let is_Act = true;
    println!("{:?}",(x,y,is_Act));
    //也可以从表达式获得bool值,不赘述*
    //甚至可以用unicode保存emoji,格式为"\u{codeX}"
    let face = '\u{1f600}';
    println!("{}",face);

字符串类型

相似,不赘述

    let mut hello = String::from("Hello!");      //声明一个可变字符串变量
    println!("{}",hello);
    //有判空、获得长度、获得占用空间、接续字符/字符串等类方法
    println!("Length: {}",hello.len());
    hello.push('!');
    println!("{}",hello);
    hello.push_str("???");
    println!("{}",hello);
    println!("cap:{}",hello.capacity());
    println!("isEmpty:{}",hello.is_empty());
    //可以匹配内部内容,如contain返回是否包含字段,replace返回替换指定内容的字符串(不改变原本内容)
    println!("Contains \"Hello\"?: {}",hello.contains("Hello"));
    println!("Contains \"World\"?: {}",hello.contains("World"));
    println!("Replace: {}",hello.replace("llo", "LLO"));
    hello = String::from("Hello world!");
    for word in hello.split_whitespace(){
        println!("{}",word);
    }
    //可以指定字符串所占的空间
    let mut s = String::with_capacity(10);
    s.push('a');
    s.push('b');

    //断言语句,不成立时投出panic
    //assert_eq!(3,s.len());    //cause panic!
    assert_eq!(2,s.len());
    println!("{}",s);

tuple元组

元组是不同类型数据的集合,最多拥有十二个数据。

let person:(&str,&str,i8) = ("Brad","Mass",20);
    println!("{} is from {} and is {}",person.0,person.1,person.2);

静态数组array

支持索引、切片。

    //显式指定类型和长度
    let mut numbers :[i32;5] = [1,2,3,4,5];
    //let numbers :[i32;5] = [1,2,3,4]; //会报错-长度必须匹配

    println!("{:?}",numbers);
    //用索引得到单独的值
    println!("{}",numbers[1]);
    //对可变的数组可以对其中的值单独重新赋值
    numbers[2] = 12;
    println!("{:?}",numbers);
    //求长度
    println!("Array Len: {}", numbers.len());
    //这里使用std::mem库获得占有空间大小
    println!("Array occupies {} bytes",std::mem::size_of_val(&numbers));
    //切片语法
    let slc:&[i32] = &numbers[0..2];
    println!("Slice:{:?}",slc);

动态数组vectors

和array类似,可以push和pop,用迭代器进行遍历

    //只要明确类型
    let mut numbers: Vec<i32> = vec![1,2,3,4];
    //添加
    numbers.push(5);
    println!("{:?}",numbers);
    //弹出首元素
    numbers.pop();
    println!("{:?}",numbers);
    //用迭代器进行遍历
    for x in numbers.iter(){
        println!("Numbers: {}",x);
    }
    //用可变迭代器可以对内容进行修改
    for x in numbers.iter_mut(){
        *x *=2;
    }
    println!("Numbers Vec:{:?}",numbers);

逻辑结构

条件语句

    let age = 15;
    let gender:char = 'M';
    //If-else
    if age>=18 {
        println!("Adult!");
    } else {
        println!("Not");
    }
    if age<=18 && gender=='M'{
        println!("Boy");
    }
    //用if-else进行快速赋值,类似于?:表达式
    let is_adult = if age >= 18 {true} else {false};
    println!("An adult: {}", is_adult);

循环语句

    let mut count = 0;
    //最基本的loop循环,需要内部指明跳出条件
    loop{
        count += 1;
        println!("Number: {}",count);
        if count == 5{
            break;}
    }
    //while循环,用法类似其他
    while count <= 100{
        if count % 15 == 0{
            println!("Fuzzbuzz");
        } else if count % 25 == 0{
            println!("by 25");
        } else if count % 5 == 0 {
            println!("{}",count);
        }
        count += 1;
    }
    //for循环,遍历容器中的内容
    for x in 0..20{
        if x % 5 == 0 {println!("Go!{}",x);}
    }

函数调用

参数的声明以及返回值的书写比较值得注意,闭包的写法也要注意

pub fn run(){
    greeting("Jane", "Hello");
    println!("2+3={}",add(2,3));
    //闭包可以使用外部的变量
    let n3:i32 = 3;
    let add_nums = |n1:i32, n2:i32| n1 + n2 + n3;

    println!("Sum:{}",add_nums(1,2));
}

fn greeting(greet: &str, name: &str){
    println!("{},{}!",greet,name);
}

fn add(n1:i32, n2:i32) -> i32      //类型在此声明
{
    n1 + n2      //返回值后面没有分号
}

引用指针

这里只是简单的介绍,还有很多内容没有写入

    let arr1 = [1,2,3];
    let arr2 = arr1;

    println!("{:?}",arr1);
    println!("{:?}",arr2);

    //Array为原生类型,因此在这里无事发生
    //非原生类型重新赋值时会导致赋值方不再保留原来的内容,出现所有权的移交
    //这种情况下需要使用引用指针

    let vec1 = vec![1,2,3];
    let vec2 = &vec1;       //使用了引用,vec1认为无事发生
    //let vec2 = vec1;      //这个语句会导致vec1不再拥有原来的数据
    println!("Val:{:?}",(&vec1,vec2));

结构体

比较特殊,从成员变量的声明到成员函数的加入。

//最基本的结构体,注意成员变量间用','分隔
struct Color {
    red: u8,
    green: u8,
    blue: u8,
}

//元组的形式声明的结构体
struct Color2(u8,u8,u8);

//一个部署了成员方法的结构体,方法在后面用impl引出
struct Person{
    first_name: String,
    last_name: String,
}

impl Person{
    //构造函数
    fn new(first: &str, last: &str) -> Person{
        Person{
            first_name: first.to_string(),
            last_name: last.to_string(),
        }
    }

    fn full_name(&self) -> String{
        format!("{} {}", self.first_name,self.last_name)
    }
    fn set_last_name(&mut self, last: &str){
        self.last_name = last.to_string();
    }
    fn to_tuple(self) -> (String,String){
        (self.first_name,self.last_name)
    }
}

pub fn run(){
    //最基本的初始化方法
    let mut c = Color {
        red: 255,
        green: 0,
        blue: 0,
    };
    //使用和修改时指明名称即可
    println!("Color: {} {} {}",c.red,c.green,c.blue);
    c.red = 200;
    println!("Color: {} {} {}",c.red,c.green,c.blue);
    //初始化元组结构体
    let mut d = Color2(0,255,0);
    //使用和修改时指明位置
    println!("Color: {} {} {}",d.0,d.1,d.2);
    //使用构造函数和其他成员函数
    let mut p = Person::new("John", "Doe");
    println!("Person {} {}",p.first_name,p.last_name);
    println!("Person {}",p.full_name());
    p.set_last_name("Williams");
    println!("Person {}",p.full_name());
    println!("{:?}",p.to_tuple());
}

枚举类

枚举是只有具体的几个值的数据类型。具体值由编写者确定。

enum Movement{
    Up, Down, Left, Right
}

可以作为参数,也可以用match进行选择

fn move_avatar(m: Movement){
    match m {
        Movement::Up => println!("Avatar moving up"),
        Movement::Down => println!("Avatar moving down"),
        Movement::Left => println!("Avatar moving left"),
        Movement::Right => println!("Avatar moving right"),
    }//match类似于switch,注意用=>指向具体操作,之间用逗号分隔。
}

pub fn run(){
    let avatar1 = Movement::Up;
    let avatar2 = Movement::Down;
    let avatar3 = Movement::Left;
    let avatar4 = Movement::Right;

    move_avatar(avatar2);
    move_avatar(avatar3);
    move_avatar(avatar1);
    move_avatar(avatar4);
}

以上介绍了Rust的基本写法。

(0)

相关推荐

  • (25条消息) Rust: 属性(attribute)的含义及文档大全

    Rust中满地都是属性,对于这些,我们是需要有所了解,否则会感觉 到晕: #[lang="copy"] :表示Rust语言本身使用 #[lang ="drop" ...

  • (25条消息) Rust 中的属性

    属性是什么 属性(Attribute)是一种通用的自由格式的元数据,Rust 中的属性以ECMA-335中的为模型,其语法则来自ECMA-334(C#). 属性的用途 属性只能应用于 Rust 中的项 ...

  • Rust 中的 Closure

    原理 有些语言中没有 closure 和普通函数的区分,但 Rust 有.对 Rust 来说普通函数就是一段代码.而 closure 和 C 类似:每个 closure 会创建一个匿名的struct, ...

  • Rust 不适合开发 Web API

    Rust 是一门神奇的编程语言,有非常好的 CLI 工具,比如 ripgrep 和 exa.像 Cloudflare 这样的公司正在使用并鼓励人们写 Rust 来运行微服务.Rust 编写的软件可能比 ...

  • AR实时求解数独 |Mixlab混合现实

    首先,什么是WebAssembly? 我们需要知道它到底是什么! WebAssembly是一种可以让C/C++这些非JavaScript语言编写的代码在浏览器上运行,是一种在web上运行二进制文件的技 ...

  • 【Rust每周一知】 Attribute 属性

    属性是作用在 Rust 语言元素上的元数据. Rust 中的属性数量非常多.而且具有可扩展性(可自定义属性).Rust 的属性语法遵从 C# 定义并标准化了的属性规范ECMA-334. Rust 代码 ...

  • Rust 为什么需要生命周期注解

    fn main() { let b; { let a = 10; b = &a; } println!("{}", b); } 此时,a的作用域比b要小.rust的生命周期 ...

  • Rust中的各种指针

    xtutujs.golang.rust.关注他49 人赞同了该文章Rust 中的指针大体可以分为以下四种:引用 references"胖指针 fat pointers"(该分类存有 ...

  • 如何编写一个过程宏(proc

    更新到(syn, quote, proc-macro)-1.0 过程宏是rust里的强大的武器,非常值得学习rust的人去掌握.但过程宏的编写有点难度,且文档也不太详细,最近也专门学习了下过程宏,算是 ...

  • (25条消息) 【Rust每周一知】Rust中的读写锁RwLock

    本文简单介绍 Rust 中的读写锁RwLock,内容概览如下: 经典问题 读者-作家问题 基本概念 临界区 Critical p 互斥量 Mutex 信号量 Semaphore 读写锁 RWLock ...

  • Any和反射

    Rust 中文社区 · 更新于 2018-11-28 11:00:43 Any和反射 熟悉Java的同学肯定对Java的反射能力记忆犹新,同样的,Rust也提供了运行时反射的能力.但是,这里有点小小的 ...

  • Rust 过程宏简单仿写Lombok 功能

    概念 使用JDK8开发应用的时候,经常会用到Lombok中的一些注解功能,比如使用@Data来生成类成员的Get/Set 方法. 今天尝试下使用Rust中的过程宏来实现类似功能. 实践 流程: 使用S ...