Skip to content

4. Fehlerbehandlung

In der Programmierung gibt es eine unumstößliche Regel: Ein Programm darf niemals unerwartet „abstürzen“. Alle Fehler, die während der Programmausführung auftreten können, müssen behandelt werden, und es müssen aussagekräftige Fehlermeldungen generiert werden.

Kehren wir zu dem zuvor besprochenen Steuerbeispiel zurück: Was passiert, wenn der Benutzer einen beliebigen Wert für die Anzahl der Kinder eingibt? Sehen wir uns dieses Beispiel an:

1
2
3
C:\>cscript impots1.vbs o xyzt 200000

C:\impots1.vbs(33, 3) Erreur d'exécution Microsoft VBScript: Type incompatible: 'cint'

Dies ist ein sogenannter „Wild Crash“. Die Anweisung enfants=cint(wscript.arguments(1)) verursachte einen „Crash“, da arguments(1) die Zeichenfolge „xyzt“ enthielt.

Bevor Sie eine Variante verwenden, deren genaue Beschaffenheit unbekannt ist, müssen Sie deren genauen Subtyp überprüfen. Dazu gibt es mehrere Möglichkeiten:

  • Prüfen Sie den tatsächlichen Typ der in einer Variablen enthaltenen Daten mit den Funktionen vartype oder typename
  • Verwenden Sie einen regulären Ausdruck, um zu überprüfen, ob der Inhalt der Variablen einem bestimmten Muster entspricht
  • Lassen Sie den Fehler auftreten, fangen Sie ihn dann ab und behandeln Sie ihn

Wir werden diese verschiedenen Methoden untersuchen.

4.1. Den genauen Typ eines Datenelements bestimmen

Denken Sie daran, dass Sie mit den Funktionen vartype und varname den genauen Typ eines Datenelements ermitteln können. Dies ist nicht immer sehr hilfreich. Wenn wir beispielsweise Daten einlesen, die über die Tastatur eingegeben wurden, geben uns die Funktionen „vartype“ und „varname“ an, dass es sich um eine Zeichenkette handelt, da alle über die Tastatur eingegebenen Daten als solche behandelt werden. Dies sagt uns jedoch nicht, ob diese Zeichenkette beispielsweise als gültige Zahl angesehen werden kann. Wir verwenden daher andere Funktionen, um auf diese Art von Informationen zuzugreifen:

isNumeric(Ausdruck)
gibt „true“ zurück, wenn „expression“ als Zahl verwendet werden kann
isDate(Ausdruck)
gibt „true“ zurück, wenn „expression“ als Datum verwendet werden kann
isEmpty(var)
gibt „true“ zurück, wenn die Variable var nicht initialisiert wurde
isNull(var)
gibt „true“ zurück, wenn die Variable var ungültige Daten enthält
isArray(var)
gibt „true“ zurück, wenn var ein Array ist
isObject(var)
gibt „true“ zurück, wenn var ein Objekt ist

Das folgende Beispiel fordert den Benutzer auf, Daten über die Tastatur einzugeben, bis diese als Zahl erkannt werden:

Programm

' read data until it is recognized as a number

Option Explicit

Dim fini, nombre

' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)

fini=false
Do While Not fini
    ' we ask for the number
    wscript.stdout.write "Tapez un nombre : "
    ' we read it
    nombre=wscript.stdin.readLine
    ' the type is necessarily string when read
    wscript.echo "Type de la donnée lue : " & typename(nombre) & "," & vartype(nombre)
    ' test the actual type of data read
    If isNumeric(nombre) Then
        fini=true
    Else
        wscript.echo "Erreur, vous n'avez pas tapé un nombre. Recommencez svp..."
    End If
Loop

' confirmation
wscript.echo "Merci pour le nombre " & nombre

' and end
wscript.quit 0

Ergebnisse

1
2
3
4
5
6
Tapez un nombre : a
Type de la donnée lue : String,8
Erreur, vous n'avez pas tapé un nombre. Recommencez svp...
Tapez un nombre : -12
Type de la donnée lue : String,8
Merci pour le nombre -12

