home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-12-20 | 99.3 KB | 2,129 lines |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //////// // // //
- // // /// // //
- // // //// // //
- //////// // // // //
- // // //// //
- // // /// //
- // // // ///////
-
-
-
-
-
- Pascal NewsLetter
- Issue #5
- December, 1990
-
-
- Editor: Pete Davis
-
-
-
-
-
-
-
-
-
-
-
-
-
- The Programmer's Forum BBS is the home of
- PNL. It can be reached in Washington, DC at
- (202)966-3647. Information is available
- through the following locations:
-
- FidoNet: Pete Davis@1:109/138
- GEnie: P.DAVIS5
- BitNet: HJ647C@GWUVM & UE356C@GWUVM
- InterNet: HJ647C@GWUVM.GWU.EDU
- or UE356C@GWUVM.GWU.EDU
- Uucp: Pete.Davis@f138.n109.z1.fidonet.org
-
-
- 2
-
- Table of Contents
-
-
-
- Introduction ............................... 3 (P.D.)
-
-
- The Lazy Programmer's Guide
- to Graphics in Pascal ...................... 4 (R.M.)
-
-
- Introduction to Multiple Concept
- Pascal Programming ......................... 15 (P.R.)
-
-
- For Beginners .............................. 22 (B.G.)
-
-
- Recursion is Easy .......................... 32 (C.B.)
-
-
- Conclusion ................................. 38 (P.D.)
-
-
- Distribution List .......................... 40
-
-
-
-
-
-
-
- P.D. -> Pete Davis (Editor-in-Chief, Writer)
- R.M. -> Richard A. Morris (Editor-Over-the-Pond, Writer)
- B.G. -> Bob Gowans (Staff writer)
- P.R. -> Paul Robinson (Contributing writer)
- C.B. -> Chris Burke (Contributing writer)
-
- 3
-
- Introduction
-
- Well, finally getting to another issue of the Pascal
- NewsLetter. We're making a few changes in the organization
- of PNL. First of all, I've promoted myself to Editor-in-
- Chief. That's really what I've been all along, but it was to
- make room for some new titles.
-
- We've got a new staffer, Richard A. Morris, with the
- distinguished title of 'Editor-Over-the-Pond'. Richard will
- be a collection point in Australia for PNL contributions and
- will be editing and sending them on to me for inclusion in
- the NewsLetter. For a profile of Richard, read the end of
- his article. If you live in Australia, send your
- Contributions to Richard A. Morris. His Fido-Net Address is
- 3:640/378. His system's phone number is 61-7-878-1194.
-
- Richard is also writing "The Lazy Programmer's Guide to
- Graphics in Pascal", a series of articles about, you guessed
- it, graphics programming in Pascal. It's very thorough
- coverage of graphics, so many of you will surely find it
- interesting.
-
- Many of you probably already know that I had been
- planning on putting the newsletter out as 'Subscription-
- only'. Well, I ran into some problems un-related to the
- newsletter which have forced me to postpone, at least until
- summer, this course.
-
- Also, I would like to thank everyone who has been
- contributing. It seems that the number of submissions is
- increasing slightly, which is a terrific bonus. If you can
- keep them coming in, the newsletter just might find a way to
- come out a bit more often.
-
- In this issue, Paul Robinson will be talking a bit
- about writing large programs in Pascal and will cover some
- programming techniques. Bob Gowans continues his popular
- "For Beginner's" column, and last, but not least, Chris
- Burke shows you how simple recursion can be.
-
- Well, that's about it for this issue. I hope you enjoy
- it.
-
- 4
-
- The Lazy Programmers Guide to Graphics in Pascal
- by Richard A. Morris
- Fido 3:640/378
- Brisbane, AUSTRALIA
-
- I have been running a BBS and reading FIDO echoes for
- some years now and invariably the first 2 things Novice
- programmers want to write with their new language are a
- better BBS, and a better Graphic Game. Well I'll leave the
- intricate subject of Data communications to the "Build a
- better Mousetrap "experts, and Game theory to the Academics,
- Rather in the next 6 Articles I'll discuss Graphics
- programming with Turbo Pascal.
-
- The Idea behind the Lazy programmers Guide, is that if
- you are like me, you often wondered how easy it would be to
- do some particular programming task, but never had the time
- or inclination to get around to opening the manual at that
- section. Well this article is both for the novice, and the
- experienced (Lazy Programmer) and will take you from very
- simplistic exercises to quite complex Graphic programming in
- a short time, by program examples, and prodding your
- imagination to experiment a bit :-).
-
- These articles are based on Turbo Pascal on the PC, and
- I apologize in advance to those not using that, in
- particular versions 4, 5, and 5.5 (And I apologize in
- Advance to all Americans as I intend to use the word Color a
- lot :-). I am sure that the topics I intend to cover will
- have some relevance for all Graphic programming. I don't
- promise that you will be able to write a better Flight
- Simulator (Although if you do I want a mention :-) but you
- will understand a bit more about how it's done, and probably
- gain a lot of respect for these Graphic Wizards.
-
- The articles will assume that you have some knowledge
- of programming concepts (Such as Binary mathematics,
- Trigonometry) and Turbo Pascal (there will be very little
- handholding :-), and will take you from simple graphics to
- quite Advanced programming concepts.
-
- The Articles will comprise the following Topics;
-
- Basic Graphics with Turbo Pascal GRAPH unit.
- Graphs, Statistics, and windows with the GRAPH unit.
- Simple Animation and Sprites using the GRAPH unit.
- User defined programming in the GRAPH Unit
- Writing Directly to the EGA/VGA.
- Animation using Direct writes to the EGA/VGA.
- Three Dimensional Graphics directly to the EGA/VGA.
-
-
-
- 5
-
-
- ------------------------------------------------------------
- The Lazy Programmers guide to Turbo Pascal Graphics - Part 1
- - Basic Graphics with the GRAPH unit -
- ------------------------------------------------------------
-
-
- A Brief History of PC Displays - Apologies to S. Hawkins
- :-).
- ------------------------------------------------------------
-
- Graphics in the Personal computer world refer to
- non-text display information. The original PC released a
- decade ago, was equipped with a display called the
- Monochrome Display, and a driver called (Surprise surprise)
- the Monochrome Display Adapter. This Display had a
- resolution of 720x350 and displayed ONLY the IBM PC
- character set in black and white.
-
- It was not long before the popularity of computers such
- as the Apple II, with it's bit mapped display, caused demand
- for a graphic display, and the Hercules (from a PC add-on
- company Hercules Computer Technology) was born. The
- Hercules still displayed data in black and white, but it
- allowed you to show bitmapped graphics. Soon IBM got the
- hint and released the Color Graphics Adapter with 16 color
- text and 4 color bit mapped graphics, unfortunately the CGA
- design featured a lot of compromises such as display to
- inferior composite displays, and offered poor display
- resolution (320x200), but it did have Color, and it is one
- of the most popular displays around.
-
- Eventually due to increasing market pressure from
- companies like Apple, Atari, and Commodore, IBM brought out
- a reasonable display called the ECD, and drove it with the
- Enhanced Color Adapter, this gave programmers access to a
- resolution of 640x350 with 16 simultaneous Colors from a
- palette of 64. Lately VGA technology has become a standard
- and it increases displays up to 640x480 and 256 colors (at
- 320x200). These articles will concentrate on the EGA and
- VGA modes, but the GRAPH unit stuff will cover some aspects
- of general graphic device programming, and this first part
- only requires a CGA Screen..
-
-
- BGI - The Borland Graphics Interface
- ------------------------------------
-
- Due to the nature of the PC market, any programmer who
- wrote his code for any particular Graphic standard limited
- his earnings by limiting his User base to only that machine.
- True, most of the standards are Downward compatible, which
-
-
- 6
-
- means that a CGA only application would run on a VGA, but
- given the choice a VGA owner would surely choose a product
- that displayed VGA graphics.
-
- Until Borland brought out BGI's most Languages did not
- support Graphics at all, relying on third party toolboxes,
- with Turbo Pascal and Turbo C Borland introduced the concept
- of a Graphic Interface whereby a programmer wrote code to
- call the BGI which would then do all the hard work of
- working out what device it was talking to and how to display
- that information.
-
- This is a great concept, as it provides portability of
- programs across graphic devices, but of late a lot of
- programmers have decided to bypass Borlands interface to
- talk instead directly with the graphic device. The main
- reason for this is speed, Borland Drivers use the computer
- BIOS in a lot of cases (Which itself wastes time deciding
- what device it is talking to), and are themselves quite
- slow, hence I shall devote a fair bit of time in later
- Articles on programming Directly to the Graphic device.
-
-
- Setting up to display Graphics
- ------------------------------
-
- Firstly to Show graphics on our monitor we must tell the
- device to get into graphics mode, at the end of displaying
- what we want we must also return the system to the original
- display mode. Additionally as we will be using BGIs during
- this article, we must tell Turbo pascal where to find our
- BGI control files.
-
- A sample of a simple program to get into graphics mode
- display a line of text (More of this in this article), and
- go back to text mode is in the following program put it into
- a file called GRAPH_TE.PAS. To compile it load it into the
- editor, change line 7 to make BGI_Directory point to the
- directory you have put all the BGI files into (eg:I use
- c:\TP\BGI).
-
- ~ Prog 1 ~~~~~~GRAPH_TE.PAS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- {$M 16384,16384,655360}
- Program Graph_Test;
- Uses
- CRT,
- GRAPH;
- Const
- BGI_Directory = 'C:\TP\BGI';
- var
- GraphDriver : Integer;
- GraphMode : Integer;
-
- 7
-
- ErrorCode : Integer;
- tempstr : String;
- begin
- GraphDriver := Detect;
- InitGraph(GraphDriver,GraphMode,BGI_Directory);
- ErrorCode := GraphResult;
- if ErrorCode <> grok then
- begin
- Writeln('Error initialising Graphics :',ErrorCode);
- Writeln('Error Message :',GraphErrorMsg(ErrorCode));
- Halt(1);
- end;
-
- {Graphics stuff begins}
- Str(GraphMode,TempStr);
- OutText('We are in Graphics mode number :'+TempStr);
- Str(GraphDriver,TempStr);
- OutText('This is Device number :'+TempStr);
- {End of Graphics stuff}
-
- delay(1000);
- CloseGraph;
- end.
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- O.K. let's dissect this test program, firstly in line 4
- we USE the GRAPH unit, this will give us access to all of
- the graphics routines, and constants. We declare the
- directory that all the BGI files will be found into a
- constant, and declare 4 variables GraphDriver to store the
- type of graphics device we have, GraphMode to store the
- graphics mode we will use, ErrorCode to store any error
- numbers, and TempStr to temporarily store integers as
- strings.
-
- Then we set GraphDriver to the GRAPH constant DETECT.
- DETECT is defined as 0 and will tell Turbo Pascal to
- automatically detect the Graphic device connected to the PC,
- and select for us the maximum available Graphics mode. The
- next line calls the GRAPH function INITGRAPH, we tell this
- function what device to talk to (or AUTO detect in our
- case), which mode we want (In this case the Auto detect will
- select one for us), and the location of the BGI files. We
- can actually pre-select the type of device by specifying the
- GraphDriver and GraphMode before running InitGraph, as in
- the following inset (Replace Grafdriver := detect).
-
- ~~~~~~~~~~~~~~~~~~~~~~
- GraphDriver := CGA;
- GraphMode := cgac0;
- ~~~~~~~~~~~~~~~~~~~~~~
-
-
- 8
-
- This will set up the Graphic device for working with a
- CGA compatible device, running in mode CGAc0, or the first
- CGA color mode. InitGraph allocates some memory on the heap
- to work with, so you must have some heap memory available
- (Hence the $M directive in line 1), such as a general 4K
- buffer for graphics, and space to put the BGI file.
-
- The GRAPH function GraphResult will have an errorcode
- after most GRAPH routines and will be zero if the routine
- proceeded without error, or will contain an error number if
- an error occurred, the function GraphErrorMsg can give you a
- textual error message if you send it the error number as we
- have in the test program. If an error occurs the program
- describes the error and aborts.
-
- Assuming successful initialization of the Graphic
- system the next step is to perform the Graphics routines,
- which in this case is to write out a message describing the
- Device that autodetect found and the Mode. We have to use
- the str routine to convert integers into strings, as the
- Graph text writing expects a string as a parameter, and
- can't use the abilities of write and writeln. Finally we
- close the graphics drivers with CLOSEGRAPH. Close Graph
- releases all memory assigned by InitGraph and restores the
- original text mode.
-
- Now when you run the program it will quickly display
- the graphics data, and jump back to text mode, so I've
- inserted a delay in before the call to close graph. You may
- notice a delay before loading graphics while the system
- loads the BGI file, in some systems this may be unacceptable
- or you may wish to distribute just on EXE file and not
- include a whole lot of BGIs, so Borland have given you a
- demo of how to do this in the example file BGILINK.PAS.
-
- If you have problems with this sample file you should
- check that you have a graphics capable device, and that the
- BGI files are indeed where you specified them.
-
-
- Displaying Pixels
- -----------------
-
- O.K. so far you've managed to Display some funny shaped
- text on the screen, Big Deal you say. Well from here on in
- this part we will use the program Graph_Test, to set up the
- graphics device, and close it after use, and in place of the
- above Graphics stuff (In this case the OUTTEXTs) we put in
- specialized code. The next step is to display a point on
- the screen, we call one of these a PiXel or Picture Element.
-
- As you know different Display technologies have
-
-
- 9
-
- different Screen resolutions (Pixels on the Screen) for
- example you fit 320 pixels across and 200 down in CGA mode
- 5. In the BGI routines, you can put a pixel in a location
- that is not on the screen. This may seem strange, but when
- you realize that under EGA you can put a pixel in the last
- column at column 639 (the first column is always 0 so 0-639
- = 640 pixels), which would be way of the screen in CGA. For
- the purposes of this Article we'll do most of our work in
- the range of 0 - 99 columns and 1 - 99 rows, which will be
- displayable on all monitors.
-
- The routine to display a pixel on the screen is
- (Surprise) PutPixel(x,y : Integer; Color: word) X and Y are
- not surprisingly Column and Row coordinates, and Color is
- the color of the pixel. O.K. so lets do some Graphics.
- Insert the following declarations at the beginning of
- Graph_Test, and the routine in the Graphics stuff section.
-
- ~ Declarations ~~~~~~~~~~~~~~~~~~~~~~~~
- VAR
- Counter : Integer;
- Color : Word;
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Color := 1;
- For Counter := 0 to 99 do
- begin
- PutPixel(0 ,Counter,color);
- PutPixel(99 ,Counter,color);
- PutPixel(Counter,0 ,color);
- PutPixel(Counter,99 ,color);
- end;
- PutPixel(50 ,50 ,Color);
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- This routine will Firstly set the variable color to 1
- (The first available color, in which case all devices will
- show a color distinct from the background color), which in
- most modes is Dark blue, in the 320x200 cga modes this will
- be Green, or Cyan. The system then counts from 0 to 99 and
- puts a box on the screen, by plotting a point in the left,
- right, top and Bottom edge. To see how it does this dot by
- dot put the line DELAY(100) before the end in the FOR loop,
- you will see each dot being drawn. Then it will put a dot
- almost in the middle of the box, depending on the resolution
- of your display mode, the box could be anything from a
- perfect square to an elongated rectangle, GRAPH has a
- procedure called GetAspectRatio which will tell you the
- ratio you may use to draw a perfect square (We'll talk about
- this later on), and various functions and procedures to ask
- the Graphics device how wide and tall (in pixels) it is, we
- will discuss these in the next article on Graphs.
-
-
- 10
-
- Play with the colors for your default (Auto
- detected) mode, then try playing with the Graphdevice and
- Graph mode, to get the hang of your Graphics device, as you
- will need to know later on about the capabilities of
- your system. You can also move the x,y position of the
- single pixel, or even draw some simple shapes.
-
- An example of a little function to draw a shape would
- be to stick this line in the FOR loop.
-
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- PutPixel(Counter,50+trunc(sin((counter/100)*2*pi)*20),color)
- ;
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- It plots a point for each x position of counter, based
- on a sin function (A Turbo function that gives a value on a
- sin curve (Wave !?!) between -1 and 1 for every position
- between 0 and 2*Pi radians). TRUNC converts the Sin value
- from a Real into an integer for PutPixels Y value,
- sin((Counter/100)*2*pi) gives a real between -1 and 1 as
- (Counter/100) goes from 0 to almost 1, and we multiply this
- by 20 to make the wave oscillate between 50-20 and 50+20 to
- put the wave in the middle of the box.
-
-
- Lines, Arcs and other Objects
- -----------------------------
-
- Drawing a line is a bit slow plotting a pixel at a
- time, so Turbos GRAPH unit includes a LINE function so
- firstly we'll replace our FOR Loop box Drawing routines
- with;
-
- ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- SetLineStyle(SolidLn,0,NormWidth);
- SetColor(1);
- Line(0,0,0,99);
- Line(0,99,99,99);
- Line(99,99,99,0);
- Line(99,0,0,0);
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- You will also notice that LINE doesn't include a color
- parameter, GRAPH has a routine called SETCOLOR (Which we set
- before we draw the lines) which defines a color to be used
- by all line and object drawing routines. Graph has another
- surprise with a routine called SETLINESTYLE which allows us
- to select the style, pattern, and thickness of the lines
-
-
- 11
-
- we'll draw, again I've included that one above for a
- SolidLn, but you might like to try styles of DottedLn,
- CentreLn, or DashedLn and a Thickness of Thickwidth.
- Pattern is a special value we'll discuss in the next topic.
-
- There is an even Better method to display a Box
- called RECTANGLE, which combined the 4 lines commands, try
- this.
-
- ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- SetLineStyle(SolidLn,0,NormWidth);
- SetColor(1);
- Rectangle(0,0,99,99);
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Now try this, it uses three more line based object
- drawing routines;
- ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- SetLineStyle(SolidLn,0,NormWidth);
- SetColor(1);
- Rectangle(0,0,99,99);
- Circle(50,50,40);
- Arc(50,60,225,315,20);
- Ellipse(40,40,0,360,5,10);
- Ellipse(60,40,0,360,5,10);
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- What these routines do is Draw a Circle with the centre
- at 50,50 with a radius of 40 pixels (This routine uses
- GetAspectRatio to makes as round a circle as possible), Arc
- draws a part of a circle with a centre at 50,60 (10 pixels
- below the centre of the circle) going from 225 degrees
- (Unlike the Trigonometric functions the Graphics routines
- represent angles in Degrees, starting from 0 horizontally to
- the right) to 315 degrees with a radius of 20 pixels, the
- two Ellipses draw two identical squashed circles with
- centres 10 pixels either side of the middle point, and 10
- pixels above it, each ellipse goes from angle 0 around a
- full circle to 360, and with a x radius of 5 and a Y radius
- of 10. If this explanation seems a bit obtuse, run the demo
- first and you'll see what I mean <grin>.
-
- The Last Line Based Object drawing routine is the
- PolyDraw routine which will draw any polygon, although it
- needs a bit of setting up. What you have to do is define a
- variable as an array of pointType which is a GRAPH global
- type, a record of (x,y) coordinates. Then you fill the
- array elements with x,y coordinate data (I often use Graph
- paper to work out how I'm going to do a shape), and simply
- call the DrawPoly routine with the number of points, and the
- Shapearray, try this one which draws two triangles on our
- face shape;
-
- ~ Delcaration ~~~~~~~~~~~~~~~~~~~~~~~~~
-
-
- 12
-
- Triangle : Array[1..4] of PointType;
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Triangle[1].x := 50;
- Triangle[1].y := 85;
- Triangle[2].x := 20;
- Triangle[2].y := 75;
- Triangle[3].x := 20;
- Triangle[3].y := 95;
- Triangle[4].x := 50;
- Triangle[4].y := 85;
- DrawPoly(4, Triangle);
- Triangle[2].x := 80;
- Triangle[3].x := 80;
- DrawPoly(4, Triangle);
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Patterns and fills
- ------------------
-
- O.K. from the previous program, add the following lines
- after that last DrawPoly routine;
-
- ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- SetFillStyle(solidFill,Color);
- FloodFill(50,5,Color);
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- A fill is a bit like a color-in that kids do, it will
- fill an area with a color. Now this one takes a bit of
- explaining, firstly SetFillStyle sets the type of fill any
- solid routine will use, and the color that it will color in
- with, in this case it will be a SolidFill, you can fill with
- diagonal lines (SlashFill), or hatchs (HatchFill), dots
- (CloseDotFill) or others, play around with it. The second
- line calls the fill, by specifying the x and y position of
- any point within the area to fill, and the color that will
- border the area.
-
- If there are any breaks in the border then the flood
- fill will leak through, try putting this routine to remove
- one of the bowties edges in before the FloodFill Routine,
- you'll notice the floodfill will bleed into the second
- triangle;
-
- ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- SetColor(0);
-
- Line(Triangle[2].x,Triangle[2].y,Triangle[3].x,Triangle[3].y
- );
- SetColor(1);
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- You can draw the polygon and fill at the same time,
-
- 13
-
- with a GRAPH routine called FillPoly, remove the previous
- routine to delete the edge of the bowtie, remove the
- floodfill, and Change the two DRAWPOLYs into FILLPOLLY and
- put
- ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- SetFillStyle(WideDotFill,Color);
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- anywhere before both FillPolys and the routines will perform
- a poly draw AND a fill at the same time. You can use
- FillEllipse in the same way to draw and fill an ellipse, or
- Bar to draw and fill a rectangle.
-
-
- Text and Fonts
- --------------
-
- To draw text there are several commands the first
- SetTextStyle loads up BGI files for the Font type (Much like
- initgraph sets up the Device BGI files), sets the direction
- of the text (Try this next procedure with VertDir instead of
- HorizDir, and set the text to start at 10,5), and the size
- of the characters. The second Command OutTextXY(X,Y :
- Integer;Text : String) sends text of the defined Style to
- the output port at the requested X,Y location.
-
- ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- SetTextStyle(DefaultFont,HorizDir,1);
- OutTextXY(20,5,'Mr Happy');
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Try different commands such as different fonts
- (TriplexFont, GothicFont), different sizes (Each fonts text
- will be a different size), and different orientations.
-
- One major problem with Ad hoc text placement in
- Graphics modes is working out where to put the next line, as
- you probably won't know where the current text finishes and
- the next should begin. Turbo provides two procedures
- TextHeight and TextWidth for just this problem. Simply said
- they return the size in pixels take up by a string. Let's
- go straight to an example, and I'll show you what I mean.
-
- Remove all the old graphic stuff leaving only the Box
- routine, and after drawing the box, add the following;
-
- ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- SetTextStyle(DefaultFont,HorizDir,1);
- Charheight := TestHeight('M');
- OutTextXY(20,5,'Simple example');
- OutTextXY(20,5+textheight,'of text spaced');
- OutTextXY(20,5+textheight+textheight,'at even heights');
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-
- 14
-
- As you see you will get each new line starting after
- the previous line has finished, regardless of font,
- character, or graphics device.
-
-
- Summary
- -------
-
- Well I hope I haven't offended too many sensibilities
- with the simplistic nature of the exercises, we have gone
- over some very basic Graphic concepts here, that are
- fundamental to further understanding graphic manipulation.
- Next PNL I will be discussing Business, mathematic and
- Scientific Graphics such as Bar, Pie, Scatter, Hi_Lo graphs,
- the graphing of mathematic functions in 2 and 3 dimensions,
- and Fractal representations such as Sierpenski, Mandlebrot,
- and Benoit sets. As well as topics, like windows, Auto
- Scaling graph axes, and further discussion of aspects of
- text drawing.
-
- Author
- ------
-
- Richard Morris is the Owner/operator of KHIRON
- Software, in Brisbane AUSTRALIA, a company that specializes
- in Graphic Databases in Turbo Pascal for Health care
- professionals, as well as providing contract staff for as
- diverse projects as Robotic process control software, to
- various Industry support software. Current Supported
- Packages DENTAPAC tm - Dental practice management tools,
- PHYSIOPAC tm - Phyiotherapy management tools, and ORTHOPAC -
- Orthodontic practice management tools.
-
- References
- -----------
-
- The Turbo Pascal Reference Guide
- (C)89 Borland Int.
-
- Advanced Programmer's Guide to the EGA/VGA
- George Sutty/Steve Blair
-
- Advanced MsDos
- Ray Duncan
-
- INTER490
- Ralf Brown
-
-
- 15
-
- (C) Copyright 1990, Tansin A. Darcos & Co. Commercial
- Reproduction rights are reserved.
-
- Introduction to Multiple-Concept Pascal Programs
- Paul Robinson
-
- Most large or commercial programs tend to do a number
- of things. I was trying to do a program that would count
- all the words in a text file - which might be almost any
- line format, and produce an alphabetical list of words.
- This meant that I had to do several things:
-
- o Read a file that might have Carriage Return
- ("CR") followed by Line Feed ("LF") for an
- end of line, LF then CR, LF only, or CR
- only, or might be from one of those weird
- programs that just generates "stream ASCII"
- in which it takes words until the line is
- full then at the next space issues a "soft"
- carriage return. The only requirement was
- that the file be non-coded, i.e. that
- characters appear as normal character values
- (Wordstar, for example, puts a high-bit code
- on some words to use as paragraph or line
- breaks).
-
- o When reading the words, store them in memory. The
- program might read a small file or it might
- read a 1/2 million word book, so the number
- of words would be indeterminant, and the
- word sizes would all be different.
-
- o List each word and the number of times used, in
- alphabetical order. The first qualification
- precluded the use of Pascal's standard
- READLN/EOLN construct to check for end of
- line. This meant I'd have to read the file
- in on a character by character basis. The
- second provision was because, with as much
- memory as is on a PC, there is really no need
- - unless you get a huge file - to use disk
- space to store word counts (also because of
- something I was trying to do that I wanted to
- use a in-memory word list). The third
- provision was what I had wanted: an
- alphabetical word list. (If I had been more
- concerned with the number of uses, I would
- have had the words listed in order by number
- of usages rather than alphabetically). These
- provisions made the choice of using a
- linked list quite obvious. The questions that
- came up included what type of linked list to
-
-
- 16
-
- use and how to implement it. That will be
- discussed below.
-
-
-
- Understanding Pointer Variables
- Paul Robinson
-
- One of the things I needed to do one day was read one
- or more disk files and create an alphabetized list of the
- words in each file, for something I was working on. I
- wanted to store the list of words used in the file in
- memory because I did not want to spend a lot of time reading
- and writing the disk in addition to all the disk reads
- being used to read the original file(s). Since the number
- of words to be stored would vary, storing them in
- arrays might either not provide enough memory space or waste
- a lot of memory.
-
- Pascal (and other languages) have a capability in
- which a variable can point to a block of storage that
- only exists after the program explicitly requests to be
- issued that storage. Arrays and variables are created (for
- the main program) when it is executed, and exist until the
- program ends. This special storage is allocated
- dynamically if, as and when needed, by the programmer
- specifically asking to be given a block of this
- memory. The programmer can also give back this memory
- when finished using it, and perhaps even re-use it later on.
-
- To access this dynamic memory, the programmer creates a
- class of variable called a pointer. A pointer is a
- variable that describes a memory location indirectly. Let
- me explain that a little closer.
-
- An ordinary variable exists at a specific location in
- memory, and contains a value such as a number, or a
- character (or two). This is an ordinary, direct access to a
- value. A pointer, however, goes one step further, in that
- it contains not a value, but the address of a value.
-
- For example, let me examine a record:
-
- TYPE
- maxstring = STRING[255];
-
- tokp = ^tok ;
- tok = RECORD
- next : tokp ;
- count : LONGINT ;
- token : maxstring;
- END ;
- 17
-
- The first item indicates that the identifier
- 'maxstring' is a string of the maximum size. Next, I
- indicate that the identifier 'tokp' is a pointer to (that's
- what the ^ indicates: "Pointer to") the identifier 'tok'.
- But tok is not defined until after tokp. This is the one
- exception to the rule in Pascal that everything must be
- defined before use; pointers may refer to identifiers which
- are not defined when the pointer is.
-
- Tok is a record beginning with a 'next' field, which
- since we know tokp is a pointer, that 'next' is a pointer
- to another record of the same type. The 'count' variable is
- a long integer, and 'token' is a string of maximum length.
- Why is there yet another pointer when one is already
- defined? The 'next' field is what is called a 'traverse'
- pointer. In order to find records in a linked list, you
- have to be able to follow ('traverse') the list in whatever
- order it is maintained. The way to do this is to change
- the pointer that looks at a record from the current
- record to the next one in the list. This would be done
- by assigning the 'next' value to the pointer which
- is referencing this record. Some pointer records will
- also carry a 'back' or 'prev' pointer to go backward in the
- list. Note that all this has done is create a set of
- names so that we can use this record - or the tokp pointer-
- in the program, but we cannot yet use them because we did
- not define variables that do, like this:
-
- VAR
- name:maxstring;
- T,t1: tokp;
-
- We still can't access the memory, because the
- pointers do not really contain the data, they contain only
- the address of the data. We have to allocate the space
- for that data in order to be able to access them. There
- are two ways that a programmer can be given access to
- dynamic memory. Both require the programmer pass a
- pointer to a procedure that allocates memory to that
- pointer.
-
- The first method is the NEW procedure, which is called
- in the form
-
- NEW(T);
-
- however, in our instance, allocating 255 bytes for each
- word probably wastes memory, especially since each word
- probably is no larger than 20 characters. There are two ways
- around this: pick a maximum and assume no word will be
- larger than that, or size the records to fit, which is
- option 2.
-
- 18
-
- The second method involves knowing what the program
- does; since I will know that 'name' will contain the string
- to be stored in the 'token' field of the tok record. So,
- I could allocate a specific sized block of memory with a
- special procedure available in Turbo Pascal called GETMEM,
- and it works like this:
-
- GETMEM(T,LENGTH(NAME)+10);
-
- where the first argument is the pointer to use, and the
- second argument is the amount of memory in bytes to allocate
- to the pointer. The LENGTH(NAME) value gives us the actual
- size of the string, the +10 is because the pointer takes 4
- bytes, the longint takes 4 bytes, the length of the string
- adds one byte, and I want the next allocation to come on a
- word boundary.
-
- In either the NEW or GETMEM options, the variable is
- now ready for use. We can access it by referencing the
- pointer followed by a fieldname:
-
- T^.Count := 1; or T^.Token := Name;
- T^.Token := Name; T^.Count := 1;
-
- Also, it is usually best to ensure that any unused
- or traverse pointers are cleared, so we should also say:
-
- T^.Next := NIL;
-
- (NIL is a special value which indicates a pointer is not in
- use).
-
- If we later add another record, we have to keep the
- old one, so we might do something like this:
-
- T1 := T;
- WHILE T1^.Next <> NIL DO
- T1 := T1^.NEXT;
- GETMEM(T1^.Next,LENGTH(Name)+10);
- T1 := T1^.Next;
-
- (I am trying to simplify this example. Things like
- alphabetizing the entries, checking for duplicates, etc.,
- has been omitted.)
-
- When finished with the memory pointed to by a pointer,
- you release it back to the system. On some systems they use
- MARK and RELEASE, in which you create a mark pointer, and
- store the current memory list in the marked pointer with
-
- MARK(markpointer);
-
-
- 19
-
- then when you don't need the memory any more, you get rid of
- it with
-
- RELEASE(markpointer);
-
- This cancels all usage of the NEW procedure done
- after the MARK procedure call. Any pointers allocated after
- that MARK are now invalid. Some systems do a better job
- at allocating memory, in which you use the NEW procedure (or
- on Turbo Pascal, you can also use GETMEM), then when
- you don't need a particular piece of memory, you can use
- DISPOSE (if you called NEW) or FREEMEM (if you called
- GETMEM). You would use them like this:
-
- NEW(T1);
-
- ...
-
- DISPOSE(T1);
-
-
- (* OR *)
-
- GETMEM(T1,LENGTH(NAME)+10);
-
- ...
-
- FREEMEM(T1,LENGTH(NAME)+10);
-
- Note: if a program is exiting, it does not have to
- release the memory it allocated; the system will do so for
- it.
-
- Pointers do not have to point to records. In some
- systems, pointers are used as a means to simulate the
- PEEK/POKE function from BASIC, as in the following
- example:
-
- PP = ^CHAR;
- VAR
- P: PP;
- I: array[1..2] of integer absolute P;
- Colr,Mono,Both:boolean;
-
- BEGIN
- I[2] := $B800;
- I[1] := 0;
- Colr := FALSE;
- Mono := FALSE;
- P^ := 'A';
- IF P^ = 'A' THEN Colr := TRUE;
- I[2] := $B000;
-
-
- 20
-
- I[1] := 0;
- P^ := 'A';
- IF P^ = 'A' THEN Mono := TRUE;
- IF Colr and Mono THEN Both := True;
- ...
-
-
- This little program segment checks to see if a color
- adapter is installed, then it checks to see if a monochrome
- adapter is installed, by checking the physical addresses
- to see if there is memory in their spaces. This piece of
- code is here to show that a pointer can point to
- something other than a record. Turbo Pascal has the
- MemW[] and Mem[] arrays, but some compilers do not, and this
- is one way it may be simulated.
-
- Understanding A Linked List
- Paul Robinson
-
-
- Going back to my original idea, I wanted to create
- an alphabetized word list. I wanted merely to do a
- single linked list where each item points to the next one in
- memory. If I checked the words first, I could store the
- table automatically in alphabetical order and thus
- generating the table would be trivial.
-
- Almost all the books and articles I see deal only
- with double-linked lists, where there is a pointer to a
- previous record, and a pointer to a record that is next in
- line. This would be overcomplicated for something as
- simple as just generating a list of words in
- alphabetical order. I didn't want frequency counts in a
- binary tree, I just wanted a list of words - and it seemed
- trivial.
-
- I have used Pascal for over 5 years and doing this
- little exercise taught me something about the language and
- how it works. It also taught me a little about the way I
- was thinking about certain concepts.
-
- Every time I started on the means to store the table, I
- kept either losing items or not storing the new entries.
- The standard method for working with a linked list is to
- have a start pointer, and additionally to have a 'traverse'
- pointer, as described above. You follow down the links
- until you find the entry you want or until you run out of
- items.
-
- One thing I had misunderstood was that when you have a
- second pointer, the pointer is not the data, and two
- pointers pointing to the same place are not the same
-
-
- 21
-
- thing. This means, if you have
-
- var
- T,T1:Tokp;
- name:maxstring;
-
- begin
- NEW(T);
- T1 := T;
-
- That any change to T1 will not have any effect on the
- system, unless you do something to one of the fields pointed
- to by t1. Remember, just because T and T1 point to the
- same place do not make them the same thing. And that is
- what caused me so much trouble.
-
- In the enclosed program (WORDCOUNT.PAS) is the word
- count program I wrote. If you notice the section where T2 is
- allocated then the values are all moved:
-
- IF t1^.token > tab.sym THEN
- BEGIN
- new(t2);
- tab.nwords := tab.nwords+1;
- t2^.count := t1^.count;
- t2^.token := t1^.token;
- t2^.next := t1^.next;
- t1^.count := 1;
- t1^.token := tab.sym;
- t1^.next := t2;
- END;
-
- Merely assigning values to T2 would not have worked,
- because T2 is local to that procedure. The only way to
- get the values to stick is to use the existing values and
- attach these.
-
- This program sample was added to fix two glaring
- deficiencies: the lack of an explanation in the use of
- single linked lists, and one mistake I was making,
- confusing the reference pointer with the data. My guess is
- that if I am doing this, others are also.
-
- 22
-
- For Beginners
- By Bob Gowans
-
- Having discussed important features of programming such
- as design, input and output statements in Pascal, the use of
- relevant comments and programming style we can give
- ourselves a self congratulatory pat on the back, but...
- before you can achieve the ultimate goal, writing that
- elusive master program, complete with pop up menus and user
- friendly screens you must learn to master the art of being
- selectively repetitive in your programming technique. The
- computer is really worth it's weight in gold when it can
- carry out, on our behalf, long and boring tasks producing
- results at amazing speed. For example a payroll program,
- used by a large company, has to calculate net pay of each of
- it's employees - this is essentially a repetitive task. The
- same program may base it's calculations on variable tax
- rates, depending on gross pay. Thus, the program has to
- select a course of action for certain circumstances. Lets
- take the issue of selection and repetition and treating each
- as a separate concept briefly consider their use in program
- design.
-
- Selection
- =========
-
- When we are faced with a problem we usually embark on a
- course of action arrived at through a mental process called
- decision making. Decisions are an important part of our
- everyday lives, we make countless decisions each day and
- branch out along different courses of action to achieve what
- we want. From many different alternatives we SELECT a
- particular course of action. IF I get home on time tonight
- THEN I will watch the game on T.V. ELSE I will read PNL
- might be a simplified way to express a form of decision
- making. In terms of program design decision making is an
- important concept and one way to deal with this is very
- similar to the human decision example given above. We would
- express this as follows :-
-
- if ( test of truth of a statement)
- then
- carry out a set of instructions when the test is true
- else
- carry out a set of instructions when the test is false
- ifend
-
- For example, what follows is a design language
- implementation of a simple selection statement which tests
- whether a person is married or not and writes out a message
- accordingly.
-
-
- 23
-
-
- 1.1 if married = true
- 1.2 then
- 1.3 write out 'congratulations'
- 1.4 else
- 1.5 write out 'keep trying'
- 1.6 ifend
- If the person is married he gets the message
- 'congratulations', if not then is presented with the 'keep
- trying' message. Remember the position of the words if,
- then, else and ifend and note the indentation of the actions
- to be performed.
-
-
- Repetition
- ==========
-
- Repetitive execution of program statements involves the
- use of loops. A conditional loop is controlled ie. started
- or finished, by simple or complex conditions.There are
- several ways in which loops can be implemented , initially
- we will deal with a type that tests for the
- stopping/starting condition at the beginning of a loop. At
- this stage we will not be dealing with unconditional loops,
- this type of loop will execute a predetermined number of
- statements, however it is as well that you are aware that
- they exist. If the loop is to be executed while a condition
- is true, then the loop control is written as LOOP WHILE
- condition. The loop will take the following form :-
-
- loop test (ie. loop while condition is true.)
- statement 1
- statement 2
- etc...
- loopend
-
- It is very important to observe two rules when using
- conditional loops. The first rule is to initialize any
- variables, prior to entering the loop, which will be updated
- within the loop. The second rule is to initialize any
- variables used in the loop test ( ie. the condition ) prior
- to entering the loop. To illustrate the importance of this
- lets consider the following design which repetitively reads
- in a real number from the keyboard and sums the total of all
- the numbers entered and outputs the final total.
-
- 1 initialize variables updated in the loop
- 2 read in first number
- 3 loop while number is positive
- 4 update total
- 5 read in next number
- 6 loopend
-
-
- 24
-
- 7 write out total
-
- Note that total is a variable that is consistently updated,
- within the loop and that number is the variable used to
- determine the condition of the loop ( ie. continue or stop
- ). This information can be tabulated as follows :-
-
- Identifier Description Type
- ========= =========== =====
-
- number number input real variable
-
- total accumulated total of
- numbers input real variable
-
- Following the top-down methodology lets individually refine
- the steps given above.
-
- Steps 2,4,5 and 7 are easy :-
-
- 2.1 read in number
-
- 4.1 set total to total + number
-
- 5.1 read in number
-
- 7.1 write out 'The total sum of all the numbers is ',total.
-
- Lets not forget to include relevant input prompts. Steps 2.1
- and 5.1 will require further refinement.
-
- 2.1 write out 'Enter any positive number (negative number to
- quit)'
- 2.2 read in number
-
- 5.1 write out 'Enter any positive number (negative number to
- end)'
- 5.2 read in number
-
-
- The two steps that read in number at 2.2 and 5.2 are
- required because the initial condition of the loop at step 3
- depends on the value of number read in at step 2.2 - we
- have thus met the requirement of loop rule #2 by setting
- number to it's initial value. Once the loop has been entered
- control passes through steps 4.1,5.1,5.2 until at step 6,
- control passes back to step 3. The condition of the loop is
- tested again and it's execution depends on the data entered
- at step 5.2. The two input statements are necessary - the
- first to test the loop initially and the second to provide
- subsequent test of the loop condition.
-
-
- 25
-
- Refining step three requires us to see that the
- condition is true as long as number is positive. So if
- number is entered as a negative the loop will terminate.
- This is a simple condition and can be expressed as follows
- :-
-
- 3.1 loop while number >= 0
-
- If you are unsure what the condition operators mean,
- refer to the table under the section IMPLEMENTATION OF IF
- THEN ELSE which is further on in the article.
-
- The stopping data item ( ie a negative number ) is
- known as a SENTINEL VALUE. If the number variable has a
- negative value the loop condition is not true and the loop
- is not executed. In this case the execution of the loop is
- controlled by user input.
-
- To further refine step 1 we require to know the
- variables that will be updated in the loop. Both total and
- number are updated within the loop but only total is updated
- by assignment ( number is updated as being input ), so total
- requires to be initialized before being used in the loop.
- This would necessitate setting total to zero. The complete
- design is given below :
-
- 1.1 set total to 0
- 2.1 write out 'Enter any positive number (negative number to
- quit)'
- 2.2 read in number
- 3.1 loop while number >= 0
- 4.1 set total to total + number
- 5.1 write out 'Enter any positive number (negative
- quits)'
- 5.2 read in number
- 6 loopend
- 7.1 write out 'The total sum of all the numbers is ',total.
-
- We have dealt, briefly with a method of selection and a
- method of repetition and program language methods which
- allow these concepts are called CONTROL STRUCTURES. As you
- guessed there are other control structures but we will leave
- those for another article. Lets go on to implement the two
- control structures we have discussed in Pascal.
-
-
- IMPLEMENTATION OF IF THEN ELSE
- ==============================
-
- The if statements of the design are written, in Pascal,
- similarly except you do not need to include the ifend
- statement.
-
-
-
- 26
-
-
- if condition
- then
- begin
- statement 1;
- statement 2;
- ........ etc
- end
- else
- begin
- statement 1;
- statement 2;
- ......... etc
- end;
-
- Note that the Pascal reserved words BEGIN and END mark
- the start and finish of multiple statements. If there is
- only one statement to be executed then the BEGIN and END may
- be excluded. Lets discuss the implementation of our design
- concerning the married or single survey. I have added to the
- basic design by stipulating an interactive program that
- prompts the user to respond 'y' or 'n' to a question. This
- introduces us to the data structure CHAR. The data type
- char, provided by Pascal, enables us to manipulate character
- sets including upper-case letters, the digits and some
- punctuation marks and mathematical symbols. When the user
- inputs a character - in this case either 'y' or 'n', the
- character input is assigned to the char variable RESPONSE.
- By using the if... then... else... control structure the
- program determines what the user input; the users
- response.If it is 'y' then the a message is output, if it is
- 'n' then a different message is output. Please note that
- when testing for characters they should be included in
- single quotation marks. When inputting characters they
- should be written as they are - without quotation marks.
-
- program ismarried;
-
- var
-
- response : char;
-
- begin
- write('Are you married ( enter y or n ) > ');
- read(response);
- if response = 'y' {Condition test. Note
- test for character uses ''}
- then
- writeln('You lucky person')
- else
- writeln('What''s your phone number?'); {Ifend}
- writeln;
- 27
-
- end.
-
- A condition is a test which is carried out on the
- values of variables to compare them in some way. As your
- knowledge of Pascal evolves their use will become more
- apparent to you. For now lets summarize the various tests
- for conditions in a table.
-
- Operator Condition
- ======== =========
-
- > is greater than
- < is less than
- = is equal to
- <> is not equal to
- >= is greater than or equal to
- <= is less than or equal to
-
- You can probably see, that comparison operators are a
- powerful programming tool that can be used to test for a
- variety of conditions. Now try the following exercises.
- Solutions will be given at the end of the article.
-
-
- Ex1
- ____________________________________________________________
-
- Devise a design to read in two numbers, compare them
- and print out the two numbers in ascending order.
-
-
- Ex2
-
-
- Length, width and height are integer variables and
- woman, man and child are char variables. Which of the
- following are valid conditions?
-
- Solutions are given at end of article.
-
- (a) length > 24
- (b) woman = 'Wendy'
- (c) child = 5
- (d) height = 63
- (e) man >= 70
- (f) width = '6'
- (g) child = 'C'
-
-
- 28
-
- IMPLEMENTATION OF THE WHILE DO LOOP
- ===================================
-
- While loops are implemented in Pascal as given below
-
- while condition do
- begin
- statement1;
- statement2;
- .........etc
- end;
-
- The statements to be executed repeatedly are separated
- by semicolons and if there is only one statement within the
- loop the keywords BEGIN and END may be exclude. Now lets go
- back to our design from the REPETITION section in the
- article and implement this in Pascal.
-
- program addup;
- { Adds up and prints total, to the screen, of real numbers
- input by the user }
- var
- total,number : real;
-
- begin
- total := 0; {Initialize variables updated in loop}
- write('Enter a positive number (negative number to exit)
- > ');
- readln(number);
- while number >= 0 do { start of loop }
- begin
- total := total + number;
- writeln;
- write('Enter a positive # (neg. # to exit) > ');
- readln(number)
- end;{ of while do loop }
- writeln;
- writeln('The total sum of numbers entered is ',total:5:2)
- end.
-
- As you can see the actual implementation of the design
- into Pascal was fairly straightforward, the brain work was
- required at the design stage. So while you are in the mood
- try out the following exercise :-
-
- Ex3
-
-
- Design a program that will read in the ages of all the
- participants, the program will keep a count of the total
- amount of users and will print out the maximum age plus the
- total amount of users. Hint - do not forget the sentinel.
-
- 29
-
-
- Before I give the solutions to the exercises I thought
- I would include this useful Turbo Pascal routine that checks
- the amount of space available on a default hard disk. The
- routine is not really aimed at beginners but gives you an
- insight into the power of Turbo Pascal and it's control over
- DOS. To more experienced users, feel free to modify the code
- to suit your own needs.
-
- program HDcheck;
-
- uses crt,dos;
-
- var
- i : integer;
- totalspace,usedspace,freespace : real;
-
- begin
- clrscr;
- writeln;
- totalspace := disksize(0)/1000000;
- writeln('Total disk space = ',totalspace:5:2,' MBytes');
- writeln;
- usedspace := (disksize(0) - diskfree(0))/1000000;
- writeln('Disk space used = ',usedspace:5:2,' MBytes');
- writeln;
- freespace := diskfree(0)/1000000;
- writeln('Space free = ',freespace:5:2,' MBytes');
- for i := 1 to 15 do
- writeln;
- writeln('HDCheck by B.Gowans');
- writeln;
- writeln('Press enter to continue');
- readln;
- clrscr
- end.
-
- The use of control statements such as IF...THEN...ELSE
- and WHILE DO will greatly enhance your programming abilities
- and this is just the start of the control structures
- available to Pascal. Practice using these structures by
- following the examples found in the text books and get
- comfortable in using them. Here are the solutions to the
- exercises
-
- Ex1 :
-
- 1 initialize variables
- 2 compare the numbers
- 3 write out numbers in order
-
- 1.1 read in number1
-
-
- 30
-
- 1.2 read in number2
- 2.1 if number1 > number2
- 2.2 then
- 2.3 write out number1
- 2.4 write out number2
- 2.5 else
- 2.6 write out number2
- 2.7 write out number1
- 2.8 ifend
-
-
-
- Ex2 :
-
- (a) valid
- (b) invalid - variable is of type char and not string.
- (c) invalid - variable is of type char and not integer.
- (d) valid
- (e) invalid - for same reasons as (c).
- (f) invalid - width is integer variable and not char.
- (g) valid.
-
- Ex3 :
-
- 1. initialize variables
- 2. loop while users to be processed
- 3. process age
- 4. process count
- 5. loopend
- 6. write out count, maxage
-
- Further refinement :-
-
- 1.1 set count to 0
- 1.2 set max to 0
- 1.3.1 write out 'Please enter age ( enter -1 to quit )'
- 1.3.2 read in age
- 2.1 loop while age < > -1
- 3.1 if age > max
- 3.2 then
- 3.3 set max to age
- 3.4 else
- 3.5 { do nothing }
- 3.6 ifend
- 4.1 set count to count + 1
- 4.2 write out 'Please enter age ( enter -1 to quit )'
- 4.3 read in age
- 5 loopend
- 6.1 write out 'The maximum age was ',maxage
- 6.2 write out 'Out of a total of ',count,' people.'
-
- The implementation in Pascal follows - please note there may
-
- 31
-
- be small changes in the implementation which does not affect
- the overall design.
-
- program age_survey;
-
- var
-
- age : integer;
- maxage : integer;
- count : integer;
-
- begin
- write('Enter age to nearest year ( -1 to quit ) > ');
- readln(age);
- count := 0;
- maxage := 0;
- while age <> -1 do { start loop, stop with age = -1 }
- begin
- if age > maxage { if start }
- then
- maxage := age
- else
- { do nothing };{no other branching is necessary so ifend}
- count := count + 1;
- writeln;
- write('Enter age to nearest year (-1 to quit ) > ');
- readln(age)
- end;
- writeln;
- writeln('The greatest age was ',maxage,' years');
- writeln;
- writeln('The total number surveyed was ',count)
- end.
-
- All the code in this article has been written and
- compiled using Turbo Pascal v4. The executable code was run
- on an Opus PC 5 under DOS 3.3. There is no guarantee that
- the same code will run under your own particular
- configuration.
-
- 32
-
- Recursion is Easy
- By Chris Burke
-
- Recursion and pointers seem to be the two subjects that
- cause beginners in pascal the most heartache. This brief
- article aims to delve into the subject of recursion.
-
- Introduction
-
- Imagine you (Alfred) are talking to Bob, when Christine
- walks up and rudely interrupts and starts talking to you.
- You put up with it and talk to Christine (she is prettier
- than Bob anyway). While talking to Christine, her mum
- (Daphne) wants a bit of a chat - you being the wise person
- you are (and liking Christine so much) decide to talk to
- Daphne, just after finishing your chat and commencing
- conversing with Christine, the telephone rings - you answer
- and (OH NO!!) it is Elaine wanting to go to the movies
- tonight, you quickly say sure no problems see you at 8, see
- you then, bye and continue talking to Christine. After a
- little while Christine leaves and you restart talking to
- Bob.
-
- So, What have you been doing - well
- 1. You have been two-timing, and deserve all you get.
- 2. You have been using your 'Talk' function recursively.
-
- i.e.
- Talk(Bob)
- Talk(Christine)
- Talk(Daphne)
- Return to Talk(Christine)
- Talk(Elaine)
- Return to Talk(Christine)
- Return to Talk(Bob)
-
- So now that you understand a bit about the concepts of
- recursion lets go onto more computer oriented problems of
- recursion.
-
- One of the most common examples of recursion is the
- factorial program - as it gets quoted so often I shall use
- the example here. For those not familiar with what a
- factorial is - here is an explanation :
-
- The factorial of a positive number (0,1,2...) is
- defined as follows :
-
- factorial of N = N*(N-1)*(N-2)....*1
- factorial of 0 = 1 (by definition - i.e. for no real
- reason)
-
-
- 33
-
- (For those with a little curiosity, there is a related
- function called the gamma function which works on negative
- numbers and non-integers.)
-
- The factorial is represented using the ! symbol
-
- i.e. 12! represents the factorial of 12
-
- The first way the programmer would go about defining a
- function to calculate the factorial is as follows :
-
- function factorial(N:longint):longint;
- var
- Count,Temp:longint;
- begin
- Temp:=1;
- for Count:=1 to N do
- Temp:=Temp*Count;
- Factorial:=Temp;
- end;
-
- which would in effect for N=5 calculate the following
-
- factorial(N) = 1*2*3*4*5
-
- which adheres to the formula above.
-
-
- The Quantum Leap
-
- The quantum leap in thought is to realize that the
- above formula:
-
- N!=N*(N-1)*(N-2)*(N-3)...*1 can be written differently.
-
- Lets take an example, say 5!.
-
- 5!=5*(5-1)*(5-2)*(5-3)*(5-4)
-
- or =5* 4 * 3 * 2 * 1 BUT LOOK!! this can be
- written
-
- =5* 4!
- and
- 4!=4*3*2*1 = 4*3! AND SO ON.....
-
- which means the original formula can be written as
-
- N!=N*(N-1)! - This is the mathematical equivalent of
- recursion.
-
- converting this to pascal is a fairly simple step :
-
- 34
-
- function factorial(N:longint):longint;
- begin
- factorial:=N*factorial(N-1)
- end;
-
- EASY - just a straight implementation in pascal....
-
- The only thing left to do is to implement what is known
- as an exit condition - or a termination condition, this
- tells the above factorial function when to stop what is
- currently an infinite loop, the easiest way to do this is to
- realize that factorial(0)=1 as defined by our mathematical
- gurus. The modified code is :
-
- function factorial(N:longint):longint;
- begin
- if N=0 then factorial:=1
- else factorial:=N*factorial(N-1)
- end;
-
- This is where the IDE environment in the turbo pascal
- compiler comes in handy. Write a little program that
- includes the above function as follows :
-
- program TestRecursion;
- function factorial(N:longint):longint;
- begin
- if N=0 then factorial:=1
- else factorial:=N*factorial(N-1)
- end;
- begin
- writeln('Factorial 5=',factorial(5));
- writeln('Factorial 0=',factorial(0));
- end.
-
- Try tracing through this code remembering to use the
- 'step over' on the 'begin' and the 'step into' on the two
- writeln statements. After a little playing and placing
- watches on N. (Don't forget to put Local Symbols and Debug
- Information on in the options). By now recursion should be
- somewhat more obvious.
-
- Something A Little More Useful
-
- This subject may be of a little more interest, but as I
- have always found - the best way of learning is by doing,
- and when you have it working you will be far more satisfied.
-
- The following hints should get you on your way to a
- routine which does some function MYFUNC on every file on
- your hard disk - in every directory on your hard drive.
-
- 35
-
- In english here is what you would do :
-
- 1. Write a routine which does MYFUNC on every file in a
- specified
- directory something like the following :
-
- procedure DoMyFuncHere(D:Pathstring);
- var
- F:FileString;
- begin
- F:=GetFirstName; (* Remember : *)
- while F is valid do (* we want all directories
- and files *)
- begin
- MYFUNC(D+F);
- F:=GetNextName;
- end;
- end;
-
- test this procedure out and see if it works - OK
-
- 2. Modify this routine so that it calls itself recursively
- when there is a subdirectory (remember - don't get worried
- by the fact that the routine is calling itself)
-
- { Ed. Note: Semi-Pascal algorithm }
-
- | procedure DoMyFuncHere(D:Pathstring);
- | var
- | F:FileString;
- |
- | begin
- | F:=GetFirstName; (* Remember : *)
- | while F is valid do (* we want all directories and
- files *)
- | begin
- | if (F='.') or (F='..') then
- |
- DontGoHereThereIsProblemsIfYouDo;
- | else if F_IsADirectory then
- | DoMyFuncHere(D+F)
- | else MYFUNC(D+F);
- | F:=GetNextName;
- | end;
- | end;
-
- { Ed. Note: Actual Pascal algorithm }
- ~program test;
- ~uses crt,dos;
- ~
- ~ Procedure MyFunc (FileRec : SearchRec);
- ~ begin
- ~ Writeln(FileRec.Name);
- ~ end;
- ~
- 36
-
- ~ procedure DoMyFuncHere(D:Pathstr);
- ~ var
- ~ SR : SearchRec;
- ~
- ~ begin
- ~ FindFirst(D+'*.*',Directory+Archive,SR);
- ~ while DosError = 0 do
- ~ begin
- ~ if (SR.Name <> '.') AND (SR.Name <> '..') then
- ~ If (SR.Attr AND Directory) > 0 then
- ~ DoMyFuncHere(SR)
- ~ else
- ~ MYFUNC(D+SR.NAME);
- ~ FindNext(SR);
- ~ end;
- ~ end;
- ~
- ~begin
- ~ DoMyFuncHere('C:\');
- ~end.
-
- Try this out by calling DoMyFuncHere('C:\');
- I am sure you can put your imagination to other uses for
- such a recursive directory engine, ie: finding and deleting
- ALL BAK files on a drive, or counting the size of
- subdirectories, you can modify the search criterion in the
- FINDFIRST line.
-
- A BIT OF EXPLAINING
- ------------------
- Imagine a simple directory like this,
-
- COMMAND.COM 1 calls MYFUNC
- AUTOEXEC.BAT 1 calls MYFUNC
- <DOS> 1 calls DoMyFuncHere - recursively
- <.> 2 skips
- <..> 2 skips
- FDISK.COM 2 calls MYFUNC
- DEBUG.COM 2 calls MYFUNC
- 2 returns from second level
- CONFIG.SYS 1 calls MYFUNC
- <UTILS> 1 calls DoMyFuncHere - recursively
- <.> 2 skips
- <..> 2 skips
- LIST.COM 2 calls MYFUNC
- <NU> 2 calls DoMyFuncHere - recursively
- <.> 3 skips
- <..> 3 skips
- SI.EXE 3 calls MYFUNC
- 3 returns from third level
- 37
-
- 4EDIT.EXE 2 calls MYFUNC
- 2 returns from second level
- 4DOS.COM 1 calls MYFUNC
- 1 returns and exits to main program
-
- By following the above (the number represents how deep
- you have gone) you should be able to see how simple the
- program to look at every file on your hard disk is.
-
- If you want any more assistance on recursion see the section
- above called 'A BIT OF EXPLAINING' otherwise continue to the
- conclusion.
-
- Conclusion
-
- I hope that this description of recursion will answer
- your questions on recursion, if you have any questions for
- me then I have a point called 'Mindware' fidonet 3:640/305.1
-
- Christopher Burke
- Brisbane, Queensland
- AUSTRALIA
-
-
- Chris Burke is owner/operator of a contract Programming
- company called Mindware in Brisbane, Australia. He programs
- commercially using various languages including Turbo Pascal
- from version 2.0 through to version 5.5 professional (Using
- Object Professional), Assembler, and Clarion.
- He runs a point Fidonet system, and can be contacted at
- 3:640/305.1.
-
-
- 38
-
- Conclusion
-
- There are a couple things I'd like to point about some
- future issues. Bob Gowans will, of course, continue to produce
- his column, which has become incredibly popular. Richard is going
- to give us quite bit of stuff on graphics in Pascal, so that will
- also be a regular contribution. I will be starting a series
- pretty soon on doing large projects. I am just finishing up a
- large project that involved 5 other programmers and quite a bit
- of design work before the implementation. I'd like to go over a
- lot of the stuff we did. This alone should take several issues,
- but I think you will find it very interesting. The code alone,
- because it is so vast, will be broken up into several issues and
- each unit will be covered alone and then the final integration of
- the entire project will be examined.
-
- I feel bad that I can't seem to get the newsletter out as
- often as I would like, but like many of you, I have to set my
- priorities, one of them, earning a living. Hopefully you will
- forgive me for this. All I can do is make a promise that I will
- try my best to get each issue out as soon as possible.
-
- I would also like to ask, as I do in every issue, that you
- try to find the time to send in some of your own material for
- inclusion in the newsletter. Without user contributions, I just
- can't keep this going. They have been good lately, but I could
- handle a few more. So, please, if you don't feel you can
- contribute, try to find friends that can. Try to get them to send
- in stuff they've done.
-
- One last word on the distribution list. I keep quite a bit
- of the updates in a directory which I search at the end of the
- month to make updates to the distribution list. Several days ago,
- because of a strange problem, that directory, almost exclusively,
- was completely wiped out. I have been unable to make any
- corrections to the distribution list. If you sent in a
- correction, or addition, please send me the information again so
- that I can make those corrections. I'm sorry for any
- inconvenience this may have caused.
-
- Ah, and one final thing that I almost forgot. I have
- recently put a second computer together. This should help me put
- a little more time into the newsletter, as I won't have to worry
- about bringing my BBS down every time I want to work on the
- newsletter.
-
- Well, enjoy the holidays and hopefully I'll have a brand new
- issue out in early January.
-
- _Pete Davis
-
-
- 39
-
-
- The Pascal NewsLetter is Copyrighted by Pete Davis.
- Articles submitted by others are the property of the authors and
- are used with permission. They may not be treated separately
- from this newsletter without the author's permission and thus
- maintain all distribution rules of the newsletter as a whole. It
- may be freely distributed in un-modified form, but no charge
- whatsoever may be incurred on the recipient. All code is provided
- 'as-is' with no guarantees whatsoever.
-
- The Pascal NewsLetter can be obtained from the
- following locations:
-
- GEnie : General Electric Network for Information
- Exchange. It is located in the IBMPC
- filelist.
-
- Simtel : Internet address: 26.2.0.74 or
- Simtel20.ARPA It is located in the
- <MSDOS.PASCAL> directory.
-
- Programmer's Forum : This is the home of the PNL.
- Each issue can be found in
- the MAG directory from the main area.
- The number is on the title page.
-
- If you would like to receive back issues of PNL
- directly from me, send a diskette and $2.00 for shipping.
- Don't forget to include your address.
-
- Send your order to:
- Peter Davis
- 4851 Brandywine St. NW
- Washington, DC 20016
-
- If you are a SysOp that will regularly carry PNL and
- would like to have your bulletin board listed as such, here,
- send me a message either by postal mail or at one of the
- electronic addresses given on the title page, with your
- bulletin board's name, phone number, and your name.
-
- 40
-
- Distribution List
-
- The following is the phone numbers to bulletin boards known
- to carry PNL. If you would like your bulletin board's name and
- number added to or deleted from this list, please send me a
- message at one of my many addresses. I can not guarantee whether
- a listed board will have any particular issue.
-
- The Programmer's Forum ................. Phone: (202) 966-3647
- The Programmer's Forum is the home of the PNL.
-
- BBS | FidoNet Addrs | Phone #
- --------------------------+----------------------+---------------
- The Bored | 1:397/3 | (512) 303-0471
- Classic City BBS | 1:370/10 | (404) 548-0726
- Thieve's World BBS | 1:106/805 | (713) 463-8053
- Hippocampus BBS | 1:141/205 | (203) 484-4621
- Rogers State College | 1:170/708 | (918) 341-8982
- The Foxtrot BBS | 1:272/26 | (914) 567-1814
- Turbo City BBS | 1:208/2 | (209) 599-7435
- Austin IEMUG/MIDI BBS | 1:382/14 | (512) 258-0626
- Laser Publishers | 1:170/403 | (918) 438-2749
- Fargo RBBS-PC | 1:10/8 | (701) 293-5973
- Momentary Lapse of Reason | | (704) 327-6361
- The Demon's Den | | (508) 433-2702
- The Cannibal Cafe | | (508) 840-6589
- IBM Tech FIDO | | (508) 433-6491
- The User Friendly BBS | | (704) 323-8223
- The Disseminator BBS | 3:640/378 | 61-7-368-1239
- Beyound Fronttiers BBS | 2:230/101 | (+45)8694-1609
- Collision Theory | | (703) 503-9441
- Merlin's Mailbox | 2:245/39 |
- Ed-Net9600 | 1:153/734 | (604) 732-8877
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-