vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Erstellen von dynamischen Kontextmen?s - wann immer Sie sie brauchen!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück
Rubrik: Variablen/Strings   |   VB-Versionen: VB200821.04.09
Beschreibung der Funktion 'VAL'

Details zur Arbeitsweise der Val-Funktion

Autor:   Manfred BohnBewertung:     [ Jetzt bewerten ]Views:  15.470 
ohne HomepageSystem:  Win2k, WinXP, Win7, Win8, Win10, Win11kein Beispielprojekt 

Die Val-Funktion (in 'Microsoft.VisualBasic.Conversion') wandelt einen (Teil-) String in einen 'Double'-Wert, bzw. ein Einzelzeichen in einen Integer um.

Obwohl es sich dabei um eine "klassische" Basic-Funktion handelt, ist ihr Gebrauch aufgrund des sehr speziellen Verhaltens KAUM ZU EMPFEHLEN.

Bevorzugen sie die 'TryParse'-Methode, die bei den numerischen Datentypen enthalten ist, oder greifen Sie auf die Methoden von 'System.Convert' zurück. Die grundsätzlichen Unterschiede zu 'Val' besteht darin, dass die 'Numerics' aufgrund kulturspezifischer Kennungen gebildet werden und dass immer der gesamte String einbezogen wird.

Die VB-Dokumentation der 'Val'-Funktion ist unvollständig, so dass es zu Mißverständnissen und in der Folge zu Fehlanwendungen kommen kann.

Deshalb hier eine Übersicht über wichtige Eigenarten der Arbeitsweise von 'Val':
Übergibt man als Parameter ein einzelnes Zeichen, erhält man '0.0#' zurück (bzw. die dem Zeichen entsprechende Ziffer als 'Integer'-Wert).

