2016-01-25 14 views
5

Sto riscontrando alcuni problemi con alcune operazioni di I/O di base. In particolare, il testo "Inserisci il tuo nome" è scritto all'uscita dopo digito il mio nome e ha colpito Enter:Perché viene letto l'input prima della stampa?

use std::io; 

fn main() { 
    print!("Please enter your name: "); 

    let mut name = String::new(); 
    match io::stdin().read_line(&mut name) { 
     Ok(_) => println!(""), 
     Err(err) => println!("Could not parse input: {}", err) 
    } 

    println!("Hello, {}!", name.trim()); 
} 

ha pronunciato la seguente uscita:

Compiling chat v0.1.0 (file:///home/marcus/dev/rust/chat) 
    Running `target/debug/chat` 
marcus 
Please enter your name: 
Hello, marcus! 

Qualora il il primo "marcus" è stato inserito da me. Perché il programma non stamperà "Prego inserire il tuo nome" prima di attendere l'input?


E 'possibile "non fare nulla" se un restituito Result è Ok? Nell'esempio, Ok() significa che ho salvato l'input nel nome della variabile. È fantastico. Ma cosa faccio con Ok() => in questo caso?

risposta

7

Perché il programma non stampa "Inserisci il tuo nome" prima di attendere l'immissione?

Beh, è ​​ha. È solo che, per motivi di prestazioni, l'output standard è memorizzato nel buffer. La scrittura è stata completata, ma è stata solo la scrittura in memoria. Se vuoi che venga effettivamente visualizzato all'utente, devi attivare un flush. Questo può essere fatto sia scrivendo un ritorno a capo, o facendo in modo esplicito:

io::Write::flush(&mut io::stdout()).expect("flush failed!"); 

// If you "use" `io::Write`... 
io::stdout().flush().expect("flush failed!"); 

Inoltre, è possibile "non fare nulla" se un risultato restituito è Ok?

Sicuro. Solo ... non fare niente.

match io::stdin().read_line(&mut name) { 
    Ok(_) => { /* nothing */ }, 
    Err(err) => println!("Could not parse input: {}", err) 
}  

Il requisito rilevante qui è che tutti i bracci in una match devono avere lo stesso tipo di risultato.Nel caso di println!, risulta (); oltre a un blocco vuoto (o un'altra funzione che restituisce ()), si può semplicemente utilizzare un letterale:

match io::stdin().read_line(&mut name) { 
    Ok(_) =>(), 
    Err(err) => println!("Could not parse input: {}", err) 
} 
+1

Dovresti probabilmente menzionare 'if let Err (err) = io :: stdin(). Read_line (& mut name) {println! (" Impossibile analizzare l'input: {} ", err); } '. – Veedrac

11

Questo è spiegato su documentation per print!. Dal momento che print! non emette una nuova riga e lo stdout è in modalità line buffer, non si vedrà alcun output. È possibile stdout filo manualmente:

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

print!("Please enter your name: "); 
io::stdout().flush(); 

riguarda la seconda domanda si può sempre tornare unità esplicitamente:

Ok(_) =>(), 

Così il vostro programma diventa:

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

fn main() { 
    print!("Please enter your name: "); 
    io::stdout().flush(); 

    let mut name = String::new(); 
    match io::stdin().read_line(&mut name) { 
     Ok(_) =>(), 
     Err(err) => println!("Could not parse input: {}", err) 
    } 

    println!("Hello, {}!", name.trim()); 
} 

Come @Veedrac sottolineato nella loro (ora eliminato) commento, è possibile utilizzare uno if let expression al posto di match sul risultato di read_line:

if let Err(err) = io::stdin().read_line(&mut name) { 
    println!("Could not parse input: {}", err) 
} 
+0

Ah, in realtà avevo provato, ma avuto qualche errore perché non ha riconosciuto il '.flush() 'funzione. Si scopre che avevo perso l'ultima parte 'uso std :: io :: {self, Write};'. Ti piacerebbe elaborare cosa significa '{self, Write}'? Non riesco a trovarlo nella documentazione – mnordber

Problemi correlati