Speaker Posted April 10, 2006 Share Posted April 10, 2006 I have written these functions because IMO the standard AutoIt conversion function called 'Number()' is inadequate, e.g. it just stops conversion when a non-digit character is found. If _any_ kind of badly formed string is found, the function should report an error and abort conversion. Also 'Number() does not distinguish integers and floats which may be important in certain situations, and it cannot convert binary or hexadecimal strings. My functions are intended for situations when error reporting is important (e.g. manual input or reading values from a text file). If you are absolutely sure that there will be no errors in the number format then you can use 'Number(). But can you ever be absolutely sure? At the end of this post, in separate code sections, there are to simple test scripts to demostrate how these functions work. Description of functions: StringToInt(str, base) Converts the string 'str' to an integer using the number base 'base' (2, 10 or 16). Returns the converted value. In case of error the return value is zero. Sets '@error' as follows: 0 = no error -1 = bad argument(s) -2 = string too long or too short -3 = string contains non-digit character(s) StringToFloat(str) Converts the string 'str' to a floating point number. Accepts the following formats ('n' represents one or more decimal digits): n -n .n -.n n. -n. n.n -n.n nEn nE-n -nEn -nE-n n.nEn -n.nEn n.nE-n -n.nE-n There must be at most 3 digits in the exponent, and its absolute value must not be larger than 300. The maximum number of characters in 'str' is 22 (sufficient for 15-digit precision in the longest format with full exponent and two minus signs). Returns the converted value. In case of error returns zero. Sets '@error' as follows: 0 = no error -1 = bad argument -2 = string too long or too short -3 = non-digit character where digit is expected -4 = formatting error (not a proper floating point number) Formatting errors (code -4) include: - neither integer nor fractional part present - decimal point is after the exponent mark 'E' - minus sign is in bad position (not the first char in exponent) - multiple decimal points - multiple exponent marks 'E' - Exponent marker 'E' without exponent digits - too many digits in exponent - exponent value too big (> 300) expandcollapse popup; numconv.au3 ; ; String to number conversion with proper error detection and reporting. ; ; AutoIt Version: 3.0 ; Language: English ; Platform: Win9x/NT ; Author: Laszlo Menczel (menczel@invitel.hu) ; Date: 4/9/2006 ; ; Include this file at the start of your script (use 'include-once'). ; Exp10(pow) ; Helper function to calculate power of 10 (for exponent values). ; WARNING: This is NOT a general purpose function, it works only with integer arguments! Func Exp10($pow) Dim $i, $res, $x $x = Round($pow) If $x = 0 Then Return 1 Endif $res = 1; If $x > 0 Then For $i = 1 TO $x $res = 10.0 * $res Next Else $x = -1 * $x For $i = 1 TO $x $res = $res / 10.0 Next Endif Return $res EndFunc ;------------------------------------------------------------------------------- ; CharToNumber(chr, digits) ; Helper function to get the numeric value of a character interpreted ; as a digit. Valid characters are specified in 'digits'. Func CharToNumber($chr, $dig) Dim $pos, $next, $len $len = StringLen($dig) $pos = 1 While $pos <= $len $next = StringMid($dig, $pos, 1) If $chr = $next Then Return $pos - 1 Endif $pos = $pos + 1 Wend Return -1 EndFunc ;------------------------------------------------------------------------------- Func StringToInt($s, $base) Dim $pos, $len, $maxlen, $val, $tmp Dim $fact, $mult, $sum, $sign, $digits, $start If $s = "" Then SetError(-1) Return 0 Endif If $base <> 2 AND $base <> 10 AND $base <> 16 Then SetError(-1) Return 0 Endif $start = 1 $sign = 1 Select Case $base = 2 $mult = 2 $maxlen = 32 $digits = "01" Case $base = 10 $mult = 10 $maxlen = 10 $digits = "0123456789" $tmp = StringMid($s, 1, 1) If $tmp = "-" Then $maxlen = $maxlen + 1 $start = 2 $sign = -1 Endif Case $base = 16 $mult = 16 $maxlen = 8 $digits = "0123456789ABCDEF" EndSelect $pos = StringLen($s) If $pos > $maxlen OR ($pos - $start) < 1 Then SetError(-2) Return 0 Endif $fact = 1 $sum = 0 While $pos >= $start $tmp = StringMid($s, $pos, 1) $val = CharToNumber($tmp, $digits) If $val = -1 Then SetError(-3) Return 0 Endif $sum = $sum + $fact * $val $fact = $fact * $mult $pos = $pos - 1 Wend $sum = $sum * $sign SetError(0) Return $sum EndFunc ;------------------------------------------------------------------------------- Func StringToFloat($s) Dim $tmp, $val, $factor, $len, $pos, $start, $digits Dim $int_present, $frac_present, $exp_present Dim $dotpos, $fracval, $intval, $sign Dim $exppos, $expbeg, $expval, $expsign ;--------- check argument If $s = "" Then SetError(-1) Return 0.0 Endif $len = StringLen($s) If $len < 1 OR $len > 22 Then SetError(-2) Return 0.0 Endif ;----------- initialize variables $sum = 0.0 $sign = 1.0 $expsign = 1.0 $expval = 0.0 $fracval = 0.0 $intval = 0.0 $int_present = 0 $frac_present = 0 $exp_present = 0 $start = 1 $digits = "0123456789" ;----------- scan string & collect info $tmp = StringMid($s, 1, 1) ; check for minus sign If $tmp = "-" Then If $len < 2 Then ; no digits SetError(-2) Return 0.0 Else $sign = -1.0 $start = 2 Endif Endif $dotpos = 0 $exppos = $len + 1 $pos = $start While $pos <= $len $tmp = StringMid($s, $pos, 1) Select Case $tmp = "." If $dotpos > 0 Then ; multiple decimal points SetError(-4) Return 0.0 Else $dotpos = $pos Endif Case $tmp = "e" ; multiple exponent markers If $exppos < $len + 1 Then SetError(-4) Return 0.0 Else $exppos = $pos Endif EndSelect $pos = $pos + 1 Wend ;----------- check positions & set flags If $dotpos > $exppos Then SetError(-4) Return 0.0 Endif If $exppos < $len + 1 Then $expbeg = $exppos If $expbeg = $len Then ; no exponent spec SetError(-4) Return 0.0 Endif $tmp = StringMid($s, $expbeg + 1, 1) If $tmp = "-" Then ; check for minus sign $expbeg = $expbeg + 1 If $expbeg = $len Then ; no digits SetError(-4) Return 0.0 Else If ($len - $expbeg) > 3 Then ; too many digits SetError(-4) Return 0.0 Else $expsign = -1.0 Endif Endif Endif $exp_present = 1 Endif If $dotpos > 0 Then ; decimal point present If ($exppos - $dotpos) > 1 Then $frac_present = 1 Endif If ($dotpos - $start) > 0 Then $int_present = 1 Endif Else ; only integer part if any If ($exppos - $start) > 0 Then $int_present = 1 Endif Endif If $int_present = 0 AND $frac_present = 0 Then SetError(-4) Return 0.0 Endif ;----------- convert the exponent if present If $exp_present > 0 Then $pos = $len $factor = 1.0 $expval = 0.0 While $pos > $expbeg $tmp = StringMid($s, $pos, 1) $val = CharToNumber($tmp, $digits) If $val < 0 Then SetError(-3) Return 0.0 Else $expval = $expval + $val * $factor $factor = 10.0 * $factor Endif $pos = $pos - 1 Wend If $expval > 300 Then SetError(-4) Return 0.0 Endif Endif ;----------- convert fractional part if present If $frac_present > 0 Then $pos = $dotpos + 1 $factor = 0.1 While $pos < $exppos $tmp = StringMid($s, $pos, 1) $val = CharToNumber($tmp, $digits) If $val < 0 Then SetError(-3) Return 0.0 Else $fracval = $fracval + $val * $factor $factor = $factor / 10.0 Endif $pos = $pos + 1 Wend Endif ;------------ convert integer part if present If $int_present > 0 Then If $dotpos > 0 Then $pos = $dotpos - 1 Else $pos = $exppos - 1 Endif $factor = 1.0 While $pos >= $start $tmp = StringMid($s, $pos, 1) $val = CharToNumber($tmp, $digits) If $val < 0 Then SetError(-3) Return 0.0 Else $intval = $intval + $val * $factor $factor = $factor * 10.0 Endif $pos = $pos - 1 Wend Endif ;------------ calculate & return the final value $val = $sign * ($intval + $fracval) * Exp10($expsign * $expval) SetError(0) Return $val EndFunc ; Script to test StringToInt() #include <GUIConstants.au3> #include "numconv.au3" Opt("ExpandVarStrings", 1) Opt("RunErrorsFatal", 0) $tmp = InputBox("Number base", "2, 10 or 16:") $x = Number($tmp) If $x <> 2 AND $x <> 10 AND $x <> 16 Then $str = StringFormat("bad number base %s", $tmp) MsgBox(0, "Error", $str) Exit Endif $tmp = InputBox("Input", "String to convert:") $val = StringToInt($tmp, $x) If @error = 0 Then $tmp = StringFormat("value = %d", $val) MsgBox(0, "Result", $tmp) Else $tmp = StringFormat("error %d", @error) MsgBox(0, "Result", $tmp) Endif Exit ; Script to test StringToFloat() #include <GUIConstants.au3> #include "numconv.au3" Opt("ExpandVarStrings", 1) Opt("RunErrorsFatal", 0) $tmp = InputBox("Input", "String to convert:") $val = StringToFloat($tmp) If @error = 0 Then $tmp = StringFormat("value = %f", $val) MsgBox(0, "Result", $tmp) Else $tmp = StringFormat("error %d", @error) MsgBox(0, "Result", $tmp) Endif Exit Link to comment Share on other sites More sharing options...
Jango Posted April 10, 2006 Share Posted April 10, 2006 hi, I would line to ask you it you pay attention that the decimal separator can be different than the dot "." in other countries ? Here it's the coma "," for example.. i don't know if it can be modified easily ? Cya Link to comment Share on other sites More sharing options...
RazerM Posted April 10, 2006 Share Posted April 10, 2006 nice function. @Jango If you look through the script you could easily change the '.' to a ',' or add in a stringreplace that changes the ',' to a '.' My Programs:AInstall - Create a standalone installer for your programUnit Converter - Converts Length, Area, Volume, Weight, Temperature and Pressure to different unitsBinary Clock - Hours, minutes and seconds have 10 columns each to display timeAutoIt Editor - Code Editor with Syntax Highlighting.Laserix Editor & Player - Create, Edit and Play Laserix LevelsLyric Syncer - Create and use Synchronised Lyrics.Connect 4 - 2 Player Connect 4 Game (Local or Online!, Formatted Chat!!)MD5, SHA-1, SHA-256, Tiger and Whirlpool Hash Finder - Dictionary and Brute Force FindCool Text Client - Create Rendered ImageMy UDF's:GUI Enhance - Enhance your GUIs visually.IDEA File Encryption - Encrypt and decrypt files easily! File Rename - Rename files easilyRC4 Text Encryption - Encrypt text using the RC4 AlgorithmPrime Number - Check if a number is primeString Remove - remove lots of strings at onceProgress Bar - made easySound UDF - Play, Pause, Resume, Seek and Stop. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now