Skip to content

4. Fehlerbehandlung

In der Programmierung gilt eine unumstößliche Regel: Ein Programm darf niemals einfach „abstürzen“. Alle Fehler, die während der Ausführung des Programms auftreten können, müssen behandelt und aussagekräftige Fehlermeldungen ausgegeben werden.

Wenn wir das zuvor behandelte Beispiel zur Steuerberechnung wieder aufgreifen: Was passiert, wenn der Benutzer einen beliebigen Wert für die Anzahl der Kinder eingibt? Schauen 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 wird als unkontrollierter Absturz bezeichnet. Es kam zu einem „Absturz“ bei der Anweisung children=cint(wscript.arguments(1)), da </span>*<span style="color: #000000">arguments(1) *die Zeichenkette „xyzt“ enthielt.

Bevor man eine Variante verwendet, deren genaue Beschaffenheit man nicht kennt, muss man ihren genauen Subtyp überprüfen. Dies kann auf verschiedene Arten geschehen:

  • den tatsächlichen Typ der in einer Variablen enthaltenen Daten mit den Funktionen vartype oder typename prüfen
  • einen regulären Ausdruck verwenden, um zu überprüfen, ob der Inhalt der Variablen einem bestimmten Muster entspricht
  • den Fehler auftreten lassen, ihn abfangen und anschließend behandeln

Wir werden diese verschiedenen Methoden näher betrachten.

4.1. Den genauen Typ eines Datums ermitteln

Zur Erinnerung: Mit den Funktionen vartype oder varname lässt sich der genaue Typ eines Datums ermitteln. Dies ist jedoch nicht immer eine große Hilfe. Wenn wir beispielsweise einen über die Tastatur eingegebenen Wert lesen, geben die Funktionen vartype und typename an, dass es sich um eine Zeichenkette handelt, da alle über die Tastatur eingegebenen Werte als solche betrachtet werden. Das sagt uns jedoch nicht, ob diese Zeichenkette beispielsweise als gültige Zahl angesehen werden kann. Um an diese Art von Informationen zu gelangen, verwenden wir daher andere Funktionen:

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

Das folgende Beispiel fordert dazu auf, einen Wert über die Tastatur einzugeben, bis dieser als Zahl erkannt wird:

Programm

' Ein Datenwert wird so lange eingelesen, bis er als Zahl erkannt wird

Option Explicit

Dim fini, nombre

' Schleife, solange die eingegebenen Daten nicht korrekt sind
' Die Schleife wird durch eine boolesche Variable gesteuert, die zu Beginn auf „falsch“ gesetzt ist (= noch nicht beendet)

fini=false
Do While Not fini
     ' Die Zahl wird abgefragt
    wscript.stdout.write "Tapez un nombre : "
     ' sie wird eingelesen
    nombre=wscript.stdin.readLine
     ' Der Typ ist beim Einlesen zwangsläufig „String“
    wscript.echo "Type de la donnée lue : " & typename(nombre) & "," & vartype(nombre)
     ' Der tatsächliche Typ der gelesenen Daten wird geprüft
    If isNumeric(nombre) Then
        fini=true
    Else
        wscript.echo "Erreur, vous n'avez pas tapé un nombre. Recommencez svp..."
    End If
Loop

' Bestätigung
wscript.echo "Merci pour le nombre " & nombre

' und Ende
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 ganze Zahl ist oder nicht. Um diese Information zu erhalten, sind zusätzliche Prüfungen erforderlich. Das folgende Beispiel fragt nach einer ganzen Zahl > 0:

Programm

' Ein Datenwert wird so lange eingelesen, bis er als ganze Zahl > 0 erkannt wird

Option Explicit

Dim fini, nombre

' Es wird so lange eine Schleife durchlaufen, bis der eingegebene Wert korrekt ist
' Die Schleife wird durch einen endlichen Booleschen Wert gesteuert, der zu Beginn auf „falsch“ gesetzt wird (= noch nicht beendet)

