将一串数字转换为Rust中的int/Array数组

Dav*_*ias 10 arrays string converter rust

我在STDIN上写了一串数字(例如"4 10 30 232312"),我想读取并转换为Rust中的int(或向量)数组,找不到正确的方法,到目前为止我有:

use std::io;

fn main() {
    let mut reader = io::stdin();
    let numbers = reader.read_line().unwrap();
}
Run Code Online (Sandbox Code Playgroud)

先感谢您

Vla*_*eev 13

针对Rust 1.x进行了更新

你可以这样做:

use std::io::{self, BufRead};                   // (a)

fn main() {
    let reader = io::stdin();
    let numbers: Vec<i32> = 
        reader.lock()                           // (0)
              .lines().next().unwrap().unwrap() // (1)
              .split(' ').map(|s| s.trim())     // (2)
              .filter(|s| !s.is_empty())        // (3)
              .map(|s| s.parse().unwrap())      // (4)
              .collect();                       // (5)
    println!("{:?}", numbers);
}
Run Code Online (Sandbox Code Playgroud)

首先,我们获取stdin的锁定,它允许你使用stdin作为缓冲读取器(默认情况下,Rust中的stdin是无缓冲的;你需要调用lock()它上面的方法来获取它的缓冲版本,但这个缓冲版本只有一个对于程序中的所有线程,因此应该同步对它的访问.

接下来,我们阅读下一行(1); 我正在使用lines()next()方法返回的迭代器Option<io::Result<String>>,因此只String需要获得unwrap()两次.

然后我们用空格分割它并从额外的空格中修剪得到的块(2),删除修剪后留下的空块(3),将字符串转换为i32s(4)并将结果收集到向量(5).

我们还需要导入std::io::BufReadtrait(a)才能使用lines()方法.

如果您事先知道您的输入在数字之间不会包含多个空格,则可以省略步骤(3)并将trim()呼叫从(2)移动到(1):

let numbers: Vec<i32> = 
    reader.lock()
          .lines().next().unwrap().unwrap()
          .trim().split(' ')
          .map(|s| s.parse().unwrap())
          .collect();
Run Code Online (Sandbox Code Playgroud)

更新

但是,Rust已经提供了一种方法来将字符串拆分为由空格分隔的单词序列,称为split_whitespace():

let numbers: Vec<i32> =
    reader.read_line().unwrap().as_slice()
        .split_whitespace()
        .map(|s| s.parse().unwrap())
        .collect()
Run Code Online (Sandbox Code Playgroud)

split_whitespace()事实上只是split()filter()我的原始例子中的组合.它在split()参数中使用一个函数,但它检查不同类型的空格,而不仅仅是空格字符.你可以在这里找到它的来源.

  • 你也可以使用[`.words()`](http://doc.rust-lang.org/nightly/std/str/trait.UnicodeStrSlice.html#tymethod.words)(稍微不仅仅是空格,虽然). (4认同)

Dav*_*ias 12

在Rust 1.5.x上,一个可行的解决方案是:

fn main() {    
    let mut numbers = String::new();

    io::stdin().read_line(&mut numbers).ok().expect("read error");

    let numbers: Vec<i32> = numbers
        .split_whitespace()
        .map(|s| s.parse().unwrap())
        .collect();

    for num in numbers {
        println!("{}", num);
    }
}
Run Code Online (Sandbox Code Playgroud)


Dul*_*gon 8

更安全的版本。这个会跳过失败的解析,这样失败的解包就不会恐慌。使用read_line读取一行。

let mut buf = String::new();

// use read_line for reading single line 
std::io::stdin().read_to_string(&mut buf).expect("");

// this one skips failed parses so that failed unwrap doesn't panic
let v: Vec<i32> = buf
    .split_whitespace() // split string into words by whitespace
    .filter_map(|w| w.parse().ok()) // calling ok() turns Result to Option so that filter_map can discard None values
    .collect(); // collect items into Vector. This determined by type annotation.
Run Code Online (Sandbox Code Playgroud)

您甚至可以像这样阅读 Vector of Vectors。

let stdin = io::stdin();
let locked = stdin.lock();
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();
Run Code Online (Sandbox Code Playgroud)

上面的一个适用于像这样的输入

2 424 -42 124
42 242 23 22 241
24 12 3 232 445
Run Code Online (Sandbox Code Playgroud)

然后把它们变成

[[2, 424, -42, 124],
[42, 242, 23, 22, 241],
[24, 12, 3, 232, 445]]
Run Code Online (Sandbox Code Playgroud)

filter_map接受一个返回Option<T>并过滤掉所有Nones的闭包。

ok()轮流Result<R,E>Option<R>所以在这种情况下被过滤的错误。