Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Finding the number of lines in a text file

Status
Not open for further replies.

Tamz

Technical User
Jun 29, 2002
3
MT
I'm trying to write a procedure to find the number of lines in a text file -- as far as I can see, the following *should* work, but it gives wildly innacurate results and also messes up the rest of the program (which works fine when the procedure is disabled). What am I doing wrong??


procedure chooseline;
var counter:integer;
begin
assign (listofwords, 'F:\project\words.txt');
reset (listofwords);
counter:=0;
while not eof (listofwords) do
begin
repeat
read (listofwords);
until eoln (listofwords);
counter:=counter+1;
readln;
end;
end;
 
edit: I changed the code slightly, and now it does count the number of lines correctly. However the program waits for input after each line (ie, if the textfile is 3 lines long, the user must click enter 3 times before the program continues). This ruins the screen layout and also does not make much sense .. how can I change it?

procedure chooseline;
var counter:integer;
ch:char;
begin
assign (listofwords, 'C:\pascal\hang.txt');
reset (listofwords);
counter:=0;
while not (eof (listofwords)) do
begin
repeat
read (listofwords,ch);
until eoln (listofwords);
counter:=counter+1;
readln;
end;
end;
 
Fixed. I had to write readln(listofwords), of course - silly mistake. Sorry for wasting anybody's time.
 
Also, don't forget this line:
[tt]
close(listofwords);
[/tt]
 
You haven't asked this, but just in case your next step is to bump into these, here are my favourite disasters with pascal files:

(1) If you run your procedure on a file that doesn't exist... If you are writing turbo pascal, put {$I-} before the reset statement, right at the begining of a line (it's a compiler directive rather than a piece of pascal) to tell the compiler not to include error checking when the assign is carried out at run time. Error checking can be turned on again with {$I+} straight after the reset. Then check that IOerror is zero. If it isn't, then the assign didn't work. I think that IOerror resets to zero if it is checked, so if you need to use it several times in a row, set a variable to IOerror and test the variable.
e.g.
assign(myfile, 'sillyname.fl');
{$I-}
reset(myfile);
{$I+}
myErrVar := IOerror;
if myErrVar <> 0 then
begin
writeln('It all went pear-shaped! Error was: ', myErrVar);
halt(99);
end;
the rest of your code.

(2) If you work with a non-text file ('file') then the reset statement needs to be accompanied by a block size. If you don't quote one, it won't be 1 byte.
Therefore
var
myfile : file;
begin
assign(myfile, 'sillyname.bin');
reset(myfile);
blockread(myfile, bufferplace^, 45);
end;

does NOT read 45 bytes! Had it had reset(myfile, 1), it would have done.
I still keep making this mistake!

(3) As ppc386 pointed out, if you don't close your file, then sooner or later you will hit the maximum the OS is allowing you, and everythign will stop working. But that only exists within your programme: when it terminates, the OS will close any remaining files for you.
 
> reset(myfile, 1);

Cool ! I did not know this, no wonder I could never get BlockRead to work!


> when it terminates, the OS will close any remaining files for you.

This is true for files you are reading, but if you are writing to a file you MUST close it, or else it will not be written to disk.
 
Thanks about the closing of write-files before closing the program. Good to know these things. I sort-of assume that the OS wouldn't write to disk every time I write a single character or line, but would keep a buffer and flush it to disk when it's getting full. If you just closed a programme at some random point without closing the file, I'd equally assume you'd at least lose everything still in the buffer and not yet flushed.
Thanks for interesting stuff, everyone.

 
I've never had any trouble when I didn't close binary files; text files are entirely different, but I never used them, so I wouldn't know what happens if you don't. Of course, it is always much cleaner to close them yourself and not to let someone else (you operating system for example) clean up your mess.

If you don't pass a block size parameter when resetting or rewriting untyped binary files, a standard block size of 128 bytes is assumed. The third parameter to blockread and blockwrite is the number of blocks to read. So in lionelhills example there will be read 128*45 = 5760 bytes.
Note that the entire block read must not be greater than 64K. Regards,
Bert Vingerhoets
vingerhoetsbert@hotmail.com
Don't worry what people think about you. They're too busy wondering what you think about them.
 
Yeah, if you fail to close or at least flush your text file you'll likely have unwritten data. When debugging by writing to a log file I've often had to flush things after a write to ensure the data is there after the program hangs and gets rebooted.
 
LorenPechtel, you have just brought up the one case where I would probably forget to flush a text file.
If I have a problematic programme creating a log-file as it runs to help me diagnose the problem, then I am most likely to want to see the log file if the programme broke off execution with an error. And it is just here that the finish-off code is unlikely to have been run.
Good idea to set up an exit-proc to close the logfile!
 
I tend to put the flush right after the write. When things go horribly wrong the exit procedure might not execute.
 
true, true. Even a simple endless loop would never allow exitproc to do its stuff.
 
Reset is to open a file for reading and writing, which command to use for only opening? Didn't had the problem until I put an application on CD Steven van Els
SAvanEls@cq-link.sr
 
yup, met that one. Someone might correct me if I'm wrong, but I have a feeling that at least some versions of pascal have problems about opening a file that's read only.

I met it in turbo pascal 6.0, using the .bgi Borland graphic interface files, in an environment where only the network manager and I had write-access to the program's home directory. Unfortunately that prevented users from using the program, because for some reason it opens the .bgi files with read and write access. A very rare example of someone in Borland getting something wrong.

Sorry not to be able to offer any help, just sympathy.
 
Wow! Thanks! Might have known it was my ignorance rather than Borland's not thinking.
Lionel
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top