Jump to content
Registration disabled at the moment Read more... ×
Freeeee

what wrong with this function?

Recommended Posts

function DaysInMonth ( Mo, Yr : LongInt): LongInt;
begin
     case Mo of
     1,3,5,7,8,10,12:DaysInMonth := 31;
           4,6, 9,11:DaysInMonth := 30;
                   2: If (Yr mod 4 = 0)
                       and (yr mod 400 = 0)
                       and (yr mod 100 > 0)
                        then
                          DaysInMonth := 29;
                     else
                        DaysInMonth := 28;
     end;

end;

It's based on the Gregorian calendar's rules for Leap Year.

And YES I KNOW that Delphi has Date Routines that are better than anything I can write

so, please spare me that critique.     I want to know why the compiler rejects this with 4 errors in one Unit

but accepts  in a different Unit. .

 

Share this post


Link to post

Thanks for replying.  That was a good catch.

 

I think i put that semicolon  in trying to correct the errors 

My bad.  Sorry.

 taking it out didn't change any of the four errors 

which start at the function label on line 415

interesting I can't cut and paste errors so I'm going to copy them

 

E2023 Function needs result type at line 415 (415:10)

E2029 Declaration expected but '(' found at line 415 (415:22)

E2003 Undeclared identifier: 'Mo" at line 417 (417:11)

E2993 Undeclared identifier: DaysInMonth at line 418(418:22) 

 

the function heading should be the identifier 

and I was under the impression that the arguments passed are placeholders for 

the real arguments as long as they are of the same type.  LongInt in this case.

I didn't use VAr in front of them because they shouldn't be modified.

This worked fine in a Unit where the full routine of which this is a part 

was tested.,  aside for a label a memo box and two buttons it was the only code 

the test program.

So I'm trying to determine why it works in one simple unit but not this one.

 

Share this post


Link to post

Move the code to an empty unit and try to compile that one. If it still does not compile post the full code of that new unit here. I think the problem is not in the code you have shown us but somewhere before that.

Edited by dummzeuch

Share this post


Link to post

I tried the test Unit but It recompiled without errors.  

and it would be the empty unit you described.

one memo, 1 label  2 buttons.   button 1 converts the date in the memo

and moves the answer (which is days since year zero) into the label.

Button two converts the days back into yyyy mm dd form and moves that back into

the memo.  If you used "/"  as a separator there;s no change,  If you used space, comma, period

or letters as separators they're changed to "/" so you know it worked.

ie you got back the same date.      

 

I got the idea from Microsoft.  There year zero date is 01/01/1980.

mine is 01/01/0000 .  good in a long integer (and a 5 digit year) until 31,999/12/31.

 

I think your right about something else going on that's confusing the compiler.

The Unit it's in is quite large  Over 500 lines.  and there's till more code to write to get to a working program.

I think what I'm going to have to do is fix the other typos and errors first

and just leave this code alone hoping that eventually the compiler will accept them.  I'll just comment then out

to continue testing.

 

thank for you help.  

 

 

 

Share this post


Link to post

FYI, the SysUtils unit has an IsLeapYear() function, and a MonthDays[] array, eg:

uses
  ..., SysUtils;

function DaysInMonth(Mo, Yr : Word): Word;
begin
  Result := MonthDays[IsLeapYear(Yr), Mo];
end;

Alternatively, the DateUtils unit has its own DaysInAMonth() function, eg:

uses
  ..., DateUtils;

function DaysInMonth(Mo, Yr : Word): Word;
begin
  Result := DateUtils.DaysInAMonth(Yr, Mo);
end;

No need to reinvent the wheel here...

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post

thank you Remy

the errors are

E2023 Function needs result type at line 415 (415:10)                     there - is  -  a"    : LongInt;  "    after the closing paren

E2029 Declaration expected but '(' found at line 415 (415:22)         that's the opening paren for Mo, yr: LongInt

E2003 Undeclared identifier: 'Mo" at line 417 (417:11)                     Mo was declared in the input args

E2993 Undeclared identifier: DaysInMonth at line 418(418:22)        ??? It's the name of the function.

 

I already admitted that Delphi has better date routines.

and I wrote this routine in turbo pascal before Delphi.

 

That's beside the point.  I want to know WHY the compiler 

accepts the routine without error in at least two other UNITS earlier but NOT THIS ONE?

 

the above errors don't mention 'duplicate function ; or anything that indicate that's true.

 

they are all about the way it's written.   

Is there some major flaw in the code above the routine that confuses the compiler so badly

it starts flagging errors where there are none??

 

