我正在尝试编写一个泛型函数,它将尝试将字符串转换为数字类型,如i32
,f64
等。如果字符串不可转换,则它将返回0
。我正在寻找一个合适的特征,并在下面的泛型函数中使用:
use std::str::FromStr;
fn get_num_from_str<T: FromStr>(maybe_num_str: &String) -> T {
let maybe_num = T::from_str(maybe_num_str.as_str());
if maybe_num.is_ok() {
return maybe_num.unwrap();
}
0 as T
}
fn main() {
let num_str = String::from("12");
println!("Converted to i32: {}", get_num_from_str::<i32>(&num_str));
}
我发现Rust有一个Primitive
特征,在此之前它被移除了。现在有没有其他可以替代的东西呢?
我找到了一种解决方法:
use std::str::FromStr;
fn get_num_from_str<T: Default + FromStr>(maybe_num_str: &String) -> T {
let maybe_num = T::from_str(maybe_num_str.as_str());
maybe_num.unwrap_or(Default::default())
}
正如特征界限所暗示的那样,这应该适用于同时具有Default
和FromStr
实现的任何东西,我应该重命名该函数以反映这一点,但如果知道是否存在仅用于原始number类型的特征,以确保此函数不能用于除number类型之外的任何其他类型,则仍然很好。
发布于 2018-05-10 14:28:44
在num crate中定义的Num
特征应该可以满足您的需求,但是您尝试做的事情在Rust中并不是惯用的,所以我想提供两个建议:
相反,如果您的函数可能由于多种原因而无法返回结果,请考虑使用Result<T, E>
类型,或者如果您的函数可能无法返回结果只有一个原因,请考虑使用Option<T>
类型。
在本例中,您可能希望使用Result<T, E>
,这样您的函数就可以说明转换失败的原因--字符串是否包含无效的数字字符?该值是否超出所请求类型的范围?函数的调用者可能需要知道才能最好地处理这种情况。
Rust
std::string::String::parse()
或str::parse()
方法的形式包含了您正在寻找的功能(通过泛型实现将字符串转换为值)。由于上述原因,这些方法确实会返回一个Result
.有了以上两条信息,您的代码现在可以更健壮地重写,如下所示(使用Rust 1.26+简化错误处理):
type Result<T> = std::result::Result<T, Box<std::error::Error>>;
fn main() -> Result<()> {
let num_str = String::from("12");
println!("Converted to i32: {}", num_str.parse::<i32>()?);
Ok(())
}
如果出现问题,请注意报告错误的方式有多好:
type Result<T> = std::result::Result<T, Box<std::error::Error>>;
fn main() -> Result<()> {
let num_str = "-1";
println!("Invalid u32 conversion: {}", num_str.parse::<u32>()?);
Ok(())
}
这会将Error: ParseIntError { kind: InvalidDigit }
输出到控制台,并将值std::libc::EXIT_FAILURE
返回给调用进程(表示程序退出时出现错误),而不需要任何值重载或“幻数”。
https://stackoverflow.com/questions/50266085
复制相似问题