【问题标题】:how to get element without consuming iterator int rust(problem with rewriting strtol in rust)如何在不消耗迭代器 int rust 的情况下获取元素(在 rust 中重写 strtol 的问题)
【发布时间】:2021-05-08 16:42:13
【问题描述】:

我在 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

【问题讨论】:

    标签: rust iterator strtol


    【解决方案1】:

    您的代码失败,因为您查看 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

    【讨论】:

    • Peekable 正是我想要的。非常感谢!
    【解决方案2】:

    你不能,真的,因为Iterator 不是这样工作的。

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

    虽然我也不确定您为什么要输入Chars,但为什么不输入?取一个&amp;str 并让strtol 返回一个提取数字的元组,并将“其余”作为切片返回?这似乎更像 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,
        }
    }
    

    【讨论】:

    • Peekable 可以解决我的问题。非常感谢。也感谢'while let'。 “为什么不例如取一个 &str 并让 strtol 返回一个提取数字的元组,并将“其余”作为一个切片返回?” Slice 很好,但我想实现一个基于指针的函数。只是个人喜好。
    猜你喜欢
    • 2017-09-10
    • 2020-09-02
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    相关资源
    最近更新 更多