I implement strtol
in Rust like this:
fn strtol(chars: &mut Chars<'_>) -> i64 {
let mut result: i64 = 0;
loop {
match chars.next() {
Some(c) => {
match c.to_digit(10) {
Some(i) => result = result * 10 + i64::from(i),
None => break,
}
},
None => break,
}
}
result
}
the problem is that after runing strtol
, the iterator point to the second character after number digit, which should point at the first character after number digit.
For example, if input "1234abc", after calling strtol
, iterator point to b
which should be a
.
Your code fails because you look at chars.next
to see if it's a valid digit or not then stops if it isn't. This means that the first non-digit will be consumed, as you observed. To fix this, you can pass in a Peekable
:
use std::iter::Peekable;
fn strtol<I: Iterator<Item = char>>(chars: &mut Peekable<I>) -> i64 {
let mut result: i64 = 0;
loop {
// first peek the element here
match chars.peek() {
Some(c) => match c.to_digit(10) {
Some(i) => result = result * 10 + i64::from(i),
None => break,
},
None => break,
}
// at this point we know it's a digit so we consume it
chars.next();
}
result
}
fn main() {
let test = "1234abcd";
let mut iter = test.chars().peekable();
println!("{}", strtol(&mut iter)); // 1234
println!("{}", iter.collect::<String>()); // abcd
}