[comp.lang.pascal] Third TPascal

prknoerr@immd4.informatik.uni-erlangen.de (Peter Knoerrich) (06/27/91)

Ok, here you are, the third one:

This one needs some warnings, for it will for sure not run on
any compiler. For instance, you need a word data type which
is not implemented on most unix pc compilers (for some good
reason, agreed). 

But I think most of you guys either use Borland's TurboPascal 
or perhaps some other pascal which does have unsigned data types, 
so you will perhaps be able to follow this one (I know I'm 
advertising, but at least it's for a reasonable product I do it for)

program AdjustValue;

procedure AdjustAndTrim(var value : word;change : integer);
  var
    temp : integer;
  begin
    temp := value + change;
    if (temp<0) then 
      temp := 0
    else
      if (temp>1000) then
        temp := 1000;
    value := temp;
  end;

var
  given : word

begin
  given := 0;
  AdjustAndTrim(given,-1);
end.

The "AdjustAndTrim"-procedure should add or subtract a shift to a 
word, cutting off too low and too high values to stay inside a 
constant range (0 .. 1000 here). 

As the programmer (that is me) anticipated there will be some 
negative values at first, he chose to put the sum into an integer 
first, checking whether it was legal, doing then some trimming 
and as the last operation copy the valid value back into the 
original word variable.

What goes wrong is the following: Even the first assignment fails.
Though an integer has been provided to catch up with those negative
fellows, a range check error will occur when called with the given
parameters.

Now, who of you pascalaholics can guess what went wrong? And where
do the other puzzles stay I keep scanning the group for? Does Arthur
Dent after all find out what the question to 42 is? Drop a word!

                                          Bye, Peter

PS: If I happen to type in junk, and the intended solution won't work
    (perhaps because the compiler yells at some typo error), please
    supply me not only with the solution but also with corrections/
    better solutions/enhanced puzzles. 
  
    This is called cooking and counts double.I will then take the thing
    home to my trusty 286 and figure out my errors. Seemingly one
    such thing has happened to the last puzzle, but as I were sure
    I did exactly such a thing myself some time ago, I have still to
    check it out. Keeping watching for my next post next week, which
    will also contain the solution to the first puzzle!)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

PPS: Somebody suggested I should also post puzzles of the kind:
     Which variable declarations would be necessary to make the
     following source code compilable: [figure your own example
     (and in case of agreement, also post it)] ?

     But in my opinion this sounds a bit to much like theory, where
     I prefer the "will compile, but produce unexpected results"-kind
     of puzzles, as they have an air of praxis (BTW, do you use the verb
     praxis here?) Any opinions are welcome.
     
---
sig? You must be kidding with all those SIGKILLs around on this machine!
Peter Knoerrich,        email: prknoerr@faui43.informatik.uni-erlangen.de

sml@ssc-vax (Stuart Lewis) (06/29/91)

In article <1991Jun27.131018.26430@informatik.uni-erlangen.de> prknoerr@immd4.informatik.uni-erlangen.de (Peter Knoerrich) writes:
>Ok, here you are, the third one:
>
>This one needs some warnings, for it will for sure not run on
>any compiler. For instance, you need a word data type which
>is not implemented on most unix pc compilers (for some good
>reason, agreed). 
>
>But I think most of you guys either use Borland's TurboPascal 
>or perhaps some other pascal which does have unsigned data types, 
>so you will perhaps be able to follow this one (I know I'm 
>advertising, but at least it's for a reasonable product I do it for)
>

I'm not sure I understand what you're telling me here about the word
data type.  But then, I program on the VAX - not on pc's (not until
this fall anyway).  Given that forewarning about my lack of pc
Pascal, let me approach your code from a standard VAX Pascal point of
view.......

>program AdjustValue;
>

(* the var declaration must be here - not after the procedure *)
(* that *immediately* will give compile time errors *)

VAR (* from below *)
  given : word; (* from below *)

>procedure AdjustAndTrim(var value : word;change : integer);
				       (* ^^^^^^ since "change" is
				       always -1, it would be
				       'tidier' to declare it as a
				       constant up above and not
				       worry about passing it *)
>  var
>    temp : integer;
>  begin
>    temp := value + change;

