Der Fragezeichen-Operator '?'
Teil des Abschnitts Logic & Flow der Rust-Journey von Coddy — Lektion 46 von 66.
Wenn Sie mit Funktionen arbeiten, die Result zurückgeben, müssen Sie Fehler oft handhaben, indem Sie sie entweder lokal behandeln oder an die aufrufende Funktion weitergeben. Rust bietet für dieses gängige Muster einen eleganten Operator an: den Fragezeichen-Operator ?.
Der ?-Operator bietet eine saubere Möglichkeit, Fehler weiterzugeben, ohne ausführliche match-Anweisungen schreiben zu müssen. Wenn Sie ? nach einem Result platzieren, entpackt es automatisch einen Ok-Wert oder kehrt sofort mit dem Err aus der aktuellen Funktion zurück:
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
let number = s.parse::<i32>()?; // Wenn das Parsen fehlschlägt, geben Sie den Fehler zurück
Ok(number * 2) // Wenn erfolgreich, verdoppeln Sie die Zahl
}Dies entspricht dem Schreiben einer vollständigen match-Anweisung, ist aber viel prägnanter. Wenn s.parse::<i32>() ein Ok zurückgibt, extrahiert das ? den Wert und weist ihn number zu. Wenn es ein Err zurückgibt, gibt das ? diesen Fehler sofort aus der gesamten Funktion zurück.
Beachten Sie die ::<i32>-Syntax — dies wird als Turbofish bezeichnet, und es teilt Rust mit, in welchen Typ der String umgewandelt werden soll. Die Funktion gibt Result<i32, std::num::ParseIntError> zurück, wobei i32 der Erfolgstyp ist und std::num::ParseIntError der Fehlertyp ist, der zurückgegeben wird, wenn das Parsen fehlschlägt.
Der ?-Operator kann nur in Funktionen verwendet werden, die ein Result (oder Option) zurückgeben, da er in der Lage sein muss, einen Fehler zurückzugeben.
Aufgabe
EinfachSie erhalten zwei Eingaben. Die erste Eingabe ist ein String, der in eine Ganzzahl umgewandelt werden soll, und die zweite Eingabe ist ein weiterer String, der ebenfalls in eine Ganzzahl umgewandelt werden soll. Erstellen Sie eine Funktion namens add_numbers, die zwei String-Slices als Parameter entgegennimmt und ein Result<i32, std::num::ParseIntError> zurückgibt. Verwenden Sie innerhalb der Funktion den ?-Operator, um beide Strings zu parsen und deren Summe, eingepackt in Ok, zurückzugeben. Rufen Sie die Funktion mit den beiden Eingaben auf und verarbeiten Sie das Ergebnis mit match.
Anforderungen:
- Lesen Sie die erste Eingabe (erste Zahl als String) und entfernen Sie Leerzeichen (trim)
- Lesen Sie die zweite Eingabe (zweite Zahl als String) und entfernen Sie Leerzeichen (trim)
- Erstellen Sie eine Funktion
add_numbers, die zwei&str-Parameter entgegennimmt undResult<i32, std::num::ParseIntError>zurückgibt - Parsen Sie innerhalb der Funktion den ersten String mit dem
?-Operator zui32 - Parsen Sie den zweiten String mit dem
?-Operator zui32 - Geben Sie
Ok(sum)zurück, wobei sum die Addition der beiden geparsten Zahlen ist - Rufen Sie die Funktion mit den beiden Eingabestrings auf
- Verwenden Sie einen
match-Ausdruck, um dasResultzu verarbeiten - Geben Sie im
Ok(value)-Zweig Folgendes aus:Sum: [value] - Geben Sie im
Err(_)-Zweig Folgendes aus:Parsing error
Eingabe:
- Erste Zeile: Ein String, der eine Zahl darstellt (z. B.
15) - Zweite Zeile: Ein String, der eine weitere Zahl darstellt (z. B.
27)
Ausgabe:
- Wenn beide Strings gültige Zahlen sind:
Sum: [result] - Wenn einer der Strings nicht geparst werden kann:
Parsing error
Probier es selbst
use std::io;
// TODO: Erstelle hier die Funktion add_numbers
// Sie sollte zwei &str-Parameter entgegennehmen und Result<i32, std::num::ParseIntError> zurückgeben
fn main() {
// Erste Eingabe lesen
let mut input1 = String::new();
io::stdin().read_line(&mut input1).expect("Failed to read line");
let input1 = input1.trim();
// Zweite Eingabe lesen
let mut input2 = String::new();
io::stdin().read_line(&mut input2).expect("Failed to read line");
let input2 = input2.trim();
// TODO: Rufe add_numbers mit input1 und input2 auf
// TODO: Verwende match, um das Result zu verarbeiten
// Gib "Sum: [value]" für Ok(value) aus
// Gib "Parsing error" für Err(_) aus
}Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Logic & Flow
1Fortgeschrittener Kontrollfluss
Der 'match'-AusdruckAbgleichen mehrerer WerteBereiche abgleichenDer 'if let'-AusdruckSchleifen als AusdrückeRückblick – Einfacher Befehls-Parser4Daten gruppieren mit Structs
Was ist ein Struct?Übersicht über StructsZugriff auf Struct-FelderVeränderbare StructsStructs als FunktionsparameterTupel-StructsZusammenfassung – Ein Buch-Struct erstellen7Fehlerbehandlung mit 'Result'
Was ist ein 'Result'?'match' mit 'Result' verwendenis_ok() und is_err()Abkürzungen: unwrap und expectDer Fragezeichen-Operator '?'Strings in Zahlen parsenZusammenfassung – Sichere Divisionsfunktion2Einführung in Vektoren
Was ist ein Vektor?Einen Vektor erstellenElemente mit push hinzufügenZugriff auf Vektor-ElementeÜber einen Vektor iterierenVeränderliche IterationElemente entfernenZusammenfassung – Einfacher Score-Tracker5Schlüssel-Wert-Paare mit Hash Maps
Was ist eine Hash Map?Erstellen einer Hash MapEinfügen von Schlüssel-Wert-PaarenZugreifen auf WerteIterieren über eine Hash MapAktualisieren eines WertesEntfernen eines PaaresZusammenfassung – Wortzähler8Projekt: Einfaches Artikelinventar
Projekt-SetupEinen Artikel hinzufügenLagerbestand prüfenEinen Artikel verkaufenAlles zusammenfügen11Abschluss-Herausforderungen
Wiederholung - Einzigartige ElementeWiederholung - Benutzerprofil-ValidatorWiederholung - Noten-Zusammenfassung3Kommandozeilen-To-Do-Liste
Projekt-SetupEine Aufgabe hinzufügenAlle Aufgaben anzeigenEine Aufgabe entfernenFinaler Code