Rust 第二天---Rust基础总结

news2024/12/26 21:17:24

之前已经配置好了Rust的环境,那学习一门语言最开始就是去掌握了解它的基本语法.其实Rust的语法和大多编程语言没什么差别,熟悉C++的应该很容易上手,所以今天就快速过一遍基础.

1. 变量与常量

变量应该是编程中最常用到的,但是Rust与其他语言不同的是在声明变量的时候必须说明这个变量是否可变,变量默认是不可变的.

变量声明语句:let a;,如果想声明可变变量: let mut a;

和不可变变量类似的—常量,这才是真正意义上的不可变,无法对常量使用mut,而且得使用const关键字声明,并且常量往往是全大写字母命名.

还有一种特殊的用法,那就是利用let声明同名变量实现对之前变量的“隐藏”,而这种实际上是每次创建了一个新的变量.

fn main(){
    let a=10;
    let a=20;
    let a="aaa";
    println!("{}",a)
}

image-20230531090656889

忽视掉未使用变量的警告,这段代码最终能通过编译,也实现了上面说的“隐藏”功能.

2. 数据类型

上面讲到了变量声明,有了变量那就涉及到变量所属的数据类型,所以紧接着来聊聊Rust里面的数据类型.

Rust是静态类型语言,不过借助编译器往往可以帮助我们推断出变量所属类型,如上面的代码中我并没有声明a所属的数据类型,但是依旧可以顺利编译.不过在一些特殊场景,如将命令行输入进行运算时,必须将字符串转为数值类型才能计算,而这个时候必须添加类型注解否则编译器并不能顺利推断应该转换的具体类型.Rust数据类型主要分为两类:标量类型复合类型,其中标量类型和大多语言中基本数据类型相似,而Rust原生的复合类型只有元组数组.为了方便日常编程,在标准库中包含了一系列封装的数据结构:vector,string,map

2.1 标量类型

具体包括整型,浮点型,布尔类型和字符型.这部分与其他语言类似,整型包括有符号整型和无符号整型,前缀用i和u表示.浮点型包括32位和64位浮点类型,默认是64位.

2.2 复合类型

原生复合类型包括元组数组

元组可以将不同类型的数据进行组合,但元组长度固定访问时通过.+索引

fn main(){
    let tuple:(i32,f64,u32)=(-100,3.14,100);
    let (x,_,_)=tuple;
    println!("tuple={},{},{}",tuple.0,tuple.1,tuple.2);
    println!("x={}",x);
}
​
​

image-20230608095053454

数组中的元素必须是相同类型的,并且数组的长度也是固定的.但是对于习惯了使用更具灵活性的动态数组的开发者来说,Rust在标准库中也提供了vector,所以也许vector更加常用,而数组仅仅用于明确数据量的情况(如月份,星期等等)

题外话,数组分配空间在栈上而不是在堆上,这部分内容对于C++开发者应该比较熟悉,而栈中的数据访问效率是高于堆上的,减少了指针跳转访问过程.往往在某些实时性以及安全性要求高的场景,代码执行效率和开发难度上需要做平衡.

fn main(){
    let months = ["January", "February", "March", "April", "May", "June", "July",
        "August", "September", "October", "November", "December"];
    for (index,month)  in months.iter().enumerate(){
        let index=index+1;
        match index{
            1=>println!("The {}st month is {}",index,month),
            2=>println!("The {}nd month is {}",index,month),
            3=>println!("The {}rd month is {}",index,month),
            _=>println!("The {}th month is {}",index,month),
        };
    }
}

image-20230608102535322

这个demo展示了数组的访问以及后续会讲到的for循环和match,这里就当个开胃小菜.

2.3 封装类型

2.3.1 vector

上面提到数组是不可变的,但是大多时候我们在初始化时并不知道数据量大小,而且后续可能还需要增加数据,所以这个时候就需要更加灵活的vector,当然vector同样只能存储相同的数据类型!!!

fn main(){
    let mut v:Vec<i32>=Vec::new();
    //let v=vec![1,2,3];
    v.push(1);
    v.push(2);
    v.push(3);
    v.push(4);
    println!("{:?}",v);
​
    for i in v.iter_mut(){
        *i*=2;
    }
    println!("{:?}",v);
    println!("{:?},{:?}",v[1],v.get(1));
​
    println!("{:?}",v.pop());
}

image-20230608114620286

如果想在vector中存储不同的类型,就需要对数据类型进行某些封装,例如用结构体,枚举或者trait对象.

2.3.2 string

string是由字节组成的vector,且是UTF-8编码.因此,我们可以看看下面这个demo

fn main(){
    let mut s1 = String::from("this is a ");
    let s2 = "star";
    s1.push_str(s2);
    println!("s1 is {},s2 is {}",s1,s2);
​
    let star=String::from_utf8(vec![240,159,146,150]).unwrap();
    s1+= &star;
    println!("s1 is {}",s1);
}

image-20230608141908789

我们不仅可以拼接字符串slice,还可以通过vector构建字符串进行拼接.

2.3.3 map

map也是一种常用的数据结构,通过键值对的方式实现关系映射.既然这么常用,基本概念就不过多介绍直接看demo

use std::collections::HashMap;
​
​
fn main(){
    let mut demo_map=HashMap::new();
    demo_map.insert(String::from("1"),"10");
    demo_map.insert(String::from("2"),"20");
    demo_map.insert(String::from("3"),"30");
    println!("{:?}",demo_map);
​
    let keys=vec![String::from("a"),String::from("b")];
    let values=vec![111,222];
    let map:HashMap<_,_>=keys.iter().zip(values.iter()).collect();
    println!("{:?}",map);
​
    //get
    let query=String::from("a");
    let result=map.get(&query);
    println!("query's result: {:?}",result);
​
    for (k,v) in &map{
        println!("{}:{}",k,v);
    }
​
    //update
    demo_map.insert(String::from("3"),"300");
    println!("{:?}",demo_map);
​
    //entry_insert
    demo_map.entry(String::from("5")).or_insert("50");
    let tmp=demo_map.entry(String::from("1")).or_insert("100");
    let mut tmp_string=tmp.to_string();
    tmp_string.push_str("01");
    *tmp=&tmp_string[..];
    println!("{:?}",demo_map);
​
    demo_map.remove("2");
    println!("{:?}",demo_map);
}

image-20230608232543598

这个demo基本囊括了常见的map操作,如一开始的创建,插入,访问以及最后的remove删除键值对.其中具有特色的就是entry,它可以获得map中的对应项,并进行原地操作,当访问的键不存在时可以插入新的键值对,如果存在将不会进行修改;同时or_insert会返回这个键对应值的可变引用,因此我们也可以直接对这个引用进行操作从而修改原始map中的值.

3. 函数

了解C/C++的都知道,main函数是程序的入口,第一天的内容也提到了fn作为关键字来进行函数声明,其他关于函数的内容与其他语言也没有太多差异还是比较容易接受的,这里主要来看看容易弄混的函数与表达式,语句之间的差别.

  • 语句:执行一些操作但是没有返回值
  • 表达式:计算并且产生返回值,一个数值本身就是表达式!!!

有的时候函数定义了返回值类型后,可以直接将最后的表达式作为返回值,不用return关键字也能返回.不过一定要注意最后的是表达式而不是语句,否则老老实实用return也能减少很多错误.

4. 控制流

编程中最基本的三种结构:顺序,选择,循环,在上面的那些demo中从main函数开始一行行语句执行直到结束,这就是顺序结构;但是其中有match关键字的选择结构,或者Rust中称呼的模式匹配;还有包含for语句的循环结构.上面的demo其实已经预先透露了这些控制流,这一小节就来详细介绍Rust某些特性.

