Program compiles but wont run?

vagga
vagga used Ask the Experts™
on
**Updated Code Again 24/11/02**
I dont want anyone to do my work for me, but some directon would be great!

I thought I was finished this program, and then started to read some old threads on this forum, and changed my program about a bit.  I saw some better ways of doing things. I had hacked about a bit, and saved on a good deal of program length.  After a long list of bugs were squashed it finally compiled.  Now when I run it in Free Pascal compiler (the one I have always used) it does not run at all while it compiles fine?

Any ideas why?  

{Included is the latest source of the program}
==================
program wages;

var                     {Im declaring all my different variables here}
atta, attb, adda, addb : integer;
countEmployee, day, month, year, weekno : integer;

errors, employee, printfile : text;
name:string[12];
shiftatt,shiftadd:char;
clcard, tothours, totaddhours, totlpay, addtnlhrs : integer;
taxcode:string[4];
addpay, allpay : integer;

procedure WriteError(S:String);
  begin
     writeln(errors,S);
  end;

function IntToStr(L:Longint):String;
  var S: String;
    begin
        Str(l,S);
        IntToStr:=S;
    end;

procedure inp;   {This procedure requires the user to input data}

begin
writeln('before assign');
Assign(errors,'c:\errors.txt');
writeln('after assign');
{$i-}
Append(errors);   {append to existing error file}
writeln('after append');
If IOResult<>0 then Rewrite(errors);     {if no error file exists, then create one}
{$i+}

repeat   {A loop to make sure that the shift allowance rate is valid}
     write('Please enter shift attendance allowance for shift A, between 1-100 ');
        readln(atta);
                if (atta <=0) or (atta >=101) then
                        writeln(errors,'Oops, thats an incorrect' +IntToStr(atta)+ 'entry');
     until (atta >=1) and (atta <=100);

repeat
     write('Please enter shift attendance allowance for shift B, between 1-100 ');
        readln(attb);
                if (attb <=0) or (attb >=101) then
                        writeln(errors,'Oops, thats an incorrect'+IntToStr(attb)+ 'entry');
        until (attb >=1) and (attb<=100);

repeat          {a loop to allow the entry of any additional hours for the employee}
     write('Enter the rate for an additional hour for shift A, between 1 and 10 ');
        readln(adda);
         if (adda <=0) or (adda >=11) then
                        writeln(errors,'Oops, thats an incorrect'+IntToStr(adda)+ 'entry');
     until (adda>=1) and (adda<=10);

repeat
     write('Enter the rate for an additional hour for shift B, between 1 and 10 ');
        readln(addb);
         if (adda <=0) or (adda >=11) then
                        writeln(errors,'Oops, thats an incorrect'+IntToStr(adda)+ 'entry');
     until(addb>=1) and(addb<=10);

repeat          {loops for the user to input the date}
     writeln ('Enter Month mm ');
        readln (month);
          if (month <=0) or (month >=13) then
                writeln(errors, 'DOH! Incorrect Month' +IntToStr(month)+ 'entered');
     until (month >=1) and (month <=12);

repeat
     writeln ('Enter Day dd ');
        readln (day);
          if (day <=0) or (day >=32) then
                writeln(errors, 'DOH! Incorrect Day' +IntToStr(day)+ 'entered');
     until (day >=1) and (day <=31);

repeat
     writeln ('Enter Year yyyy ');
        readln (year);
          if (year <=1900) then
                writeln(errors, 'DOH! Incorrect Entry' +IntToStr(year)+ 'entered');
          until (year >=1900);

repeat          {loop to set the week number}
     writeln ('Finally, please enter the Week No. ');
        readln(weekno);
          if (weekno <=0) or (weekno >=53) then
                writeln(errors, 'DOH! Incorrect Week No.' +IntToStr(weekno)+ 'entered');
          until (weekno >=1) and (weekno <=52)
end;

procedure reportbody;


begin         {this is the main body of the report}
assign(employee, 'c:\report.txt');  {open the employee report file}
assign(printfile,'PRN');
reset(employee);
rewrite(printfile);