Die Funktion isNumeric gibt keinen Aufschluss darüber, ob ein Ausdruck eine Ganzzahl ist oder nicht. Um diese Information zu erhalten, sind zusätzliche Prüfungen erforderlich. Das folgende Beispiel fordert eine Ganzzahl größer als 0 an:

Programm

' read data until it is recognized as an integer >0

Option Explicit

Dim fini, nombre

' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)

fini=false
Do While Not fini
    ' we ask for the number
    wscript.stdout.write "Tapez un nombre entier >0: "
    ' we read it
    nombre=wscript.stdin.readLine
    ' test the actual type of data read
    If isNumeric(nombre) Then
        ' is it a positive integer (number equal to its integer part)?
        If (nombre-int(nombre))=0 And nombre>0 Then
            fini=true
        End If
    End If
    ' possible error msg
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' confirmation
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' and end
wscript.quit 0

Ergebnisse

1
2
3
4
5
6
7
8
Tapez un nombre entier >0: a
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: -1
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 10.6
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 12
Merci pour le nombre entier >0 : 12

Kommentare:

  • int(number) gibt den ganzzahligen Teil einer Zahl zurück. Eine Zahl, die ihrem ganzzahligen Teil entspricht, ist eine ganze Zahl.
  • Es ist interessant festzustellen, dass wir den Test If (number - int(number)) = 0 And number > 0 verwenden mussten, da der Test If number = int(number) And number > 0 nicht die erwarteten Ergebnisse lieferte. Er erkannte keine positiven ganzen Zahlen. Wir überlassen es dem Leser, herauszufinden, warum.
  • Die Prüfung If (number - int(number)) = 0“ ist nicht ganz zuverlässig. Betrachten wir das folgende Beispiel:
Geben Sie eine ganze Zahl > 0 ein: 4.0000000000000000000000001

Vielen Dank für die ganze Zahl > 0: 4.0000000000000000000000001

Reelle Zahlen werden nicht exakt, sondern nur annähernd dargestellt. Und hier gab die Operation number-int(number) 0 mit der Genauigkeit des Computers zurück.

4.2. Reguläre Ausdrücke

Mit regulären Ausdrücken können wir das Format einer Zeichenkette prüfen. Auf diese Weise können wir sicherstellen, dass eine Zeichenkette, die ein Datum darstellt, im Format tt/mm/jj vorliegt. Dazu verwenden wir ein Muster und vergleichen die Zeichenkette mit diesem Muster. In diesem Beispiel müssen d, m und y also Ziffern sein. Das Muster für ein gültiges Datumsformat lautet dann „\d\d/\d\d/\d\d“, wobei das Symbol \d eine Ziffer bezeichnet. Die Symbole, die in einem Muster verwendet werden können, sind wie folgt (Microsoft-Dokumentation):

