Rust 一门赋予每个人构建可靠且高效软件能力的语言

news2024/12/25 15:12:26

目录

Rust

安装

尝试

hello, world

编译

链接出错

开启 Rust 之旅

官方教程

《Rust 程序设计语言》

《通过例子学 Rust》

核心文档

标准库

版本指南

CARGO 手册

RUSTDOC 手册

RUSTC 手册

编译错误索引表

非官方翻译教程  

Rust 程序设计语言 简体中文版

通过例子学 Rust 中文版 

语法基础

变量和数据类型

复合数据结构

元组 (Tuple)

数组 (Array)

动态数组 (Vector)

集合 (Set)

结构体 (Struct)

关键字

控制语句

条件语句

循环语句

匹配语句

函数

模块

代码实例

1. 两数之和

2. 最长子串

3. 反转整数


Rust

一门赋予每个人构建可靠且高效软件能力的语言

Rust 程序设计语言 一门赋予每个人构建可靠且高效软件能力的语言。https://www.rust-lang.org/zh-CN/

安装

官方下载网址: 

安装 Rust - Rust 程序设计语言 一门赋予每个人构建可靠且高效软件能力的语言。https://www.rust-lang.org/zh-CN/tools/install安装 Rust 需要C++生成工具的支持,Visual Studio2017+版本以上都可以。

尝试

Rust Playground 官方在线编译器A browser interface to the Rust compiler to experiment with the languageicon-default.png?t=N3I4https://play.rust-lang.org/?version=stable&mode=debug&edition=2021

hello, world

fn main() {
    println!("hello, world");
}

创建一个后缀为 .rs 的源码文本文件 hello.rs,然后用Rust编译成一个可执行文件;也可以把源码直接粘贴到官方提供的在线编译器内执行。

为什么学习众多编程语言的第一个程序都是 hello, world ?

hello world 的起源

追溯到1972年,贝尔实验室著名研究员Brian Kernighan在撰写“B语言教程与指导(Tutorial Introduction to the Language B)”时初次使用(程序),这是目前已知最早的在计算机著作中将hello和world一起使用的记录。之后,在1978年,他在他和Dennis Ritchie合作撰写的C语言圣经“The C Programming Language”中,延用了“hello,world”句式,作为开篇第一个程序。在这个程序里,输出的”hello,world”全部是小写,没有感叹号,逗号后有一空格。虽然之后几乎没能流传下来这个最初的格式,但从此用hello world向世界打招呼成为惯例。几乎每一个程序设计语言的教材中的第一个范例都是hello world程序,因此在学习一门新语言的时候用hello world作为起步已经成为计算机程序界的一个传统。

编译

在cmd窗口下,把源码文件 hello.rs 编译,然后执行。

D:\Rust\hello>rustc hello.rs

D:\Rust\hello>hello
hello, world

链接出错

当编译发生以下报错时,说明生成工具没有安装成功 

D:\Rust\hello\src>rustc main.rs
error: linker `link.exe` not found
  |
  = note: program not found

note: the msvc targets depend on the msvc linker but `link.exe` was not found

note: please ensure that Visual Studio 2017 or later, or Build Tools for Visual
Studio were installed with the Visual C++ option.

note: VS Code is a different product, and is not sufficient.

error: aborting due to previous error

执行以下2条命令进行修复

D:\Rust\hello>rustup toolchain install stable-x86_64-pc-windows-gnu

D:\Rust\hello>rustup default stable-x86_64-pc-windows-gnu

开启 Rust 之旅

官方教程

官方网站网提供了2本基础教程以及众多文档,入门零成本,基本用不上买纸质书,省钱。

《Rust 程序设计语言》

被亲切地称为“圣经”。本书从基础出发,给出了 Rust 语言的概览。您将在阅读本书的过程中构建几个项目,读完本书后,您就能扎实地掌握 Rust 语言。

https://doc.rust-lang.org/book/

《通过例子学 Rust》

如果您不喜欢阅读大量的文档来学习语言,那么此书就能涵盖您要学的知识。虽然本书花了很多篇幅来解释代码,但它展示的代码很丰富,并且尽量减少了文字解释。它还包括很多练习! 

https://doc.rust-lang.org/rust-by-example/

核心文档

以下所有文档都可以用 rustup doc 命令在本地阅读,它会在您的浏览器中离线打开这些资源!

标准库

详尽的 Rust 标准库 API 手册。

版本指南

