基本类型转换
// 不显示类型转换产生的溢出警告。
#![allow(overflowing_literals)]
fn main() {
let decimal = 65.4321_f32;
// 错误!不提供隐式转换
// let integer: u8 = decimal;
// 可以显式转换
let integer = decimal as u8;
let character = integer as char;
println!("Casting: {} -> {} -> {}", decimal, integer, character);
// 当把任何类型转换为无符号类型 T 时,会不断加上或减去 (std::T::MAX + 1)
// 直到值位于新类型 T 的范围内。
// 1000 已经在 u16 的范围内
println!("1000 as a u16 is: {}", 1000 as u16);
// 1000 - 256 - 256 - 256 = 232
// 事实上的处理方式是:从最低有效位(LSB,least significant bits)开始保留
// 8 位,然后剩余位置,直到最高有效位(MSB,most significant bit)都被抛弃。
// 译注:MSB 就是二进制的最高位,LSB 就是二进制的最低位,按日常书写习惯就是
// 最左边一位和最右边一位。
println!("1000 as a u8 is : {}", 1000 as u8);
// -1 + 256 = 255
println!(" -1 as a u8 is : {}", (-1i8) as u8);
// 对正数,这就和取模一样。
println!("1000 mod 256 is : {}", 1000 % 256);
// 当转换到有符号类型时,(位操作的)结果就和 “先转换到对应的无符号类型,
// 如果 MSB 是 1,则该值为负” 是一样的。
// 当然如果数值已经在目标类型的范围内,就直接把它放进去。
println!(" 128 as a i16 is: {}", 128 as i16);
// 128 转成 u8 还是 128,但转到 i8 相当于给 128 取八位的二进制补码,其值是:
println!(" 128 as a i8 is : {}", 128 as i8);
// 重复之前的例子
// 1000 as u8 -> 232
println!("1000 as a u8 is : {}", 1000 as u8);
// 232 的二进制补码是 -24
println!(" 232 as a i8 is : {}", 232 as i8);
}
Casting: 65.4321 -> 65 -> A
1000 as a u16 is: 1000
1000 as a u8 is : 232
-1 as a u8 is : 255
1000 mod 256 is : 232
128 as a i16 is: 128
128 as a i8 is : -128
1000 as a u8 is : 232
232 as a i8 is : -24
From
根据其他类型生成自己
use std::convert::From;
#[derive(Debug)]
struct Number {
value: i32,
}
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}
fn main() {
// 左边不需要类型,右边类似构造
let num = Number::from(30);
println!("My number is {:?}", num);
}
let my_str = "hello";
let my_string = String::from(my_str);
Into
把其他类型转为目的类型
use std::convert::From;
#[derive(Debug)]
struct Number {
value: i32,
}
// 有了From,就自然有了Into
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}
fn main() {
let int = 5;
// 左边需要类型,右边才能推断
// a类型可根据c类型构造,b类型也可根据c类型构造
// 如果让c类型直接into,c不知道是转为a还是b
let num: Number = int.into();
println!("My number is {:?}", num);
}
TryFrom 和 TryInto
use std::convert::TryFrom;
use std::convert::TryInto;
#[derive(Debug, PartialEq)]
struct EvenNumber(i32);
impl TryFrom<i32> for EvenNumber {
type Error = ();
fn try_from(value: i32) -> Result<Self, Self::Error> {
if value % 2 == 0 {
Ok(EvenNumber(value))
} else {
Err(())
}
}
}
fn main() {
// TryFrom
assert_eq!(EvenNumber::try_from(8), Ok(EvenNumber(8)));
assert_eq!(EvenNumber::try_from(5), Err(()));
// TryInto
let result: Result<EvenNumber, ()> = 8i32.try_into();
assert_eq!(result, Ok(EvenNumber(8)));
let result: Result<EvenNumber, ()> = 5i32.try_into();
assert_eq!(result, Err(()));
}
ToString
要把任何类型转换成 String,只需要实现那个类型的 ToString trait
use std::string::ToString;
struct Circle {
radius: i32
}
impl ToString for Circle {
fn to_string(&self) -> String {
format!("Circle of radius {:?}", self.radius)
}
}
fn main() {
let circle = Circle { radius: 6 };
println!("{}", circle.to_string());
}
实现fmt::Display trait,它会自动提供 ToString,并且还可以用来打印类型
use std::fmt;
struct Circle {
radius: i32
}
impl fmt::Display for Circle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Circle of radius {}", self.radius)
}
}
fn main() {
let circle = Circle { radius: 6 };
println!("{}", circle.to_string());
}
解析字符串为数字
-
用 parse 函数
只要对目标类型实现了 FromStr trait,就可以用 parse 把字符串转换成目标类型 -
“涡轮鱼” 语法(turbo fish,<>)
fn main() {
let parsed: i32 = "5".parse().unwrap();
let turbo_parsed = "10".parse::<i32>().unwrap();
let sum = parsed + turbo_parsed;
println!{"Sum: {:?}", sum};
}
总结
From和Info看着都用于构造,只不过From需要显式构造,Info有点半隐
附录
空错误类型
type Error = ()
表示一个简单的空错误类型,称为“单元类型”/“单元错误”()
空括号类型定义为 Error
的别名,来表示错误类型,不包含有用信息,只表示有错误发生。
Rust 内置了一个 Result<T, E>
枚举类型,用于处理可能发生错误的操作。
在这种情况下,类型别名 Error
可以被用作 Result<T, E>
枚举类型中的错误类型 E
的别名,表示可能出现的错误不需要包含详细的错误信息。文章来源:https://www.toymoban.com/news/detail-674967.html
在 Rust 中,()
表示一个空元组类型,因此一个空错误类型可以表示为一个空元组类型的别名。文章来源地址https://www.toymoban.com/news/detail-674967.html
// 定义了一个名称为 `Result` 的新类型别名
// 这个新类型在 `std::result::Result<T, E>` 类型的基础上重新声明
type Result<T> = std::result::Result<T, Error>;
fn process_data(data: &str) -> Result<usize> {
if data.len() > 10 {
Ok(data.len())
} else {
// 返回空错误
Err(())
}
}
到了这里,关于rust学习-类型转换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!