Zeichen
Beschreibung
\
Bezeichnet das folgende Zeichen als Sonderzeichen oder Literal. Beispielsweise entspricht „n“ dem Zeichen „n“. „\n“ entspricht einem Zeilenumbruchzeichen. Die Zeichenfolge „\\“ entspricht „\“, während „\(" dem Zeichen „(“ entspricht.
^
Stimmt mit dem Anfang der Eingabe überein.
$
Stimmt mit dem Ende der Eingabe überein.
*
Stimmt nullmal oder öfter mit dem vorangehenden Zeichen überein. Somit passt „zo*“ zu „z“ oder „zoo“.
+
Stimmt mit dem vorangehenden Zeichen ein- oder mehrmals überein. So passt „zo+“ zu „zoo“, aber nicht zu „z“.
?
Passt null- oder einmal auf das vorangehende Zeichen. Zum Beispiel passt „a?ve?“ auf „ve“ in „lever“.
.
Stimmt mit einem beliebigen einzelnen Zeichen überein, mit Ausnahme des Zeilenumbruchzeichens.
(Muster)
Sucht nach dem Muster und speichert die Übereinstimmung. Die übereinstimmende Teilzeichenfolge kann aus der resultierenden Matches-Sammlung mit Item [0]...[n] abgerufen werden. Um Übereinstimmungen mit Zeichen innerhalb von Klammern ( ) zu finden, verwende „\(" oder „\)“.
x|y
Passt entweder auf x oder y. Beispielsweise passt „z|foot“ auf „z“ oder „foot“. „(z|f)oo“ passt auf „zoo“ oder „foo“.
{n}
n ist eine nicht-negative ganze Zahl. Passt genau auf n Vorkommen des Zeichens. Beispielsweise passt „o{2}“ nicht auf „o“ in „Bob“, sondern auf die ersten beiden „o“s in „fooooot“.
{n,}
n ist eine nicht-negative ganze Zahl. Es werden mindestens n Vorkommen des Zeichens gefunden. Beispielsweise passt „o{2,}“ nicht auf das „o“ in „Bob“, findet aber alle „o“s in „fooooot“. „o{1,}“ entspricht „o+“ und „o{0,}“ entspricht „o*“.
{n,m}
m und n sind nicht-negative ganze Zahlen. Findet mindestens n und höchstens m Vorkommen des Zeichens. Beispielsweise passt „o{1,3}“ auf die ersten drei „o“ in „foooooot“, und „o{0,1}“ passt auf „o?“.
[xyz]
Zeichensatz. Findet eines der angegebenen Zeichen. Beispielsweise findet „[abc]“ das „a“ in „plat“.
[^xyz]
Negativer Zeichensatz. Findet jedes Zeichen, das nicht aufgeführt ist. Beispielsweise findet „[^abc]“ das „p“ in „plat“.
[a-z]
Zeichenbereich. Entspricht jedem Zeichen im angegebenen Bereich. Beispielsweise entspricht „[a-z]“ jedem Kleinbuchstaben zwischen „a“ und „z“.
[^m-z]
Negativer Zeichenbereich. Passt auf jedes Zeichen, das nicht im angegebenen Bereich liegt. Beispielsweise passt „[^m-z]“ auf jedes Zeichen, das nicht zwischen „m“ und „z“ liegt.
\b
Passt auf eine Wortgrenze, d. h. die Position zwischen einem Wort und einem Leerzeichen. Beispielsweise passt „er\b“ auf „er“ in „lever“, aber nicht auf „er“ in „verb“.
\B
Passt auf eine Grenze, die kein Wort darstellt. „en*t\B“ passt auf „ent“ in „bien entendu“.
\d
Passt auf ein Zeichen, das eine Ziffer darstellt. Entspricht [0-9].
\D
Passt auf ein Zeichen, das keine Ziffer ist. Entspricht [^0-9].
\f
Entspricht einem Zeilenumbruchzeichen.
\n
Entspricht einem Zeilenumbruchzeichen.
\r
Entspricht einem Wagenrücklaufzeichen.
\s
Entspricht einem beliebigen Leerzeichen, einschließlich Leerzeichen, Tabulator, Seitenumbruch usw. Entspricht „[ \f\n\r\t\v]“.
\S
Entspricht jedem Zeichen, das kein Leerzeichen ist. Entspricht "[^ \f\n\r\t\v]".
\t
Entspricht einem Tabulatorzeichen.
\v
Entspricht einem vertikalen Tabulatorzeichen.
\w
Entspricht jedem Zeichen, das ein Wort darstellt, einschließlich Unterstrich. Entspricht „[A-Za-z0-9_]“.
\W
Entspricht jedem Zeichen, das kein Wort darstellt. Entspricht „[^A-Za-z0-9_]“.
\num
Passt auf num, wobei num eine positive ganze Zahl ist. Bezieht sich auf gespeicherte Übereinstimmungen. Beispielsweise passt „(.)\1“ auf zwei aufeinanderfolgende identische Zeichen.
\n
Entspricht n, wobei n ein oktaler Escape-Wert ist. Oktale Escape-Werte müssen aus 1, 2 oder 3 Ziffern bestehen. Beispielsweise entsprechen sowohl „\11“ als auch „\011“ einem Tabulatorzeichen. „\0011“ entspricht „\001“ & „1“. Oktale Escape-Werte dürfen 256 nicht überschreiten. Ist dies der Fall, werden im Ausdruck nur die ersten beiden Ziffern berücksichtigt. Ermöglicht die Verwendung von ASCII-Codes in regulären Ausdrücken.
\xn
Entspricht n, wobei n ein hexadezimaler Escape-Wert ist. Hexadezimale Escape-Werte müssen aus genau zwei Ziffern bestehen. Beispielsweise entspricht „\x41“ dem Zeichen „A“. „\x041“ entspricht „\x04“ und „1“. Ermöglicht die Verwendung von ASCII-Codes in regulären Ausdrücken.

Ein Element in einem Muster kann einmal oder mehrmals vorkommen. Sehen wir uns einige Beispiele mit dem Symbol \d an, das für eine einzelne Ziffer steht:

Muster
Bedeutung
\d
eine Ziffer
\d?
0 oder 1 Ziffer
\d*
0 oder mehr Ziffern
\d+
1 oder mehr Ziffern
\d{2}
2 Ziffern
\d{3,}
mindestens 3 Ziffern
\d{5,7}
zwischen 5 und 7 Ziffern

Stellen wir uns nun ein Modell vor, das das erwartete Format einer Zeichenkette beschreiben kann:

Zielzeichenfolge
Muster
ein Datum im Format TT/MM/JJ
\d{2}/\d{2}/\d{2}
eine Uhrzeit im Format hh:mm:ss
\d{2}:\d{2}:\d{2}
eine vorzeichenlose Ganzzahl
\d+
eine Folge von Leerzeichen, die leer sein kann
\s*
eine vorzeichenlose Ganzzahl, der Leerzeichen vorangehen oder folgen können
\s*\d+\s*
eine ganze Zahl, die vorzeichenbehaftet sein kann und der Leerzeichen vorangehen oder folgen können
\s*[+|-]?\s*\d+\s*
eine vorzeichenlose reelle Zahl, der Leerzeichen vorangestellt oder nachgestellt sein können
\s*\d+(.\d*)?\s*
eine reelle Zahl, die vorzeichenbehaftet sein kann und der Leerzeichen vorangehen oder nachfolgen können
\s*[+|]?\s*\d+(.\d*)?\s*
eine Zeichenkette, die das Wort „just“ enthält
\bjuste\b
  

Sie können angeben, wo in der Zeichenfolge nach dem Muster gesucht werden soll:

Muster
Bedeutung
^Muster
Das Muster steht am Anfang der Zeichenfolge
Muster$
Das Muster beendet die Zeichenkette
^Muster$
Das Muster beginnt und endet die Zeichenfolge
Muster
Das Muster wird ab dem Anfang an einer beliebigen Stelle in der Zeichenfolge gesucht.
Suchzeichenfolge
Muster
eine Zeichenfolge, die mit einem Ausrufezeichen endet
!$
eine Zeichenfolge, die mit einem Punkt endet
\.$
eine Zeichenkette, die mit der Sequenz // beginnt
^//
eine Zeichenfolge, die aus einem einzelnen Wort besteht, dem wahlweise Leerzeichen vorangestellt oder nachgestellt sind
^\s*\w+\s*$
eine Zeichenfolge, die aus zwei Wörtern besteht, optional mit Leerzeichen davor oder danach
^\s*\w+\s*\w+\s*$
eine Zeichenfolge, die das Wort „secret“ enthält
\bsecret\b

Teilmuster eines Musters können „extrahiert“ werden. So können wir nicht nur überprüfen, ob eine Zeichenfolge einem bestimmten Muster entspricht, sondern auch die Elemente aus dieser Zeichenfolge extrahieren, die den in Klammern eingeschlossenen Teilmustern des Musters entsprechen. Wenn wir beispielsweise eine Zeichenfolge analysieren, die ein Datum im Format dd/mm/yy enthält, und die Komponenten dd, mm und yy dieses Datums extrahieren möchten, würden wir das Muster (\d\d)/(\d\d)/(\d\d) verwenden.

Schauen wir uns dieses Beispiel an, um zu sehen, wie dies mit VBScript funktioniert.

  • Zunächst müssen wir ein RegExp-Objekt (Regular Expression) erstellen
set modele=new regexp
  • Dann legen wir das zu prüfende Muster fest
modele.pattern="(\d\d)/(\d\d)/(\d\d)"
  • Möglicherweise möchten Sie die Groß-/Kleinschreibung ignorieren (standardmäßig wird die Groß-/Kleinschreibung beachtet). Hier spielt das keine Rolle.
modele.IgnoreCase=true
  • Möglicherweise möchten Sie mehrmals nach dem Muster in der Zeichenfolge suchen (standardmäßig ist dies nicht der Fall)
modele.Global=true

Eine globale Suche ist nur dann sinnvoll, wenn sich das verwendete Muster nicht auf den Anfang oder das Ende der Zeichenfolge bezieht.

  • Wir suchen dann nach allen Übereinstimmungen des Musters in der Zeichenfolge:
set correspondances=modele.execute(chaine)

Die Methode execute eines RegExp-Objekts gibt eine Sammlung von match-Objekten zurück. Dieses Objekt verfügt über eine Eigenschaft namens value, die das Zeichenfolgenelement enthält, das mit dem Muster übereinstimmt. Wenn Sie pattern.global=true* gesetzt haben, kann es mehrere Übereinstimmungen geben. Aus diesem Grund ist das Ergebnis der Methode execute* eine Sammlung von Übereinstimmungen.

  • Die Anzahl der Übereinstimmungen wird durch `matches.count` angegeben. Ist diese Zahl 0, bedeutet dies, dass das Muster nirgendwo gefunden wurde. Der Wert von Übereinstimmung #i wird durch `matches(i).value` angegeben. Enthält das Muster Teilmuster in Klammern, ist das Element von `matches(i)`, das der Klammer j im Muster entspricht, `matches(i).submatches(j)`.

All dies wird im folgenden Beispiel veranschaulicht:

Programm

' regular expression

' we want to check that a string contains a date in dd/mm/yy format

Option Explicit
Dim modele

' we define the
Set modele=new regexp
modele.pattern="\b(\d\d)/(\d\d)/(\d\d)\b"  ' a date anywhere in the chain
modele.global=true                      ' we will search for the model several times in the chain

' the user specifies the string in which to search for the model
Dim chaine, correspondances, i

chaine=""
' loop as long as string<>"end"
Do While true
    ' the user is asked to type a text
    wscript.stdout.writeLine "Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrêter : "
    chaine=wscript.stdin.readLine
    ' fini si chaine=fin
    If chaine="fin" Then Exit Do
    ' the string read is compared with the date template
    Set correspondances=modele.execute(chaine)
    ' was a match found
    If correspondances.count<>0 Then
        ' we have at least one match
        For i=0 To correspondances.count-1
            ' the i correspondence is displayed
            wscript.echo "J'ai trouvé la date " & correspondances(i).value
            ' we retrieve the sub-elements of correspondence i
            wscript.echo "Les éléments de la date " & i & " sont (" & correspondances(i).submatches(0) & "," _
            & correspondances(i).submatches(1) & "," & correspondances(i).submatches(2) & ")"
        Next
    Else
        ' no correspondence
        wscript.echo "Je n'ai pas trouvé de date au format jj/mm/aa dans votre texte"
    End If
Loop

' finish
wscript.quit 0

Ergebnisse

Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrÛter :
aujourd'hui on est le 01/01/01 et demain sera le 02/01/02
J'ai trouvé la date 01/01/01
Les éléments de la date 0 sont (01,01,01)
J'ai trouvé la date 02/01/02
Les éléments de la date 1 sont (02,01,02)

Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrÛter :
une date au format incorrect : 01/01/2002
Je n'ai pas trouvé de date au format jj/mm/aa dans votre texte

Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrÛter :
une suite de dates : 10/10/10, 11/11/11, 12/12/12
J'ai trouvé la date 10/10/10
Les éléments de la date 0 sont (10,10,10)
J'ai trouvé la date 11/11/11
Les éléments de la date 1 sont (11,11,11)
J'ai trouvé la date 12/12/12
Les éléments de la date 2 sont (12,12,12)

Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrÛter :
fin

Mit Hilfe regulärer Ausdrücke könnte das Programm, das prüft, ob eine Tastatureingabe tatsächlich eine positive ganze Zahl ist, wie folgt geschrieben werden:

Programm

' read data until it is recognized as a number

Option Explicit

Dim fini, nombre

' we define the model of a positive integer (which may be zero)
Dim modele
Set modele=new regexp
modele.pattern="^\s*\d+\s*$"

' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)

fini=false
Do While Not fini
    ' we ask for the number
    wscript.stdout.write "Tapez un nombre entier >0: "
    ' we read it
    nombre=wscript.stdin.readLine
    ' test the format of the data read
    Dim correspondances
    Set correspondances=modele.execute(nombre)
    ' has the model been checked?
    If correspondances.count<>0 Then
        ' it's an integer, but is it >0?
        nombre=cint(nombre)
        If nombre>0 Then
            fini=true
        End If
    End If
    ' possible error msg
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' confirmation
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' and end
wscript.quit 0

Ergebnisse

Tapez un nombre entier >0: 10.3
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: abcd
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: -4
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 0
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 1
Merci pour le nombre entier >0 : 1

Es kann manchmal eine echte Herausforderung sein, den regulären Ausdruck zu finden, mit dem wir überprüfen können, ob eine Zeichenkette einem bestimmten Muster entspricht. Mit dem folgenden Programm können Sie dies üben. Es fragt nach einem Muster und einer Zeichenkette und gibt dann an, ob die Zeichenkette dem Muster entspricht oder nicht.

Programm

' regular expression

' we want to check that a chain corresponds to a model

Option Explicit

' we define the
Dim modele
Set modele=new regexp
modele.global=true                      ' we will search for the model several times in the chain

' the user specifies the string in which to search for the model
Dim chaine, correspondances, i

Do While true
    ' the user is asked to type in a template
    wscript.stdout.write "Tapez le modèle à tester et fin pour arrêter : "
    modele.pattern=wscript.stdin.readLine
    ' finished?
    If modele.pattern="fin" Then Exit Do
        ' the user is asked for the strings to be compared with the model
        Do While true
            ' the user is asked to type in a template
            wscript.stdout.writeLine "Tapez la chaîne à tester avec le modèle [" & modele.pattern & "] et fin pour arrêter : "
            chaine=wscript.stdin.readLine
            ' finished?
            If chaine="fin" Then Exit Do
            ' the string read is compared with the date template
            Set correspondances=modele.execute(chaine)
            ' was a match found
            If correspondances.count<>0 Then
                ' we have at least one match
                For i=0 To correspondances.count-1
                    ' the i correspondence is displayed
                    wscript.echo "J'ai trouvé la correspondance " & correspondances(i).value
                Next
            Else
                ' no correspondence
                wscript.echo "Je n'ai pas trouvé de correspondance"
            End If
    Loop
Loop

' finish
wscript.quit 0

Ergebnisse

Tapez le modèle à tester et fin pour arrêter : ^\s*\d+(\,\d+)*\s*$

Tapez la chaîne à tester avec le modèle [^\s*\d+(\,\d+)*\s*$] et fin pour arrêter :
18
J'ai trouvé la correspondance [18]

Tapez la chaîne à tester avec le modèle [^\s*\d+(\,\d+)*\s*$] et fin pour arrêter :
145.678
Je n'ai pas trouvé de correspondance

Tapez la chaîne à tester avec le modèle [^\s*\d+(\,\d+)*\s*$] et fin pour arrêter :
145,678
J'ai trouvé la correspondance [  145,678   ]

4.3. Behandlung von Laufzeitfehlern

Eine weitere Methode zur Behandlung von Laufzeitfehlern besteht darin, sie auftreten zu lassen, sich über sie benachrichtigen zu lassen und sie dann zu behandeln. Normalerweise zeigt WSH bei einem Laufzeitfehler eine Fehlermeldung an und das Programm wird angehalten. Mit zwei Anweisungen können wir dieses Verhalten ändern:

on error resume next

Diese Anweisung teilt dem System (WSH) mit, dass wir Fehler selbst behandeln werden. Nach dieser Anweisung werden alle Fehler vom System einfach ignoriert.

on error goto 0

Diese Anweisung kehrt zur normalen Fehlerbehandlung zurück.

Wenn die Anweisung „on error resume next“ aktiv ist, müssen wir eventuell auftretende Fehler selbst behandeln. Das Err-Objekt hilft uns dabei. Dieses Objekt verfügt über verschiedene Eigenschaften und Methoden, von denen wir uns auf die folgenden zwei konzentrieren werden:

  • number: eine Ganzzahl, die die Nummer des zuletzt aufgetretenen Fehlers angibt. 0 bedeutet „kein Fehler“
  • description: die Fehlermeldung, die das System angezeigt hätte, wenn wir die Anweisung „on error resume next“ nicht ausgeführt hätten

Sehen wir uns das folgende Beispiel an:

Programm


' unhandled error
 
Option Explicit
Dim nombre
 
nombre=cdbl("abcd")
wscript.echo "nombre=" & nombre

Ergebnisse

C:\ err5.vbs(6, 1) Erreur d'exécution Microsoft VBScript: Type incompatible: 'cdbl'

Nun wollen wir den Fehler beheben:

Programm

' managed error

Option Explicit
Dim nombre

' we manage mistakes ourselves
On Error Resume Next
nombre=cdbl("abcd")
' was there a mistake?
If Err.number<>0 Then
    wscript.echo "L'erreur [" & err.description & "] s'est produite"
    On Error GoTo 0
    wscript.quit 1
End If
' no error - returns to normal operation
On Error GoTo 0
wscript.echo "nombre=" & nombre
wscript.quit 0

Ergebnisse

L'erreur [Type incompatible] s'est produite

Schreiben wir das Programm zur Eingabe einer ganzen Zahl > 0 mit dieser neuen Methode um:

Programm


' read data until it is recognized as a number
 
Option Explicit
 
Dim fini, nombre
 
' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)
 
fini=false
Do While Not fini
  ' we ask for the number
  wscript.stdout.write "Tapez un nombre entier >0: "
  ' we read it
  nombre=wscript.stdin.readLine
  ' test the format of the data read
  On Error Resume Next
  nombre=cdbl(nombre)
  If err.number=0 Then
    ' no error it's a number
    ' returns to normal error handling mode
    On Error GoTo 0
    ' is it an integer >0
    If (nombre-int(nombre))=0 And nombre>0 Then
      fini=true
    End If
  End If
  ' returns to normal error handling mode
  On Error GoTo 0
  ' possible error msg
  If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop
 
' confirmation
wscript.echo "Merci pour le nombre entier >0 : " & nombre
 
' and end
wscript.quit 0

Ergebnisse

Tapez un nombre entier >0: 4.5
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 4,5
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: abcd
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: -4
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 1
Merci pour le nombre entier >0 : 1

Anmerkungen:

  • Diese Methode ist manchmal die einzige, die verwendet werden kann. Vergessen Sie in diesem Fall nicht, zum normalen Fehlerbehandlungsmodus zurückzukehren, sobald die Anweisungssequenz, die den Fehler wahrscheinlich verursacht, abgeschlossen ist.

4.4. Anwendung auf das Steuerberechnungsprogramm

Wir greifen das zuvor geschriebene Steuerberechnungsprogramm wieder auf, um diesmal die Gültigkeit der an das Programm übergebenen Argumente zu überprüfen:

Programm


' calculating a taxpayer's tax liability
' the program must be called with three parameters: married children salary
' married: character Y if married, N if unmarried
' children: number of children
' salary: annual salary without cents
 
' no verification of data validity is performed, but we do
' check that there are three of them
 
' mandatory variable declaration
Option Explicit
Dim syntaxe
syntaxe= _
    "Syntaxe : pg marié enfants salaire" & vbCRLF & _
    "marié : caractère O si marié, N si non marié" & vbCRLF & _
    "enfants : nombre d'enfants (entier >=0)" & vbCRLF & _
    "salaire : salaire annuel sans les centimes (entier >=0)"
 
' we check that there are 3 arguments
  Dim nbArguments
  nbArguments=wscript.arguments.count
  If nbArguments<>3 Then
    ' error msg
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect"
    ' stop with error code 1
    wscript.quit 1
  End If

' retrieve arguments and check their validity
' an argument is passed to the program without spaces in front and behind it
' use regular expressions to check data validity
  Dim modele, correspondances
  Set modele=new regexp

  ' marital status must be among the characters oOnN
  modele.pattern="^[oOnN]$"
  Set correspondances=modele.execute(wscript.arguments(0))
  If correspondances.count=0 Then
    ' error
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect"
    ' we leave
    wscript.quit 2
  End If
  ' the value
  Dim marie
  If lcase(wscript.arguments(0)) = "o"Then
    marie=true
  Else
    marie=false
  End If

  ' children must be an integer >=0
  modele.pattern="^\d{1,2}$"
  Set correspondances=modele.execute(wscript.arguments(1))
  If correspondances.count=0 Then
    ' error
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect"
    ' we leave
    wscript.quit 3
  End If
  ' the value
  Dim enfants
  enfants=cint(wscript.arguments(1))
 
  ' salary must be an integer >=0
  modele.pattern="^\d{1,9}$"
  Set correspondances=modele.execute(wscript.arguments(2))
  If correspondances.count=0 Then
    ' error
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect"
    ' we leave
    wscript.quit 4
  End If
  ' the value
  Dim salaire
  salaire=clng(wscript.arguments(2))

  ' we define the data needed to calculate the tax in 3 tables
  Dim limites, coeffn, coeffr
  limites=array(12620,13190,15640,24740,31810,39970,48360, _
    55790,92970,127860,151250,172040,195000,0)
  coeffr=array(0,0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.45, _
    0.5,0.55,0.6,0.65)
  coeffn=array(0,631,1290.5,2072.5,3309.5,4900,6898.5,9316.5, _
    12106,16754.5,23147.5,30710,39312,49062)

  ' the number of shares is calculated
  Dim nbParts
  If marie=true Then
    nbParts=(enfants/2)+2
  Else
    nbParts=(enfants/2)+1
  End If
  If enfants>=3 Then nbParts=nbParts+0.5

  ' calculate the family quota and taxable income
  Dim revenu, qf
  revenu=0.72*salaire
  qf=revenu/nbParts

  ' tax calculation
  Dim i, impot
  i=0
  Do While i<ubound(limites) And qf>limites(i)
    i=i+1
  Loop
  impot=int(revenu*coeffr(i)-nbParts*coeffn(i))

  ' the result is displayed
  wscript.echo "impôt=" & impot

  ' leave without error
  wscript.quit 0

Ergebnisse

C:\>cscript impots2.vbs

Syntaxe : pg marié enfants salaire
marié : caractère O si marié, N si non marié
enfants : nombre d'enfants (entier >=0)
salaire : salaire annuel sans les centimes (entier >=0)

erreur : nombre d'arguments incorrect

C:\>cscript impots2.vbs a b c

Syntaxe : pg marié enfants salaire
marié : caractère O si marié, N si non marié
enfants : nombre d'enfants (entier >=0)
salaire : salaire annuel sans les centimes (entier >=0)

erreur : argument marie incorrect


C:\>cscript impots2.vbs o b c

Syntaxe : pg marié enfants salaire
marié : caractère O si marié, N si non marié
enfants : nombre d'enfants (entier >=0)
salaire : salaire annuel sans les centimes (entier >=0)

erreur : argument enfants incorrect

C:\>cscript impots2.vbs o 2 c


Syntaxe : pg marié enfants salaire
marié : caractère O si marié, N si non marié
enfants : nombre d'enfants (entier >=0)
salaire : salaire annuel sans les centimes (entier >=0)

erreur : argument salaire incorrect

C:\>cscript impots2.vbs o 2 200000

impôt=22504