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:
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
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
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:
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
- Dann legen wir das zu prüfende Muster fest
- Möglicherweise möchten Sie die Groß-/Kleinschreibung ignorieren (standardmäßig wird die Groß-/Kleinschreibung beachtet). Hier spielt das keine Rolle.
- Möglicherweise möchten Sie mehrmals nach dem Muster in der Zeichenfolge suchen (standardmäßig ist dies nicht der Fall)
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:
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
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
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
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:
Diese Anweisung teilt dem System (WSH) mit, dass wir Fehler selbst behandeln werden. Nach dieser Anweisung werden alle Fehler vom System einfach ignoriert.
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
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
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