Menu
Coddy logo textTech

do, try, catch

Teil des Abschnitts Logik & Kontrollfluss der Swift-Journey von Coddy — Lektion 45 von 56.

Die vollständige Form zur Fehlerbehandlung ist do/try/catch:

enum DivError: Error { case byZero }

func divide(_ a: Int, _ b: Int) throws -> Int {
    if b == 0 { throw DivError.byZero }
    return a / b
}

do {
    let r = try divide(10, 2)
    print(r)                      // 5
} catch DivError.byZero {
    print("can't divide by zero")
} catch {
    print("unknown error")
}

try steht vor jedem Aufruf, der einen Fehler auslösen kann. Wenn der Aufruf einen Fehler auslöst, springt die Steuerung zum passenden catch; andernfalls wird die Ausführung hinter dem do-Block fortgesetzt.

Mehrere catch-Blöcke werden von oben nach unten abgearbeitet und der erste Treffer gewinnt, genau wie bei einem switch. Der einfache catch am Ende ist der Auffangblock (catch-all); man möchte fast immer einen haben, um den Compiler zufriedenzustellen.

challenge icon

Aufgabe

Einfach

Definiere ein Enum ParseError: Error mit drei Fällen: empty, notInteger und negative.

Definiere eine throwing Funktion parsePositive(_ s: String) throws -> Int, die:

  • .empty wirft, wenn s nach dem Entfernen von Leerzeichen leer ist
  • .notInteger wirft, wenn s nicht als Int geparst werden kann
  • .negative wirft, wenn der geparste Wert < 0 ist
  • Andernfalls den geparsten Wert zurückgibt

Lies eine einzelne Zeile von stdin und rufe parsePositive in einem do/catch-Block auf. Gib Folgendes aus:

  • got: <n> bei Erfolg
  • error: empty, error: not integer oder error: negative für den jeweiligen Fall

Für die Eingabe 42 ist die Ausgabe got: 42. Für eine leere Zeile ist sie error: empty. Für abc ist sie error: not integer.

Spickzettel

Swift-Fehlerbehandlung verwendet do/try/catch. Definieren Sie Fehler mit einem Enum, das Error entspricht, markieren Sie werfende Funktionen mit throws und verwenden Sie throw, um einen Fehler auszulösen:

enum DivError: Error { case byZero }

func divide(_ a: Int, _ b: Int) throws -> Int {
    if b == 0 { throw DivError.byZero }
    return a / b
}

do {
    let r = try divide(10, 2)
    print(r)                      // 5
} catch DivError.byZero {
    print("can't divide by zero")
} catch {
    print("unknown error")        // fängt alles ab
}
  • try muss jedem werfenden Aufruf vorangestellt werden.
  • catch-Blöcke werden von oben nach unten abgeglichen; der erste Treffer gewinnt.
  • Ein einfaches catch am Ende fungiert als Auffangbecken für alle Fehler.

Probier es selbst

let line = readLine()!

// TODO: enum ParseError; func parsePositive(_:) throws -> Int;
// do/try/catch mit drei Zweigen plus dem Catch-all
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Logik & Kontrollfluss