Path: utzoo!attcan!uunet!husc6!bloom-beacon!mit-eddie!bbn!rochester!pt.cs.cmu.edu!sei!sei.cmu.edu!firth From: firth@sei.cmu.edu (Robert Firth) Newsgroups: comp.lang.pascal Subject: Re: Number-string conversions Message-ID: <5484@aw.sei.cmu.edu> Date: 17 May 88 12:59:37 GMT References: <5817@uwmcsd1.UUCP> Sender: netnews@sei.cmu.edu Reply-To: firth@bd.sei.cmu.edu.UUCP (Robert Firth) Organization: Carnegie-Mellon University, SEI, Pgh, Pa Lines: 163 In article <5817@uwmcsd1.UUCP> markh@csd4.milw.wisc.edu (Mark William Hopkins) writes: > While the issue is "on the table", I feel it appropriate to give a few >procedures to show how the conversions take place when Pascal reads & writes >in a text file. Some comments on these procedures are given thus: [! ... ] READING INTEGERS FROM TEXT: procedure ReadInt(var T : text; var I : integer); var Sign : char; begin (*** SKIP SPACES ***) while T^ = ' ' do get(T); [! may run off the end of the file] (*** GET THE SIGN ***) if T^ in ['+','-'] then begin read(T, Sign) end else Sign := '+'; (*** CONVERT THE STRING TO AN INTEGER ***) I := 0; while T^ in ['0'..'9'] do begin I := 10*I + ord(T^) - ord('0'); [! may cause false overflow on '+' if number large] get(T) end; (*** ADJUST FOR THE SIGN ***) if Sign = '-' then I := -I [! and of course fails on the most negative integer] end; READING REAL NUMBERS FROM TEXT: (The syntax allowed by this procedure is slightly more liberal than that which standard Pascal allows for.) procedure ReadReal(var T : text; var R : real); var Exponent : integer; Power : real; begin (*** CONVERT THE INTEGER PART ***) ReadInt(T, R); [! will overflow on eg 10000000000.0] (*** CONVERT THE DECIMAL PART ***) if T^ = '.' then begin get(T); Power := 1; while T^ in ['0'..'9'] do begin Power := Power / 10; [! cumulative loss of precision since binary 0.1 is approximate] R := R + ( ord(T^) - ord('0') ) * Power; get(T) end end; (*** CONVERT THE EXPONENT PART ***) if T^ in ['e','E'] then begin get(T); ReadInt(T, Exponent); while Exponent 0 do begin Exponent := Exponent - 1; R := R * 10 end; while Exponent < 0 do begin Exponent := Exponent + 1; R := R / 10 [! further loss of precision] end end end; FORMATTING INTEGERS INTO TEXT: procedure WriteInt(T : text; I : integer; FieldWidth : integer); var Sign : char; Size, Exponent : integer; begin (*** DETERMINE THE SIGN ***) if I < 0 then begin Sign := '-'; I := -I [! fails on most negative number] end else if I > 0 then Sign := '+' else Sign := '0'; (*** DETERMINE THE SIZE OF THE INTEGER STRING ***) Exponent := 1; Size := 0; while (Exponent < I) do begin Exponent := 10 * Exponent; [! overflow if I near MAXINT/10 ] Size := Size + 1 end; (*** PAD THE INTEGER TO THE LEFT, IF NECESSARY ***) if FieldWidth Size then begin while FieldWidth > Size + 1 do begin FieldWidth := FieldWidth - 1; write(T, ' ') end; if Sign = '+' then write(T, ' ') end; (*** CONVERT THE NUMBER TO A STRING ***) if Sign = '+' then write(T, ' ') else if Sign = '-' then write(T, '-') else if Sign = '0' then write(T, '0'); else while Size > 0 do begin Size := Size - 1; Exponent := Exponent / 10; write(T, chr(I mod Exponent + ord('0')) ); I := I div Exponent end end; FORMATTING REALS TO TEXT: (F1, F2 are the two field widths used for formatting real numbers and rounding them to the desired number of decimal places.) procedure WriteReal(var T : text; R : real; FW1, FW2 : integer); var Mantissa : integer; Decimal : real; begin Mantissa := trunc(R); [! overflow if R > MAXINT ] Decimal := R - Mantissa; (*** The field width FW1 includes the decimal part and decimal ***) (*** point in it. Therefore the integer part is written out ***) (*** with a field width of FW1 - FW2 - 1. ***) WriteInt(T, Mantissa, FW1 - FW2 - 1); if FW2 > 0 then begin write(T, '.'); while FW2 > 1 do begin FW2 := FW2 - 1; Decimal := Decimal * 10; write(T, chr( trunc(Decimal) + ord('0') ) ); Decimal := Decimal - trunc(Decimal) end; (*** ROUND THE LAST DECIMAL DIGIT ***) [! fails if rounding involves more than one digit ] Decimal := Decimal * 10; write(T, chr( round(Decimal) + ord('0') ) ) end end [ Me again, Robert Firth ] I find it hard to express my feelings in a manner that is both clear and polite. The above code is evidently rubbish; unfortunately it is typical of the stuff produced by amateur software writers - you can find examples galore, as bad or worse, in many packages distributed by major institutes of education. These examples would not have survived any one of: accurate specification, competent design review, code walkthrough, formal analysis, or thorough testing. I conclude that they were subjected to none of these processes. Folks, are we surprised there is a "software crisis"? And what can we, as responsible individuals, do about it?