fini=false
Do While Not fini
     ' Die Zahl wird abgefragt
    wscript.stdout.write "Tapez un nombre entier >0: "
     ' sie wird gelesen
    nombre=wscript.stdin.readLine
     ' Der Real-Typ der gelesenen Daten wird geprüft
    If isNumeric(nombre) Then
         ' Ist es eine positive ganze Zahl (Zahl, die ihrem ganzzahligen Teil entspricht)?
        If (nombre-int(nombre))=0 And nombre>0 Then
            fini=true
        End If
    End If
     ' mögliche Fehlermeldung
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' Bestätigung
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' und Ende
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

Anmerkungen:

  • int(nombre) liefert den ganzzahligen Teil einer Zahl. Eine Zahl, die ihrem ganzzahligen Teil entspricht, ist eine ganze Zahl.
  • Interessanterweise musste der Test If (Zahl - int(Zahl)) = 0 And Zahl > 0“ verwendet werden, da der Test „If Zahl = int(Zahl) And Zahl > 0“ nicht die erwarteten Ergebnisse lieferte. Er erkannte die positiven ganzen Zahlen nicht. Wir überlassen es dem Leser, herauszufinden, warum.
  • Die If-Anweisung (Zahl - int(Zahl)) = 0 ist nicht ganz zuverlässig. Betrachten wir das folgende Ausführungsbeispiel:
Tapez un nombre entier >0: 4,0000000000000000000000001

Merci pour le nombre entier >0 : 4,0000000000000000000000001

Reelle Zahlen werden nicht exakt, sondern nur annähernd dargestellt. Und in diesem Fall ergab die Operation nombre-int(nombre) den Wert 0, genau auf die Genauigkeit des Computers bezogen.

4.2. Reguläre Ausdrücke

Mit regulären Ausdrücken können wir das Format einer Zeichenkette überprüfen. So lässt sich beispielsweise sicherstellen, dass eine Zeichenkette, die ein Datum darstellt, das Format tt/mm/jj hat. Dazu verwenden wir ein Muster und vergleichen die Zeichenkette mit diesem Muster. In diesem Beispiel müssen t, m und j 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 folgenden Symbole können in einem Muster verwendet werden (Microsoft-Dokumentation):

