我如何读取具有任意分离器的通用类型的向量和所有可能流的可选限制



我想编写一个函数 read_vector,该函数应该从stdin中读取和解析T类型的项目,然后返回包含这些项目的向量。如果定界符是'n',则应分析行,否则所有项目都应在一个分界符分隔的一行中。如果计数不是None,则表示要读取的项目数。

目标是最大程度地减少代码解复功能并创建一个常规函数,而无需限制类型或其他任何内容。

但是,我遇到了一个我根本无法理解的问题。此代码:

use std::io::{self, BufRead};
fn read_line() -> String {
    let mut buf = String::new();
    io::stdin()
        .read_line(&mut buf)
        .expect("failed to read a line");
    buf
}
fn parse_iter<'a, Iter, Value>(mut iter: Iter) -> Vec<Value>
where
    Iter: std::iter::Iterator<Item = &'a str>,
    Value: std::str::FromStr,
    <Value as std::str::FromStr>::Err: std::fmt::Debug,
{
    iter.map(|x| x.parse().expect("failed to parse")).collect()
}
fn read_vector<T>(count: Option<usize>, delimiter: char) -> Vec<T>
where
    T: std::str::FromStr,
    <T as std::str::FromStr>::Err: std::fmt::Debug,
{
    match count {
        None => match delimiter {
            'n' => parse_iter(io::stdin().lock().lines().map(|x| x.unwrap())),
            _ => parse_iter(read_line().split(delimiter)),
        },
        _ => match delimiter {
            'n' => parse_iter(
                io::stdin()
                    .lock()
                    .lines()
                    .map(|x| x.unwrap())
                    .take(count.unwrap()),
            ),
            _ => parse_iter(read_line().split(delimiter).take(count.unwrap())),
        },
    }
}
fn main() {
    let vector: Vec<u32> = read_vector(None, 'n');
}

导致这些错误:

error[E0271]: type mismatch resolving `<[closure@src/main.rs:27:63: 27:77] as std::ops::FnOnce<(std::result::Result<std::string::String, std::io::Error>,)>>::Output == &str`
  --> src/main.rs:27:21
   |
27 |             'n' => parse_iter(io::stdin().lock().lines().map(|x| x.unwrap())),
   |                     ^^^^^^^^^^ expected struct `std::string::String`, found &str
   |
   = note: expected type `std::string::String`
              found type `&str`
   = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Map<std::io::Lines<std::io::StdinLock<'_>>, [closure@src/main.rs:27:63: 27:77]>`
   = note: required by `parse_iter`
error[E0271]: type mismatch resolving `<[closure@src/main.rs:35:26: 35:40] as std::ops::FnOnce<(std::result::Result<std::string::String, std::io::Error>,)>>::Output == &str`
  --> src/main.rs:31:21
   |
31 |             'n' => parse_iter(
   |                     ^^^^^^^^^^ expected struct `std::string::String`, found &str
   |
   = note: expected type `std::string::String`
              found type `&str`
   = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Map<std::io::Lines<std::io::StdinLock<'_>>, [closure@src/main.rs:35:26: 35:40]>`
   = note: required by `parse_iter`

我该如何解决问题?

很高兴看到问题的解决方案,而且还建议有关如何改善当前实施的建议,因为它仍然包含许多代码重复,并且仅与stdin一起使用而不是所有可能的流。

<</p>

我想出了这个解决方案:

use std::io::{self, BufRead};

fn read_line<T>(mut stream: T) -> String
where
    T: BufRead,
{
    let mut buf = String::new();
    stream.read_line(&mut buf).expect("failed to read a line");
    buf
}

fn read_line_from_stdin() -> String {
    let stdin = io::stdin();
    let stdin = stdin.lock();
    read_line(stdin)
}

fn parse_slice_iter<'a, Iter, Value>(iter: Iter) -> Vec<Value>
where
    Iter: std::iter::Iterator<Item = &'a str>,
    Value: std::str::FromStr,
    <Value as std::str::FromStr>::Err: std::fmt::Debug,
{
    iter.map(|x| x.trim().parse().expect("failed to parse"))
        .collect()
}

fn parse_string_iter<'a, Iter, Value>(iter: Iter) -> Vec<Value>
where
    Iter: std::iter::Iterator<Item = String>,
    Value: std::str::FromStr,
    <Value as std::str::FromStr>::Err: std::fmt::Debug,
{
    iter.map(|x| x.parse().expect("failed to parse")).collect()
}

fn read_vector<T, S>(count: Option<usize>, delimiter: char, stream: S) -> Vec<T>
where
    T: std::str::FromStr,
    <T as std::str::FromStr>::Err: std::fmt::Debug,
    S: BufRead,
{
    match count {
        None => match delimiter {
            'n' => parse_string_iter(stream.lines().map(|x| x.unwrap())),
            _ => parse_slice_iter(read_line(stream).split(delimiter)),
        },
        _ => match delimiter {
            'n' => parse_string_iter(stream.lines().take(count.unwrap()).map(|x| x.unwrap())),
            _ => parse_slice_iter(read_line(stream).split(delimiter).take(count.unwrap())),
        },
    }
}

fn read_vector_from_stdin<T>(count: Option<usize>, delimiter: char) -> Vec<T>
where
    T: std::str::FromStr,
    <T as std::str::FromStr>::Err: std::fmt::Debug,
{
    let stdin = io::stdin();
    let stdin = stdin.lock();
    read_vector(count, delimiter, stdin)
}

由于没有模板专业和默认论点等内容,我不得不编写比C 中更多的代码,并发现自己重复了很多东西。我想看看真正的生锈程序员将如何解决问题。

最新更新