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?


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).


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.


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!");

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”.


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);

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 .


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.