Rust 版本指南。

CARGO 手册

Rust 的包管理器和构建系统。

RUSTDOC 手册

学习如何为您的 crate 编写完美的文档。

RUSTC 手册

熟悉 Rust 编译器中可用的选项。

编译错误索引表

深入解释了您可能会遇到的编译错误。


非官方翻译教程  

Rust 程序设计语言 简体中文版

  1. 简介
  2. 1. 入门指南
    1. 1.1. 安装
    2. 1.2. Hello, World!
    3. 1.3. Hello, Cargo!
  3. 2. 写个猜数字游戏
  4. 3. 常见编程概念
    1. 3.1. 变量与可变性
    2. 3.2. 数据类型
    3. 3.3. 函数
    4. 3.4. 注释
    5. 3.5. 控制流
  5. 4. 认识所有权
    1. 4.1. 什么是所有权?
    2. 4.2. 引用与借用
    3. 4.3. Slice 类型
  6. 5. 使用结构体组织相关联的数据
    1. 5.1. 结构体的定义和实例化
    2. 5.2. 结构体示例程序
    3. 5.3. 方法语法
  7. 6. 枚举和模式匹配
    1. 6.1. 枚举的定义
    2. 6.2. match 控制流结构
    3. 6.3. if let 简洁控制流
  8. 7. 使用包、Crate 和模块管理不断增长的项目
    1. 7.1. 包和 Crate
    2. 7.2. 定义模块来控制作用域与私有性
    3. 7.3. 引用模块项目的路径
    4. 7.4. 使用 use 关键字将路径引入作用域
    5. 7.5. 将模块拆分成多个文件
  9. 8. 常见集合
    1. 8.1. 使用 Vector 储存列表
    2. 8.2. 使用字符串储存 UTF-8 编码的文本
    3. 8.3. 使用 Hash Map 储存键值对
  10. 9. 错误处理
    1. 9.1. 用 panic! 处理不可恢复的错误
    2. 9.2. 用 Result 处理可恢复的错误
    3. 9.3. 要不要 panic!
  11. 10. 泛型、Trait 和生命周期
    1. 10.1. 泛型数据类型
    2. 10.2. Trait:定义共同行为
    3. 10.3. 生命周期确保引用有效
  12. 11. 编写自动化测试
    1. 11.1. 如何编写测试
    2. 11.2. 控制测试如何运行
    3. 11.3. 测试的组织结构
  13. 12. 一个 I/O 项目:构建命令行程序
    1. 12.1. 接受命令行参数
    2. 12.2. 读取文件
    3. 12.3. 重构以改进模块化与错误处理
    4. 12.4. 采用测试驱动开发完善库的功能
    5. 12.5. 处理环境变量
    6. 12.6. 将错误信息输出到标准错误而不是标准输出
  14. 13. Rust 中的函数式语言功能:迭代器与闭包
    1. 13.1. 闭包:可以捕获其环境的匿名函数
    2. 13.2. 使用迭代器处理元素序列
    3. 13.3. 改进之前的 I/O 项目
    4. 13.4. 性能比较:循环对迭代器
  15. 14. 更多关于 Cargo 和 Crates.io 的内容
    1. 14.1. 采用发布配置自定义构建
    2. 14.2. 将 crate 发布到 Crates.io
    3. 14.3. Cargo 工作空间
    4. 14.4. 使用 cargo install 安装二进制文件
    5. 14.5. Cargo 自定义扩展命令
  16. 15. 智能指针
    1. 15.1. 使用Box<T> 指向堆上数据
    2. 15.2. 使用Deref Trait 将智能指针当作常规引用处理
    3. 15.3. 使用Drop Trait 运行清理代码
    4. 15.4. Rc<T> 引用计数智能指针
    5. 15.5. RefCell<T> 与内部可变性模式
    6. 15.6. 引用循环会导致内存泄漏
  17. 16. 无畏并发
    1. 16.1. 使用线程同时地运行代码
    2. 16.2. 使用消息传递在线程间通信
    3. 16.3. 共享状态并发
    4. 16.4. 使用Sync 与 Send Traits 的可扩展并发
  18. 17. Rust 的面向对象编程特性
    1. 17.1. 面向对象语言的特点
    2. 17.2. 为使用不同类型的值而设计的 trait 对象
    3. 17.3. 面向对象设计模式的实现
  19. 18. 模式与模式匹配
    1. 18.1. 所有可能会用到模式的位置
    2. 18.2. Refutability(可反驳性): 模式是否会匹配失效
    3. 18.3. 模式语法
  20. 19. 高级特征
    1. 19.1. 不安全的 Rust
    2. 19.2. 高级 trait
    3. 19.3. 高级类型
    4. 19.4. 高级函数与闭包
    5. 19.5. 宏
  21. 20. 最后的项目:构建多线程 web server
    1. 20.1. 建立单线程 web server
    2. 20.2. 将单线程 server 变为多线程 server
    3. 20.3. 优雅停机与清理
  22. 21. 附录
    1. 21.1. A - 关键字
    2. 21.2. B - 运算符与符号
    3. 21.3. C - 可派生的 trait
    4. 21.4. D - 实用开发工具
    5. 21.5. E - 版本
    6. 21.6. F - 本书译本
    7. 21.7. G - Rust 是如何开发的与 “Nightly Rust”

