Konwertować String na int w Rust?

187

Uwaga: to pytanie zawiera przestarzały kod sprzed wersji 1.0! Jednak odpowiedź jest prawidłowa.

Aby przekonwertować a strna an intw Rust, mogę to zrobić:

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

Jedyny sposób, w jaki wiem, jak przekonwertować a Stringna an, intto uzyskać jego kawałek, a następnie użyć from_strna nim w następujący sposób:

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

Czy istnieje sposób na bezpośrednią konwersję a Stringna int?

mtahmed
źródło
1
Zobacz także: stackoverflow.com/q/32381414/500207 dla niedziesiętnych (tj. Szesnastkowych).
Ahmed Fasih
2
Dość oczywiste, ale uwaga dla każdego, kto znalazł to pytanie długo po 2014 roku i zastanawiał się, dlaczego from_str nie znajduje się w zakresie, nie ma go w wstępie. use std::str::FromStr;naprawia to. Więcej informacji na temat from_str, jeśli chcesz. doc.rust-lang.org/std/str/trait.FromStr.html#tymethod.from_str
7l-l04

Odpowiedzi:

260

Możesz bezpośrednio przekonwertować na int za pomocą str::parse::<T>()metody .

let my_string = "27".to_string();  // `parse()` works with `&str` and `String`!
let my_int = my_string.parse::<i32>().unwrap();

Możesz określić typ do analizy za pomocą operatora turbofish ( ::<>), jak pokazano powyżej, lub za pomocą jawnej adnotacji typu:

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

Jak wspomniano w komentarzach, parse()zwraca plik Result. Ten wynik będzie an, Errjeśli nie można przeanalizować ciągu jako określonego typu (na przykład ciągu "peter"nie można przeanalizować jako i32).

John Vrbanac
źródło
35
Zwróć uwagę, że parsezwraca aResult , więc musisz sobie z tym odpowiednio poradzić, aby uzyskać rzeczywisty typ całkowy.
Shepmaster
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>zwraca a Result<u32, core::num::ParseIntError>i Result::unwrap„Rozpakowuje wynik, dając zawartość Okpaniki [lub], jeśli wartością jest an Err, z komunikatem paniki dostarczonym przez wartość Err's."

str::parsejest funkcją ogólną , stąd typ w nawiasach ostrych.

Jared Beck
źródło
9
Jeśli określisz typ zmiennej ( let my_u8: u8), nie potrzebujesz wartości w nawiasach ostrych. Zwróć również uwagę, że dominujący styl Rust wskazuje, że :powinien on trzymać się lewej strony.
Shepmaster
5
Konkretnie miałem na myślilet my_u32: u32 = "42".parse().unwrap()
Shepmaster
9

Jeśli otrzymujesz swój ciąg z stdin().read_line, musisz go najpierw przyciąć.

let my_num: i32 = my_num.trim().parse()
   .expect("please give me correct string number!");
Ade Yahya
źródło
6

Korzystając z ostatniej nocy, możesz to zrobić:

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

To, co się tutaj dzieje, to to, że Stringmożna teraz dereferencjonować do str. Jednak funkcja wymaga &str, więc musimy ponownie pożyczyć. Dla porównania uważam, że ten konkretny wzorzec ( &*) jest nazywany „pożyczaniem krzyżowym”.

DK.
źródło
Okay, nie jestem w nightlies, ale zaakceptuję to jako odpowiedź, ponieważ Stringw pewnym momencie próbowałem wyłuskać a i miałem nadzieję, że zadziała.
mtahmed
2
Alternatywnie możesz wyrazić my_sttring.as_slice()jako my_string[](obecnie slicing_syntaxjest ograniczony funkcjami, ale najprawdopodobniej jakaś jego forma skończy się w języku).
tempestadept
2

Możesz użyć FromStrcechyfrom_str , która jest zaimplementowana dla i32:

let my_num = i32::from_str("9").unwrap_or(0);
Karthik Cherukuri
źródło
0

Więc nie. Dlaczego miałoby być? Po prostu wyrzuć ciąg, jeśli już go nie potrzebujesz.

&strjest bardziej przydatny niż Stringwtedy, gdy trzeba tylko odczytać ciąg, ponieważ jest to tylko wgląd do oryginalnej części danych, a nie ich właściciel. Możesz go łatwiej przekazać niż Stringi jest kopiowalny, więc nie jest używany przez wywoływane metody. W tym względzie jest bardziej ogólny: jeśli masz a String, możesz przekazać go tam, gdzie &strjest oczekiwane, ale jeśli masz &str, możesz przekazać go tylko do funkcji oczekujących, Stringjeśli dokonasz nowego przydziału.

Więcej informacji na temat różnic między tymi dwoma i kiedy ich używać można znaleźć w oficjalnym przewodniku po strunach .

Vladimir Matveev
źródło
Cóż, oczywistym powodem, dla którego „powinno być”, moim zdaniem, jest to, że nie musiałbym robić za .as_slice()każdym razem, gdy muszę to zrobić from_strna String. Na przykład argumenty wiersza poleceń to jedno miejsce, w którym muszę zrobić from_strna wszystkich argumentach, aby zinterpretować je jako ints itp.
mtahmed
as_slice()jest tylko pomniejszym aspektem obsługi ciągów. Na przykład możesz użyć składni wycinania ( s[]) lub wykorzystać Derefcoercion ( &*s). Jest nawet propozycja, która pozwoliłaby po prostu pisać&s .
Vladimir Matveev
Oooo! Co by to było&s zrobił dla sznurka? Czy to odwdzięczy się str? Czy możesz wskazać mi propozycję?
mtahmed
1
Po pierwsze, strnie jest tym, z czym pracujesz; to jest &str. Są różne (ale powiązane). Pierwszy z nich to typ o dynamicznej wielkości, którego prawie nigdy nie używałbyś bezpośrednio, podczas gdy drugi to kawałek struny, który jest wskaźnikiem tłuszczu. Propozycja ta nazywa się przymusem deref ; pozwoliłoby wymusić od &Tdo &Ujeśli T: Deref<U>. Ponieważ String: Deref<str>już będziesz w stanie uzyskać &strod Stringz tylko &. Nadal toczy się dyskusja, ale wątpię, że stanie się to przed 1.0 - zostało za mało czasu.
Vladimir Matveev
-1

Więc zasadniczo chcesz przekonwertować String na liczbę całkowitą, prawda! tutaj jest to, czego najczęściej używam i jest to również wspomniane w oficjalnej dokumentacji.

fn main() {

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

}

Działa to zarówno dla String, jak i & str. Mam nadzieję, że to też pomoże.

Taimoor
źródło