4.1 if

if也是选择结构的一种,根据不同条件对应不同的操作.不过值得注意的是,Rust在if语句中的条件一定是一个布尔类型,类似于C++常用的语句if(1){...}这在Rust中是错误的,必须改为if 1>0{...}

和大多数语言一样,Rust同样支持if-else if-else这样的多重条件分支结构,并且类似于C++的三目运算符,Rust可以写成下面这样

let result=if 10>5{true} else{false};

值得注意的是,这里两个条件分支中的表达式返回的值必须是同一类型.由于Rust是强类型语言,所以定义的时候必须确切知道变量数据类型.

4.2 match

match作为选择结构,可以用来匹配不同的模式(情况),最简单的demo如下

use rand::Rng;
fn main(){
    let mut rng = rand::thread_rng();
    let flag:i32=rng.gen_range(0, 10);
    println!("flag={}",flag);
    match flag {
        1=>println!("flag=1"),
        3=>println!("flag=3"),
        5=>println!("flag=5"),
        7=>println!("flag=7"),
        _=>println!("flag is not in [1,3,5,7]"),
    }
}

image-20230609013959402

当我们不需要使用匹配到的值时,可以使用_来表示默认缺省匹配,如果需要使用通配值则可以用一个变量来代替.

use rand::Rng;
fn main(){
    let mut rng = rand::thread_rng();
    let flag:i32=rng.gen_range(0, 10);
    println!("flag={}",flag);
    match flag {
        1=>println!("flag=1"),
        3=>println!("flag=3"),
        5=>println!("flag=5"),
        7=>println!("flag=7"),
        tmp=>println!("flag={}",tmp),
    }
}

image-20230609014334859

对于一些简单的选择分支,也可以尝试使用if let来代替match

4.3 loop

loop算是一个其他语言没怎么见过的关键字,从实际使用来看loop{}其实和while true{}的差别不大,也就是说loop更适合在无限循环的场景下使用,比如不断请求重试或者保持心跳.当然,也可以在代码中加入break让循环退出.

4.4 while

上面说了loop适合无限循环,在Rust中while则适合处理不确定循环次数的情况,即保证能退出但是无法保证何时.最容易想到的场景应该就是条件变量wait的情况,当收到notify之后while也就不满足条件不会再wait.

4.5 for

for循环应该是最熟悉的循环结构了,在事先知道循环次数或者知道循环对象大小的前提下,对数据对象进行操作.

下面写个综合的demo来对比一下三种循环语句的差异

fn loop_sum(v:Vec<i32>)->i32{
    let mut vector_len=v.len();
    let mut sum=0;
    loop{
        vector_len-=1;
        sum+=v[vector_len];
​
        if vector_len==0{
            break sum;
        }
    }
}
​
fn while_sum(v:Vec<i32>)->i32{
    let mut sum=0;
    let mut vector_len=v.len();
    while vector_len>0{
        vector_len-=1;
        sum+=v[vector_len];
    }
    return sum;
}
​
​
fn for_sum(v:Vec<i32>)->i32{
    let mut sum=0;
    for value in v.iter(){
        sum+=value;
    }
    return sum;
}
​
fn main(){
    let test_vec=vec![1,2,3,4,5,6];
    println!("{}",loop_sum(test_vec.clone()));
    println!("{}",while_sum(test_vec.clone()));
    println!("{}",for_sum(test_vec.clone()));
}

image-20230609012952892

由于数据是有限个,因此这里for循环显得最优.所以应对不同业务场景要求,可以选择使用不同的循环语句来达到最高的效率.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/723367.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue最强table vxe-table 虚拟滚动列表 前端导出

最近遇到个问题。后台一次性返回2万条列表数据。 并且需求要求所有数据必须全部展示&#xff0c;不能做假分页&#xff08;不能优化了&#xff09;。 这些数据的直接来源就是CS客户端。 他们做CS客户端就是一次性加载几万条数据不分页&#xff08;说这是客户的要求&#xff…