通过例子学 Rust 中文版 

  1. 1. Hello World
    1. 1.1. 注释
    2. 1.2. 格式化输出
      1. 1.2.1. 调试(debug)
      2. 1.2.2. 显示(display)
      3. 1.2.3. 测试实例:List
      4. 1.2.4. 格式化
  2. 2. 原生类型
    1. 2.1. 字面量和运算符
    2. 2.2. 元组
    3. 2.3. 数组和切片
  3. 3. 自定义类型
    1. 3.1. 结构体
    2. 3.2. 枚举
      1. 3.2.1. 使用 use
      2. 3.2.2. C 风格用法
      3. 3.2.3. 测试实例:链表
    3. 3.3. 常量
  4. 4. 变量绑定
    1. 4.1. 可变变量
    2. 4.2. 作用域和遮蔽
    3. 4.3. 变量先声明
    4. 4.4. 冻结
  5. 5. 类型系统
    1. 5.1. 类型转换
    2. 5.2. 字面量
    3. 5.3. 类型推断
    4. 5.4. 别名
  6. 6. 类型转换
    1. 6.1. From 和 Into
    2. 6.2. TryFrom 和 TryInto
    3. 6.3. ToString 和 FromStr
  7. 7. 表达式
  8. 8. 流程控制
    1. 8.1. if/else
    2. 8.2. loop 循环
      1. 8.2.1. 嵌套循环和标签
      2. 8.2.2. 从 loop 循环返回
    3. 8.3. while 循环
    4. 8.4. for 循环和区间
    5. 8.5. match 匹配
      1. 8.5.1. 解构
        1. 8.5.1.1. 元组
        2. 8.5.1.2. 枚举
        3. 8.5.1.3. 指针和引用
        4. 8.5.1.4. 结构体
      2. 8.5.2. 卫语句
      3. 8.5.3. 绑定
    6. 8.6. if let
    7. 8.7. while let
  9. 9. 函数
    1. 9.1. 方法
    2. 9.2. 闭包
      1. 9.2.1. 捕获
      2. 9.2.2. 作为输入参数
      3. 9.2.3. 类型匿名
      4. 9.2.4. 输入函数
      5. 9.2.5. 作为输出参数
      6. 9.2.6. std 中的例子
        1. 9.2.6.1. Iterator::any
        2. 9.2.6.2. Iterator::find
    3. 9.3. 高阶函数
    4. 9.4. 发散函数
  10. 10. 模块
    1. 10.1. 可见性
    2. 10.2. 结构体的可见性
    3. 10.3. use 声明
    4. 10.4. super 和 self
    5. 10.5. 文件分层
  11. 11. crate
    1. 11.1. 库
    2. 11.2. 使用库
  12. 12. cargo
    1. 12.1. 依赖
    2. 12.2. 约定规范
    3. 12.3. 测试
    4. 12.4. 构建脚本
  13. 13. 属性
    1. 13.1. 死代码 dead_code
    2. 13.2. crate
    3. 13.3. cfg
      1. 13.3.1. 自定义条件
  14. 14. 泛型
    1. 14.1. 函数
    2. 14.2. 实现
    3. 14.3. trait
    4. 14.4. 约束
      1. 14.4.1. 测试实例:空约束
    5. 14.5. 多重约束
    6. 14.6. where 子句
    7. 14.7. newtype 惯用法
    8. 14.8. 关联项
      1. 14.8.1. 存在问题
      2. 14.8.2. 关联类型
    9. 14.9. 虚类型参数
      1. 14.9.1. 测试实例:单位检查
  15. 15. 作用域规则
    1. 15.1. RAII
    2. 15.2. 所有权和移动
      1. 15.2.1. 可变性
      2. 15.2.2. 部分移动
    3. 15.3. 借用
      1. 15.3.1. 可变性
      2. 15.3.2. 别名使用
      3. 15.3.3. ref 模式
    4. 15.4. 生命周期
      1. 15.4.1. 显式标注
      2. 15.4.2. 函数
      3. 15.4.3. 方法
      4. 15.4.4. 结构体
      5. 15.4.5. trait
      6. 15.4.6. 约束
      7. 15.4.7. 强制转换
      8. 15.4.8. static
      9. 15.4.9. 省略
  16. 16. 特质 trait
    1. 16.1. 派生
    2. 16.2. 使用 dyn 返回 trait
    3. 16.3. 运算符重载
    4. 16.4. Drop
    5. 16.5. Iterator
    6. 16.6. impl Trait
    7. 16.7. Clone
    8. 16.8. 父 trait
    9. 16.9. 消除重叠 trait
  17. 17. 使用 macro_rules! 来创建宏
    1. 17.1. 语法
      1. 17.1.1. 指示符
      2. 17.1.2. 重载
      3. 17.1.3. 重复
    2. 17.2. DRY (不写重复代码)
    3. 17.3. DSL (领域专用语言)
    4. 17.4. 可变参数接口
  18. 18. 错误处理
    1. 18.1. panic
    2. 18.2. Option 和 unwrap
      1. 18.2.1. 使用 ? 解开 Option
      2. 18.2.2. 组合算子:map
      3. 18.2.3. 组合算子:and_then
    3. 18.3. 结果 Result
      1. 18.3.1. Result 的 map
      2. 18.3.2. 给 Result 取别名
      3. 18.3.3. 提前返回
      4. 18.3.4. 引入 ?
    4. 18.4. 处理多种错误类型
      1. 18.4.1. 从 Option 中取出 Result
      2. 18.4.2. 定义一种错误类型
      3. 18.4.3. 把错误 “装箱”
      4. 18.4.4. ? 的其他用法
      5. 18.4.5. 包裹错误
    5. 18.5. 遍历 Result
  19. 19. 标准库类型
    1. 19.1. 箱子、栈和堆
    2. 19.2. 动态数组 vector
    3. 19.3. 字符串 String
    4. 19.4. 选项 Option
    5. 19.5. 结果 Result
      1. 19.5.1. ? 用法
    6. 19.6. panic!
    7. 19.7. 散列表 HashMap
      1. 19.7.1. 更改或自定义关键字类型
      2. 19.7.2. 散列集 HashSet
    8. 19.8. 引用计数 Rc
    9. 19.9. 共享引用计数 Arc
  20. 20. 标准库更多介绍
    1. 20.1. 线程
      1. 20.1.1. 测试实例:map-reduce
    2. 20.2. 通道
    3. 20.3. 路径
    4. 20.4. 文件输入输出(I/O)
      1. 20.4.1. 打开文件 open
      2. 20.4.2. 创建文件 create
      3. 20.4.3. 读取行 read lines
    5. 20.5. 子进程
      1. 20.5.1. 管道
      2. 20.5.2. 等待
    6. 20.6. 文件系统操作
    7. 20.7. 程序参数
      1. 20.7.1. 参数解析
    8. 20.8. 外部语言函数接口
  21. 21. 测试
    1. 21.1. 单元测试
    2. 21.2. 文档测试
    3. 21.3. 集成测试
    4. 21.4. 开发依赖
  22. 22. 不安全操作
  23. 23. 兼容性
    1. 23.1. 原始标志符
  24. 24. 补充
    1. 24.1. 文档
    2. 24.2. Playpen

