2016-03-08 17 views
6

Supponiamo che mi aspetto una riga con 3 numeri interi da stdin. Qual è il modo più semplice per leggerli e analizzarli? Qual è l'equivalente di ruggine di a, b, c = map(int, input().split()) in Python o scanf("%d %d %d", &a, &b, &c); in C?Qual è il modo più semplice per leggere diversi ints da stdin se è ok fallire?

Il modo migliore mi è venuta era qualcosa di simile:

let mut line = String::new(); 
io::stdin().read_line(&mut line).unwrap(); 
let parts: Vec<&str> = line.split_whitespace().collect(); 
let a: i32 = parts[0].parse().unwrap(); 
let b: i32 = parts[1].parse().unwrap(); 
let c: i32 = parts[2].parse().unwrap(); 

C'è un modo più semplice?

risposta

6

È possibile utilizzare text_io per questo:

#[macro_use] extern crate text_io; 

fn main() { 
    // reads until a whitespace is encountered 
    let a: i32 = read!(); 
    let b: i32 = read!(); 
    let c: i32 = read!(); 
} 

text_io0.1.3 supporta anche una scan! macro:

let (a, b, c): (i32, i32, i32); 
scan!("{}, {}, {}\n", a, b, c); 

nel caso in cui si desidera leggere da un file o un po 'di altra fonte, puoi anche usare entrambe le macro su qualsiasi tipo che implementa Iterator<Item=u8>:

use std::io::Read; 
let mut file = std::fs::File::open("text.txt").unwrap() 
               .bytes() 
               .map(Result::unwrap); 
let x: i32 = read!("{}\n", file); 

o

let (x, y, z): (i32, i32, i32); 
scan!(file => "{}, {}: {}", x, y, z); 

Puoi lasciare fuori le : i32 s se il compilatore può dedurre da questi tipi contesto.

Disclaimer: Sono l'autore di text_io.

+0

scusa per il ripping del tuo secondo esempio, ma hai iniziato questo;) –

9

È possibile utilizzare scan-rules per questo:

/*! 
Add this to your `Cargo.toml`, or just run with `cargo script`: 

```cargo 
[dependencies] 
scan-rules = "0.1.1" 
``` 
*/ 
#[macro_use] extern crate scan_rules; 

fn main() { 
    print!("Enter 3 ints: "); 
    readln! { 
     (let a: i32, let b: i32, let c: i32) => { 
      println!("a, b, c: {}, {}, {}", a, b, c); 
     } 
    } 
} 

Se si vuole fare qualcosa di un po 'più coinvolti, è possibile utilizzare più regole e inferenza di tipo, e specificare cosa fare se l'ingresso non corrisponde una delle regole date (di default panic! s):

readln! { 
     // Space-separated ints 
     (let a: i32, let b: i32, let c: i32) => { 
      println!("a b c: {} {} {}", a, b, c); 
     }, 

     // Comma-separated ints, using inference. 
     (let a, ",", let b, ",", let c) => { 
      let a: i32 = a; 
      let b: i32 = b; 
      let c: i32 = c; 
      println!("a, b, c: {}, {}, {}", a, b, c); 
     }, 

     // Comma-separated list of *between* 1 and 3 integers. 
     ([let ns: i32],{1,3}) => { 
      println!("ns: {:?}", ns); 
     }, 

     // Fallback if none of the above match. 
     (..line) => { 
      println!("Invalid input: {:?}", line); 
     } 
    } 

Diniego: io sono l'autore di scan-rules.

+0

scusa per il ripping del tuo testo 1: 1, ma è semplicemente perfetto;) –

+0

Wow! Questa è una potente magia di macro_rules che hai lì. –

Problemi correlati