隱私權政策

搜尋此網誌

技術提供:Blogger.

關於我自己

我的相片
目前從事軟體相關行業,喜歡閱讀、健身、喝調酒。習慣把遇到的問題記下來,每天做一些整理方便自己以後查。 Python、Rust、Kotlin等程式語言皆為自學,目前比較著重在Rust語言,歡迎一起討論。

2023年11月9日 星期四

Rust 字串parse概述 - 將字符串轉為其他類型


parse

parse被定義在str下面

用處為將一個字符串轉成其他類型

文件這樣寫到

    pub fn parse<F>(&self) -> Result<F, <F as FromStr>::Err>
    where
        F: FromStr,

F為一個字串

回傳Result,如果Ok則包含解析字串的詞

否則回傳錯誤類型


FromStr定義[2]則是

Trait std::str::FromStr

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

透過接收字符串s

解析成類型Self,成功返回Ok否則Err


例子

舉一個簡單的例子

    let num_str = "42";
    let parsed: Result<i32, _> = num_str.parse();
    match parsed {
        Ok(parsed_num) => {
            println!("Parsed number: {}", parsed_num);
        },
        Err(_) => {
            println!("Parse error.");
        }
    }
Parsed number: 42

第一行為一個整數

第二行透過parse轉成i32,回傳一個result

第三行則是使用match分析result結果

如果是Ok,回傳數值42

如果為Err,顯示err


失敗的例子

    let invalid_num_str = "abc";
    let parsed: Result<i32, _> = invalid_num_str.parse();
    match parsed {
        Ok(parsed_num) => {
            println!("Parsed number: {}", parsed_num);
        }
        Err(error) => {
            println!("Parse error: {:?}", error);
        }
    }
Parse error: ParseIntError { kind: InvalidDigit }

第一行一個字串abc

第二行想將字串透過parse轉成i32

但因為是字串轉整數所以會報錯誤

因此match的結果顯示ParseIntError,類型為無效數值


parse常用在文字輸入、文件內容等

因不確定輸入類型是什麼

不能用類似

    let invalid_num_str: &str

這種方式直接指定型態,容易發生panic

例如說有個程式會要求使用者輸入

    println!("Enter your age: ");
    let mut age_str = String::new();
    io::stdin().read_line(&mut age_str).expect("Failed to read input");

    let age: Result<u32, _> = age_str.trim().parse();
   
    match age {
        Ok(parsed_age) => println!("Your age is: {}", parsed_age),
        Err(_) => println!("Invalid age input."),
    }
Enter your age: CCC Invalid age input.

而使用者直接亂輸入一個年紀CCC

就可以透過match傳輸Err訊息


應用

舉一個比較困難的例子

假設要求使用者輸入多個數字,每個數字用逗點分開

並計算最大值、最小值以及和

use std::io;

fn main() {
    let mut input = String::new();

    println!("Enter a list of integers separated by commas:");
    io::stdin().read_line(&mut input).expect("Failed to read input");

    let numbers: Vec<i32> = input        //String
        .split(',')                      //Split<'_, char>
        .map(|s| s.trim())               //impl Iterator<Item = &str>
        .filter_map(|s| s.parse().ok())  //impl Iterator<Item = i32>
        .collect();

    if !numbers.is_empty() {
        let sum: i32 = numbers.iter().sum();
        let min: i32 = *numbers.iter().min().unwrap();
        let max: i32 = *numbers.iter().max().unwrap();

        println!("Sum: {}", sum);
        println!("Minimum: {}", min);
        println!("Maximum: {}", max);
    } else {
        println!("No valid integers entered.");
    }
}
Enter a list of integers separated by commas: 3, 1, 5, 6, C, 13, ss, 88, ,6 Sum: 122 Minimum: 1 Maximum: 88

使用者輸入後

透過分割split[3]map[4]filter_map[5]以及最後collect回傳一個數組

每個方法我都有把轉出來的型態打上去

可以看到map時候,型態為&str

而fliter_map裡面透過parse轉成i32

if以下則是判斷最大值以及最小值

這個檔案會放在GitHub[6],可以下載下來看


參考資料

[1] https://doc.rust-lang.org/std/primitive.str.html#method.parse

[2] https://doc.rust-lang.org/std/str/trait.FromStr.html

[3] https://lageeblog.blogspot.com/2023/11/rust-split.html

[4] https://lageeblog.blogspot.com/2023/10/rust-map.html

[5] https://lageeblog.blogspot.com/2023/11/rust-filtermap.html

[6] https://github.com/Lagee666/parse_practice

0 comments:

張貼留言