Преобразовать строку в int в Rust?

187

Примечание: этот вопрос содержит устаревший код до 1.0! Ответ правильный, хотя.

Чтобы преобразовать strв intв Русте, я могу это сделать:

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

Единственный способ, которым я знаю, как преобразовать a Stringв a, intсостоит в том, чтобы получить его часть, а затем использовать from_strего следующим образом:

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

Есть ли способ напрямую преобразовать Stringв int?

mtahmed
источник
1
См. Также: stackoverflow.com/q/32381414/500207 для недесятичной (то есть шестнадцатеричной).
Ахмед Фасих
2
Несколько очевидно, но замечание для любого, кто найдет этот вопрос намного позже 2014 года и задается вопросом, почему from_str не входит в сферу применения, он не входит в прелюдию. use std::str::FromStr;исправляет это. Больше на from_str, если хотите. doc.rust-lang.org/std/str/trait.FromStr.html#tymethod.from_str
7-1104

Ответы:

261

Вы можете напрямую конвертировать в int, используя str::parse::<T>()метод .

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. Этот результат будет, Errесли строка не может быть проанализирована как указанный тип (например, строка "peter"не может быть проанализирована как i32).

Джон Врбанак
источник
35
Обратите внимание, что parseвозвращает aResult , поэтому вам нужно соответствующим образом разобраться с этим, чтобы получить фактический целочисленный тип.
Шепмастер
54
let my_u8: u8 = "42".parse::<u8>().unwrap();
let my_u32: u32 = "42".parse::<u32>().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>возвращает a Result<u32, core::num::ParseIntError>и Result::unwrap«разворачивает результат, получая содержимое Okпаники [или], если значение равно Err, с сообщением паники, предоставленным Errзначением s».

str::parseявляется универсальной функцией , поэтому тип в угловых скобках.

Джаред Бек
источник
9
Если вы укажете тип переменной ( let my_u8: u8), вам не понадобится значение в угловых скобках. Также обратите внимание, что преобладающий стиль Rust указывает на то, что :следует придерживаться левой стороны.
Шепмастер
5
В частности, я имел в видуlet my_u32: u32 = "42".parse().unwrap()
Шепмастер
9

Если вы получили свою строку stdin().read_line, вы должны сначала обрезать ее.

let my_num: i32 = my_num.trim().parse()
   .expect("please give me correct string number!");
Адэ Яхья
источник
6

С недавнего вечера вы можете сделать это:

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

То, что происходит здесь, Stringтеперь может быть разыменовано в str. Тем не менее, функция хочет &str, поэтому мы должны снова позаимствовать. Для справки, я считаю, что этот конкретный шаблон ( &*) называется «перекрестное заимствование».

DK.
источник
Хорошо, я не на ночных вечерах, но я приму это как ответ, так как я действительно пытался разыменовать a Stringв одном месте и надеялся, что это сработает.
mtahmed
2
В качестве альтернативы, вы можете выразить my_sttring.as_slice()как my_string[](в настоящее время slicing_syntaxэто функциональный, но, скорее всего, какая-то его форма окажется в языке).
tempestadept
2

Вы можете использовать метод FromStrчерты from_str, который реализован для i32:

let my_num = i32::from_str("9").unwrap_or(0);
Картик Черукури
источник
0

Ну нет. Почему там должно быть? Просто отбросьте строку, если она вам больше не нужна.

&strэто более полезно, чем Stringкогда вам нужно только прочитать строку, потому что это только просмотр исходного фрагмента данных, а не его владельца. Вы можете передать его более легко, чем String, и он может быть скопирован, поэтому он не используется вызываемыми методами. В этом отношении он является более общим: если у вас есть String, вы можете передать его туда, где &strожидается, но если у вас есть &str, вы можете передать его только функциям, ожидающим, Stringесли вы сделаете новое распределение.

Вы можете найти больше информации о различиях между ними и о том, когда их использовать, в официальном руководстве по строкам .

Владимир Матвеев
источник
Ну, очевидная причина того, почему «должно быть», на мой взгляд, заключается в том, что мне не нужно было бы делать .as_slice()каждый раз, когда мне нужно делать from_strсо строкой. Например, аргументы командной строки - это единственное место, где мне нужно сделать from_strвсе аргументы, чтобы интерпретировать их как ints и т. Д.
mtahmed
as_slice()это только второстепенный аспект обработки строк. Например, вы можете использовать синтаксис нарезки ( s[]) или использовать Derefcoercion ( &*s). Есть даже предложение, которое позволило бы написать просто &s.
Владимир Матвеев
Оооо! Что бы &sсделать для строки? Это даст strназад? Не могли бы вы указать мне на предложение?
mtahmed
1
Прежде всего, strэто не то, с чем вы работаете; это так &str. Они разные (но связанные). Первый тип представляет собой динамически изменяемый тип, который вы почти никогда не будете использовать напрямую, а второй - фрагмент строки, который является толстым указателем. Предложение называется deref принуждения ; это позволило бы привести &Tк &Uесли T: Deref<U>. Поскольку String: Deref<str>уже вы сможете получить &strс Stringпомощью только что &. Это все еще обсуждается, но я сомневаюсь, что это произойдет до 1.0 - осталось слишком мало времени.
Владимир Матвеев
-1

Таким образом, в основном вы хотите преобразовать строку в целое число правильно! вот что я в основном использую, и это также упоминается в официальной документации ..

fn main() {

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

}

Это работает как для String, так и & str. Надеюсь, это тоже поможет.

Taimoor
источник