有编程基础的大概浏览一遍,很快就能上手了


语法基础

变量和数据类型

在 Rust 中,变量可以通过 let 关键字进行声明和初始化。例如:

let x = 5;
let y: i32 = 10;

第一行代码定义了一个名为 x 的变量,其类型为 Rust 推断得到的整数类型。第二行代码定义了一个名为 y 的变量,并明确指定其类型为 i32 整数类型。

Rust 中的数据类型包括数字、字符、布尔值、字符串等。其中,数字类型包括整数和浮点数,可以用 i8i16i32i64u8u16u32u64f32f64 等类型进行声明。而布尔值则用 bool 表示,取值为 true 或 false。字符类型用 char 表示,由单引号包围,例如:

let c = 'C';

字符串类型用双引号包围,可以是非 ASCII 字符串,例如:

let s = "Hello, 世界!";

注意:let mut 变量赋值

let 和 let mut 声明变量时的区别在于后者声明的变量可变,而前者声明的变量为不可变。let 声明的变量不能再次被赋值,而 let mut 声明的变量可以被修改赋值。 

复合数据结构

元组 (Tuple)

元组是将多个不同类型的值组合在一起形成一个新的复合类型。元组使用圆括号 () 来定义,元素之间使用逗号 , 隔开。元组可以通过模式匹配来解构。例如:

let person: (String, usize, f64) = (String::from("Alice"), 30, 6.0);

println!("{} is {} years old and {} feet tall.", person.0, person.1, person.2);

数组 (Array)

数组是由同一类元素组成的数据集合。数组的长度在编译时就已经确定,不可改变。数组使用中括号 [] 来定义。例如:

let numbers: [i32; 5] = [1, 2, 3, 4, 5];

println!("The third element is {}.", numbers[2]);

向量 (Vector)

向量是一种动态数组类型,可以在运行时动态地增加或减少其大小。Vector 可以存储任意类型的数据,并且支持快速随机访问元素、在末尾追加元素、在任意位置插入和删除元素等操作。Vector 使用 Vec 类型来创建,例如:

let mut numbers: Vec<i32> = vec![1, 2, 3, 4, 5];

// 访问某个元素
println!("The third element is {}.", numbers[2]);

// 在末尾追加元素
numbers.push(6);

// 插入元素到特定位置
numbers.insert(3, 10);

// 删除特定位置的元素
numbers.remove(2);

// 遍历所有元素
for num in &numbers {
    println!("{}", num);
}

集合 (Set)

集合类型存储一组唯一的、无序的元素。Set 具有高效地判定元素是否存在的功能,但是不支持对元素的随机访问和插入。Set 使用 HashSet 类型来创建,例如:

use std::collections::HashSet;

let mut colors = HashSet::new();

// 插入元素
colors.insert(String::from("red"));
colors.insert(String::from("green"));
colors.insert(String::from("blue"));

// 判断元素是否存在
if colors.contains("red") {
    println!("The set contains red.");
}

// 删除元素
colors.remove("green");

// 遍历所有元素
for color in &colors {
    println!("{}", color);
}

结构体 (Struct)

结构体是一种自定义类型,可以包含不同类型的字段。通过在结构体中定义多个字段,可以将它们组合成一个单独的数据类型。结构体使用 struct 关键字来定义,字段可以是不同的类型,并且也可以包含其他的结构体。例如:

struct Person {
    name: String,
    age: usize,
    height: f64,
}

let alice = Person {
    name: String::from("Alice"),
    age: 30,
    height: 6.0,
};

println!("{} is {} years old and {} feet tall.", alice.name, alice.age, alice.height);

关键字

as          const       else        enum        extern      
false       fn          for         if          impl        
in          let         loop        match       mod         
move        mut         pub         ref         return      
Self        self        static      struct      super       
trait       true        type        unsafe      use         
where       while       abstract    become      box         
do          final       macro       override    priv        
typeof      unsized     virtual     yield

这些关键字具有不同的含义和用法,例如:

  • fn: 声明一个函数
  • let: 声明一个变量
  • ifelseforwhile 等: 分别表示条件语句、循环语句
  • match: 匹配表达式的值与模式
  • moduse: 分别表示模块声明与模块引用
  • structenumtraitimpl 等: 分别表示结构体、枚举类型、特质、实现等

在 Rust 中,使用这些关键字需要注意避免与现有标识符冲突。如果需要使用与关键字同名的标识符,则可以使用反引号   将标识符括起来,例如:

let `match` = 3;
println!("the value of match is {}", `match`);

以上代码中,用反引号括起来的 match 可以作为变量名使用,但是不推荐这么做,因为会让代码不够清晰。

控制语句

Rust 支持常见的控制流语句,包括条件语句、循环语句和匹配语句等。

条件语句

用 if 和 else 关键字表示,例如:

let x = 10;
if x < 0 {
    println!("x is negative");
} else if x > 0 {
    println!("x is positive");
} else {
    println!("x is zero");
}

循环语句