By the way,  Why would I need to qualify a variable on a form when it's the ONLY form in the program?

example (   ABCycle.Visible  ) is a E2003    -     but if I put in  (    Form5.ABCycle.Visible  )   in the code it's accepted. 

And Form5 IS the only form in this particular program

 

Same program as the DaysInMonth problem

Share this post


Link to post
2 hours ago, Freeeee said:

thank you Remy

the errors are

E2023 Function needs result type at line 415 (415:10)                     there - is  -  a"    : LongInt;  "    after the closing paren

E2029 Declaration expected but '(' found at line 415 (415:22)         that's the opening paren for Mo, yr: LongInt

E2003 Undeclared identifier: 'Mo" at line 417 (417:11)                     Mo was declared in the input args

E2993 Undeclared identifier: DaysInMonth at line 418(418:22)        ??? It's the name of the function.

Since we can't see the rest of your code, we can't help you with these errors. The sole function you have shown only had one mistake in it. So clearly these other errors are caused by other problems (likely other syntax mistakes) higher up in your code that we can't see.

2 hours ago, Freeeee said:

I want to know WHY the compiler 

accepts the routine without error in at least two other UNITS earlier but NOT THIS ONE?

Because clearly THIS unit has other mistakes in it that are breaking its compilation.

2 hours ago, Freeeee said:

Is there some major flaw in the code above the routine that confuses the compiler so badly it starts flagging errors where there are none??

Obviously yes, but what that flaw could be specifically is anybody guess without seeing the rest of the code in question.

2 hours ago, Freeeee said:

By the way,  Why would I need to qualify a variable on a form when it's the ONLY form in the program?

example (   ABCycle.Visible  ) is a E2003    -     but if I put in  (    Form5.ABCycle.Visible  )   in the code it's accepted.

That behavior happens when the failing code is NOT inside a non-static method of the TForm5 class, thus requires an explicit object reference to reach the ABCycle member.

2 hours ago, Freeeee said:

And Form5 IS the only form in this particular program

It doesn't matter if you have 1 Form or 100. You need a valid TForm5 object reference in order to access its ABCycle member. Inside of a method of the TForm5 class, that reference can be the implicit 'Self' pointer. But code outside of TForm5's methods will need an explicit pointer to the Form5 object. 

2 hours ago, Freeeee said:

Same program as the DaysInMonth problem

That behavior would happen if DaysInMonth() is a non-static method of the TForm5 class, and thus must be called on a valid Form5 object reference, but the calling code does not have such a reference without qualifying it. 

Share this post


Link to post

 

Is there some reason for using Non-Static as opposed to Active or Dynamic when talking about classes? 

What I'm understanding is any Procedure code generated from the Tform by some action (like a mouse clik) is in the TForm class.

so as long as you do ALL of your coding inside one of those procedures you don't have to qualify back to the TForm.

But if you call something like a WriteRecord procedure that was NOT generated by an action in./of/on the form you do have to qualify because you;ve gone outsife of the scope of the TForm class.   

 

or are the nuances ?? like hierarchy rules.    Is it "You know when your outside of the class scope when you have to qualify".  or is there an easier way?

 

 

Share this post


Link to post
5 hours ago, Freeeee said:

 

Is there some reason for using Non-Static as opposed to Active or Dynamic when talking about classes?

There's no such thing as an "active" class method.

 

Non-static, dynamic, virtual methods - these all have a hidden implicit Self pointer to the object instance they are called on.

Quote

What I'm understanding is any Procedure code generated from the Tform by some action (like a mouse clik) is in the TForm class.

so as long as you do ALL of your coding inside one of those procedures you don't have to qualify back to the TForm.

Yes, because they will all be using the Self pointer. For example

procedure TForm5.FormClick(Sender: TObject);
begin
  ABCycle.Visible := True;
end;

Is really this:

procedure TForm5.FormClick(Sender: TObject);
begin
  Self.ABCycle.Visible := True;
end;

Quote

But if you call something like a WriteRecord procedure that was NOT generated by an action in./of/on the form you do have to qualify because you;ve gone outsife of the scope of the TForm class.   

If such a procedure is trying to access members of the Form of object, then yes.

Quote

or are the nuances ?? like hierarchy rules.    Is it "You know when your outside of the class scope when you have to qualify".  or is there an easier way?

I suggest you brush up on your fundamentals. For instance:

 

https://docwiki.embarcadero.com/RADStudio/en/Procedures_and_Functions_Index

 

https://docwiki.embarcadero.com/RADStudio/en/Classes_and_Objects_Index

 

https://docwiki.embarcadero.com/RADStudio/en/Methods_(Delphi)

