home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / pascal / PAS_TUT.ZIP / CHAP11.TXT < prev    next >
Encoding:
Text File  |  1991-02-04  |  28.2 KB  |  590 lines

  1.  
  2.  
  3.  
  4.                                                        Chapter 11
  5.                                                 FILE INPUT/OUTPUT
  6.  
  7. FILES HANDLE SERIAL DATA
  8. _________________________________________________________________
  9.  
  10. One of the most common operations when using a computer is to
  11. either read from, or write to a file.  You are already somewhat
  12. experienced in file handling from the last chapter, because in
  13. computer terminology, the keyboard, terminal, and printer are all
  14. classified as files.  A file is any serial input or output device
  15. that the computer has access to.  Since it is serial, only one
  16. piece of information is available to the computer at any instant
  17. of time. This is in contrast to an array, for example, in which all
  18. elements of the array are stored internally and are all available
  19. at any time.
  20.  
  21.  
  22. A SHORT HISTORY LESSON
  23. _________________________________________________________________
  24.  
  25. Several years ago computers were all large cumbersome machines with
  26. large peripheral devices such as magnetic tape drives, punch card
  27. readers, paper tape readers or punches, etc.  It was a simple task
  28. to assign the paper tape reader a symbol and use that symbol
  29. whenever it was necessary to read a paper tape.  There was never
  30. more than one file on the paper tape being read, so it was simply
  31. read sequentially, and hopefully the data was the desired data. 
  32. With the advent of floppy disks, and hard disks, it became
  33. practical to put several files of data on one disk, none of which
  34. necessarily had anything to do with any of the other files on that
  35. disk.  This led to the problem of reading the proper file from the
  36. disk, not just reading the disk.
  37.  
  38. Pascal was originally released in 1971, before the introduction of
  39. the compact floppy disk.  The original release of Pascal had no
  40. provision for selecting a certain file from among the many included
  41. on the disk.  Each compiler writer had to overcome this deficiency
  42. and he did so by defining an extension to the standard Pascal
  43. system.  Unfortunately, all of the extensions were not the same,
  44. and there are now several ways to accomplish this operation.  There
  45. are primarily two ways, one using the Assign statement, and the
  46. other using the Open statement.  They are similar to each other and
  47. they accomplish the same end result.
  48.  
  49.  
  50. BACK TO THE PRESENT TIME
  51. _________________________________________________________________
  52.  
  53. All of the above was described to let you know that we will have
  54. a problem in this chapter, namely, how do we cover all of the
  55. possible implementations of Pascal available?  The answer is, we
  56. can't.  Most of what is covered in this chapter will apply to all
  57.  
  58.                                                         Page 11-1
  59.  
  60.                                    Chapter 11 - File Input/Output
  61.  
  62. compilers, and all that is covered will apply to the TURBO Pascal
  63. compilers.  As we have mentioned before, this tutorial is
  64. especially written for the TURBO Pascal compilers, but you should
  65. be warned that you will find differences in Pascal implementations
  66. if you have occasion to use a different Pascal compiler someday. 
  67. You may, for example, need to use a mini-computer or a mainframe
  68. computer someday to complete a programming assignment.  When that
  69. happens, you will find that the area of input/output control will
  70. probably be the biggest difference in the implementations of
  71. Pascal.
  72.  
  73.  
  74. READING AND DISPLAYING A FILE
  75. _________________________________________________________________
  76.  
  77. Examine the file READFILE.PAS for an example of  ================
  78. a program that can read a text file from the       READFILE.PAS
  79. disk.  In fact, it will read itself from the     ================
  80. disk and display itself on the video monitor. 
  81. The first statement in the program is the Assign
  82. statement.  This is TURBO Pascal's way of selecting which file on
  83. the disk will be either read from or written to.  In this case we
  84. will read from the disk.  The first argument in the Assign
  85. statement is the device specifier similar to Lst used in the last
  86. chapter for the printer.  We have chosen to use the name Turkey for
  87. the device identifier, but could have used any valid identifier. 
  88. This identifier must be defined in a var declaration as a text type
  89. variable as illustrated in line 4.  The next argument is the
  90. filename desired.  The filename can be defined as a string
  91. constant, as it is here, or as a string variable.
  92.  
  93. The text type is a predefined type and is used to define a file
  94. identifier.  It is predefined as a "file of char", so it can only
  95. be used for a text file.  We will see later that there is another
  96. type of file, a binary file.
  97.  
  98. You will find that the operating system that you are using requires
  99. a file name to follow certain conventions when it is named, and the
  100. Pascal programming language has a set of rules by which an
  101. identifier can be named.  Since these two conventions are not
  102. necessarily the same, it is necessary to give each file an external
  103. name which the operating system is happy with, and an internal
  104. filename which Pascal is happy with.  It now becomes necessary to
  105. tie these two names together, and this is the primary job of the
  106. Assign statement.
  107.  
  108. Now that we have a file identified, it is necessary to prepare it
  109. for reading by executing a reset statement in line 9.  The Reset
  110. statement positions the read pointer at the beginning of the file,
  111. ready to read the first piece of information in the file.  Once we
  112. have done that, data is read from the file in the same manner as
  113. it was when reading from the keyboard.  In this program, the input
  114. is controlled by the while loop which is executed until we exhaust
  115. the data in the file.
  116.  
  117.                                                         Page 11-2
  118.  
  119.                                    Chapter 11 - File Input/Output
  120.  
  121. WHAT ARE THE "EOF" AND "EOLN" FUNCTIONS?
  122. _________________________________________________________________
  123.  
  124. The Eof function is new and must therefore be defined.  When we
  125. read data from the file, we move closer and closer to the end of
  126. the file, until finally we reach the end and there is no more data
  127. to read.  This is called "end of file" and is abbreviated Eof. 
  128. Pascal has this function available as a part of the standard
  129. library which returns FALSE until we reach the last line of the
  130. file.  When there is no more data to read left in the file, the
  131. function Eof returns TRUE.  To use the function, we merely give it
  132. our file identifier as an argument.  It should be clear to you that
  133. we will loop in this program until we read all of the data
  134. available in the input file.
  135.  
  136. The Eoln function is not used in this program but is a very useful
  137. function.  If the input pointer is anywhere in the text file except
  138. at the end of a line, the Eoln returns FALSE, but at the end of a
  139. line, it returns a value of TRUE.  This function can therefore be
  140. used to find the end of a line of text for variable length text
  141. input.
  142.  
  143. To actually read the data, we use the Readln procedure, giving it
  144. our identifier Turkey and the name of the variable we want the data
  145. read into.  In this case, we read up to 80 characters into the
  146. string and if more are available, ignore them.  You should remember
  147. when we did this in the last chapter from the keyboard input.  We
  148. are using the same technique here except we are reading from a file
  149. this time.  Since we would like to do something with the data, we
  150. output the line to the default device, the video monitor.  It
  151. should be clear to you by now that the program will read the entire
  152. file and display it on the monitor.
  153.  
  154. Finally, we Close the file Turkey.  It is not really necessary to
  155. close the file because the system will close it for us
  156. automatically at program termination, but it is a good habit to get
  157. into.  It must be carefully pointed out here, that you did not do
  158. anything to the input file, you only read the data and left it
  159. intact.  You could Reset it and reread it again in this same
  160. program.  Compile and run this program to see if it does what you
  161. expect it to do.
  162.  
  163.  
  164. A PROGRAM TO READ ANY FILE
  165. _________________________________________________________________
  166.  
  167. Examine the next program READDISP.PAS for an     ================
  168. improved file reading program.  This is very       READDISP.PAS
  169. similar to the previous program, except that it  ================
  170. asks you for the name of the file which you wish
  171. to display.  After you enter the filename, it
  172. enters the name into a 12 character string  which is named
  173. Name_Of_File_To_Input which will be the external filename.  This
  174. is then used in the Assign statement to select the file to be read,
  175.  
  176.                                                         Page 11-3
  177.  
  178.                                    Chapter 11 - File Input/Output
  179.  
  180. and to connect the external filename to the internal filename,
  181. Chicken.  The file is then reset as before.  Lines 15 through 18
  182. display a header, and from that point on, the program is identical
  183. to the last one with a few small additions.  In order to
  184. demonstrate the use of a function within the Writeln specification,
  185. the program calls for the length of the input string in line 23 and
  186. displays it before each line.  The lines are counted as they are
  187. read and displayed, and the line count is displayed at the end of
  188. the listing.  Both of these operations are done only to illustrate
  189. to you how they can be done. 
  190.  
  191. You should be able to understand clearly how each of these
  192. operations is accomplished.  Compile and run this program, entering
  193. any filename we have used so far as the file to be listed on the
  194. monitor (be sure to include the .PAS extension).  After a
  195. successful run, enter a nonexistent filename and see the I/O error
  196. generated by the Pascal runtime system.  The next example program
  197. will illustrate a more graceful method of detecting this error.
  198.  
  199.  
  200. HOW TO COPY A FILE (SORT OF)
  201. _________________________________________________________________
  202.  
  203. Examine the file READSTOR.PAS for an example of  ================
  204. reading from a file and writing to another one.    READSTOR.PAS
  205. In this program we request an operator input for ================
  206. the filename to read, after which we Assign the
  207. name to the file and Reset it.  When we reset
  208. the file however, we go to a bit of extra trouble to assure that
  209. the file actually exists.  Note that this is an extension to TURBO
  210. Pascal and will probably not work with other Pascal compilers.
  211.  
  212. Suppose we input a filename, and the file did not exist because the
  213. file was actually missing, or because we entered the name of the
  214. file wrong.  Without this extra effort, the TURBO Pascal runtime
  215. system would indicate a run-time error, and terminate the program
  216. returning us to the operating system.  In order to make a program
  217. easier to use, it would be nice to tell the operator that the file
  218. didn't exist and give him the opportunity to try again with another
  219. file name.  The method given in lines 16 through 20 of this program
  220. will allow you to do just that.
  221.  
  222.  
  223. USING A COMPILER DIRECTIVE
  224. _________________________________________________________________
  225.  
  226. First you must disable the built in TURBO Pascal I/O checking by
  227. inserting the compiler directive in line 16.  This tells the system
  228. to ignore any I/O errors from this point on and if the file doesn't
  229. exist, the system will not abort when you attempt to reset it in
  230. line 17.  Another compiler directive is given in line 18 to enable
  231. I/O checking again for the remainder of the program.  
  232.  
  233.  
  234.  
  235.                                                         Page 11-4
  236.  
  237.                                    Chapter 11 - File Input/Output
  238.  
  239.  
  240. WE DO OUR OWN FILE CHECKING
  241. _________________________________________________________________
  242.  
  243. If the file didn't exist and could not therefore be reset, we have
  244. a problem because the program thinks the file is available for use
  245. but it actually isn't.  Fortunately, TURBO Pascal has a built in
  246. variable, named IOResult that informs us of the result of each I/O
  247. operation.  Following any I/O operation, if this variable contains
  248. the value of zero, the I/O operation was correct, and if it
  249. contains any other value, the operation had some sort of error. 
  250. In our case, we simply compare it to zero to generate a boolean
  251. value, then based on the boolean value we either give an error
  252. message and stop, or perform the desired file operations.
  253.  
  254. It would be good programming practice to check all file openings
  255. in this manner to allow the operator to recover from a simple
  256. oversight or spelling error.
  257.  
  258. If the file was opened properly, then in line 21 through 24 we
  259. request a different filename to write to, which is assigned to a
  260. different identifier.  Note that the output file is not checked for
  261. a valid opening in this example as it should be.  The statement in
  262. line 24 is new to us, the Rewrite statement.  This name apparently
  263. comes from the words REset for WRITEing because that is exactly
  264. what it does.  It clears the entire file of any prior data and
  265. prepares to write into the very beginning of the file.  Each time
  266. you write into it, the file grows by the amount of the new data
  267. written.
  268.  
  269. Once the identifier has been defined, and the Rewrite has been
  270. executed, writing to the file is identical to writing to the
  271. display with the addition of the identifier being specified prior
  272. to the first output field.  With that in mind, you should have no
  273. trouble comprehending the operation of the program.  This program
  274. is very similar to the last, except that it numbers the lines as
  275. the file is copied.  After running the program, look in your
  276. default directory for the new filename which you input when the
  277. system asked for the output filename.  Examine that file to see if
  278. it is truly a copy of the input file with line numbers added.  
  279.  
  280. Actually a much better style would result if the logic for each
  281. file opening was put into a procedure of its own.  In addition to
  282. this being easier to debug and understand, the completed procedures
  283. could be reused in other programs in the future.
  284.  
  285. One word of caution.  If you used an existing filename for the
  286. output file, the file was overwritten, and the original destroyed. 
  287. In that case, it was good that you followed instructions at the
  288. beginning of this tutorial and made a working copy of the
  289. distribution disk.  You did do that, didn't you?
  290.  
  291. Compile and run this program two different ways, once with a valid
  292. input filename that should run properly, and the second time with
  293.  
  294.                                                         Page 11-5
  295.  
  296.                                    Chapter 11 - File Input/Output
  297.  
  298. an input filename that doesn't exist to prove to yourself that the
  299. test actually does work correctly.
  300.  
  301.  
  302. HOW TO READ INTEGER DATA FROM A FILE
  303. _________________________________________________________________
  304.  
  305. It is well and good to be able to read text from a file, but now
  306. we would like to read other forms of data from a file.  First we
  307. will look at an example program to read data from a text file, then
  308. later we will see an example program that reads from a binary file. 
  309.  
  310. Examine the program READINTS.PAS for an example  ================
  311. of reading data from a text file.  A text file     READINTS.PAS
  312. is an ASCII file that can be read by a text      ================
  313. editor, printed, displayed, or in some cases,
  314. compiled and executed.  It is simply a file made
  315. up of a long string of char type data, and usually includes
  316. linefeeds, carriage returns, and blanks for neat formatting. 
  317. Nearly every file on the Tutorial disk you received with this
  318. package is a text file.  One notable exception is the file named
  319. LIST.EXE, which is an executable program file.
  320.  
  321. The example program has nothing new, you have seen everything in
  322. it before.  We have an assignment, followed by a reset of our file,
  323. followed by four read and write loops.  Each of the loops has a
  324. subtle difference to illustrate the Read and Readln statements. 
  325. Notice that the same file is used for reading four times with a
  326. Reset prior to each, illustrating the nondestructive read mentioned
  327. a few paragraphs ago.
  328.  
  329. The file we will be using is named INTDATA.TXT and is on your disk. 
  330. You could display it at this time using the program READDISP.PAS
  331. we covered recently.  Notice that it is simply composed of the
  332. integer values from 101 to 148 arranged four to a line with a
  333. couple of spaces between each for separation and a neat appearance. 
  334. The important thing to remember is that there are four data points
  335. per line.
  336.  
  337.  
  338. READ AND READLN ARE SLIGHTLY DIFFERENT
  339. _________________________________________________________________
  340.  
  341. As variables are read in with either procedure, the input file is
  342. scanned for the variables using blanks as delimiters.  If there are
  343. not enough data points on one line to satisfy the arguments in the
  344. input list, the next line is searched also, and the next, etc. 
  345. Finally when all of the arguments in the input list are satisfied,
  346. the Read is complete, but the Readln is not.  If it is a Read
  347. procedure, the input pointer is left at that point in the file, but
  348. if it is a Readln procedure, the input pointer is advanced to the
  349. beginning of the next line.  The next paragraph should clear that
  350. up for you.
  351.  
  352.  
  353.                                                         Page 11-6
  354.  
  355.                                    Chapter 11 - File Input/Output
  356.  
  357. The input data file INTDATA.TXT has four data points per line but
  358. the first loop in the program READINTS.PAS requests only three each
  359. time through the loop.  The first time through, it reads the values
  360. 101, 102, and 103, and displays those values, leaving the input
  361. pointer just prior to the 104, because it is a Read procedure.  The
  362. next time through, it reads the value 104, advances to the next
  363. line and reads the values 105, and 106, leaving the pointer just
  364. prior to the 107.  This continues until the 5 passes through the
  365. loop are completed.
  366.  
  367. The loop in lines 19 through 22 contains a Readln procedure and
  368. also reads the values 101, 102, and 103, but when the input
  369. parameter list is satisfied, it moves the pointer to the beginning
  370. of the next line, leaving it just before the 105.  The values are
  371. printed out and the next time we come to the Readln, we read the
  372. 105, 106, and 107, and the pointer is moved to the beginning of the
  373. next line.  It would be good to run the program now to see the
  374. difference in output data for the two loops.  Remember that the
  375. only difference is that the first loop uses the Read procedure, and
  376. the second uses the Readln procedure.
  377.  
  378. When you come back to the program again, observe the last two
  379. loops, which operate much like the first two except that there are
  380. now five requested integer variables, and the input file still only
  381. has four per line.  This is no problem.  Both input procedures will
  382. simply read the first four in the first line, advance to the second
  383. line for its required fifth input, and each will do its own
  384. operation next.  The Read procedure will leave the input pointer
  385. just before the second data point of the second line, and the
  386. Readln will advance the input pointer to the beginning of the third
  387. line.  Compile and run this program and observe the four output
  388. fields to see an illustration of these principles.
  389.  
  390.  
  391. NOW TO READ SOME REAL VARIABLES FROM A FILE
  392. _________________________________________________________________
  393.  
  394. Examine the file named REALDATA.TXT supplied on your Pascal
  395. Tutorial disk.  You will see 8 lines of what appears to be
  396. scrambled data, but it is good data that Pascal can read.  Notice
  397. especially line 4 which has some data missing, and line 6 which has
  398. some extra data.
  399.  
  400. Examine the program file READDATA.PAS which will ================
  401. be used to illustrate the method of reading real   READDATA.PAS
  402. type data.  Everything should be familiar to     ================
  403. you, since there is nothing new here.  The
  404. Readln statement is requesting one integer
  405. variable, and three real variables, which is what most of the input
  406. file contains.  When we come to the fourth line, there are not
  407. enough data points available, so the first two data points of the
  408. next line are read to complete the fourth pass through the loop. 
  409. Since the file pointer is advanced to the beginning of the next
  410. line, we are automatically synchronized with the data again.  When
  411.  
  412.                                                         Page 11-7
  413.  
  414.                                    Chapter 11 - File Input/Output
  415.  
  416. we come to the sixth line, the last two data points are simply
  417. ignored.  Run the program to see if the results are as you would
  418. predict.
  419.  
  420. If a Read were substituted for the Readln in line 14 of the
  421. program, the file pointer would not be advanced to the beginning
  422. of line 6 after the fourth pass through the loop.  The next attempt
  423. to read would result in trying to read the value 0.0006 as an
  424. integer, and a run time error would result.  Modify the program,
  425. substituting a Read for the Readln in line 14, and see if this is
  426. not true.  It will be left as an exercise for the diligent student
  427. to add code to detect and act on the error in a manner similar to
  428. that illustrated in READSTOR.PAS earlier in this chapter.
  429.  
  430. It should be pointed out that TURBO Pascal requires a digit both
  431. before and after the decimal point in all data that is to be read
  432. in as real type data or it will be flagged as a run-time error and
  433. the program will be halted.  The digits can be zero as they are in
  434. several places in the example file but they must be there.
  435.  
  436. That is all there is to reading and writing text files.  If you
  437. learn the necessities, you will not be stumbling around in the area
  438. of input/output which is very intimidating to many people. 
  439. Remember to Assign, then Reset before reading, Rewrite before
  440. writing, and Close before quitting.  It is of the utmost importance
  441. to close a file you have been writing to before quitting to write
  442. the last few buffers to the file, but it is not as important to
  443. close read files unless you are using a lot of them, as there is
  444. an implementation dependent limit of how many files can be open at
  445. once.  It is possible to read from a file, close it, reopen it, and
  446. write to it in one program.  You can reuse a file as often as you
  447. desire in a program, but you cannot read from and write into a file
  448. at the same time.
  449.  
  450.  
  451.  
  452. NOW FOR BINARY INPUT AND OUTPUT
  453. _________________________________________________________________
  454.  
  455. Examine the file BINOUT.PAS for an example of    ================
  456. writing data to a file in binary form.  First       BINOUT.PAS
  457. there is a record defined in the type            ================
  458. declaration part composed of three different
  459. variable types.  In the var part, Output_File is
  460. defined as a "file of Dat_Rec", the record defined earlier.  The
  461. variable Dog_Food is then defined as an array of the record, and
  462. a simple variable is defined.
  463.  
  464. Any file assigned a type of text, which is a "file of char", is a
  465. text file.  A text file can be read and modified with a text
  466. editor, printed out, displayed on the monitor, etc. If a file is
  467. defined with any other definition, it will be a binary file and
  468. will be in an internal format as defined by the Pascal compiler and
  469. may not be readable by any compiler other than the one used to
  470.  
  471.                                                         Page 11-8
  472.  
  473.                                    Chapter 11 - File Input/Output
  474.  
  475. write it.  Attempting to display such a file will result in very
  476. strange looking gibberish on the monitor.
  477.  
  478. When we get to the program, the output file is assigned a name in
  479. line 15, and a Rewrite is performed on it to reset the input
  480. pointer to the beginning of the file, empty the file, and prepare
  481. for writing data into it.  The loop in lines 18 through 22 simply
  482. assigns nonsense data to all of the variables in the 20 records so
  483. we have something to work with.
  484.  
  485. We write a message to the display that we are ready to start
  486. outputting data, then we output the data one record at a time with
  487. the standard Write statement.  A few cautions are in order here. 
  488. The output file can be defined to store any simple variable type,
  489. integer, byte, real, or a record, but the types cannot be mixed. 
  490. The record itself however, can be any combination of data including
  491. other records if desired, but any file can only have one type of
  492. record written to it.  
  493.  
  494. A Writeln statement is illegal when writing to a binary file
  495. because a binary file is not line oriented.  A Write statement is
  496. limited to one output field per statement.  This is not a serious
  497. limitation since it is a simple matter to put one Write statement
  498. in the program for each variable you wish to write out to the file. 
  499. It is important to Close the file when you are finished writing to
  500. it.
  501.  
  502.  
  503. WHY USE A BINARY FILE
  504. _________________________________________________________________
  505.  
  506. A binary file written by a Pascal program cannot be read by a word
  507. processor, a text editor or any other application program such as
  508. a database or spreadsheet, and it may not even be readable by a
  509. Pascal program compiled by a different companies compiler because
  510. the actual data structure is implementation dependent.  It can't
  511. even be read by a Pascal program using the same compiler unless the
  512. data structure is identical to the one used to write the file. 
  513. With all these rules, it seems like a silly way to output data, but
  514. there are advantages to using a binary output.
  515.  
  516. A binary file uses less file space than a corresponding text file
  517. because the data is stored in a packed mode.  Since all significant
  518. digits of real data are stored, it is more precise unless you are
  519. careful to output all significant data to the corresponding text
  520. file.  Finally, since the binary data does not require formatting
  521. into ASCII characters, it will be considerably faster than
  522. outputting it in text format.  When you run this example program,
  523. it will create the file KIBBLES.BIT, and put 20 records in it. 
  524. Return to DOS and look for this file and verify its existence.  If
  525. you try to TYPE it, using the DOS TYPE command, you will have a
  526. real mess on your monitor because it does not contain char type
  527. data, but that might be a good exercise.
  528.  
  529.  
  530.                                                         Page 11-9
  531.  
  532.                                    Chapter 11 - File Input/Output
  533.  
  534. READING A BINARY FILE
  535. _________________________________________________________________
  536.  
  537. BININ.PAS is another example program that will    ===============
  538. read in the file we just created.  Notice that       BININ.PAS
  539. the variables are named differently, but the      ===============
  540. types are all identical to those used to write
  541. the file and they are in the same order.  An
  542. additional line is found in the program, the if statement.  We must
  543. check for the "end of file" marker to stop reading when we find it
  544. or Pascal will list an error and terminate operation.  Three pieces
  545. of information are written out to verify that we actually did read
  546. the data file in.
  547.  
  548. Once again, a few rules are in order.  A Readln is illegal since
  549. there are no lines in a binary file, and only one variable or
  550. record can be read in with each Read statement.
  551.  
  552.  
  553. FILE POINTERS, GET, AND PUT STATEMENTS
  554. _________________________________________________________________
  555.  
  556. File pointers and the Get and Put procedures are a part of standard
  557. Pascal, but since they are redundant and therefore not needed, they
  558. are not a part of TURBO Pascal.  The standard Read and Write
  559. procedures are more flexible, more efficient, and easier to use. 
  560. The use of Get and Put will not be illustrated or defined here. 
  561. If you ever have a need for them, they should be covered in detail
  562. in your Pascal reference manual for the particular implementation
  563. you are using.
  564.  
  565. Pointers will be covered in detail in the next chapter of this
  566. tutorial.
  567.  
  568.  
  569. PROGRAMMING EXERCISES
  570. _________________________________________________________________
  571.  
  572. 1.   Modify READFILE.PAS so that after reading and displaying the
  573.      file, the file is reset, then read and displayed again.  This
  574.      was suggested in the text.
  575.  
  576. 2.   Write a program to read the data from any text file, and
  577.      display it on the monitor with line numbers and the number of
  578.      characters in each line. Finally display the number of lines
  579.      found in the file, and the total number of characters in the
  580.      entire file. Compare this number with the filesize given by
  581.      the DOS command DIR.
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.                                                        Page 11-10
  590.