将一个字符串转换为整数?

472

注意:这个问题包含过时的1.0版本前的代码!答案是正确的。

在 Rust 中,将一个 str 转换成 int,我可以这样做:

let my_int = from_str::<int>(my_str);

我知道将 String 转换为 int 的唯一方法是获取其切片,然后像这样使用 from_str

let my_int = from_str::<int>(my_string.as_slice());

有没有一种方法可以直接将String转换为int


1
参见:https://dev59.com/x1wY5IYBdhLWcg3wpJE-,用于非十进制(即十六进制)的情况。 - Ahmed Fasih
7
如果您在2014年之后查看此问题,并想知道为什么 from_str 不在作用域内,那么需要注意的是它不在预导入中。使用 use std::str::FromStr; 可以解决这个问题。如果您想了解更多关于 from_str 的内容,请参考https://doc.rust-lang.org/std/str/trait.FromStr.html#tymethod.from_str。 - cryptograthor
8个回答

649
你可以使用 str::parse::<T>() 方法直接将其转换为 int,该方法会返回包含 int 的 Result
let my_string = "27".to_string();  // `parse()` works with `&str` and `String`!
let my_int = my_string.parse::<i32>().unwrap();

您可以通过如上所示的turbofish运算符(::<>)指定要解析为的类型,也可以通过显式类型注释来指定:

let my_int: i32 = my_string.parse().unwrap();

由于 parse() 返回一个 Result,所以如果字符串不能被解析为指定的类型(例如,字符串 "peter" 无法被解析为 i32),它将返回一个 Err,否则将返回带有该值的 Ok


2
如果您已经知道如何处理结果,这将非常有帮助。我建议扩展答案以适应任何不了解的人。 - Josh Vander Hook
20
“_turbofish operator_”?这个名字很酷。以前从来没听说过 :) - Saeed Ahadian
https://turbo.fish/ - user1068352
@SaeedAhadian 这真的是这个东西的名称:https://doc.rust-lang.org/reference/glossary.html?highlight=turbo#turbofish - undefined

127
let my_u8: u8 = "42".parse().unwrap();
let my_u32: u32 = "42".parse().unwrap();

// or, to be safe, match the `Err`
match "foobar".parse::<i32>() {
  Ok(n) => do_something_with(n),
  Err(e) => weep_and_moan(),
}

str::parse::<u32>返回一个Result<u32, core::num::ParseIntError>类型的值,Result::unwrap方法可以“展开”这个返回值,并提取其中的Ok值,如果是Err则会报错,并且错误信息由Err的值提供。

str::parse是一个泛型函数,因此在尖括号中指定了具体的类型。


55

如果您从stdin().read_line获取字符串,则需要首先进行修剪。

let my_num: i32 = my_num.trim().parse()
   .expect("please give me correct string number!");

6
非常重要的细节! - Marco Antonio
你能解释一下为什么吗? - DataBach
1
好的,在rust-book.cs.brown.edu上找到答案。String实例上的trim方法将消除任何开头和结尾处的空白,我们必须这样做才能将字符串与i32进行比较,因为i32只能包含数值数据。用户必须按回车键来满足read_line,并输入他们的猜测,这将在字符串中添加一个换行符。 - DataBach

16

最近的夜间版本中,您可以这样做:

let my_int = from_str::<int>(&*my_string);

这里发生的情况是,String 现在可以转换为 str。但是函数需要一个 &str,所以我们必须再次进行借用。参考一下,我相信这个特定的模式(&*)被称为“交叉借用”。


好的,我现在不在夜间版本上,但我会接受这个答案,因为我曾经尝试过对一个String进行解引用并希望它能正常工作。 - mmtauqir
2
另外,您可以将my_string.as_slice()表达为my_string[](目前slicing_syntax是特征门控的,但最有可能某种形式会出现在该语言中)。 - tempestadept

9
您可以使用 i32 实现的 FromStr 特质中的 from_str 方法。
let my_num = i32::from_str("9").unwrap_or(0);

8

是的,您可以使用parse方法将一个字符串直接转换为整数,例如:

let my_string = "42".to_string();
let my_int = my_string.parse::<i32>().unwrap();

parse方法返回一个Result对象,因此您需要处理无法将字符串解析为整数的情况。您可以像上面展示的那样使用unwrap来获取值(如果解析成功),或者如果解析失败,它将会panic。

或者您可以使用match表达式分别处理成功和失败的情况,如下所示:

let my_string = "42".to_string();
let my_int = match my_string.parse::<i32>() {
    Ok(n) => n,
    Err(_) => {
        println!("Failed to parse integer");
        0
    },
};

需要注意的是,parse方法适用于任何实现FromStr trait的类型,它包括所有整数类型(例如i32、i64等)以及许多其他类型,例如f32和bool。


2

不需要。如果您不再需要字符串,请将其丢弃。

当您仅需要读取字符串时,&strString更有用,因为它只是原始数据的视图,而不是所有者。您可以更轻松地传递它而不会被调用的方法消耗掉。在这方面,它更加通用:如果您有一个String,则可以将其传递到期望&str的位置,但是如果您有&str,则只能将其传递给期望String的函数,如果您进行新的分配。

您可以在官方字符串指南中了解有关这两者之间差异和何时使用它们的更多信息。


在我看来,「应该有」的一个明显原因是,我不需要每次都使用.as_slice()来进行from_str操作。例如,命令行参数是一个需要将所有参数解释为整数等类型的地方,我就需要使用from_str函数。 - mmtauqir
as_slice()只是字符串处理的一个小方面。例如,您可以使用切片语法(s[])或利用Deref强制转换(&*s)。甚至有一个提案允许仅编写&s - Vladimir Matveev
哦!&s对于字符串会做什么?它会返回一个str吗?你能指向提案的位置吗? - mmtauqir
1
首先,你所使用的不是 str,而是 &str。它们虽然相关但却不同。前者是一种动态大小的类型,你几乎不会直接使用它,而后者是一个字符串切片,是一个胖指针。该提案称为 deref coercions;如果 T: Deref<U>,它将允许从 &T 强制转换为 &U。由于 String: Deref<str>,因此你只需使用 & 就可以从 String 中获取 &str。这仍在讨论中,但我怀疑在 1.0 版本之前不会发生 - 剩下的时间太少了。 - Vladimir Matveev

0

所以基本上你想把一个字符串转换成整数是吧!这是我大部分使用的方法,它也在官方文档中提到了...

fn main() {

    let char = "23";
    let char : i32 = char.trim().parse().unwrap();
    println!("{}", char + 1);

}

这适用于 String 和 &str 两种类型。希望这也能有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接