Zeichen
Beschreibung
\
Markiert das folgende Zeichen als Sonderzeichen oder Literal. Beispielsweise entspricht „n“ dem Zeichen „n“. „\n“ entspricht einem Zeilenumbruch. Die Sequenz „\\“ entspricht „\“, während „\(" dem Zeichen „(“ entspricht.
^
Entspricht dem Anfang der Eingabe.
$
Entspricht dem Ende der Eingabe.
*
Entspricht dem vorhergehenden Zeichen nullmal oder mehrmals. So entspricht „zo*“ sowohl „z“ als auch „zoo“.
+
Entspricht dem vorhergehenden Zeichen ein- oder mehrmals. So entspricht „zo+“ beispielsweise „zoo“, aber nicht „z“.
?
Entspricht dem vorhergehenden Zeichen null- oder einmal. Zum Beispiel entspricht „a?ve?“ dem Zeichen „ve“ in „lever“.
.
Entspricht einem beliebigen einzelnen Zeichen, mit Ausnahme des Zeilenumbruchzeichens.
(Vorlage)
Sucht nach „modèle“ und speichert die Übereinstimmung. Die übereinstimmende Teilzeichenfolge kann mithilfe von „Item [0]...[n]“ aus der erhaltenen Sammlung „Matches“ extrahiert werden. Um Übereinstimmungen mit Zeichen in Klammern ( ) zu finden, verwenden Sie „\(" oder „\)“.
x|y
Entspricht entweder x oder y. Beispielsweise entspricht „z|foot“ entweder „z“ oder „foot“. „(z|f)oo“ entspricht entweder „zoo“ oder „foo“.
{n}
n ist eine nicht-negative ganze Zahl. Entspricht genau dem n-fachen des Zeichens. Beispielsweise entspricht „o{2}“ nicht dem „o“ in „Bob“, sondern den ersten beiden „o“ in „fooooot“.
{n,}
n ist eine nicht-negative ganze Zahl. Entspricht mindestens n-mal dem Zeichen. Beispielsweise entspricht „o{2,}“ nicht dem „o“ in „Bob“, sondern allen „o“ in „fooooot“. „o{1,}“ entspricht „o+“ und „o{0,}“ entspricht „o*“.
{n,m}
m und n sind nicht-negative ganze Zahlen. Entspricht mindestens n und höchstens m Mal dem Zeichen. Beispielsweise entspricht „o{1,3}“ den ersten drei „o“ in „foooooot“ und „o{0,1}“ entspricht „o?“.
[xyz]
Zeichensatz. Entspricht einem der angegebenen Zeichen. Beispielsweise entspricht „[abc]“ dem Zeichen „a“ in „plat“.
[^xyz]
Negativer Zeichensatz. Entspricht jedem nicht angegebenen Zeichen. Beispielsweise entspricht „[^abc]“ dem Zeichen „p“ in „plat“.
[a-z]
Zeichenbereich. Entspricht jedem Zeichen in der angegebenen Zeichenfolge. Beispielsweise entspricht „[a-z]“ jedem Kleinbuchstaben zwischen „a“ und „z“.
[^m-z]
Negativer Zeichenbereich. Entspricht jedem Zeichen, das nicht in der angegebenen Zeichenfolge enthalten ist. Beispielsweise entspricht „[^m-z]“ jedem Zeichen, das nicht zwischen „m“ und „z“ liegt.
\b
Entspricht einer Wortgrenze, d. h. der Position zwischen einem Wort und einem Leerzeichen. Beispielsweise entspricht „er\b“ dem Wortteil „er“ in „lever“, nicht jedoch dem Wortteil „er“ in „verbe“.
\B
Entspricht einer Grenze, die kein Wort darstellt. „en*t\B“ entspricht „ent“ in „bien entendu“.
\d
Entspricht einem Zeichen, das eine Ziffer darstellt. Entspricht [0-9].
\D
Entspricht einem Zeichen, das keine Ziffer darstellt. Entspricht [^0-9].
\f
Entspricht einem Seitenumbruchzeichen.
\n
Entspricht einem Zeilenumbruchzeichen.
\r
Entspricht einem Wagenrücklaufzeichen.
\s
Entspricht allen Leerzeichen, einschließlich Leerzeichen, Tabulatoren, Seitenumbrüchen usw. Entspricht „[ \f\n\r\t\v]“.
\S
Entspricht jedem nicht-weißen Leerzeichen. Entspricht „[^ \f\n\r\t\v]“.
\t
Entspricht einem Tabulatorzeichen.
\v
Entspricht einem vertikalen Tabulatorzeichen.
\w
Entspricht jedem Zeichen, das ein Wort darstellt und einen Unterstrich enthält. Entspricht „[A-Za-z0-9_]“.
\W
Entspricht jedem Zeichen, das kein Wort darstellt. Entspricht „[^A-Za-z0-9_]“.
\num
Entspricht num, wobei num eine positive ganze Zahl ist. Bezieht sich auf gespeicherte Zuordnungen. Beispielsweise entspricht „(.)\1“ zwei aufeinanderfolgenden identischen 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 den Wert 256 nicht überschreiten. Sollte dies der Fall sein, werden nur die ersten beiden Ziffern im Ausdruck berücksichtigt. Ermöglicht die Verwendung der Codes ASCII in regulären Ausdrücken.
\xn
Entspricht n, wobei n ein hexadezimaler Escape-Wert ist. Hexadezimale Escape-Werte müssen zwingend aus zwei Ziffern bestehen. Beispielsweise entspricht „\x41“ dem Zeichen „A“. „\x041“ entspricht „\x04“ und „1“. Ermöglicht die Verwendung der Codes ASCII in regulären Ausdrücken.

Ein Element in einer Vorlage kann ein- oder mehrfach vorkommen. Betrachten wir einige Beispiele rund um das Symbol \d, das für eine Ziffer steht:

Vorlage
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 das Modell vor, mit dem das erwartete Format einer Zeichenkette beschrieben werden kann:

gesuchte Zeichenfolge
Modell
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 möglicherweise leere Folge von Leerzeichen
\s*
eine vorzeichenlose Ganzzahl, der Leerzeichen vorangestellt oder nachgestellt sein können
\s*\d+\s*
eine ganze Zahl, die vorzeichenbehaftet sein kann und der Leerzeichen vorangestellt oder nachgestellt sein 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 Leerräume vorangestellt oder nachgestellt sein können
\s*[+|]?\s*\d+(.\d*)?\s*
eine Zeichenfolge, die das Wort „juste“ enthält
\bjuste\b
  

Man kann angeben, an welcher Stelle in der Zeichenfolge nach dem Muster gesucht werden soll:

Muster
Bedeutung
^Muster
Das Muster steht am Anfang der Zeichenfolge
Muster$
Das Muster beendet die Zeichenfolge
^Muster$
Das Muster beginnt und beendet die Zeichenfolge
Muster
Das Muster wird überall in der Zeichenkette gesucht, beginnend am Anfang der Zeichenkette.
gesuchte Zeichenfolge
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 nur aus einem Wort besteht, dem gegebenenfalls Leerzeichen vorangestellt oder nachgestellt sind
^\s*\w+\s*$
eine Zeichenfolge, die aus zwei Wörtern besteht, denen gegebenenfalls Leerzeichen vorangehen oder folgen
^\s*\w+\s*\w+\s*$
eine Zeichenfolge, die das Wort „secret“ enthält
\bsecret\b

Die Teilmengen eines Musters können „extrahiert“ werden. So lässt sich nicht nur überprüfen, ob eine Zeichenfolge einem bestimmten Muster entspricht, sondern es können auch die Elemente aus dieser Zeichenfolge extrahiert werden, die den in Klammern gesetzten Teilmengen des Musters entsprechen. Wenn man also eine Zeichenfolge analysiert, die ein Datum im Format TT/MM/JJ enthält, und zusätzlich die Elemente TT, MM und JJ dieses Datums extrahieren möchte, verwendet man das Muster (\d\d)/(\d\d)/(\d\d).

Sehen wir uns anhand dieses Beispiels an, wie man mit VBScript vorgeht.

  • Zunächst müssen wir ein Objekt RegExp (Regular Expression) erstellen
set modele=new regexp
  • Anschließend legen wir das zu testende Muster fest
modele.pattern="(\d\d)/(\d\d)/(\d\d)"
  • Möglicherweise möchten wir die Groß-/Kleinschreibung ignorieren (standardmäßig wird sie berücksichtigt). In diesem Fall spielt das keine Rolle.
modele.IgnoreCase=true
  • Man kann das Muster möglicherweise mehrmals in der Zeichenfolge suchen (standardmäßig ist dies nicht der Fall)
modele.Global=true

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

  • Man sucht dann nach allen Übereinstimmungen des Musters in der Zeichenkette:
set correspondances=modele.execute(chaine)

Die Methode execute eines Objekts RegExp gibt eine Sammlung von Objekten vom Typ „match“ zurück. Dieses Objekt verfügt über eine Eigenschaft „value“, die das Element von chaine angibt, das dem Muster entspricht. Wenn modele.global=true gesetzt wurde, können mehrere Übereinstimmungen vorliegen. Deshalb ist das Ergebnis der Methode execute eine Sammlung von Übereinstimmungen.

  • Die Anzahl der Übereinstimmungen wird durch correspondances.count angegeben. Ist diese Zahl gleich 0, wurde das Modell nirgendwo gefunden. Der Wert der Übereinstimmung Nr. i wird durch correspondances(i).value angegeben. Wenn das Muster in Klammern eingeschlossene Untermuster enthält, dann ist das Element von correspondances(i), das der Klammer j des Musters entspricht, „Übereinstimmungen(i).submatches(j)“.

All dies wird im folgenden Beispiel veranschaulicht:

Programm

' regulärer Ausdruck

' Es soll überprüft werden, ob eine Zeichenfolge ein Datum im Format TT/MM/JJ enthält

Option Explicit
Dim modele

' Man definiert das Muster
Set modele=new regexp
modele.pattern="\b(\d\d)/(\d\d)/(\d\d)\b"  ' une date n'importe où dans la chaîne
modele.global=true                      ' on recherchera le modèle plusieurs fois dans la chaîne

' Der Benutzer gibt die Zeichenfolge an, in der nach dem Muster gesucht wird
Dim chaine, correspondances, i

chaine=""
' Es wird so lange eine Schleife durchlaufen, wie die Zeichenfolge ungleich „Ende“ ist
Do While true
     ' Der Benutzer wird aufgefordert, einen Text einzugeben
    wscript.stdout.writeLine "Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrêter : "
    chaine=wscript.stdin.readLine
     ' Beenden, wenn Zeichenfolge = „Ende“
    If chaine="fin" Then Exit Do
     ' Die eingelesene Zeichenkette wird mit dem Datumsmuster verglichen
    Set correspondances=modele.execute(chaine)
     ' Wurde eine Übereinstimmung gefunden?
    If correspondances.count<>0 Then
         ' Es gibt mindestens eine Übereinstimmung
        For i=0 To correspondances.count-1
             ' Die Übereinstimmung i wird angezeigt
            wscript.echo "J'ai trouvé la date " & correspondances(i).value
             ' Die Unterelemente der Übereinstimmung i werden abgerufen
            wscript.echo "Les éléments de la date " & i & " sont (" & correspondances(i).submatches(0) & "," _
            & correspondances(i).submatches(1) & "," & correspondances(i).submatches(2) & ")"
        Next
    Else
         ' kein Treffer
        wscript.echo "Je n'ai pas trouvé de date au format jj/mm/aa dans votre texte"
    End If
Loop

' Fertig
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 regulären Ausdrücken könnte das Programm, das prüft, ob eine Tastatureingabe tatsächlich eine positive ganze Zahl ist, wie folgt geschrieben werden:

Programm

' Ein Datenelement wird so lange gelesen, bis es als Zahl erkannt wird

Option Explicit

Dim fini, nombre

' Das Muster einer positiven ganzen Zahl (die jedoch Null sein kann) wird definiert
Dim modele
Set modele=new regexp
modele.pattern="^\s*\d+\s*$"

' Es wird so lange eine Schleife durchlaufen, bis die eingegebenen Daten korrekt sind
' Die Schleife wird durch eine boolesche Variable gesteuert, die zu Beginn auf „falsch“ gesetzt ist (= noch nicht beendet)

fini=false
Do While Not fini
     ' Die Zahl wird abgefragt
    wscript.stdout.write "Tapez un nombre entier >0: "
     ' die Zahl wird eingelesen
    nombre=wscript.stdin.readLine
     ' Das Format der eingelesenen Daten wird geprüft
    Dim correspondances
    Set correspondances=modele.execute(nombre)
     ' Wurde das Muster überprüft?
    If correspondances.count<>0 Then
         ' Es handelt sich um eine ganze Zahl, aber ist sie > 0?
        nombre=cint(nombre)
        If nombre>0 Then
            fini=true
        End If
    End If
     ' Mögliche Fehlermeldung
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' Bestätigung
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' und Ende
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 ist manchmal eine echte Herausforderung, 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 üben. Es fragt nach einem Muster und einer Zeichenkette und gibt dann an, ob die Zeichenkette dem Muster entspricht oder nicht.

Programm

' Regulärer Ausdruck

' Man möchte überprüfen, ob eine Zeichenkette einem Muster entspricht

Option Explicit

' Man definiert das Muster
Dim modele
Set modele=new regexp
modele.global=true                      ' on recherchera le modèle plusieurs fois dans la chaîne

' Der Benutzer gibt die Zeichenfolge ein, in der nach dem Muster gesucht wird
Dim chaine, correspondances, i

Do While true
     ' Der Benutzer wird aufgefordert, ein Muster einzugeben
    wscript.stdout.write "Tapez le modèle à tester et fin pour arrêter : "
    modele.pattern=wscript.stdin.readLine
     ' Fertig?
    If modele.pattern="fin" Then Exit Do
         ' Der Benutzer wird aufgefordert, die mit der Vorlage zu vergleichenden Zeichenfolgen anzugeben
        Do While true
             ' Der Benutzer wird aufgefordert, ein Muster einzugeben
            wscript.stdout.writeLine "Tapez la chaîne à tester avec le modèle [" & modele.pattern & "] et fin pour arrêter : "
            chaine=wscript.stdin.readLine
             ' Fertig?
            If chaine="fin" Then Exit Do
             ' Die eingelesene Zeichenfolge wird mit dem Datumsmuster verglichen
            Set correspondances=modele.execute(chaine)
             ' Wurde eine Übereinstimmung gefunden?
            If correspondances.count<>0 Then
                 ' Es gibt mindestens eine Übereinstimmung
                For i=0 To correspondances.count-1
                     ' Die Übereinstimmung i wird angezeigt
                    wscript.echo "J'ai trouvé la correspondance " & correspondances(i).value
                Next
            Else
                 ' keine Übereinstimmung
                wscript.echo "Je n'ai pas trouvé de correspondance"
            End If
    Loop
Loop

' Fertig
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. Laufzeitfehler abfangen

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

on error resume next

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

on error goto 0

Diese Anweisung versetzt uns wieder in den normalen Fehlerbehandlungsmodus zurück.

Wenn die Anweisung „on error resume next“ aktiv ist, müssen wir eventuell auftretende Fehler selbst behandeln. Dabei hilft uns das Objekt „Err“. Dieses Objekt verfügt über verschiedene Eigenschaften und Methoden, von denen wir die folgenden beiden hervorheben möchten:

  • number: Eine ganze Zahl, die die Nummer des zuletzt aufgetretenen Fehlers angibt. 0 bedeutet „kein Fehler“
  • Beschreibung: Die Fehlermeldung, die das System angezeigt hätte, wenn der Befehl „on error resume next“ nicht ausgegeben worden wäre

Sehen wir uns das folgende Beispiel an:

Programm


' Fehler nicht behandelt

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'

Behandeln wir nun den Fehler:

Programm

' Fehler behandelt

Option Explicit
Dim nombre

' Wir behandeln die Fehler selbst
On Error Resume Next
nombre=cdbl("abcd")
' Ist ein Fehler aufgetreten?
If Err.number<>0 Then
    wscript.echo "L'erreur [" & err.description & "] s'est produite"
    On Error GoTo 0
    wscript.quit 1
End If
' kein Fehler – Rückkehr zum Normalbetrieb
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


' Daten werden so lange eingelesen, bis sie als Zahl erkannt werden

Option Explicit

Dim fini, nombre

' Die Schleife wird so lange wiederholt, bis die eingegebenen Daten korrekt sind
' Die Schleife wird durch eine endliche Boolesche Variable gesteuert, die zu Beginn auf „falsch“ gesetzt ist (= noch nicht beendet)

fini=false
Do While Not fini
  ' Die Zahl wird abgefragt
  wscript.stdout.write "Tapez un nombre entier >0: "
  ' sie wird eingelesen
  nombre=wscript.stdin.readLine
  ' Das Format der eingelesenen Daten wird geprüft
  On Error Resume Next
  nombre=cdbl(nombre)
  If err.number=0 Then
    ' Kein Fehler, es handelt sich um eine Zahl
    ' Rückkehr zum normalen Fehlerbehandlungsmodus
    On Error GoTo 0
    ' Ist es eine ganze Zahl > 0?
    If (nombre-int(nombre))=0 And nombre>0 Then
      fini=true
    End If
  End If
  ' Rückkehr zum normalen Fehlerbehandlungsmodus
  On Error GoTo 0
  ' Mögliche Fehlermeldung
  If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' Bestätigung
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' und Ende
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. Man darf dann nicht vergessen, zum normalen Fehlerbehandlungsmodus zurückzukehren, sobald die Anweisungssequenz, die den Fehler auslösen könnte, beendet ist.

4.4. Anwendung auf das Steuerberechnungsprogramm

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

Programm


' Berechnung der Steuer eines Steuerpflichtigen
' Das Programm muss mit drei Parametern aufgerufen werden: verheiratet, Kinder, Gehalt
' verheiratet: Zeichen O, wenn verheiratet, N, wenn unverheiratet
' Kinder: Anzahl der Kinder
' Gehalt: Jahresgehalt ohne Cent

' Es wird keine Überprüfung der Datengültigkeit durchgeführt, aber es
' wird überprüft, ob es tatsächlich drei sind

' Variablendeklaration obligatorisch
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)"

' Es wird überprüft, ob 3 Argumente vorhanden sind
  Dim nbArguments
  nbArguments=wscript.arguments.count
  If nbArguments<>3 Then
    ' Fehlermeldung
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect"
    ' Abbruch mit Fehlercode 1
    wscript.quit 1
  End If

' Die Argumente werden abgerufen und auf ihre Gültigkeit überprüft
' Ein Argument wird ohne Leerzeichen davor und dahinter an das Programm übergeben
' Zur Überprüfung der Gültigkeit der Daten werden reguläre Ausdrücke verwendet
  Dim modele, correspondances
  Set modele=new regexp

  ' Der Familienstand muss zu den Zeichen oOnN gehören
  modele.pattern="^[oOnN]$"
  Set correspondances=modele.execute(wscript.arguments(0))
  If correspondances.count=0 Then
    ' Fehler
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect"
    ' Beenden
    wscript.quit 2
  End If
  ' Der Wert wird abgerufen
  Dim marie
  If lcase(wscript.arguments(0)) = "o"Then
    marie=true
  Else
    marie=false
  End If

  ' „Kinder“ muss eine ganze Zahl >= 0 sein
  modele.pattern="^\d{1,2}$"
  Set correspondances=modele.execute(wscript.arguments(1))
  If correspondances.count=0 Then
    ' Fehler
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect"
    ' Beenden
    wscript.quit 3
  End If
  ' Wert wird abgerufen
  Dim enfants
  enfants=cint(wscript.arguments(1))

  ' Das Gehalt muss eine ganze Zahl >= 0 sein
  modele.pattern="^\d{1,9}$"
  Set correspondances=modele.execute(wscript.arguments(2))
  If correspondances.count=0 Then
    ' Fehler
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect"
    ' Beenden
    wscript.quit 4
  End If
  ' Wert wird abgerufen
  Dim salaire
  salaire=clng(wscript.arguments(2))

  ' Die für die Steuerberechnung erforderlichen Daten werden in drei Tabellen definiert
  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)

  ' Anzahl der Anteile berechnen
  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

  ' man berechnet den Familienquotienten und das zu versteuernde Einkommen
  Dim revenu, qf
  revenu=0.72*salaire
  qf=revenu/nbParts

  ' Die Steuer wird berechnet
  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))

  ' Das Ergebnis wird angezeigt
  wscript.echo "impôt=" & impot

  ' Das Programm wird ohne Fehler beendet
  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