Rust 基础练习笔记
下面代码是用差不多一天时间整理出来的一些基础笔记,发现学一门新语言用这种方式更高效些,然后再做一些的项目,如命令行程序等,还有看开源的程序代码等,差不多可以入门了。
fn main() {
for_const();
for_var();
for_condition();
for_loop();
for_tuple();
for_array();
for_ownership();
for_borrow();
for_slice();
for_struct();
for_enum();
for_mod();
for_collections();
for_error();
for_closure();
for_pointer();
for_thread();
for_stdin();
for_file();
}
// 常量
fn for_const() {
mark("常量");
// 基本数据类型(整型,浮点型,布尔类型,字符类型)
// 1.只能赋值,名称要大写
// 2.数据类型不可以忽略
// 3.不能出现同名
const SERVER: &'static str = "https://zee.kim";
const PORT: u16 = 8080;
println!("常量: {}:{}", SERVER, PORT);
}
// 设置类型和变量
fn for_var() {
mark("设置类型和变量");
/*
大小 有符号 无符号
8 bit i8 u8
16 bit i16 u16
32 bit i32 u32
64 bit i64 u64
128 bit i128 u128
Arch isize usize(x86 机器上为 32 位,在 x64 机器上为 64 位)
*/
let _int: usize = 1024;
println!("整数: {}", _int);
println!("最大整数: {}", std::u128::MAX);
println!("最小整数: {}", std::i128::MIN);
let _float: f64 = 89_898.141_526; //数字分隔符“_”,更容易看清
println!("浮点: {}", _float);
let _bool: bool = true;
println!("布尔值: {}", _bool);
let _string: &str = "Huawei♥♥";
println!("字符串: {}", _string);
let empty_string = String::new();
println!("长度是 {}", empty_string.len());
let content_string = String::from("简单教程");
println!("长度是 {}", content_string.len());
let name1 = " 幸福彼岸".to_string(); //原字符串对象
println!("去掉左右空格/回车/换行/制表符:{}", name1.trim());
let name2 = name1.replace("彼岸", "使者"); // 查找并替换
println!("{}", name2);
let name3 = name2.contains("使者"); // 是否包含
let name4 = "#".repeat(4); //重复
println!("{}=>{}", name3, name4);
let name5 = name2.as_str(); //将字符串对象转换为字符串字面量
println!("{}", name5);
let name6 = name2.trim().chars(); //将字符串打散为字符数组
println!("{:?}", name6);
let number = 2021;
let number_as_string = number.to_string();
// 转换数字为字符串类型
println!("{}", number_as_string);
println!("{}", number_as_string == "2021");
// 格式化宏 format!
let n1 = 1024;
let n2 = "KB".to_string();
let n3 = format!("{}{}", n1, n2);
println!("{}", n3);
// LET 变量
// 1.变量名中可以包含 字母、数字 和 下划线。
// 2.变量名必须以 字母 或 下划线 开头。
// 3.变量名是 区分大小 写的。
// 4.let 在第一次赋值之后不可重新赋值,如要变则要加mut
let mut status = "yes";
println!("status: {}", status);
status = "no";
println!("status: {}", status);
}
// 条件判断
// @不支持自增自减运算符 ++ 和 --
fn for_condition() {
mark("条件判断");
let score = 80;
if score == 100 {
println!("满分!");
} else if score >= 80 {
println!("合格");
} else {
println!("不合格!");
}
let sex = "1";
let sex_string = match sex {
"0" => "女",
"1" => "男",
_ => "",
};
println!("{}", sex_string);
}
// 循环语句
fn for_loop() {
mark("循环语句");
for x in 1..3 {
println!("x is {}", x);
}
let mut xx = 0;
loop {
xx += 1;
if xx == 1 {
continue;
}
if xx == 5 {
break;
}
println!("loop {}", xx);
}
let mut xxx = 0;
while xxx < 3 {
xxx += 1;
println!("while {}", xxx);
}
}
// 元组
fn for_tuple() {
mark("元组");
let tuple: (i32, f64, u8) = (-325, 4.9, 22);
println!("{:?}", tuple);
println!("integer is :{:?}", tuple.0);
println!("float is :{:?}", tuple.1);
println!("unsigned integer is :{:?}", tuple.2);
}
// 数组
// @数组中所有的元素的值初始化为 -1
// @数组可以理解为相同数据类型的值的集合
// @数组的定义其实就是为分配一段 连续的相同数据类型 的内存块。
// @数组是静态的。这意味着一旦定义和初始化,则永远不可更改它的长度。
// @数组下标从 0 开始。
// @可以更新或修改数组元素的值,但不能删除数组元素。如果要删除功能,你可以将它的值赋值为 0 或其它表示删除的值。
fn for_array() {
mark("数组");
// 不可变
let arr: [i32; 4] = [10, 20, 30, 40];
println!("array is {:?}", arr);
println!("array size is :{}", arr.len());
for val in arr.iter() {
println!("数组 :{}", val);
}
for key in 0..4 {
println!("数组 key:{},value:{}", key, arr[key]);
}
// 可变
let mut arr: [i32; 4] = [10, 20, 30, 40];
arr[1] = 0;
println!("可变数组 {:?}", arr);
}
// 所有权
// @所有权只会发生在堆上分配的数据
// @基本类型的存储都在栈上,因此没有所有权的概念。
fn for_ownership() {
mark("所有权");
let v = vec![1, 2, 3];
let v2 = v; //这里v嫁给了v2,就销毁了,后面不能再用了
println!("所有权 {:?}", v2);
}
// 借用
fn for_borrow() {
mark("借用");
fn echo(x: &Vec<i32>) {
// 1. 第一步,定义参数接受一个引用
println!("Inside print_vector function {:?}", x);
}
let v = vec![10, 20, 30];
echo(&v); // 传递变量的引用给函数
println!("{}", v[0]);
// 可变的借用
// 1.变量本身是可变更的,也就是定义时必须添加 mut 关键字。
// 2.函数的参数也必须定义为可变更的,也就是必须添加 &mut 关键字。
// 3.传递 借用 Borrowing 或者说引用也必须声明时 可变更传递,也就是传递参数时必须添加 &mut 关键字。
fn mut_echo(x: &mut i32) {
// 1. 第一步,定义参数接受一个引用
*x = 2;
}
let mut v2 = 1;
mut_echo(&mut v2);
println!("{}", v2);
}
// 切片(一般使用=>数组 array、向量 vector、字符串 string)
// 1.一个 切片( slice ) 就是指向一段 内存 的指针
// 2.因此 切片 可用于访问内存块中 连续区间内的数据。
// 3.访问切片内容的时候,下标索引是从 0 开始的。
// 4.切片 的大小是运行时才可知的,并不是数组那种编译时就必须告知的。
fn for_slice() {
mark("切片");
let n1 = "ABCDEDF".to_string();
println!("length: {}", n1.len());
let s1 = &n1[0..5];
println!("{}", s1);
}
// 结构体
// 1.结构体名 Name_of_structure 和元素/字段名 fieldN 遵循普通变量的命名语法。
// 2.结构体中中的每一个元素/字段都必须明确指定数据类型。可以是基本类型,也可以是另一个结构体。
fn for_struct() {
mark("结构体");
struct Employee {
name: String,
company: String,
age: u32,
}
let e = Employee {
company: String::from("哇哈哈"),
name: String::from("小李"),
age: 50,
};
println!(
"Name is :{} company is {} age is {}",
e.name, e.company, e.age
);
let mut e2 = Employee {
company: String::from("哇哈哈"),
name: String::from("小李"),
age: 50,
};
e2.name = "金哲".to_string();
println!(
"Name is :{} company is {} age is {}",
e2.name, e2.company, e2.age
);
// 实现方法
impl Employee {
fn plus(&mut self) {
self.age += 1;
}
fn new(company: String, name: String, age: u32) -> Employee {
return Employee {
company: company,
name: name,
age: age,
};
}
}
let mut e3 = Employee::new("华为".to_string(), "李娜".to_string(), 30);
e3.plus();
println!("New age is {}", e3.age);
e3.plus();
println!("New age is {}", e3.age);
}
// 枚举
fn for_enum() {
mark("枚举");
#[derive(Debug)]
enum Color {
Blue,
Green,
Red,
}
println!("{:?}/{:?}/{:?}", Color::Blue, Color::Green, Color::Red);
}
// 模块
fn for_mod() {
mark("模块");
pub mod movies {
pub fn play(name: String) {
println!("Playing movie {}", name);
}
}
movies::play("Herold and Kumar".to_string());
}
// 容器
// Rust 语言的容器标准库提供了最常见的通用的数据结构的实现。包括 向量 (Vector)、哈希表( HashMap )、哈希集合( HashSet ) 等等。
fn for_collections() {
mark("容器 Vec");
let mut v = Vec::new();
v.push(20);
v.push(30);
v.push(40);
v.remove(1); //删除索引==1
if v.contains(&40) {
println!("found 40");
}
for i in &v {
//借用,要不后面不能用了
println!("{}", i);
}
println!("size of vector is :{}", v.len());
println!("{:?}", v);
mark("容器 HashMap");
// 哈希表 HashMap 就是 键值对 的集合
let mut m = std::collections::HashMap::new();
m.insert("name", "Zee"); //如果键已经存在,则更新为新的简直对,并则返回旧的值。
m.insert("site", "https://zee.kim");
m.insert("who", "balabala");
m.remove(&"who"); //移除
println!("{:?}", m);
// 遍历
for (key, val) in m.iter() {
println!("key: {} val: {}", key, val);
}
// 是否存在
if m.contains_key(&"name") {
println!("found key");
}
match m.get(&"name") {
Some(value) => {
println!("Value for key name is {}", value);
}
None => {
println!("nothing found");
}
}
mark("容器 HashSet");
// 没有重复值的相同数据类型的值的集合
let mut s = std::collections::HashSet::new();
s.insert("Python");
s.insert("Rust");
s.insert("Ruby");
s.insert("PHP");
s.insert("Rust"); // 插入失败但不会引发异常
for language in s.iter() {
println!("{}", language);
}
if s.contains(&"Rust") {
println!("Contains found rust");
}
match s.get(&"Rust") {
Some(value) => {
println!("Match found {}", value);
}
None => {
println!("Not found");
}
}
s.remove(&"PHP");
println!("{:?}", s);
}
// 错误处理
fn for_error() {
// let f = std::fs::File::open("main.jpg"); // main.jpg 文件不存在
// match f {
// Ok(f)=> {
// println!("file found {:?}",f);
// },
// Err(e)=> {
// println!("file not found \n{:?}",e); // 处理错误
// }
// }
// 自定义错误信息
// let f=std::fs::File::open("main.jpg").expect("error!");
// println!("file found {:?}",f);
}
// 闭包
fn for_closure() {
mark("闭包");
let is_even = |x| x % 2 == 0;
let no = 13;
println!("{} is even ? {}", no, is_even(no));
}
// 智能指针
fn for_pointer() {
mark("智能指针");
let x = 5; // 值类型数据,存在栈上
let y = Box::new(x); // y 是一个智能指针,指向堆上存储的数据 5
println!("{}",5==x);
println!("{}",5==*y); // 为了访问 y 存储的具体数据,需要解引用
}
// 线程
fn for_thread(){
mark("线程");
let mut pool = vec![];
// 启动线程
for i in 0..10 as i32 {
pool.push(std::thread::spawn(move || println!("this is {}", i)));
}
// 返回一个结果
for fish in pool {
let _ = fish.join();
}
}
// 标准输入
fn for_stdin(){
mark("控制台输入");
let mut line = String::new();
println!("请输入你的名字:");
let b1 = std::io::stdin().read_line(&mut line).unwrap();
println!("你好 , {}", line);
println!("读取的字节数为:{}", b1);
}
// 文件操作
fn for_file(){
mark("文件操作");
std::fs::write("data.txt", "2021-04-28").expect("could not write file");
println!("写文件data.txt");
let data = std::fs::read_to_string("data.txt").expect("could not read file");
println!("读文件:{:?}",data);
std::fs::copy("data.txt", "bar.txt").expect("could not copy file");
std::fs::rename("bar.txt", "foo.txt").expect("could not rename file");
println!("bar.txt=>foo.txt");
std::fs::remove_file("foo.txt").expect("could not remove file");
println!("foo.txt is removed");
std::fs::create_dir_all("./abc").expect("could not create dir");
println!("dir is created");
std::fs::remove_dir_all("./abc").expect("could not remove dir");
println!("dir is removed");
std::fs::remove_file("data.txt").expect("could not remove file");
println!("data.txt is removed");
// 读取文件列表
fn get_files(target:String) {
let path = std::path::Path::new(&target);
let entrys = std::fs::read_dir(path).expect("Failed to read src directory");
for entry in entrys {
if let Ok(entry) = entry {
let dir = entry.path();
let name = dir.to_str().unwrap();
if name.contains(".DS_Store") {
continue;
}
// println!("{:?}", dir);
if dir.is_file() {
println!("{}",name);
}else{
get_files(name.to_string())
}
}
}
}
get_files("./src/".to_string());
}
// 显示标题
fn mark(s: &str) {
let left = "<".to_string().repeat(20);
let right = ">".to_string().repeat(20);
println!("{}", format!("{}{}{}", left, s.to_string(), right));
}