BUGS
If you find bugs, please try to fix them - but please report them to me as well. If you fix them, please let me have a copy of the fix.
I haven't found any bugs, but I have a suggestion which -- IMHO -- would improve ValReal (the same applies to ValInteger, etc).
First, my modified ValReal; second, an explanation of the modification.
type str255 = string [255];
function sscanf (inputstr, format : pChar; ... ) : Integer; C;
Procedure ValReal ( S : str255; var Dest : Double; var ErrCode : Integer ); Var i, c : integer; Begin s[Length(s)+1] := chr ( 0 ); { s := s + chr(0) }
c := sscanf (pChar (@s[1]), "%lf", @dest); { Read double variable }
if (c = 1) then { sscanf returned one number = NO errors } begin ErrCode := 0; Exit; end;
{ There is an error in s; locate it for compatibility with BP Val proc }
{ check for non-numeric values} for i := 1 to length ( s ) do if s [i] in ['0' .. '9', '.', '-'] then {} else begin ErrCode := i; Break; end; end;{* ValReal *}
COMMENTS:
1) The C library function converting the null-terminated string into a double checks for errors itself (sscanf returns 0 if the string cannot be converted to a double; meaning 0 values read from the string), so there is no need to parse the string (to find the position where the error occurs), unless there is an error in the string. BTW, this speedup is not possible with atof because atof returns 0.0 if the string cannot be converted to a double. That's why I use sscanf instead (sscanf is ANSI C, and must be in any C library, so no concerns about portability between Linux, DJGPP, etc).
As an aside, the string '1.1e3', is now converted to 1100.0, which is the correct behavior. The code checking for errors should really be rewritten to handle this. For example, the error position for '1.0ef3' is not at position 4, but the 'f' at position 5. Adding 'e' to the list of admissible chars would improve things a bit, but still not totally correct.
2) The formal parameter S is declared as a string[255], instead of the schema type 'string' (which has a different meaning than in Borland Pascal, where it means string[255]). As you add a #0 to the string variable 's', it should be large enough not to overflow (length gets out of range).
I don't think the original version would work if called with a string constant, because S would be a string with the same length as the string constant, and adding #0 would (should) cause an exception.
3) Unless GPC is really good at optimizing string expressions, the "hack"
s[Length(s)+1] := chr ( 0 )
is faster than adding chr(0) to the string variable. Of course, it cannot be range-checked ...
Best wishes,
Jesper Lund