用 loopwhile 和 for 关键字表示,例如:

let mut x = 0;
loop {
    x += 1;
    if x == 10 {
        break;
    }
}
println!("x is {}", x);

let mut y = 0;
while y < 10 {
    y += 1;
}
println!("y is {}", y);

let a = [1, 2, 3, 4, 5];
for element in a.iter() {
    println!("element is {}", element);
}

匹配语句

用 match 关键字表示,可以根据不同的值匹配执行不同的代码块。例如:

let x = 5;
match x {
    1 => println!("x is one"),
    2 | 3 | 4 => println!("x is two or three or four"),
    // 匹配任何其他数字 
    _ => println!("x is {}", x),
}

函数

Rust 中的函数可以通过 fn 关键字进行定义,例如:

fn add(x: i32, y: i32) -> i32 {
    x + y
}

fn main() {
    let a = add(1, 2);
    let b = add(2, 3);
    println!("{}\n{}", a, b);
}

该函数接受两个 i32 参数 x 和 y,返回它们的和。

函数的最后一个表达式被视为返回值,这与其它大多数语言不同:可以省去 return 关键字

Rust 支持函数的默认参数和可变参数,例如:

fn mul(x: i32, y: i32, z: i32) -> i32 {
    return x * y * z
}

fn div(x: f32, y: f32) -> f32 {
    if y == 0.0 {
        panic!("division by zero");
    }
    return x / y
}

fn print(words: &str, times: i32) {
    for _ in 0..times {
        println!("{}", words);
    }
}

fn main() {
    let a = mul(1, 2, 3);
    let b = div(10.0, 3.0);
    let c = "hello";
    println!("{}\n{}", a, b);
    print(c, 3);
}

Rust 也支持泛型类型参数,例如:

fn add<T: std::ops::Add<Output=T>>(x: T, y: T) -> T {
    x + y
}

fn foo<T>(x: T) -> T {
    x
}

fn main() {
    let a = add(1, 2);
    let b = add(2.0, 3.0);
    println!("{}\n{}\n", a, b);

    let a = foo(1); // a 为整数类型
    let b = foo("hello"); // b 是字符串类型
    let c = foo(vec![1, 2, 3]); // c 是一个整数向量类型
    println!("{}\n{}\n{:?}", a, b, c);
}

模块

模块是 Rust 中的一种隔离和组织代码的方式,其可以分为本地模块和外部模块。本地模块用 mod 关键字表示,用于组织和封装代码,例如:

mod math {
    fn add(x: i32, y: i32) -> i32 {
        x + y
    }

    pub fn sub(x: i32, y: i32) -> i32 {
        x - y
    }
}

该代码中,定义了一个 math 模块和其中的两个函数 add 和 sub。其中,函数 add 是私有的,只能在模块内部使用,而函数 sub 是公有的,可以在其他模块中使用。

除了本地模块之外,Rust 还支持使用 extern crate 加载外部依赖库,并通过 use 关键字引用其模块、类型和函数等。例如:

extern crate rand;

use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();
    let n: i32 = rng.gen_range(1, 7);
    println!("the random number is: {}", n);
}

以上就是 Rust 语言的基础语法介绍,包括变量和数据类型、控制流、函数和模块等内容。Rust 相比于其他语言,具有更加严格的类型检查和所有权规则等特性,可以保证代码的内存安全和高效运行。


代码实例

1. 两数之和

use std::collections::HashMap;

fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
    let mut map = HashMap::new();
    for (i, &num) in nums.iter().enumerate() {
        if let Some(&j) = map.get(&(target - num)) {
            return vec![j as i32, i as i32];
        }
        map.insert(num, i);
    }
    vec![]
}

fn main() {
    let nums = vec![2, 7, 11, 15];
    let target = 9;
    let result = two_sum(nums, target);
    println!("{:?}", result);  // 输出 [0, 1]
}

2. 最长子串

pub fn length_of_longest_substring(s: String) -> i32 {
    let mut chars = s.chars();
    let mut map = std::collections::HashMap::new();
    let mut max_length = 0;
    let mut start = 0;
    let mut end = 0;
    while let Some(c) = chars.next() {
        if let Some(index) = map.get(&c) {
            start = start.max(*index + 1);
        }
        end += 1;
        map.insert(c, end - 1);
        max_length = max_length.max(end - start);
    }
    max_length as i32
}

