home *** CD-ROM | disk | FTP | other *** search
- FUNCTION char2real(inchar : CHAR;VAR out# :REAL):BOOLEAN;
- {
- Comment : converts a numeric character to its equivalent REAL value.
- If successful returns TRUE , else FALSE.
- }
- VAR testchar : BOOLEAN;
- BEGIN
- testchar := inchar IN ['0'..'9'];
- IF testchar THEN out# := ORD(inchar) - ORD('0');
- char2real := testchar;
- END; { of : function char2real }
-
- FUNCTION str2real(VAR inputstr : str255;
- VAR real# : REAL) : BOOLEAN;
- {
- Comment : Parses a string that represents a real number and calculates
- the corresponding value.Unlike the Pascal/Z parser it is not upset if
- the string contains a period without a preceding zero. As of 9/15/82 I
- have not yet incorporated checks to prevent floating input underflow
- or overflow.These should be added in the future.
- Requires : FUNCTION length;
- " index;
- " char2real;
- PROCEDURE setlength;
- }
- VAR
- temp#,mult : REAL;
-
- p, { location of decimal point }
- e, { " " E [for exponential factor]}
- intpart, { " " last CHAR before decimal point }
- dec1st, { " " 1st " after decimal point }
- declast, { " " last " " point but before E }
- explength, { number of CHARs in exponent including +/- }
- l,i,sig#s : INTEGER;
-
- negative,good# : BOOLEAN;
-
- newstr : str255;
-
- digit : CHAR;
-
- PROCEDURE expone(n : INTEGER); { internal to str2real : used in factoring
- in the exponent term.}
- VAR
- temp1,
- factor : REAL;
- BEGIN
- factor := 1.0;
- good# := good# AND char2real(inputstr[n],temp#);
- IF (good# AND (temp# > 0.0))
- THEN for i := 1 TO TRUNC(temp#) DO factor := factor * ABS(mult);
- IF mult < 0
- THEN BEGIN
- temp1 := real# / factor;
- temp1 := real# - (temp1 * factor);
- real# := (real# + temp1)/factor;
- END
- ELSE real# := real# * factor;
- END; { of : procedure expone }
-
- BEGIN { str2real }
- real# := 0.0;
- negative := FALSE;
- good# := TRUE;
- l := length(inputstr);
- IF inputstr[1] IN ['+','-'] { if a sign character used get the sign
- and then snip off the sign character! }
- THEN BEGIN
- negative := (inputstr[1] = '-');
- setlength(newstr,(l - 1));
- FOR i := 1 TO (l - 1) DO newstr[i] := inputstr[i + 1];
- inputstr := newstr;
- END; { now there is no + or - }
- l := length(inputstr);
- p := index(inputstr,'.'); { where is the decimal point? }
- e := index(inputstr,'E');
- IF e = 0 THEN e := index(inputstr,'e'); { is there an exponent ? }
- IF p > 0 THEN BEGIN
- intpart := p - 1;
- dec1st := p + 1;
- IF e > 0 THEN declast := e - 1 ELSE declast := l;
- END
- ELSE BEGIN
- IF e > 0 THEN intpart := e - 1 ELSE intpart := l;
- dec1st := 0;
- declast := 0;
- END;
- FOR i := 1 to l DO { look for any invalid characters in the string }
- BEGIN
- digit := inputstr[i];
- good# := good# AND
- ( (digit IN ['0'..'9']) OR
- ((digit = '.') AND (i = p)) OR
- ((digit IN ['E','e']) AND (e > 0) AND (i = e)) OR
- ((digit IN ['+','-']) AND (e > 0) AND (i = (e + 1)))
- );
- END;
- IF good# THEN { start actual conversion here : IF string is ok! }
- BEGIN
- mult := 1;
- FOR i := intpart DOWNTO 1 DO
- BEGIN { calculate the value of the part to the left of period }
- good# := good# AND char2real(inputstr[i],temp#);
- IF good#
- THEN BEGIN
- real# := real# + (mult * temp#);
- mult := mult * 10;
- END;
- END;
- mult := 1;
- IF (dec1st + declast) > 0
- THEN BEGIN { Calculate the value of the part to the right of period.
- Note the recursive call to str2real.}
- setlength(newstr,(declast - dec1st + 5));
- i := dec1st - 1;
- sig#s := 0;
- REPEAT
- i := i + 1;
- IF (inputstr[i] > '0') or (sig#s > 0)
- THEN BEGIN
- sig#s := sig#s + 1;
- newstr[sig#s] := inputstr[i];
- END;
- UNTIL (sig#s > 6) or (i = declast);
- newstr[sig#s + 1] := 'e';
- newstr[sig#s + 2] := '-';
- i := i - dec1st + 1;
- IF i < 10
- THEN BEGIN
- newstr[sig#s + 3] := CHR(i + ORD('0'));
- setlength(newstr,(sig#s + 3));
- END
- ELSE BEGIN
- newstr[sig#s + 3] := CHR((i DIV 10) + ORD('0'));
- newstr[sig#s + 4] := CHR((i MOD 10) + ORD('0'));
- setlength(newstr,(sig#s + 4));
- END;
- good# := good# AND str2real(newstr,temp#);
- real# := real# + temp#;
- END; { of : calculating in the fractional part }
- IF e = 0 THEN explength := 0 ELSE explength := l - e;
- CASE explength OF { Last step : factor in the exponent if present }
- 0 : BEGIN
- END; { no exponent.}
- 1 : BEGIN { only 1 char after the e : positive by default }
- mult := 10.0;
- expone(l);
- END;
- 2 : BEGIN { 2 char : signed or unsigned exponent ? }
- IF (inputstr[l - 1] = '-')
- THEN BEGIN
- mult := -10.0;
- expone(l);
- END
- ELSE BEGIN
- mult := 10.0;
- expone(l);
- IF inputstr[l-1] <> '+'
- THEN BEGIN
- mult := 100;
- expone(l-1);
- END;
- END;
- END; { case explength = 2 }
- 3 : BEGIN { 3 char exponent : 1st MUST be the sign }
- good# := good# AND (inputstr[l - 2] IN ['+','-']);
- IF good#
- THEN BEGIN
- IF inputstr[l-2] = '+'
- THEN mult := 10.0
- ELSE mult := -10.0;
- expone(l);
- mult := mult * 10.0;
- expone(l-1);
- END;
- END; { case explength = 3 }
- ELSE : good# := FALSE
- END; { of : case list for factoring in the exponent }
- IF negative THEN real# := 0 - real#;
- END; { of : conversion }
- str2real := good#;
- END; { of : function str2real }
-
- FUNCTION readreal(VAR realvar : REAL) : BOOLEAN;
-
- {
- Comment : Readreal allows a REAL variable to be input from the console
- in a more forgiving and flexible manner than do the Pascal/Z standard
- READ and READLN utilities.It should be noted that the basically lousy
- error checking of Pascal is so because it was not originally conceived
- of as an interactive language.That is it was designed for a batch
- processing system that could not permit runtime correction of input
- errors.That does not,however excuse Ithaca's highly inconsistent methods
- of error trapping.
- Using readreal , the input REAL may have a period as the first
- or second character,(e.g. .123 , or +.123 , or -.123) or be a null string
- (i.e.'',produced by hitting RETURN).If null ,the variable is set to 0 &
- the return value of the function readreal is FALSE.Otherwise the real is
- set to the input string equivalent and readreal returns TRUE.This allows
- you to set any other default value for a null by checking ((readreal =
- FALSE) AND (realvar = 0.0)).(Pascal/Z has the annoying habit of crashing
- out of your program if you give such inputs to its READ or READLN utility).
- The conversion from STRING input to REAL uses the procedures str2real and
- char2real.
- On detecting invalid characters readreal gives an error message
- and loops,rather than crashing.
- Note that it is readreal that accepts the null string and str2real
- that accepts the period without a preceding zero.
- Hopefully at some time soon ITHACA will polish up the input error
- checking for REALS allowing this function to be eliminated or cut in size.
-
- Requires : FUNCTION length;
- FUNCTION index;
- PROCEDURE setlength;
-
- }
- VAR
- realstring : str255;
- done : BOOLEAN;
-
-
- BEGIN { readreal }
- REPEAT
- READLN(realstring);
- IF LENGTH(realstring) = 0
- THEN BEGIN
- realvar := 0.0;
- readreal := FALSE;
- done := TRUE;
- END
- ELSE BEGIN
- readreal := TRUE;
- done := str2real(realstring,realvar);
- IF NOT done THEN WRITELN('error in real input : try again.');
- END; { of : if length = 0 then..else... }
- UNTIL done;
- END; { of : procedure readreal }
-