Edited by Remy Lebeau
  • Like 1

Share this post


Link to post

I didn't know that you can use a case statement where the numbers used are not in order..

 

1,3,5,7,8,10,12:DaysInMonth := 31;

And in the next line you use 4,6,9 and 11 while the line before ends with 12..

 

4,6, 9,11:DaysInMonth := 30;

What if you replace all the old Pascal style return vars DaysInMonth into Result like:

 

1,3,5,7,8,10,12:Result := 31;

 

Share this post


Link to post

Hi 

the function worked perfectly in Turbo Pascal when I first wrote it.

then you used the name of the function to return the value.

and Yes I could use Result rather than function name.

 

but the question was why is the compiler finding these

errors (that are not errors).  Why did this function Pass  in 2 other Units

but not this one.   

Share this post


Link to post
10 minutes ago, Freeeee said:

but the question was why is the compiler finding these

errors (that are not errors). 

As mentioned elsewhere, you need to show more code that is before the function. The function code is correct, it is something before it that makes the compiler unhappy.

  • Like 1

Share this post


Link to post
18 minutes ago, Freeeee said:

Why did this function Pass  in 2 other Units but not this one.   

Because as Remy suggested these 2 other units don't have DateUtils or SysUtils in the uses?

 

But if you change the "DaysInMonth:=" into "Result:=" does that work ?

Share this post


Link to post

Messed up structure elements can lead to odd errors in others parts of the code. 

 

It may look like a block of code is part of a function but due to messed up structure elements it actually isn't. 

Your first error indicates you are still probably still inside a begin/end code block - the same error is produced by the code below in a simple button click

 

procedure TForm1.Button1Click(Sender: TObject);
begin
   function AddTwo(a,b:integer):integer;
end;

 

Share this post


Link to post

thanks 

Remy agrees that I've screwed up something higher up in the code so the compiler is confused.

I'm still 're-' Learning. 🙂

 

Edited by Freeeee
Added relearning

Share this post


Link to post
18 hours ago, Freeeee said:

I got the idea from Microsoft.  There year zero date is 01/01/1980.

mine is 01/01/0000 .  good in a long integer (and a 5 digit year) until 31,999/12/31.

mmm,  I run win 11 are you still using DOS.  

procedure TForm16.Button4Click(Sender: TObject);
var
  SL: TStrings;    // F1 click bait
begin

   SL := memo1.Lines;
   for var aDate in [0, 1,2,3, 30000-2*365-32-17 , 30000, 40000, 50000, 100000] do
   begin
     SL.Add(DateToStr(aDate));
   end;
end;

 

 

 

Share this post


Link to post

Yes, I am running MSDos, 

AND

Window XP

And 

Window 10

and my game machine is a Win 11.

Emulators are great,  if you can remember which system your in.

but I don't like side kick at all.

Share this post


Link to post

Putting the function definition inside a Begin / End code block produces the multiple errors posted. So the unit has an open code block where the function definition currently is. 

  • Like 1

Share this post


Link to post

code was from ? 2000,.  Worked then.

There wasn't a reserved word "Result"

so you  used the function name at the end of the code set equal to whatever variable 

you were using to get the results. 

 Function doSomething: Integer;

var X : integer

begin 

    X := code to do something; 

doSomething := X;

end.

 

  • Confused 1

Share this post


Link to post
3 hours ago, Freeeee said:

code was from ? 2000,.  Worked then.

There wasn't a reserved word "Result"

so you  used the function name at the end of the code set equal to whatever variable 

you were using to get the results. 

 Function doSomething: Integer;

var X : integer

begin 

    X := code to do something; 

doSomething := X;

end.

 

What are you expecting anyone to do with this? 

  • Like 2

Share this post


Link to post
4 hours ago, Freeeee said:

code was from ? 2000,.  Worked then.

There wasn't a reserved word "Result"

so you  used the function name at the end of the code set equal to whatever variable 

you were using to get the results. 

The Result variable (enabled by default via the {$EXTENDEDSYNTAX ON} / {$X+} directive) has been available for a very very long time, much earlier than 2000. But even so, assigning values to the function's name is still an allowed option, too. 

  • Like 2

Share this post


Link to post

Just to clear and sum up: The error is in the 414 lines of code above this totally fine function. So, until one of the following two things happens, this will turn in to a merry game of guessing:

1) You provide us with the top 414 lines of code

2) You let your IDE format the code and discover formatting is "out of whack" beginning somewhere above line 415, and home in on the problem yourself

 

In any case, I do hope you will provide us with the solution to this riveting riddle.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×