android_mars老师_定位_获取最佳的provider

结果展示 ManiActivity package com.example.locationmanager2;import androidx.appcompat.app.AppCompatActivity;import android.content.Context; import android.location.Criteria; import android.location.LocationManager; import android.os.Bundle; import android.…

开放式耳机对耳朵伤害大吗?开放式耳机是什么意思?

​今天来跟大家一起聊聊&#xff0c;开放式耳机对耳朵伤害大不大&#xff0c;还有就是开放式耳机到底是什么类型的耳机&#xff0c;且开放式耳机有哪些比较好用的... 开放式耳机对耳朵伤害大吗&#xff1f; 开放式耳机对耳机的伤害是比较小的&#xff0c;传统入耳式耳机佩戴久了…

【Linux实验】将个人主页上传到服务器

一、实验目的 l 网页制作&#xff1b; l 熟悉 Linux FTP or scp 拷贝&#xff1b; l 熟悉 apache 权限配置。 二、实验内容 l 创建个人主页&#xff1b; l 用 FTP 或 scp 上传服务器&#xff1b; l chmod 设置目录权限&#xff1b; l Web 访问。 三、实验代码 略…

ModaHub魔搭社区:Milvus向量数据库最权威全面的百科

目录 什么是 Milvus&#xff1f; Milvus 向量数据库专为向量查询与检索设计&#xff0c;能够为万亿级向量数据建立索引。与现有的主要用作处理结构化数据的关系型数据库不同&#xff0c;Milvus 在底层设计上就是为了处理由各种非结构化数据转换而来的向量而生。 产品版本 强…

进行EE存储时需要关中断

一、调度中执行存储 在task调度里执行存储任务&#xff0c;在存储之前必须关掉中断&#xff0c;存储之后再打开中断&#xff0c;否则将会影响存储。以下两个函数分别执行挂起所有嵌套的中断和恢复所有嵌套的中断。 二、下电存储 在下电存储之前也需要使EcuM Shutdown或者Shut…

彻底掌握IDEA Debug技巧让你的开发不受任何阻挠

高效开发&#xff1a;IntelliJ IDEA Debug技巧 Debug用来追踪代码的运行流程&#xff0c;通常在程序运行过程中出现异常&#xff0c;启用Debug模式可以分析定位异常发生的位置&#xff0c;以及在运行过程中参数的变化。通常我们也可以启用Debug模式来跟踪代码的运行流程去学习…

3-Spring cloud之搭建Ribbon负载均衡——服务器上实操(上)

3-Spring cloud之搭建Ribbon负载均衡——服务器上实操&#xff08;上&#xff09; 1. 前言2. ribbon整合eureka入门2.1 修改相关配置2.1.1 修改服务消费者pom&#xff0c;引入ribbon相关依赖2.1.2 修改服务消费者yml&#xff0c;将客户端注册进eureka服务列表内2.1.3 修改配置类…

Python爬虫爬取双色球开奖结果源码

使用Python编写双色球爬虫&#xff1a;解析彩票数据 引言&#xff1a; 在数字化时代&#xff0c;彩票已经成为人们休闲娱乐的一种方式。而双色球无疑是最受欢迎的彩票之一&#xff0c;它的中奖概率和巨额奖金吸引了无数人的注意。在本文中&#xff0c;我们将介绍如何使用Python…

华为OD机试真题 Python 实现【知识图谱新词挖掘1】【2023Q1 100分】

目录 一、题目描述二、输入描述三、输出描述四、解题思路五、Python算法源码六、效果展示1、输入2、输出3、说明 一、题目描述 小华负责公司知识图谱产品&#xff0c;现在要通过新词挖掘完善知识图谱。 新词挖掘: 给出一个待挖掘文本内容字符串Content和一个词的字符串word&am…