while not eof(employee) do
begin   {read the employee report information}
        readln(employee, name);
        readln(employee, clcard);
        readln(employee, shiftatt);
        readln(employee, tothours);
        readln(employee, totaddhours);
        readln(employee, taxcode);

        if shiftatt = 'A' then    {this is where we do calculations for total pay and so on}
                totlpay := atta * tothours;
        if shiftatt = 'B' then
                totlpay := atta * tothours;
        if shiftatt = 'A' then
                addtnlhrs := adda * totaddhours;
        if shiftatt = 'B' then
                addtnlhrs := addb * totaddhours;

writeln('end of reading report');
{write the data into a file for printing}
writeln(printfile, ' ':1,name:12,' ':5,clcard:4,'':3,shiftatt:1,' ':2,tothours:4,' ':4,totaddhours:4,' ':9,taxcode:4,' '
:2,totlpay:4,'':4,addtnlhrs:4);
allpay := allpay + totlpay;
addpay := addpay + addtnlhrs;

end;
close(employee);
close(printfile);
end;



procedure xheader;    {procedure for the report header}

begin
assign(printfile,'PRN');
rewrite(printfile);
write(printfile,' ':41, 'Company Name');
writeln(printfile);
writeln(printfile, ' ':38, 'Employee Wages report');
writeln(printfile);
writeln(printfile, ' ':31, 'Date ',day:2, '/',month:2,'/',year:4);
writeln(printfile);
writeln(printfile,' ':31,'Week Number ',weekno:2);
writeln(printfile); writeln(printfile); writeln(printfile);
writeln(printfile, ' ':15,'Name', ' ':3,'Clock card no',' ':2,'Shifts attended',' ':2,
'Total Hours',' ':2,'Shift Attendance', ' ':2,'Additional Hours');
writeln(printfile,' ':55,'Attended',' ':10,'Pay', ' ':15,'Pay');
writeln(printfile);
end;      {this ends the actual wage report header}



procedure footer;  {this is the procedure for the footer to the report}

begin
assign(printfile,'PRN');
rewrite(printfile);
writeln(printfile);writeln(printfile);writeln(printfile);writeln(printfile);
writeln(printfile);writeln(printfile);writeln(printfile);writeln(printfile);
writeln(printfile);writeln(printfile);writeln(printfile);writeln(printfile);
writeln(printfile,' ':1,'Total No. of employees:',countEmployee:4,'':1);
writeln(printfile,' ':1,'Total pay for all employees:',allpay:4,'':1,'Pounds');
writeln(printfile,' ':1,'Total additional hours pay for all employees:',addpay:4,'':1,'Pounds');
writeln(printfile);
writeln(printfile,' ':1,'Basic pay for shift A.',atta:2,'':1,'Pounds per shift');
writeln(printfile,' ':1,'Additional hourly rate for shift A.',adda:2,'':1,'Pounds per hour');
writeln(printfile,' ':1,'Basic pay for shift B.',attb:2,'':1,'Pounds per shift');
writeln(printfile,' ':1,'Additional hourly rate for shift B.',addb:2,'':1,'Pounds per hour');

end;               {report footer ends here}


begin
writeln('Calling inp');
inp;
writeln('Calling reportbody');
reportbody;
writeln('Calling xheader');
xheader;
writeln('Calling footer');
footer;
end.    {this is the very end of the report}
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Commented:
A program can be compiled if it is SYNTACTICALLY correct - that is, each variable used is defined and is of the corrrect type, etc.

This does not mean that the program is LOGICALLY correct, since the compiler is unaware of the precise logic flow of the program. For instance, a line reading a file may be correct in syntax, but if it is executed before the file is opened, or after it is closed, or when the file is being written to, then the compiler sees no problem, but the program eecutable will fail.

Normally, some variety of error message is generated - you make no mention of any message. Does the program ask for input? If so, what input did you give it?

I'm unfamiliar with the particulars of your compiler - but some things are obviously wrong.

Take the first procedure executed:

                procedure inp;   {This procedure requires the user to input data}

                begin
                assign(F,'a:\errors.txt');    {create the error file}
                {$l-}
                Reset(F);
                If IOResult<>0 then Rewrite(F);
                {$l+}
                Append(F);

                repeat   {A loop to make sure that the shift allowance rate is valid}
                    write('Please enter shift attendance allowance for shift A, between 1-100 ');
                       readln(atta);
                               if (atta <=0) or (atta >=100) then
                                       writeln (errors,'Oops, thats an incorrect' +IntToStr(atta)+'entry');
                    until (atta >=1) and (atta <=100);
