2017-12-01 6 views
0

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 `<[[email protected]/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<'_>>, [[email protected]/main.rs:27:63: 27:77]>` 
    = note: required by `parse_iter` 

error[E0271]: type mismatch resolving `<[[email protected]/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<'_>>, [[email protected]/main.rs:35:26: 35:40]>` 
    = note: required by `parse_iter` 

가 어떻게이 문제를 해결할 수

?

많은 코드 반복을 포함하고 가능한 모든 스트림 대신 Stdin에서만 작동하기 때문에 현재의 구현을 향상시키는 방법에 대한 조언뿐만 아니라 문제에 대한 수정을 보는 것이 좋을 것입니다.

답변

0

내가이 솔루션을 내놓았다 : 때문에 템플릿 전문화 및 기본 인자와 같은 것들의 부재

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에서와 이상을 써야했다 발견 . 나는 진정한 녹 프로그래밍이 어떻게 문제를 해결할 수 있는지 알고 싶다.

+0

이것은 사용자의 요구 사항을 충족시키지 못합니다 : * "가능한 모든 스트림"* - 당신은'BufRead'를 구현해야합니다! – Shepmaster

+0

@Shepmaster 나는 Stdin과 비슷한 엔티티를 암시했다. (그래서 ReadBuf가 내가 지원하고 싶어하는 것 같다.) 나는 녹의 용어를 잘 사용하지 않는다. C++의 용어를 사용했다. 아마 100 % 정확하지 않을 것이다. . – StrausMG

관련 문제