如何在不消耗迭代器 int rust 的情况下获取元素(在 rust 中重写 strtol 的问题)

how to get element without consuming iterator int rust(problem with rewriting strtol in rust)

我在 Rust 中实现 strtol 是这样的:

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
}

问题是在运行strtol之后,迭代器指向数字后的第二个字符,它应该指向数字后的第一个字符。 例如,如果输入“1234abc”,在调用 strtol 之后,迭代器指向 b 应该是 a.

您的代码失败是因为您查看 chars.next 以查看它是否是有效数字,如果不是则停止。正如您所观察到的,这意味着第一个非数字将被消耗。要解决此问题,您可以传入 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
}

Playground link

你不能,真的,因为那不是 Iterator 的工作方式。

你可能需要一个 Peekable,它可以让你 peek() 迭代器而不消耗该项目,但我认为仅此而已:AFAIK 而 Rust 有 DoubleEndedIterator 让你从后面迭代,它没有 双向 迭代器(让你向后移动/调整迭代器),至少我不知道。

虽然我也不确定你为什么要输入 Chars,但为什么不呢,例如拿一个 &str 并让 strtol return 提取数字的元组和“其余”作为切片?这看起来更像 Rust。

顺便说一下,您的 loop 可以通过使用 while let:

来简化

while let Some(c) = chars.next()
    match c.to_digit(10) {
        Some(i) => result = result * 10 + i64::from(i),
        None => break,
    }
}