fn main() {
    let s = String::from("abcabcbb");
    let result = length_of_longest_substring(s);
    println!("{}", result);
    let s = String::from("bbbbb");
    let result = length_of_longest_substring(s);
    println!("{}", result);
    let s = String::from("pwwkew");
    let result = length_of_longest_substring(s);
    println!("{}", result);
}

3. 反转整数

pub fn reverse(x: i32) -> i32 {
    let mut x = x;
    let mut res = 0;
    while x != 0 {
        let pop = x % 10;
        x /= 10;
        if res > std::i32::MAX / 10 || (res == std::i32::MAX / 10 && pop > 7) {
            return 0;
        }
        if res < std::i32::MIN / 10 || (res == std::i32::MIN / 10 && pop < -8) {
            return 0;
        }
        res = res * 10 + pop;
    }
    res
}

fn main() {
    let x = 123;
    println!("{}", reverse(x));
    let x = -123;
    println!("{}", reverse(x));
    let x = 120;
    println!("{}", reverse(x));
}

2023.5.3

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

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

相关文章

543. 二叉树的直径【71】

难度等级&#xff1a;容易 上一篇算法&#xff1a; 199. 二叉树的右视图【111】 力扣此题地址&#xff1a; 543. 二叉树的直径 - 力扣&#xff08;Leetcode&#xff09; 1.题目&#xff1a;543. 二叉树的直径 给定一棵二叉树&#xff0c;你需要计算它的直径长度。一棵二叉树的…

玩一玩 Ubuntu 下的 VSCode 编程

一&#xff1a;背景 1. 讲故事 今天是五一的最后一天&#xff0c;想着长期都在 Windows 平台上做开发&#xff0c;准备今天换到 Ubuntu 系统上体验下&#xff0c;主要是想学习下 AT&T 风格的汇编&#xff0c;这里 Visual Studio 肯定是装不了了&#xff0c;还得上 VSCode…

Spring:依赖注入的方式(setter注入、构造器注入、自动装配、集合注入)

依赖注入的方式有setter注入、构造器注入、自动装配、集合注入 首先&#xff0c;Maven项目pom.xml依赖包如下&#xff1a; pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:…

Servlet中转发和重定向的区别

什么是转发&#xff0c;重定向&#xff1f; 转发和重定向都是用于在服务器和浏览器之间进行页面跳转的方式。 转发是在服务器内部进行的&#xff0c;当一个Servlet接收到请求后&#xff0c;它可以将请求转发给另一个Servlet或JSP页面来处理请求&#xff0c;但是浏览器不知道这…

C语言-学习之路-04

C语言-学习之路-04 数组与字符串一维数组一维数组的定义和使用一维数组的初始化数组名一维数组练习 二维数组二维数组的定义和使用二维数组的初始化数组名 字符数组与字符串字符串的输入输出随机数字符串处理函数 数组与字符串 数组&#xff1a;为了方便处理数据把具有相同类型…

等保工作的定级指南文件

定级主要依据国家标准信息安全技术网络安全等级保护基本要求来整改。有关等保工作流程和明细,请见:https://luozhonghua.blog.csdn.net/article/details/130465356?spm=1001.2014.3001.5502 5网络安全等级保护概述 5.1等级保护对象 等级保护对象是指网络安全等级保护工作中…

微服务注册中心-Nacos概述

1、Nacos基本介绍 1.1. 什么是 Nacos&#xff1f; Nacos 是阿里巴巴推出来的一个新开源项目&#xff0c;这是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。 Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集&#xff0c;帮…

详解Transformer (Attention Is All You Need)

先导知识 Attention残差网络Layer Normalization 前言 注意力&#xff08;Attention&#xff09;机制[2]由Bengio团队与2014年提出并在近年广泛的应用在深度学习中的各个领域&#xff0c;例如在计算机视觉方向用于捕捉图像上的感受野&#xff0c;或者NLP中用于定位关键token…

kvm GPU直通/GPU透传 之修改Windows虚拟机分辨率

为了方便对服务器进行自动管理,我们需要对硬件进行虚拟化。对于显卡而言,Nvidia有专门支持GPU虚拟化的显卡,比如GRID GPU系列。以NVIDIA GRID K2为例,显存8GB,可虚拟出2块GPU。 对于GTX系列的显卡,如果Host主机为linux系统,想将显卡给虚拟机(windows或者linux)使用,…

函数的栈帧与销毁(栈帧可不是战争哦)

