Der Fragezeichen-Operator '?'
Teil des Abschnitts Logic & Flow der Rust-Journey von Coddy — Lektion 46 von 66.
Beim Arbeiten mit Funktionen, die Result zurückgeben, müssen Sie Fehler oft handhaben, indem Sie sie entweder lokal behandeln oder an die aufrufende Funktion weitergeben. Rust bietet einen eleganten Operator für dieses häufige Muster: 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, den Fehler zurückgeben
Ok(number * 2) // Wenn erfolgreich, die Zahl verdoppeln
}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.
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 geben Sie deren Summe in Ok eingepackt zurück. 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) ein und entfernen Sie Leerzeichen mit trim
- Lesen Sie die zweite Eingabe (zweite Zahl als String) ein und entfernen Sie Leerzeichen mit 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 beider 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
Spickzettel
Der Fragezeichen-Operator ? bietet eine prägnante Möglichkeit, Fehler in Funktionen zu propagieren, die ein Result zurückgeben.
Wenn er hinter einem Result platziert wird, bewirkt der ?-Operator Folgendes:
- Entpackt einen
Ok-Wert und setzt die Ausführung fort - Gibt sofort ein
Erraus der aktuellen Funktion zurück, falls eines auftritt
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
let number = s.parse::<i32>()?; // Wenn das Parsen fehlschlägt, gib den Fehler zurück
Ok(number * 2) // Wenn erfolgreich, verdopple die Zahl
}Der ?-Operator kann nur in Funktionen verwendet werden, die einen Result- oder Option-Typ zurückgeben.
Probier es selbst
use std::io;
// TODO: Erstellen Sie 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: add_numbers mit input1 und input2 aufrufen
// TODO: match verwenden, um das Result zu verarbeiten
// "Sum: [value]" für Ok(value) ausgeben
// "Parsing error" für Err(_) ausgeben
}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