wqpw_blog

= =

View on GitHub
7 October 2019

Rust简单整理(c7-c9)

by wqpw

基于官方教程《The Rust Programming Language》

7. Managing Growing Projects with Packages, Crates, and Modules

Packages: A Cargo feature that lets you build, test, and share crates
Crates: A tree of modules that produces a library or executable
Modules and use: Let you control the organization, scope, and privacy of paths
Paths: A way of naming an item, such as a struct, function, or module

pub, super::, pub use, use, as, Glob Operator(*), ......

8. Common Collections

fn main() {
    vec_test();
    string_test();
    hashmap_test();
}

fn hashmap_test() {
    use std::collections::HashMap; //one is the least often used
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
    let teams = vec![String::from("Red"), String::from("Black")];
    let init_scores = [20, 30];
    let t = teams.iter().zip(init_scores.iter());
    let scores2: HashMap<_, _> = t.collect();
    let s1 = String::from("ttt");
    let v1 = 20; //has Copy trait
    scores.insert(s1, v1); //s1 moved. &s1 
    // references point to must be valid for at least as long as the hash map is valid
    println!("{}", v1);
    let team_name = String::from("Black");
    println!("Black: {:?}", scores2.get(&team_name)); //Option<&V> Some(&30)
    for (key, value) in &scores {
        println!("{}: {}", key, value);
    }
    //update
    scores.insert(String::from("Blue"), 233);
    println!("{:?}", scores);
    /*
return a mutable reference to the value for the corresponding Entry key 
if that key exists, and if not, 
inserts the parameter as the new value for this key 
and returns a mutable reference to the new value.
    */
    scores.entry(String::from("Blue")).or_insert(50);
    //--------------------count words
    let text = "hello world wonderful world";
    let mut map = HashMap::new();
    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0);
        *count += 1;
    }
    println!("{:?}", map);
}

fn string_test() {
    let mut s = String::new();
    let data = "str233";
    let data = data.to_string();
    s = 1.to_string();
    println!("{} {}", s, data);
    let data = "go".to_string();
    println!("{}", data);
    let hello = String::from("你好"); //utf8
    println!("{} {}", hello, "こんにちは");
    let mut s = String::from("foo");
    s.push_str("bar");
    s.push('c');
    println!("{}", s);
    let s2 = "aaa";
    s.push_str(s2); //takes a string slice not ownership!
    println!("{}", s2);
    let ss = s + &s2; //note ownership. s moved
    //fn add(self, s: &str) -> String
    // we can only add a &str to a String
    //Rust coerce the &String argument into a &str. 
    //deref coercion, Rust turns &s2 into &s2[..]
    println!("{}", ss);
    let s1 = String::from("tic");
    let s2 = String::from("tac");
    let s3 = String::from("toe");
    let s = s1 + "-" + &s2 + "-" + &s3; //just s1 moved
    println!("{}", s2);
    let s1 = String::from("tic");
    let s = format!("{}-{}-{}", s1, s2, s3); //doesn’t take ownership
    println!("{}", s);
    //Rust strings don’t support indexing
    //A String is a wrapper over a Vec<u8>
    let len = String::from("Здравствуйте").len();
    println!("{}", len); //24
    let hello = "Здравствуйте";
    let s = &hello[0..4]; //4 bytes
    println!("{}", s);
    for c in "中国人均GDP".chars() { //bytes()
        println!("{}", c);
    }
}

fn vec_test() {
    let v: Vec<i32> = Vec::new();
    let v = vec![1, 2]; //i32
    let mut v = Vec::new();
    v.push(5);
    v.push(6);
    let v = vec![1, 2, 3, 4];
    let third: &i32 = &v[2]; //v[10] crash
    println!("{}", third);
    match v.get(2) { // -> Option<&T>  get(10) None user-friendly
        Some(third) => println!("{}", third),
        None => println!("No third."),
    }
    for i in &v {
        println!("i: {}", i);
    }
    let mut v = vec![1, 2, 3, 4];
    for i in &mut v {
        *i += 50;
        println!("i+50: {}", i);
    }
    //known different types
    enum SpreadsheetCell {
        Int(i32),
        Float(f64),
        Text(String),
    }
    let row = vec![
        SpreadsheetCell::Int(3),
        SpreadsheetCell::Text(String::from("blue")),
        SpreadsheetCell::Float(10.12),
    ];
    for i in &row {
        match i {
            SpreadsheetCell::Int(i) => println!("{}", i),
            SpreadsheetCell::Float(i) => println!("{}", i),
            SpreadsheetCell::Text(i) => println!("{}", i),
        }
    }
}

9. Error Handling

use std::fs::File;
use std::io::ErrorKind;
use std::io::Read;
use std::io;

fn main() {
    let f = File::open("hello.txt");
    let f = match f {
        Ok(file) => file,
        Err(error) => match error.kind() {
            ErrorKind::NotFound => match File::create("hello.txt") {
                Ok(fc) => fc,
                Err(e) => panic!("Problem creating the file: {:?}", e),
            },
            other_error => panic!("Problem opening the file: {:?}", other_error),
        },
    };
    //no match
    let f = File::open("hello.txt").unwrap_or_else(|error| {
        if error.kind() == ErrorKind::NotFound {
            File::create("hello.txt").unwrap_or_else(|error| {
                panic!("Problem creating the file: {:?}", error);
            })
        } else {
            panic!("Problem opening the file: {:?}", error);
        }
    });
    //file handle or call default panic!
    let f = File::open("hello.txt").unwrap();
    //self-define msg pass to panic!
    let f = File::open("hello.txt").expect("Failed to open hello.txt");
}
//Propagating Errors
fn read_username_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),
    }
}
//same functionality
//'?' convert error type automatically
fn _read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("hello.txt")?;
    let mut s = String::new();
    f.read_to_string(&mut s)?;
    Ok(s)
}
fn __read_username_from_file() -> Result<String, io::Error> {
    let mut s = String::new();
    File::open("hello.txt")?.read_to_string(&mut s)?;
    Ok(s)
}
fn ___read_username_from_file() -> Result<String, io::Error> {
    fs::read_to_string("hello.txt")
}
//The ? operator can only be used in functions that have a return type of Result
/*
fn main() -> Result<(), Box<dyn Error>> {
    let f = File::open("hello.txt")?;
    Ok(())
}
*/

//guess.rs
mod test {
    pub struct Guess {
        value: i32, //private
    }
    impl Guess {
        pub fn new(value: i32) -> Guess {
            if value < 1 || value > 100 {
                panic!("Guess value must be between 1 and 100, got {}.", value);
            }
            Guess {
                value
            }
        }
        pub fn value(&self) -> i32 {
            self.value
        }
    }
}
fn main() {
    use test::Guess;
    let a = Guess::new(3);
    println!("{}", a.value());
}
tags: blog