.........

Here, file 'F' is opened in append mode
You then appear to have the potential to write to the file 'errors' (if ATTA is invalid) but you have yet to OPEN the file 'errors'.
The compiler cannot possibly know that you want errors to be reported on' F', not 'errors'.



    aside :
                assign(F,'a:\errors.txt');
                {$l-}
                Append(F);    {append to existing error file}
                If IOResult<>0 then Rewrite(F);    {create the error file if none exists}
                If IOResult<>0 then write_out_some_error_message;    {could neither create nor append}
                {$l+}

     might work better for you - I'll let you set up the error reporting (consider when A:\ERRORS.TXT is read-only, or on a read-only floppy, a full floppy, etc.)

...Bill
Mike McCrackenSenior Consultant
Most Valuable Expert 2011
Top Expert 2013

Commented:
DO you get an error?  

Obviously the program runs somehow just doesn't produce the output you expect.

Have you tried putting in some writeln statements in the main program to see if you get anything.

Something like

begin
writeln ("Calling inp");
inp;
writeln ("Calling xheader");
xheader;
writeln ("Calling Readdat");
readdat;
writeln ("Calling footer");
footer;
end.

With that you should be able to see where the program stops.  Then you can put similar code in the procedure and find out where it is hung up.

mlmcc
mlmcc
Mike McCrackenSenior Consultant
Most Valuable Expert 2011
Top Expert 2013

Commented:
Minor logic error

repeat   {A loop to make sure that the shift allowance rate is valid}
    write('Please enter shift attendance allowance for shift A, between 1-100 ');
       readln(atta);
               if (atta <=0) or (atta >=100) then
                       writeln (errors,'Oops, thats an incorrect' +IntToStr(atta)+'entry');
    until (atta >=1) and (atta <=100);


If I enter 100 I will get an error message but it will be accepted.  Use either >= 100  in the if test and < 100 in the until test or > 100  in the if test and <= 100 in the until test.

Similarly in all your code.

mlmcc
OWASP: Forgery and Phishing

Learn the techniques to avoid forgery and phishing attacks and the types of attacks an application or network may face.

Author

Commented:
Thanks for all the help guys!

I put writeln statements in the code, as mlmcc suggested.  And what comes up is when I run is "Calling inp".  As I would expect.

What should come up next is "Please enter your shift allowance for for shift A...." and we start the user input part of the program.  But what happens is that the following comes up..

Execption_Continue_Execution set
call siginal called

And this repeats forever...

Thanks in advance for any help you can direct my way :)

(http://www.freepascal.org/ => Free Pascal Compiler!)
try to change
assign(F,'c:\errors.txt');    {create the error file}

to AssignFile(.....

Mike McCrackenSenior Consultant
Most Valuable Expert 2011
Top Expert 2013

Commented:
Another problem

assign(F,'c:\errors.txt');    {create the error file}
{$l-}
Append(F);   {append to existing error file}
If IOResult<>0 then Rewrite(F);     {if no error file exists, then create one}
{$l+}

repeat   {A loop to make sure that the shift allowance rate is valid}
    write('Please enter shift attendance allowance for shift A, between 1-100 ');
       readln(atta);
               if (atta <=0) or (atta >=100) then
                       writeln (errors,'Oops, thats an incorrect' +IntToStr(atta)+'entry');
    until (atta >=1) and (atta <=100);

The file errors is not open.  You open File F for output then try to write to File errors.

I realize this is after where the error is occurring but it may be playing in.

Try outtig writelns in and around the opening of File F.

writeln ("Before Assign");
assign(F,'c:\errors.txt');    {create the error file}
writeln ("After assign");
{$l-}
Append(F);   {append to existing error file}
writeln )"After Append");
If IOResult<>0 then Rewrite(F);     {if no error file exists, then create one}
{$l+}

In doing this make sure the file c:\errors.txt exists.

mlmcc

Commented:
seems to be an echo in here

Bill

