rust中vec、string、hashmap、错误处理
Vector
创建和删除
fn main() {
// 创建vector,因为刚开始创建的时候不知道元素类型
let v: Vec<i32> = Vec::new();
// 或者刚开始不指定,后续加元素的时候会自动指定
let mut v2 = Vec::new();
v2.push(1);
// 使用初始值创建
let v3 = vec![1,2,3];
// 删除vector
// 离开作用域时,会删除
}
读取vector元素
- 索引
- get方法
let v = vec![1,2,3,4,5];
let second = &v[1];
println!("{}",second); //2
match v.get(1) {
Some(second) => println!("haha"), //haha
None => println!("no such thing"),
}
越界问题
let v = vec![1,2,3,4,5];
let second = &v[1];
//let second = &v[100];
// panicked at 'index out of bounds: the len is 5 but the index is 100'
//println!("{}",second); //2
match v.get(100) {
Some(second) => println!("haha"),
None => println!("no such thing"), //no such thing
}
遍历
let v = vec![1,2,3,4,5];
for i in &v {
println!("{}",i);
}
遍历更改:
fn main() {
let mut v = vec![1,2,3,4,5];
for i in &mut v {
*i += 50;
}
println!("{:#?}",v);
// [
// 51,
// 52,
// 53,
// 54,
// 55,
// ]
}
enum存储不同的数据类型
enum SpreadssheetCell {
Int(i32),
Float(f64),
Text(String),
}
fn main() {
let row = vec![
SpreadssheetCell::Int(3),
SpreadssheetCell::Text("blue".to_string()),
SpreadssheetCell::Float(1.234),
];
}
String
创建
String::new()
String::from("")
"".to_string();
demo
fn main() {
let mut s = String::from("foo");
s.push_str("bar");
println!("{}", s);
}
format!
不会取得参数所有权。
fn main() {
let s1 = String::from("foo");
let s2 = String::from("bar");
let s = format!("{}-andyou {},",s1,s2);
println!("{}",s);
println!("{}",s1);
println!("{}",s2);
// foo-andyou bar,
// foo
// bar
}
索引访问
String
是对vec<u8>
的包装。
fn main() {
let s = String::from("❤️✨");
println!("{}",s.len()); //9
}
遍历
fn main() {
let s = String::from("❤️✨");
println!("{}",s.len()); //9
for b in s.bytes() {
print!("{} ",b); // 226 157 164 239 184 143 226 156 168
}
println!("");
for b in s.chars() {
print!("{} ",b); // ❤ ️ ✨
}
println!("");
}
切割
fn main() {
let s = String::from("❤️✨");
println!("{}",s.len()); //9
let cc = &s[0..6];
println!("{}",cc);
}
必须严格按照字符边界切割,否则会panic
HashMap
数据存储在heap
上。
collect方法创建HashMap
在元素类型为tuple的vector上使用collect方法,可以创建一个HashMap。demo:
fn main() {
let colors = vec![String::from("Red"),String::from("Blue")];
let scores = vec![1,2];
let map: HashMap<_,_> =
colors.iter().zip(scores.iter()).collect();
}
所有权
fn main() {
let colors = vec![String::from("Red"),String::from("Blue")];
let scores = vec![1,2];
let map: HashMap<_,_> =
colors.iter().zip(scores.iter()).collect();
let name = String::from("Blue");
let score = map.get(&name);
// pub fn get<Q>(&self, k: &Q) -> Option<&V>
match score {
Some(s) => println!("{}",s),
None => println!("color not exist"),
}
println!("{}",name);
for (k,v) in map {
println!("{} {}",k,v);
}
// 2
// Blue
// Blue 2
// Red 1
}
更新
HashMap大小可变
or_insert不存在才插入,返回到这个值的可变引用。
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Red"), 20);
scores.insert(String::from("Blue"), 30);
println!("{:?}",scores); //{"Blue": 30, "Red": 20}
scores.entry(String::from("Black")).or_insert(100);
scores.entry(String::from("Blue")).or_insert(999);
println!("{:?}",scores); // {"Black": 100, "Blue": 30, "Red": 20}
}
统计单词个数
fn main() {
let text = "I love you love me";
let mut map = HashMap::new();
for word in text.split_whitespace() {
let count = map.entry(word).or_insert(0);
// 返回的是map k对应v的可变引用
*count += 1;
}
println!("{:#?}",map);
// {
// "you": 1,
// "I": 1,
// "me": 1,
// "love": 2,
// }
}
错误处理
Rust没有异常机制。
- 可恢复错误:Result
- 不可恢复错误:panic!
当panic!宏执行时:打印错误信息、展开清理调用栈、退出程序。
panic!
panic可以手动调用,也可以错误了自动panic。
let v = vec![1,2,3];
v[99];
// thread 'main' panicked at 'index out of bounds:
// the len is 3 but the index is 99', src\main.rs:5:5
Result枚举与可恢复的错误
来处理可能失败但是可以恢复的场景。
pub enum Result<T, E> {
/// Contains the success value
#[lang = "Ok"]
#[stable(feature = "rust1", since = "1.0.0")]
Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
/// Contains the error value
#[lang = "Err"]
#[stable(feature = "rust1", since = "1.0.0")]
Err(#[stable(feature = "rust1", since = "1.0.0")] E),
}
打开一个文件,如果不存在,则创建文件:
use std::fs::File;
fn main() {
let f = File::open("1.txt");
let f = match f {
Ok(file) => file,
Err(error) => match error.kind() {
std::io::ErrorKind::NotFound => match File::create("1.txt") {
Ok(fc) => fc,
Err(e) => panic!("Error create"),
},
other_error => panic!("Error open file"),
}
};
}
使用了很多match,后面会有闭包closure简化。
例如改良版:
unwrap
unwrap是match表达式的一个快捷方法。
let f = File::open("1.txt").unwrap();
Ok就返回里面的值,Err就panic。
expect
类似unwrap,但是可以指定错误信息。
let f = File::open("1.txt").expect("无法打开1.txt");
传播错误
demo:
fn read_name_from_file() -> Result<String,io::Error> {
let f = File::open("hello.txt");
let mut f = match f {
Ok(file) => file,
Err(e) => return Err(e),
};
let mut s = String::new();
match f.read_to_string(&mut s) {
Ok(_) => Ok(s),
Err(e) => Err(e),
}
}
?
运算符
传播错误的一种简化方式。
fn read_name_from_file() -> Result<String,io::Error> {
let mut f = File::open("hello.txt")?;
// ? 成功就得到file,不成功就return err
let mut s = String::new();
f.read_to_string(&mut s)?;
Ok(s)
}
?
所接收到的错误会默认调用其中的from
函数转化为返回的函数类型。但是不一定都能转。
链式调用
let mut s = String::new();
let mut f = File::open("hello.txt")?;.read_to_string(&mut s)?;
Ok(s)