2012-11-27 20 views
31

編者按:這個問題是指在Rust 1.0之前的Rust部分,但一般的概念在Rust 1.0中仍然有效。如何讀取Rust中的用戶輸入?

我打算做一個標記器。我需要閱讀每行用戶類型,並停止閱讀,一旦用戶按下ctrl - D

我搜索了周圍,只發現one example Rust 0甚至沒有編譯。我查看了io模塊的文檔,發現read_line()功能是ReaderUtil接口的一部分,但stdin()改爲返回Reader

,我想將基本上看起來像下面的C++

vector<string> readLines() { 
    vector<string> allLines; 
    string line; 

    while (cin >> line) { 
     allLines.push_back(line); 
    } 

    return allLines; 
} 

回答

0

編者按:這個答案早拉斯特1.0。請參閱現代解決方案的其他答案。

在Rust 0.4中,使用ReaderUtil特徵訪問read_line函數。請注意,您需要將值顯式地轉換爲特徵類型,例如,reader as io::ReaderUtil

fn main() { 
     let mut allLines = ~[]; 
     let reader = io::stdin(); 

     while !reader.eof() { 
       allLines.push((reader as io::ReaderUtil).read_line()); 
     } 

     for allLines.each |line| { 
       io::println(fmt!("%s", *line)); 
     } 
} 
+1

我不認爲我很明白投魯斯特是如何工作的。 :-(它看起來與我在C/C++中習以爲常的轉換類似,當你將某些東西轉換爲特徵類型時,這意味着什麼?它是否僅僅指示編譯器讓你從特徵類型到你正在投射的東西上?(在這種情況下,它是'stdin()'返回的任何東西......) –

+0

我對Rust內部並不熟悉,但我猜是因爲類型檢查是因爲cast實際的調用方法是在運行時決定的 –

+1

hmm okay。這是我想要的解決方案,所以你的答案被接受:-)謝謝! –

1

呃......許多試驗和錯誤代碼之後,我已經找到了解決辦法。

我仍然希望看到更好的解決方案,所以我不打算接受我自己的解決方案。

下面的代碼正好打印出用戶輸入的內容。

mod tokenizer { 

pub fn read() -> ~[int] { 
    let reader = io::stdin(); 
    let mut bytes: ~[int] = ~[]; 

    loop { 
     let byte: int = reader.read_byte(); 
     if byte < 0 { 
      return bytes; 
     } 
     bytes += [byte]; 
    } 
} 

} 

fn main() { 
    let bytes: ~[int] = tokenizer::read(); 
    for bytes.each |byte| { 
     io::print(#fmt("%c", *byte as char)); 
    } 
} 
0

這是我想出了(從友善的人一些幫助在irc.mozilla的#rust IRC頻道.ORG):

use core::io::ReaderUtil; 

fn read_lines() -> ~[~str] { 
    let mut all_lines = ~[]; 

    for io::stdin().each_line |line| { 
     // each_line provides us with borrowed pointers, but we want to put 
     // them in our vector, so we need to *own* the lines 
     all_lines.push(line.to_owned()); 
    } 

    all_lines 
} 

fn main() { 
    let all_lines = read_lines(); 

    for all_lines.eachi |i, &line| { 
     io::println(fmt!("Line #%u: %s", i + 1, line)); 
    } 
} 

和證明,它的作品:)

$ rustc readlines.rs 
$ echo -en 'this\nis\na\ntest' | ./readlines 
Line #1: this 
Line #2: is 
Line #3: a 
Line #4: test 
124

鏽病的1.x(見documentation):

use std::io; 
use std::io::prelude::*; 

fn main() { 
    let stdin = io::stdin(); 
    for line in stdin.lock().lines() { 
     println!("{}", line.unwrap()); 
    } 
} 

鏽病0.10-0.12(見documentation):

use std::io; 

fn main() { 
    for line in io::stdin().lines() { 
     print!("{}", line.unwrap()); 
    } 
} 

鏽病0.9(見0.9 documentation):

use std::io; 
use std::io::buffered::BufferedReader; 

fn main() { 
    let mut reader = BufferedReader::new(io::stdin()); 
    for line in reader.lines() { 
     print(line); 
    } 
} 

鏽0.8:

use std::io; 

fn main() { 
    let lines = io::stdin().read_lines(); 
    for line in lines.iter() { 
     println(*line); 
    } 
} 

鏽0.7:

use std::io; 

fn main() { 
    let lines = io::stdin().read_lines(); 
    for lines.iter().advance |line| { 
     println(*line); 
    } 
} 
+4

關於'for'循環如何可以討論的內容,請參閱[rust on rust-dev中迭代器的未來](https://mail.mozilla.org/pipermail/rust-dev/2013-June/004364.html)在將來變得更簡單(基本上除掉'.iter()。advance')。 – robinst

+0

這實際上可以是'for io :: stdin()。each_line | line | {..}',或使用['extra :: fileinput'](http://static.rust-lang.org/doc/extra/fileinput.html):'for fileinput :: input | line | {..}' – huon

+1

生鏽的1.0.0版本(頂部)不再編譯(即使當std :: io更改爲std :: old_io時)。 :/ – weberc2

10

截至2015年4月17日從mdcox上mozilla鏽irc。

use std::io; 

fn main() { 
    let mut stdin = io::stdin(); 
    let input = &mut String::new(); 

    loop { 
     input.clear(); 
     stdin.read_line(input); 
     println!("{}", input); 
    } 
} 
+2

當我執行'stdin.read_line(input);'時,編譯器警告我這條線沒有被使用。 – yagooar

+1

@yagooar,它應該警告* result *沒有被使用,而不是行。這意味着從標準輸入讀取可能會導致錯誤,但您沒有檢查它。 – gsingh2011

2

問題是從標準輸入讀取行並返回一個向量。 On Rust 1.7:

fn readlines() -> Vec<String> { 
    use std::io::prelude::*; 
    let stdin = std::io::stdin(); 
    let v = stdin.lock().lines().map(|x| x.unwrap()).collect(); 
    v 
} 
0

我能想到的方法很少。

閱讀所有輸入到單個String

let mut input = String::new(); 
io::stdin().read_to_end(&mut input); 

讀線成Vector。當讀取一條線路失敗時,這不是panic,而是跳過那條失敗的線路。

let stdin = io::stdin(); 
let locked = stdin.lock(); 
let v: Vec<String> = locked.lines().filter_map(|line| line.ok()).collect(); 

而且如果要分析它:這樣做

讀取到的字符串之後。您可以將其解析爲實現FromIterator的其他集合。集合中的包含元素也必須實現FromStr。只要特質約束滿足你可以改變VEC任何Collection:FromIteratorCollection<T: FromStr>

let v: Vec<i32> = "4 -42 232".split_whitespace().filter_map(|w| w.parse().ok()).collect(); 

您也可以使用它在StdinLock

let vv: Vec<Vec<i32>> = locked 
    .lines() 
    .filter_map(|l| 
     l.ok().map(|s| 
      s.split_whitespace().filter_map(|word| word.parse().ok()).collect() 
     ) 
    ) 
    .collect();