Commented:
I've tried your revised code under freepascal 1.0.6 using NT4.

I cannot reproduce the errors you reported.

(BTW - {$I+} not {$l+} - 'i' not 'l')

I get runtime error 103 if invalid input is supplied

(file not open - as I mentioned in my first reply, file 'F' is opened, but the code writes errors to file 'error', which is never opened)

I get runtile error 2 if valid input is supplied (file not found - not surprising, since I don't have (or want)
'c:\report.txt')

your code

assign(employee, 'c:\report.txt');        {where to put the report}
assign(printfile,'PRN');

seems to be ill-commented - shouldn't you be reading your employee data from some file (surely not 'report.txt') and reporting to 'report.txt' - or are you reporting directly to 'PRN'?

...Bill

Author

Commented:
a huge thanks to both billous and mlmcc for all your help.  I think I have it cracked now!  I have updated the code here, and Im almost happy with it (as happy as Im going to be!)

The core of my problem was using l and not i as bilous described above, and again as bilous said a stupid error on my part opening file F and writing to file errors.txt.

To explain how this should work.  I read in from the user input and from an employee data file (report.txt) and output the error file for any errors, and output a payments to report direct to a printer.

Im currently checking this part of the program, and hoping to knock this on the head today, and get on with real work next week :)
Commented:
Hmm...

you don't appear to use the writerror procedure at all.

It appears to me that producing a file of errors entered from the keyboard
is pointless - I would suggest that the error responses in the inp
procedure should be produced to screen.

I would further suggest that the writerror procedure should be used to
produce a report of errors found in the input data file - for instance
where shiftatt is neither 'A' nor 'B', as in
 
   if (shiftatt <> 'A') and (shiftatt <> 'B') then
      writerror('invalid shift ' + shiftatt + ' for ' + name + '('
                 + intostr(clcard) + ')');

or better, using CASE

   case shiftatt of
   'A' :
       begin
         totlpay := atta * totlhrs;
         addtnlhrs := adda * totaddhrs;
       end;
   'B' :
       begin
         .....
       end;
   else
      writerror('invalid shift ' + shiftatt + ' for ' + name + '('
                 + intostr(clcard) + ')');
   end; {case}

note that writerror could also be used for invalid tax code, missing name,
etc.


bug1:

if shiftatt = 'B' then
   totlpay := attB * totlhrs;

   (not attA)


bug2:

you are assigning, rewriting and closeing printfile in reportbody,
then assigning and rewriting printfile in xheader
and finally assigning and rewriting printfile in footer.

attempting to produce body...header...footer.



You should
assign and rewrite in xheader
produce report body
close in footer

which produces the report sequence header...body...footer

what I do with reports is:

1. establish pagenumber and linenumber, assign values 0 and 99.
   establish maxlines, assign as required.

2. before producing each line of report body, determine whether a
   new page is required, and execute header if a new page is required.

   if linenumber >= maxlines then
     header;

   {produce your report line}
   inc(linenumber);


3. procedure header;
   begin
     if pagenumber = 0 then {producing first page of report}
     begin
       assign(printfile,.....
       rewrite(printfile...
     end
     else
       write(printfile,chr(12)); {form-feed to new page}
     inc(pagenumber);
     {now produce header lines - note page number conveniently in pagenumber}
     linenumber := ... {note : caters for any number of header lines}
   end;

4. procedure footer;
   begin
     if linenumber + number_of_footer_lines > maxlines then
       header;
     {produce footer lines}
     write(printfile,chr(12)); {form-feed to new page}
     close(printfile);
   end;

   which automatically produces a new page for the footer if the footer
   will not fit on the current page after the report body.

   Note also that this technique allows you to change the number of lines
   printed on a page by simply changing maxlines. It is normal to report
   only to an imaginary margin about an inch or so above the bottom of
   the page, so maxlines would be about 60, not 66 (standard "computer
   paper" is 11" x 15", 6 lines per inch, 132-column. Other sizes -
   just change maxlines...)

   It also correctly handles the opening & closing of the printfile.


...Bill

Author

Commented:
All your help has been amazing bill!  If I knew you, I would buy you a beer :)

Author

Commented:
good stuff, you have been a great help :)

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial