It depends on what your definition of "better". If you simply want to remove the needless String creation, then you can use atoi crate.
Alternatively, you can also use the nom crate, and use digit0() to create your own atoi() function:
// 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 })`
}
The unwrap() is safe, as if there are no digits then Ok is still returned, and the empty string is handled by parse().
Since you don't want to use any external crates, then instead you can use find() to get the index of the first non-numeric character.
Note that, @AlexLarionov's answer panics on overflow, while this one does not.
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 })`
}