&#x1f929;本文作者&#xff1a;大家好&#xff0c;我是paperjie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 &#x1f970;内容专栏&#xff1a;这里是《C语言》专栏&#xff0c;笔者用重金(时间和精力)打造&#xff0c;将C语言知识一网打尽&#xff0c;希望可…

码出高效:Java开发手册笔记(java对象四种引用关系及ThreadLocal)

码出高效&#xff1a;Java开发手册笔记&#xff08;java对象四种引用关系及ThreadLocal&#xff09; 前言一、引用类型二、ThreadLocal价值三、ThreadLocal副作用 前言 “水能载舟&#xff0c;亦能覆舟。”用这句话来形容 ThreadLocal 最贴切不过。ThreadLocal 初衷是在线程并…

《C和指针》笔记3:置一和清零

在C语言中&#xff0c;移位运算符<<和>>表示二进制数左移或右移&#xff0c;我们可以利用它们很轻松地对变量中单个位进行置一和清零。 我们可以规定变量二进制数最右边一位是第0位&#xff0c;定义bit_number是0&#xff0c;对应地&#xff0c;从最右边一位往左数…

iOS开发系列--打造自己的“美图秀秀”

--绘图与滤镜全面解析 概述 在iOS中可以很容易的开发出绚丽的界面效果&#xff0c;一方面得益于成功系统的设计&#xff0c;另一方面得益于它强大的开发框架。今天我们将围绕iOS中两大图形、图像绘图框架进行介绍&#xff1a;Quartz 2D绘制2D图形和Core Image中强大的滤镜功能…

【OpenVinoSharp】基于C#和OpenVINO部署PaddleOCR模型

基于C#和OpenVINO部署PaddleOCR模型 1.OpenVINO2.PaddleOCRPP-OCRv2PP-OCRv3 3.模型下载与转换3.1 Detection model3.2 Direction classifier3.3 Recognition model 4.OpenVinoSharp安装4.1 获取OpenVinoSharp源码4.2 配置OpenVINO依赖项 5. PaddleOCR5. 1模型推理C#实现&#…

Kali 安装中文输入法(超详细)

1.进入管理员下的控制台。 2. 输入密码后点击“授权”。 3.在控制台内输入下面的命令。 apt install fcitx 4.敲击回车后会开始安装&#xff0c;这里输入“y”。 5.回车后会继续进行安装&#xff0c;安装完成后会自动停止。 6.输入下面的命令来安装google输入法。 apt-get in…

【Python】【进阶篇】22、Django模板加载与响应

目录 22、Django模板加载与响应1. 什么是模板1) 模板的配置2) 修改settings配置文件 2. 模板的加载与响应方式3. render方法详解 22、Django模板加载与响应 在前文章节《Django模板系统》中&#xff0c;我们对 Django 的模板系统有了初步的认识&#xff0c;在本章我们将重点讲…

mongodb v4.4.19 分片精进实操,吐血分享

第一步&#xff1a;创建文件夹&#xff0c;data1111存放config server,data2222/data3333存放shard 第二步&#xff1a;启动服务 2.1 启动config server 2.2 启动shard --port 设置端口 --dbpath 设置数据库路径 --logappend 使用追加的方式写日志 --replS…

ReentrantLock原理剖析

前言 本文主要讲解底层逻辑&#xff0c;基本不会贴代码&#xff0c;目的是让大家能够真正的知晓原理&#xff0c;对照着逻辑去理解代码看代码也会很快就能看懂。 在讲ReentrantLock原理之前&#xff0c;我们先回顾下ReentrantLock的基本用法。ReentrantLock是一个锁编程api&am…

Compiler Lab2- 自制极简编译器

笔者实现的这个超级迷你版编译器&#xff08;词法分析、语法分析、生成中间代码&#xff08;cpp&#xff09;&#xff09;仅支持四则运算&#xff0c;功能真的是非常非常简单&#xff0c;不过其中的流程&#xff08;词法分析 -> 语法分析 -> 中间代码生成&#xff09;还是…

各SQL引擎的SQL转换过程对比

SQL引擎 参考文档:高级语言的解析过程—解析树 从 MySQL、Oracle、TiDB、CK,到 Hive、HBase、Spark,从关系型数据库到大数据计算引擎,他们大都可以借助 SQL 引擎,实现 “接受一条 sql 语句然后返回查询结果” 的功能。 他们核心的执行逻辑都是一样的,大致可以通过下面…