rust学习笔记之小练习:错误处理

错误处理

Result

pub fn gen_nametag(name: String) -> Result<String,&'static str> {
    if name.is_empty() {
        Err("`name` was empty; it must be nonempty.")
    } else {
        Ok(format!("Hi! My name is {}", name))
    }
}

fn main(){
    assert_eq!(gen_nametag("Beyoncé".into()), Ok("Hi! My name is Beyoncé".into()));
    assert_eq!(gen_nametag("".into()),Err("`name` was empty; it must be nonempty.".into()));
}

?传播错误

use std::num::ParseIntError;

pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
    let processing_fee = 1;
    let cost_per_item = 5;
    let qty = item_quantity.parse::<i32>()?;

    Ok(qty * cost_per_item + processing_fee)
}

fn main(){
    assert_eq!(total_cost("34"), Ok(171));
    assert_eq!(total_cost("beep boop").unwrap_err().to_string(),"invalid digit found in string");
  
    let mut tokens = 100;
    let pretend_user_input = "8";
    let cost = total_cost(pretend_user_input);
    if let Ok(cost_num)=cost {
        if cost_num > tokens {
            println!("You can't afford that many!");
        } else {
            tokens -= cost_num;
            println!("You now have {} tokens.", tokens);
        }
    }else{
        println!("ParseIntError");
    }
}

Box 封装任意错误类型

use std::error;
use std::fmt;
use std::num::ParseIntError;

#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);

#[derive(PartialEq, Debug)]
enum CreationError {
    Negative,
    Zero,
}

impl PositiveNonzeroInteger {
    fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
        match value {
            x if x < 0 => Err(CreationError::Negative),
            x if x == 0 => Err(CreationError::Zero),
            x => Ok(PositiveNonzeroInteger(x as u64)),
        }
    }
}

impl fmt::Display for CreationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let description = match *self {
            CreationError::Negative => "number is negative",
            CreationError::Zero => "number is zero",
        };
        f.write_str(description)
    }
}

impl error::Error for CreationError {}

fn parse_input(input:&str) -> Result<PositiveNonzeroInteger, Box<dyn error::Error>> {
    let x: i64 = input.parse()?;
    Ok(PositiveNonzeroInteger::new(x)?)
}

fn main(){
    println!("{:?}", parse_input("42").unwrap()); // PositiveNonzeroInteger(42)
    println!("{}", parse_input("a b").unwrap_err()); // invalid digit found in string
    println!("{}", parse_input("-1").unwrap_err()); // number is negative
    println!("{}", parse_input("0").unwrap_err()); // number is zero
}

自定义错误类型

自定义错误类型,使调用者可以根据函数返回错误做判断,而不是将错误打印出来或向前传播。

use std::num::ParseIntError;

// 自定义错误类型
#[derive(PartialEq, Debug)]
enum ParsePosNonzeroError {
    Creation(CreationError),
    ParseInt(ParseIntError),
}

impl ParsePosNonzeroError {
    fn from_creation(err: CreationError) -> ParsePosNonzeroError {
        ParsePosNonzeroError::Creation(err)
    }

    fn from_parseint(err: ParseIntError) -> ParsePosNonzeroError {
        ParsePosNonzeroError::ParseInt(err)
    }
}

fn parse_pos_nonzero(s: &str) -> Result<PositiveNonzeroInteger, ParsePosNonzeroError> {
    let x: i64 = s.parse::<i64>().map_err(ParsePosNonzeroError::from_parseint)?;
    PositiveNonzeroInteger::new(x).map_err(ParsePosNonzeroError::from_creation)
}

#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);

#[derive(PartialEq, Debug)]
enum CreationError {
    Negative,
    Zero,
}

impl PositiveNonzeroInteger {
    fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
        match value {
            x if x < 0 => Err(CreationError::Negative),
            x if x == 0 => Err(CreationError::Zero),
            x => Ok(PositiveNonzeroInteger(x as u64)),
        }
    }
}

fn main(){
        assert!(matches!(parse_pos_nonzero("not a number"),Err(ParsePosNonzeroError::ParseInt(_))));
        assert_eq!(parse_pos_nonzero("-555"),Err(ParsePosNonzeroError::Creation(CreationError::Negative)));
        assert_eq!(parse_pos_nonzero("0"),Err(ParsePosNonzeroError::Creation(CreationError::Zero)));
        let x = PositiveNonzeroInteger::new(42);
        assert!(x.is_ok());
        assert_eq!(parse_pos_nonzero("42"), Ok(x.unwrap()));
}

Option

struct Point {
    x: i32,
    y: i32,
}

fn main(){
    assert_eq!(maybe_icecream(9), Some(5));
    assert_eq!(maybe_icecream(10), Some(5));
    assert_eq!(maybe_icecream(23), Some(0));
    assert_eq!(maybe_icecream(22), Some(0));
    assert_eq!(maybe_icecream(25), None);
    if let Some(icecreams) = maybe_icecream(12){
       assert_eq!(icecreams, 5); 
    }
    
    let mut range = 10;
    let mut optional_integers: Vec<Option<i8>> = Vec::new();
    for i in 0..(range + 1) {
        optional_integers.push(Some(i));
    }
    while let Some(Some(integer)) = optional_integers.pop() {
        assert_eq!(integer, range);
        range -= 1;
    }
    
    let y: Option<Point> = Some(Point { x: 100, y: 200 });
    match y {
        Some(ref p) => println!("Co-ordinates are {},{} ", p.x, p.y),
        _ => println!("no match"),
    }
    y; 
}

fn maybe_icecream(time_of_day: u16) -> Option<u16> {
    if time_of_day>23{
        None
    }else if time_of_day<22{
        Some(5)
    }else{
        Some(0)
    }
}
posted @ 2025-08-01 17:01  carol2014  阅读(14)  评论(0)    收藏  举报