(* I don't know what TYPE "word" is (pc exclusive?), but this last
line will not work unless "value" (VAR'd "given") is ultimately
either an INTEGER value or CHAR value, because "temp" is declared as
type INTEGER.  You can declare a data type word = INTEGER; up above
your global VAR's, and then it would work. *)

>    if (temp<0) then 
>      temp := 0
>    else
>      if (temp>1000) then
>        temp := 1000;
>    value := temp;
>  end;
>
>var (* global VAR - delete this line - move to above *)
>  given : word (* ditto - plus syntax error, need ";" at end *)
>
>begin
>  given := 0;

(* here again, I don't know what type "word" is, but you're
assigning an INTEGER (or possibly CHAR) value to "given" - save
yourself some trouble and declare it as one of those two *)

>  AdjustAndTrim(given,-1);
>end.
>
[stuff deleted]
>
>What goes wrong is the following: Even the first assignment fails.
>Though an integer has been provided to catch up with those negative
>fellows, a range check error will occur when called with the given
>parameters.
>
[stuff deleted]
just a matter of personal preference or style, but here's what I
would do....

PROGRAM AdjustValue (input, output);

   CONST
      change = -1;

   TYPE
      word = INTEGER;

   VAR
      given : word;

	PROCEDURE AdjustAndTrim (VAR value : word);

	   VAR
	      temp : INTEGER;

	   BEGIN (* PROCEDURE AdjustAndTrim *)
	      temp := value + change;
	      IF (temp < 0) THEN
		 value := 0
	      ELSE IF (temp > 1000) THEN
		 value := 1000
	      ELSE
		 value := temp;
	   END; (* PROCEDURE AdjustAndTrim *)
   
   BEGIN (* MAIN *)
      write('Enter a value : ');
      readln(given);
      AdjustAndTrim(given);
      writeln('Adjusted value is : ', given);
   END. (* MAIN *)

I added read & write statements - the program isn't very useful as a
learning tool unless you can see what the heck it's doing! :-)
Again, this is just my personal style, but it does solve the TYPE
problems with "word" and "given".  I didn't run this, but I'd be
*real* embarassed if it crashed on somebody!

>---
>sig? You must be kidding with all those SIGKILLs around on this machine!
>Peter Knoerrich,        email: prknoerr@faui43.informatik.uni-erlangen.de

Stuart Lewis
sml@ssc-vax

pshuang@athena.mit.edu (Ping-Shun Huang) (07/01/91)

To Stuart:

 > (* the var declaration must be here - not after the procedure *)
 > (* that *immediately* will give compile time errors *)

One of the reasons that he specified Turbo Pascal is that this compiler
is more lax than ones which are strictly compatible -- it permits you to
intermix VAR, CONST, FUNCTION, and PROCEDURE declarations in any order
before your main BEGIN-END pair.

A word is a 16-bit integer, by the way.

 > 				       (* ^^^^^^ since "change" is
 > 				       always -1, it would be
 > 				       'tidier' to declare it as a
 > 				       constant up above and not
 > 				       worry about passing it *)

Peter said that change would often be negative at first, *NOT* that it
would always be -1.

 > (* I don't know what TYPE "word" is (pc exclusive?), but this last
 > line will not work unless "value" (VAR'd "given") is ultimately
 > either an INTEGER value or CHAR value, because "temp" is declared as
 > type INTEGER.  You can declare a data type word = INTEGER; up above
 > your global VAR's, and then it would work. *)

The type word is assign-compatible with integer -- when going word to
integer, the value is sign-extended, when going from integer to word the
extra bits are truncated.

-------------------------------------------------------------------------

To Peter:

Except for the below-noted typo, I can't see why this is causing the
range error -- I'm a Pascalholic but the academic/real world has been
forcing me to use Scheme and C instead, respectively, so my recall isn't
as good as it used to be. {sigh} A couple of vague thoughts which are
running through my head involve whether the TP compiler is using
unsigned or signed intermediate results and the fact that an integer -1
is all binary one's in two's complement notation and therefore looks
like MaxWord when casted to word.

Oh, if you want to post puzzles which are clearer, be sure to be more
specific about what happens.  "The first assignment", where the range
error occurs, is unclear; do you mean the first assignment which occurs
in the source code file, or the first one which the computer executes?
That sort of thing needs to be more clearly stated.

If I read your posts correctly, this is being posed as a puzzle and not
as a real problem you're facing which needs solution.  Just in case it
is the latter, though, you should be able to re-write as "IF
(Value+Change)<0 THEN", i.e. process the negative sum as a special case
altogether, rather than doing the sum and then correcting afterwards.

 > var
 >   given : word

{typo? missing a semicolon here after "word"}

--
Above text where applicable is (c) Copyleft 1991, all rights deserved by:
UNIX:/etc/ping instantiated (Ping Huang) [INTERNET: pshuang@athena.mit.edu]