Bei String-Parametern gilt:
Die Funktion 'Val' unterscheidet bei der Analyse des als Parameter übergebenen Strings grundsätzlich drei Arten von Zeichen:

  • ignorierte Zeichen ( = Zeilenvorschub, Tabulator, Leerzeichen), gleichgültig an welcher Stelle im String sie stehen;
  • numerisch interpretierbare Zeichen (Standard-Vorzeichen, Ziffern, Exponentialkennungen E,e und D,d, Exponentialvorzeichen und die nachgestellten BASIC-Typsymbole %, &, !, #, @), sowie den Standard-Dezimalseparator (.)
  • Abbruchzeichen (alle anderen Zeichen und die Wiederholung von bereits gesetzten Numeric-Kennungen); der Rest-String hinter dem ersten Abbruchzeichen wird ignoriert.

Im einzelnen:
Wenn bereits das erste Zeichen im String als Abbruchzeichen identifiziert worden ist, gibt die Funktion 0.0# zurück. Das gilt auch in allen Fällen, in denen kein Numeric erkannt werden konnte. Man kann bei der Rückgabe von 0.0# nicht entscheiden, ob er einem gültigen 'Numeric'-String entspricht.

Obwohl 'Val' unter bestimmten Bedingungen Ausnahmen auslöst, tut sie das in wichtigen Fällen nicht.

Die Val-Funktion erkennt kulturspezifische Zeichen nicht und wertet sie deshalb als Abbruchkennung. Auch das in Deutschland übliche Dezimaltrennzeichen ',' wird von der 'Val'-Funktion als Abbruchkennung identifiziert. Die Strings zur Identifikation von IEEE-Sonderwerten (z. B. "n. def.") sind ebenfalls kulturspezifisch und werden deshalb von der 'Val'-Funktion nicht erkannt.

Numerische Werte werden nach starren Regeln gebildet:

  • vorangestelltes Vorzeichen: + oder -
  • Dezimaltrennzeichen: .
  • Exponentialdarstellung: E, e, D, d
  • Exponential-Vorzeichen hinter D/E: + oder -

Wenn dem Exponent-Identifizierer kein gültiger numerischer Teilstring folgt, dient er als AbbruchKennung. Der Code Val("123E-W") liefert deshalb 123,0#. Ein Exponent-Überlauf führt aber zu einer Overflow-Exception. Im Exponentteil wird das Dezimaltrennzeichen ggf. als Abbruchkennung identifiziert. Der Aufruf Val("123E3.5") ergibt 123000.0#.

Im 'visuellen' Basic sonst ungewohnt, wird als Exponentialdarstellung auch das Zeichen 'D' identifiziert. Die Konvertierung und Verarbeitung erfolgt immer im Datentyp 'Double'; das bedeutet auch, dass diese Zeichen im Ergebnis keine Exponentialdarstellung erzwingen können.

Bei der Wiederholung eines der Numeric-Kenner im Parameter-String wird das zweite Auftreten als Abbruchkennung gewertet.

Die oben genannten VB-Datentyp-Identifizierer werden von der 'Val'-Funktion ausgewertet, dienen aber zugleich als Abbruchkennung.
Man beachte (VB.Net), dass die Identifizierer den Standard früherer BASIC-Versionen wiederspiegeln. Das Prozentzeichen steht deshalb für einen 16-Bit-Integer (=Net-VB: Short) und das kaufm. Pluszeichen für einen 32-Bit-Integer (=Net-VB: Integer).

Identifizierer können bei falscher Verwendung zur Auslösung von Ausnahmen führen:

  • Der Code Val("2.5&") liefert deshalb eine Fehlermeldung, weil 2.5 keine Ganzzahl ist.
  • Der String "42345%" wirft eine 'Overflowexception', weil die Obergrenze des Datentyps 'Short' überschritten wird.
  • Der String Val("-1E30@") führt zum Überlauf, weil das Limit des Datentyps 'Decimal' unterschritten ist.

Der Code Val("2.5123456789123!") wirft keine Ausnahme, führt aber ein Parsen im Datentyp 'Single' durch. Das Ergebnis wird dann in einen 'Double'-Wert konvertiert (Rückgabe: 2.5123457908630371 - nur 8 gültige Stellen!!). Der String "1E60!" führt deshalb zur Rückgabe des IEEE-Sonderwertes 'PositiveInfinity'.

Die Literalzeichen für Datentypen (z.B. "D" oder "UL") werden nicht identifiziert, sondern wirken als Abbruchkennung.

Obwohl die Funktion 'Double' zurückgibt, akzeptiert sie oktale und hexadezimale Zeichen, denen ein entsprechender Identifizierer vorangestellt ist. Der Code Val("&HFFF") liefert 4095.0# und entspricht somit der Rückgabe von CDbl(Convert.ToInt32("FFF", 16)).

Der Code Val("&O111") ergibt 73.0# => CDbl(Convert.ToInt32("111", 8).
Bei diesen Präfixen kommt es ggf. NICHT zu einer Überlauf-Ausnahme, sondern es wird 0.0# zurückgegeben. Ungültige Ziffern werden als Abbruchkennung verwendet. Der Code Val("&O118") gibt deshalb 9.0# zurück (= &O11), weil bei der oktal ungültigen Ziffer '8' abgebrochen wird.

Die Funktion akzeptiert als Eingabe nicht nur eine Stringvariable, sondern einen beliebigen Ausdruck (der freilich eine numerisch interpretierbare Zeichenfolge ERGEBEN muss.) Es ist z.B. nicht möglich, eine StringBuilder-Variable direkt als Argument zu verwenden - die Methode 'ToString' ist erforderlich. Der Code Val(1 + 7) ergibt - als Ergebnis eines Ausdrucks - 8.0#. Der Code Val("1+7") liefert 1.0#, weil innerhalb eines String das Additionszeichen als Abbruchkennung dient.

Wenn der Nachkomma-Anteil in einem numerischen String zu 'lang' für 'Double' ist (Ziffernfolge), wird der Rest-String ignoriert. Wie viele Ziffern einbezogen werden, hängt von der jeweiligen Größe des Vorkomma-Wertes ab.
Enthält der Vorkommaanteil zu viele Stellen, wird er - wie bei 'Double' üblich - mit reduzierter Genauigkeit verarbeitet und in Exponentialdarstellung angezeigt. Zu lang darf der numerische Anteil des Strings nicht werden. Der Code Val(StrDup(308, "1")) wird noch ausgeführt. Längere Ziffernfolgen oder Exponenten > +/-307 können zu einem Double-Überlauf führen. Bei einem Überlauf des Datentyps 'Double' wird von 'Val' eine entsprechende Ausnahme ausgelöst.

Das Ignorieren von Tabulatoren und Zeilentrennern ist als besonders problematisch einzustufen. Der Code Val("12345." & vbTab & "678") liefert den Wert 12345,678. Beim Einlesen von Strings aus einer Datei ist Vorsicht geboten.

In den aktuellen VB-Versionen gibt es die sogenannten 'White-Space'-Zeichen ('Leerraumzeichen'), die z.B. in der Dokumentation der Methode 'String.Trim' aufgelistet sind. Eine erweiterte Liste steht bei der Methode 'Char.IsWhiteSpace'. Dort findet sich auch der Verweis auf die 'UniCode'-Zeichenkategorien. (Der in der deutschen VB-Dokumentation verwendete Begriff 'Leerraumzeichen' ist irreführend. Es handelt sich um Zeichen, die bei bestimmten Funktionen als Identifizierer für spezielle Bearbeitungen - Separatoren, Vorschübe u.a. - interpretiert werden.)

'Val' eliminiert NUR einige der in BASIC ('Namespace: Microsoft.VisualBasic') definierten 'White-Space'-Zeichen: Leerzeichen (vBEmpty), Tabulator (vbTab), Zeilenvorschub (vbLf, vbNewLine) und Wagenrücklauf (vbCR). Andere in BASIC definierte Sonderzeichen werden von 'Val' NICHT entfernt, z.B. 'vbBack', 'vbFormFeed'. Diese Zeichen-Codes stammen noch aus der Zeit vor UNICODE. Die ersten 128 UNICODE-Zeichen entsprechen aber den ersten 128 ASCII-Zeichen.

Vor den Aufruf von 'Val' sollte man im Einzelfall folgende Zeichenersetzungen in Erwägung ziehen:

Dim Str as String = "irgendein numerischer String"
 
Str.Trim ' White-Spaces am Anfang und Ende des Strings entfernen
Str.Replace(",", ".") ' kulturspezifischer Dezimalpunkt --> Standard-Dezimalpunkt
 
Str.Replace(vbCr, "X") ' Zeilen-Zusammenfassung vermeiden
Str.Replace(vBLf, "X")
Str.Replace(vbTab, "X") ' Feld-Zusammenfassung vermeiden
 
Str.Replace(" ", "X") ' Leerzeichen als Abbruchkennung identifizierbar machen
 
Str.Replace("%", "X") ' Short-Überlauf verhindern 
Str.Replace("&", "X") ' Integer-Überlauf verhindern
Str.Replace("@", "X") ' Decimal-Überlauf verhindern
Str.Replace("!", "X") ' Single-Überlauf verhindern

Das nicht-numerische Zeichen "X" dient dabei als Abbruchkennung. Beachten Sie aber, dass sich durch die Ersetzung des Datentyp-Identifizierers der Parse-Vorgang ändert - er wird dann als 'Double' vorgenommen - so dass ein unterschiedliches Resultat zustande kommen kann:

Val("2.5123456789123!") --> 2.5123457908630371 ' Single-Parser
Val("2.5123456789123X") --> 2.5123456789123 ' Double-Parser

Falls die kulturspezifischen 'Signs' vom Standard abweichen sollten, ist ebenfalls eine Ersetzung erforderlich.

Um alle 'White-Space'-Character innerhalb des String zu entfernen (meist nicht empfehlenswert!) müssen Sie den String zunächst zeichenweise durch die Methode 'Char.IsWhiteSpace' analysieren.

Als eine 'Umkehrfunktion' von 'Val' kann 'Str' eingestuft werden. Auch diese Routine arbeitet nicht mit den kulturspezifischen Zeichen. Es handelt sich bei beiden Funktionen um 'Überbleibsel' aus den Anfängen von BASIC.

Hinweis für VB6-Umsteiger:
Wenn Sie sich jetzt wundern, liegen Sie richtig!

Obwohl die 'Val'-Funktion dem klassischen BASIC entstammt, hat sie ihr Verhalten den Framework-Eigenarten anpassen müssen.

Ausdrücke, die in VB6 zu einer Überlauf-Ausnahme führen - Val(199 / 0) - ergeben in VB2008 einen IEEE-Sonderwert.

In VB6 ignoriert 'Val' den Typ-Identifizierer 'Single', parst immer im Datentyp 'Double'. Die oben angegebene Unterscheidung zwischen Single- und Double-Parser gibt es nicht.

In VB6 akzeptiert 'Val' beim Datentyp-Identifizierer für 'Decimal' nur Ganzzahlen und löst sonst eine Ausnahme aus. Der Code Val("1.11111111@") liefert in VB2800 den Wert '1.11111111'.

Bitte beachten Sie, dass ich die Unterschiede nur grob untersucht habe. Weitere Abweichungen sind durchaus möglich.

Dieser Tipp wurde bereits 15.470 mal aufgerufen.

Voriger Tipp   |   Zufälliger Tipp   |   Nächster Tipp

Über diesen Tipp im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Tipp, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel