中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Rust常用的標準庫工具有哪些

發布時間:2021-10-13 10:51:25 來源:億速云 閱讀:380 作者:iii 欄目:編程語言

本篇內容主要講解“Rust常用的標準庫工具有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Rust常用的標準庫工具有哪些”吧!

Rust常用的標準庫工具有哪些

Prelude

我們一般使用use語句把其他模塊的內容引入當前模塊中,但對于標準庫中一些非常常用的工具,每次都寫use語句就過于冗余,因此標準庫提供了一個std::prelude模塊,在這個模塊中導出一些最常見的工具,然后編譯器為用戶編寫的每一個crate都自動插入一句話:

use std::prelude::*;

如此,一些最常見的工具就可以直接使用,而無需use了。對這個std::prelude模塊所包含內容的權衡是需要細致考量的,因為如果包含的內容過多則會引入很多不被使用的工具,這反倒不美了。當下的std::prelude模塊中包含的內容在std::prelude::v1中。

類型轉換

除了as關鍵字可以用來進行基本類型之間的轉換,Rust還提供了很多trait來實現自定義類型之間的轉換。

AsRef / AsMut

AsRef的含義是該類型可以通過調用as_ref方法得到另外一個類型的共享引用,同理,AsMut得到的是另外一個類型的可讀寫引用,它們的定義如下:

pub trait AsRef<T: ?Sized> {
    fn as_ref(&self) -> &T;
}

pub trait AsMut<T: ?Sized> {
    fn as_mut(&mut self) -> &mut T;
}

AsRef很適合用于泛型代碼中,例如,下面的泛型函數接受各種類型,只要可以被轉換為&[u8]即可:

fn iter_bytes<T: AsRef<[u8]>>(arg: &T) {
    for i in arg.as_ref() {
        println!("{}", i);
    }
}

fn main() {
    let s = String::from("this is a string");
    let v = vec![1, 2, 3];
    let c = "hello";

    iter_bytes(&s);
    iter_bytes(&v);
    iter_bytes(&c);
}
Borrow / BorrowMut

BorrowBorrowMut這兩個trait的設計和AsRefAsMut很類似:

pub trait Borrow<Borrowed: ?Sized> {
    fn borrow(&self) -> &Borrowed;
}

pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

但區別在于兩點:

  • 標準庫為所有的T&T&mut T默認實現了BorrowBorrowMut,以Borrow為例:

impl<T: ?Sized> Borrow<T> for T {
    fn borrow(&self) -> &T {
        self
    }
}

impl<T: ?Sized> Borrow<T> for &T {
    fn borrow(&self) -> &T {
        &**self
    }
}

impl<T: ?Sized> Borrow<T> for &mut T {
    fn borrow(&self) -> &T {
        &**self
    }
}
  • Borrow要求返回的類型,必須和原來的類型具備同樣的hash值。這是一個約定,如果違反了這個約定,那么把這個類型放到HashMap里時可能會出現問題。

From / Into

AsRefBorrow都是從&T&U的轉換,而From/Into是從TU的轉換:

pub trait From<T>: Sized {
    fn from(_: T) -> Self;
}
pub trait Into<T>: Sized {
    fn into(self) -> T;
}

由于FromInto是互逆的一組轉換,因此標準庫提供了這樣一個實現:

impl<T, U> Into<U> for T
where
    U: From<T>,
{
    fn into(self) -> U {
        U::from(self)
    }
}

這段代碼的含義是:如果存在U: From<T>,則為類型T實現Into<U>。也就是說,我們只需為類型實現From即可,Into會自動實現。標準庫中還有一組對應的TryFromTryInto,他們是為了處理類型轉換過程中可能發生轉換錯誤的情況,因此返回值是Result類型。

ToOwned

ToOwned提供一種更泛化的Clone的功能,Clone是從&T類型變量創造一個新的T類型變量,而ToOwned是從一個&T類型變量創造一個新的U類型變量,標準庫中也提供了ToOwned調用clone方法的默認實現:

pub trait ToOwned {
    type Owned: Borrow<Self>;

    fn to_owned(&self) -> Self::Owned;

    fn clone_into(&self, target: &mut Self::Owned) {
        *target = self.to_owned();
    }
}

impl<T> ToOwned for T
where
    T: Clone,
{
    type Owned = T;
    fn to_owned(&self) -> T {
        self.clone()
    }

    fn clone_into(&self, target: &mut T) {
        target.clone_from(self);
    }
}
ToString / FromStr

ToString提供了其他類型轉換為String類型的能力:

pub trait ToString {
    fn to_string(&self) -> String;
}

標準庫中為所有實現了Displaytrait的類型默認實現了ToString,而Display可以通過derive實現:

impl<T: fmt::Display + ?Sized> ToString for T {
    default fn to_string(&self) -> String {
        use fmt::Write;
        let mut buf = String::new();
        buf.write_fmt(format_args!("{}", self))
            .expect("a Display implementation returned an error unexpectedly");
        buf
    }
}

FromStr提供了從字符串切片向其他類型轉換的能力:

pub trait FromStr: Sized {
    type Err;
    fn from_str(s: &str) -> Result<Self, Self::Err>;
}

IO

這里的IO指的是標準輸入輸出和文件輸入輸出。

標準輸入輸出

我們之前介紹過的println!宏可以方便地隨手輸出一些信息,但如果要對標準輸入輸出作更精細的控制,則需要調用std::io::stdin()函數和std::io::stdout()函數來獲取StdinStdout結構體的實例。這兩個實例的簡單用法如下:

use std::io::{self, Read};

fn main() -> io::Result<()> {
    let mut buffer = String::new();
    let mut stdin = io::stdin(); 
    stdin.read_to_string(&mut buffer)?;
    Ok(())
}

為了線程安全考慮,每次讀取操作都需要上鎖,這降低了效率。解決的方法是手動調用lock()方法,但這又增添了使用標準輸入輸出的復雜度。

事實上,我們受學生時代做各種C語言大作業的影響,導致我們認為標準輸入輸出是非常重要的功能,可我們細想一下,正兒八經的命令行程序誰會用標準輸入來和用戶交互呢?一般都是通過兩種方式,一則是調用程序的時候指定參數,另一則是通過文件讀取用戶配置。

文件輸入輸出

文件輸入輸出首先要解決路徑問題。Rust中的字符串類型是Stringstr,它們都是用utf-8進行編碼的。但是,在具體的操作系統上并不是統一使用utf-8編碼,為了應付這種情況,Rust中設計了OsStringOsStr,這兩種類型使用方法和Stringstr類似,并且它們之間也可以互相轉換。

Rust標準庫提供了std::path::PathBufstd::path::Path來處理路徑,PathBuf對內部數據擁有所有權,而Path只是借用,事實上,PathBuf內部存儲了一個OsString,而Path則是存儲了Path

Rust的文件操作主要通過std::fs::File來完成,可以實現打開、創建、復制等文件操作。對于文件的讀寫,就要用到std::io模塊中的一些trait了,例如ReadWriteFile實現了這 兩個trait,因此擁有read等讀取文件的方法。

下面看一個例子來演示說明文件輸入輸出的方法:

use std::fs::File;
use std::io::{BufRead, BufReader, Read};

fn test_read_file() -> Result<(), std::io::Error> {
    let mut path = std::env::current_dir().unwrap();
    path.push("Cargo.toml");

    let mut file = File::open(&path)?;
    let mut buffer = String::new();
    file.read_to_string(&mut buffer)?;

    println!("{}", buffer);
    Ok(())
}

fn main() {
    match test_read_file() {
        Ok(_) => {}
        Err(e) => {
            println!("{}", e);
        }
    }
}

容器

和C++的STL類似,Rust的標準庫也給我們提供了一些比較常用的容器以及相關的迭代器,目前實現了的容器有:

容器描述
Vec可變長數組,連續存儲
VecDeque雙向隊列,適用于從頭部和尾部插入刪除數據
LinkedList雙向鏈表,非連續存儲
HashMap基于Hash算法存儲一系列鍵值對
BTreeMap基于B樹存儲一系列鍵值對
HashSet相當于沒有值的HashMap
BTreeSet相當于沒有值的BTreeMap
BinaryHeap基于二叉堆實現的優先級隊列

這里不詳細展開講,以后會對各個容器的用法和實現原理進行深入探究。

迭代器

Rust中的迭代器是指實現了std::iter::Iterator這個trait的類型,其定義如下:

pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
    ...
}

它最主要的方法是next(),返回一個Option<Item>,迭代完成則返回None。實現了Iterator的類型可直接用于for循環。

迭代器擁有一個很重要的特性,就是它是可組合的,這有點類似于Java中的流式編程。Iterator中有很多方法,它們返回的類型也實現了Iterator,這意味著,我們調用這些方法可以從一個迭代器創造出一個新的迭代器,例如:

fn main() {
    let v = vec![1, 2, 3, 4, 5, 6, 7, 8];
    let mut iter = v
        .iter()
        .take(5)
        .filter(|&x| x % 2 == 0)
        .map(|&x| x * x)
        .enumerate();
    while let Some((i, v)) = iter.next() {
        println!("{}: {}", i, v);
    }
}

這段代碼的含義是:從v這個Vec的前五個元素中篩選元素,要求它必須是2的倍數,并把該元素進行平方,因此,最終的輸出結果是0: 41: 16

運算符重載

Rust支持自定義類型重載部分運算符,只需該類型實現std::ops模塊下相應的trait即可。以Add為例:

pub trait Add<Rhs = Self> {
    type Output;
    fn add(self, rhs: Rhs) -> Self::Output;
}

它具備一個泛型參數RHS和一個關聯類型Output。標準庫中早已為基本的數字類型實現了這個trait:

macro_rules! add_impl {
    ($($t:ty)*) => ($(
        #[stable(feature = "rust1", since = "1.0.0")]
        impl Add for $t {
            type Output = $t;

            #[inline]
            #[rustc_inherit_overflow_checks]
            fn add(self, other: $t) -> $t { self + other }
        }

        forward_ref_binop! { impl Add, add for $t, $t }
    )*)
}

add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }

到此,相信大家對“Rust常用的標準庫工具有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

探索| 山东省| 濉溪县| 灵川县| 宜兰市| 科技| 蒙山县| 邵东县| 迁安市| 九龙城区| 城口县| 双辽市| 江油市| 呼和浩特市| 龙江县| 马龙县| 四子王旗| 宣恩县| 定结县| 塔城市| 济南市| 宝丰县| 荣成市| 阿坝县| 广元市| 徐闻县| 石城县| 额济纳旗| 广饶县| 呼伦贝尔市| 东台市| 焉耆| 吴忠市| 清远市| 安义县| 吐鲁番市| 射洪县| 大丰市| 湟源县| 商河县| 噶尔县|