解析整数,忽略任何非数字后缀

Net*_*råm 5 rust

我有一个全部以数字开头的字符串列表。然而,我不知道他们的结局是什么。一些示例可能是"12/1/1"、、"33""17abc"。我想读取每个字符串开头的数字,将示例分别转换为1233、 和17

我已经让它与下面的代码一起工作。

"12/1/1".chars().take_while(|c| c.is_numeric()).collect::<String>().parse::<usize>()
Run Code Online (Sandbox Code Playgroud)

然而,我确实觉得存在更高效/更清洁的解决方案。一种没有字符串集合和/或不那么冗长的方法。
我不想使用任何外部板条箱。

Val*_*tin 2

这取决于你对“更好”的定义。如果您只是想删除不必要的String创建,那么您可以使用atoicrate

或者,您也可以使用nomcrate,并使用它digit0()来创建您自己的atoi()函数:

// nom = "6.0"
use nom::character::complete::digit0;
use nom::error::Error;
use std::str::FromStr;

fn atoi<F: FromStr>(input: &str) -> Result<F, <F as FromStr>::Err> {
    digit0::<_, Error<_>>(input).unwrap().1.parse::<F>()
}

fn main() {
    println!("{:?}", atoi::<usize>("12/1/1")); // Prints `Ok(12)`
    println!("{:?}", atoi::<usize>("33"));     // Prints `Ok(33)`
    println!("{:?}", atoi::<usize>("17abc"));  // Prints `Ok(17)`
    println!("{:?}", atoi::<usize>("abc"));    // Prints `Err(ParseIntError { kind: Empty })`
    println!("{:?}", atoi::<usize>(""));       // Prints `Err(ParseIntError { kind: Empty })`
}
Run Code Online (Sandbox Code Playgroud)

unwrap()安全的,就好像没有数字一样,Ok仍然返回,空字符串由 处理parse()


由于您不想使用任何外部板条箱,因此您可以使用find()来获取第一个非数字字符的索引。

请注意,@AlexLarionov 的答案会因溢出而恐慌,而这个则不会。

use std::str::FromStr;

fn atoi<F: FromStr>(input: &str) -> Result<F, <F as FromStr>::Err> {
    let i = input.find(|c: char| !c.is_numeric()).unwrap_or_else(|| input.len());
    input[..i].parse::<F>()
}

fn main() {
    println!("{:?}", atoi::<usize>("12/1/1")); // Prints `Ok(12)`
    println!("{:?}", atoi::<usize>("33"));     // Prints `Ok(33)`
    println!("{:?}", atoi::<usize>("17abc"));  // Prints `Ok(17)`
    println!("{:?}", atoi::<usize>("abc"));    // Prints `Err(ParseIntError { kind: Empty })`
    println!("{:?}", atoi::<usize>(""));       // Prints `Err(ParseIntError { kind: Empty })`

    println!("{:?}", atoi::<usize>("123456789101112131415"));
    // Prints `Err(ParseIntError { kind: PosOverflow })`
}
Run Code Online (Sandbox Code Playgroud)