apple pencil二代平替笔哪个好用?好用的苹果笔推荐

自从ipad和其他的平板电脑都搭配上了电容笔以后&#xff0c;电容笔很好地取代了我们的手指&#xff0c;书写的效率就大大提升了&#xff0c;但由于苹果原装电容笔的价格不够人性化&#xff0c;一直高居不下给普通人带来了很大的负担&#xff0c;特别是对于学生们来说&#xff0…

6个提高图片分辨率的在线网站,真的超级实用!

在日常生活中&#xff0c;我们经常会遇到保存的图片模糊不清的情况。有时候这可能是由于保存方式不当&#xff0c;有时候则是由于图片在上传至网站时被压缩所致&#xff0c;导致画质和分辨率下降。 那么&#xff0c;有没有办法可以提高图片的分辨率和画质呢&#xff1f;事实上…

【笔记】微机原理及接口技术5 -- MCS51单片机概述

MCS-51 CPU 由两个部分组成&#xff1a;运算器和控制器 运算器&#xff1a;算术逻辑单元&#xff08;ALU&#xff09;、位处理器、累加器 ACC 等组成&#xff1b; 控制器&#xff1a;主要有内部晶振和一些定时、控制逻辑组成 存储器 拥有三个存储器地址空间 程序存储器地址…

【内网穿透】Linux服务使用宝塔面板搭建网站,并内网穿透实现公网远程访问

文章目录 前言1. 环境安装2. 安装cpolar内网穿透3. 内网穿透4. 固定http地址5. 配置二级子域名6. 创建一个测试页面 转载自cpolar极点云文章&#xff1a;Linux使用宝塔面板搭建网站&#xff0c;并内网穿透实现公网访问 前言 宝塔面板作为简单好用的服务器运维管理面板&#xf…

第七章 商品详情三

流程&#xff1a; 1、用户在订单服务&#xff08;192.168.232.101&#xff09;下单后&#xff0c;订单服务以生产者身份往rabbitmq&#xff08;192.168.232.104&#xff09;推送消息&#xff0c;下单后将减库存信息推送到rabbitmq 2、数据worker&#xff08;192.168.232.100&…

造船码头行车/电动葫芦限位器无线应用

一、应用背景 近年来&#xff0c;我国造船业在高技术船舶研发和建造方面持续取得新突破&#xff0c;据统计截止到2022年&#xff0c;我国造船业完工量、新接订单量、手持订单量三大指标国际市场份额均保持世界前列。连续13年位居全球居首。随着船舶制造的综合能力不断提高&…

【算法与数据结构】459、LeetCode重复的子字符串

文章目录 一、题目二、解法2.1 暴力破解法2.2 KMP算法2.3 Sunday算法2.4 官方查找算法 三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 2.1 暴力破解法 思路分析&#xff1a;子串多次循环才能构成整个…

【回溯算法part03】| 39.组合总和、40.组合总和||、131.分割回文串

目录 &#x1f388;LeetCode39. 组合总和 &#x1f388;LeetCode40.组合总和|| &#x1f388;LeetCode131.分割回文串 &#x1f388;LeetCode39. 组合总和 链接&#xff1a;39.组合总和 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 …

nuxt3 fullpage.js踩坑, fullpage.js 全屏滚动

nuxt3 fullpage.js踩坑&#xff0c; fullpage.js 全屏滚动, fullpage is underfind 我用的是 nuxt 3.6.1 1.引入 fullpage.js(3.0.1), 下载地址 github链接&#xff0c;下载后放到assets文件下 app: {head: {script: [{ src: /assets/fullpage.js, type: "text/javascript…

[BitSail] Connector开发详解系列二:SourceSplitCoordinator

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 ource Connector 本文将主要介绍创建、管理Split的角色SplitCoordinator。 SourceSplitCoordinator 大数据处理框架的核心目的就是将大规模的数据拆分成为多个合理…