How Do I Make This Delphi Function Work?

Okay... I've got a function called GetCond that works directly below:

function GetCond (c : string) : Integer;   {X}
begin
   if length (c) = 0 then
     begin
       result := -1;
       exit;
     end;
   CASE C[1] OF
      'N':  result  := 0;
      'A':  result  := 2;
      'C':  result  := 4;
      'S':  result  := 4;
      'X':  result  := 99;
   else
       result := -1;
   end;
end;

Now I wish to create another function based upon the results of the GetCond function only if the value returned is 99, which is the result of 'X' in the above code.

If it is 99, then I want the result for my new function to be NULL. I will be using this NULL value (empty value) to overwrite another field in a different Procedure.

Below is what I have so far, and it needs help:

function TestValueNull (tvn : string) : Integer;   {X}
begin
   if GetCond.value = 99 then
     begin
       result := ""
   end;

Thanks in advance!
zberg007Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

rfwoolfCommented:
Well in your TestValueNull function, your result is integer, right?
You then later try to set integer to null.
This would free the integer - something you shouldn't be doing.
Perhaps you want to return an integer value of -1 to represent null, a value of 0 to represent false and a value of 1 to represent true.

Something like this:
function TestValueNull (tvn : string) : Integer;   {X}
begin
  result := 0; //false
   if GetCond.value = 99 then
       result := -1
  else
  result := 1;
   end;
rfwoolfCommented:
Oh and you shouldn't say GetCond.value. GetCond will return the value of type integer, so you can just say if GetCond = 99.
Also in your wrong example,  you said result := ''''; Well your result is declared as type integer, and here you are trying to set it to a string ('''') which you can't do. You can do stuff like StrToInt('5') or IntToStr(5) and you could even do result := null if you want, but you might get some access violations if you call your TestValueNull function -- or maybe not :p
Emmanuel PASQUIERFreelance Project ManagerCommented:
what do you mean by null value ? an integer cannot be null. It can be 0, or another value that you will use as null if you need otherwise the 0 as a valid value. -1 for example, that you also use in GetCond

you could use Variants as a return type to hold integer values or Null, but it is a bit heavy to use.

You must tell us what you want to do with this so that we can give you the best answer

besides, your syntax with GetCond call is all wrong

here is the best we could do before you tell us more about what you do with that
Const
 Null_Value=-1;

function GetCond (c : string) : Integer; 
begin
 result := Null_Value;
 if length (c) = 0 then exit;
 Case C[1] Of
  'N':  result  := 0;
  'A':  result  := 2;
  'C':  result  := 4;
  'S':  result  := 4;
  'X':  result  := 99;
 end;
end;

function TestValueNull (tvn : string) : Integer;
begin
 if GetCond(tvn) = 99 then result := Null_Value;
end;

Open in new window

OWASP Proactive Controls

Learn the most important control and control categories that every architect and developer should include in their projects.

zberg007Author Commented:
I apologize about the Integer mixup. Since I just need it to be an empty value and not an Integer, would this work instead:

function TestValueNull (tvn : string) : string;
begin
 if GetCond(tvn) = 99 then result := "";
end;
rfwoolfCommented:
Almost.
Two things, your string quote character in delphi is a single-apostrophe, i.e. '
so change this line:
   if GetCond(tvn) = 99 then result := "";
to
 if GetCond(tvn) = 99 then result := '';

Next, you need the equivalent of an else statement, because what will happen if GetCond(tvn) <> 99? The result variable is invisible but it exists, so it will be null or it could be some other strange value.

So you should set your result to something else either like this:
function TestValueNull (tvn : string) : string;
begin
 result := 'Hello World!';
 if GetCond(tvn) = 99 then result := '';
end;

or like this:
function TestValueNull (tvn : string) : string;
begin
 if GetCond(tvn) = 99 then result := ''
else
  result := 'Hello World!';
end;

or did you want something like this

function TestValueNull (tvn : string) : string;
begin
  result := 'Hello World';
 if GetCond(tvn) = 99 then result := '';
 if GetCond(tvn) = 0 then result := 'zero';
 if GetCond(tvn) = 2 then result := 'two';
//note: A case statement would be better than the above.
end;
Emmanuel PASQUIERFreelance Project ManagerCommented:
zberg007, yes that would work also with a string. But really, the best solution depends on what is the real purpose of TestValueNull , and as rfwoolf said, what are the other values it could return.
Without the big picture here, it's really impossible to counsel beyond simple Delphi/Pascal syntax
zberg007Author Commented:
Once again, I apologize... I need this null value to be re-purposed elsewhere in my code. So this function will be used to overwrite another result value, like this:


procedure InsertParameter (tc, result, FLAG : string );
    var  pName, fName : String;
    begin
      PName  := '@'+tc;
      FName := PName +'_F';
      With dm.spUpdateTests.Parameters do
           begin
             ParambyName(PName).Value := TestValueNull(result); //new function used here
             ParamByName(FName).Value := GetCond(Flag);
           end;
    end;

procedure InsertParameter (tc, result, FLAG : string );
    var  pName, fName : String;
    begin
      PName  := '@'+tc;
      FName := PName +'_F';
      With dm.spUpdateTests.Parameters do
           begin
             ParambyName(PName).Value := TestValueNull(result); //new function used here
             ParamByName(FName).Value := GetCond(Flag);
           end;
    end;

Open in new window

zberg007Author Commented:
One other note... I really don't want it to return any other values. I just want it to do that one thing if it finds that condition, so how do I represent that in this example. I'm rather new to this, so thanks for being patient.
rfwoolfCommented:
First, a procedure doesn't return a result, a function does, so in your procedure when you say result, you obviously mean the result of the function.
You could declare a variable to store the result of your function, and then evaluate its value before using it, e.g.
Var
  Myresult : string;
Begin
 ...
Myesult := getcond(flag);
If myresult = '' then
 ParamByName(FName).value = '';
zberg007Author Commented:
I need to clarify that the result is actually a result from this procedure. Here's the rest of that code snippet to illustrate.
procedure InsertParameter (tc, result, FLAG : string );
    var  pName, fName : String;
    begin
      PName  := '@'+tc;
      FName := PName +'_F';
      With dm.spUpdateTests.Parameters do
           begin
             ParambyName(PName).Value := TestValueNull(result); //new function used here
             ParamByName(FName).Value := GetCond(Flag);
           end;
    end;
   
begin
   InsertParameter('visc_40', Tarray[v40c].result, tarray[v40c].flag);
   InsertParameter('visc_100',Tarray[v100c].result, tarray[v100c].flag);
   InsertParameter('water',  tarray[h20].result,tarray[h20].flag);
   InsertParameter('SOOt',   tarray[soot].result, tarray[soot].flag);
   InsertParameter('fuel',   tarray[fuel].result, tarray[fuel].flag);
   InsertParameter('glycol', tarray[gly].result, tarray[gly].flag);
   InsertParameter('FE',     tarray[fe].result, tarray[fe].flag);
   InsertParameter('CR',     tarray[cr].result, tarray[cr].flag);
   InsertParameter('PB',     tarray[pb].result, tarray[pb].flag);
   InsertParameter('CU',     tarray[cu].result, tarray[cu].flag);
   InsertParameter('SN',     tarray[sn].result, tarray[sn].flag);
etc. etc.

Open in new window

Emmanuel PASQUIERFreelance Project ManagerCommented:
ok, but then you still need TestValueNull to return something else for the cases where GetCond does not return 99, is that the string you test (tvn) ? (see first code)

As a parameter value is a variant, then TestValueNull really could return Variant as well, then you can use Null (second code)
function TestValueNull (tvn : string) : string;
begin
 if GetCond(tvn) = 99 
  then result := ''
  Else result := tvn;
end;

function TestValueNull (tvn : string) : Variant;
begin
 if GetCond(tvn) = 99 
  then result := Null
  Else result := tvn;
end;

Open in new window

zberg007Author Commented:
So how do I use the ELSE part of the statement from this:

function TestValueNull (tvn : string) : string;
begin
 if GetCond(tvn) = 99 then result := '';
else
  result := 'Hello World!';
end;

to really be left as it was before this function call if it doesn't meet my condition of 99? In other words I don't really want it to do anything else, like 'Hello World' or any other value, other than to just be left alone, again, if it doesn't meet my condition.

Thanks!
Emmanuel PASQUIERFreelance Project ManagerCommented:
>> "to really be left as it was before this function call if it doesn't meet my condition of 99?"
that does not have any sense. If you are talking about the result, it has no initial value.
If you are talking about the ParambyName(PName).Value that function result is assigned to, then I think it is necessary to move the pb one level up, to InsertParameter function.

procedure InsertParameter (tc, result, FLAG : string );
var 
 pName, fName : String;
 Cond:Integer;
begin
 PName  := '@'+tc;
 FName := PName +'_F';
 With dm.spUpdateTests.Parameters do
  begin
   Cond:=GetCond(Flag);
   ParamByName(FName).Value := Cond;
   if Cond=99 Then ParambyName(PName).Value := Null;
  end;
end;

Open in new window

zberg007Author Commented:
Let me paste in the whole code piece below. What I need is to simply apply this parameter: ParambyName(PName).Value := result;

with an empty string, if the GetCond function has a result of 99.

Otherwise, the PName result and everything else should remain the same.
function GetCond (c : string) : Integer;   {X}
begin
   if length (c) = 0 then
     begin
       result := -1;
       exit;
     end;
   CASE C[1] OF
      'N':  result  := 0;
      'A':  result  := 2;
      'C':  result  := 4;
      'S':  result  := 4;
      'X':  result  := 99;
   else
       result := -1;
   end;
end;

    procedure InsertParameter (tc, result, FLAG : string );
    var  pName, fName : String;
    begin
      PName  := '@'+tc;
      FName := PName +'_F';
      With dm.spUpdateTests.Parameters do
           begin
             ParambyName(PName).Value := result; //need logic here
             ParamByName(FName).Value := GetCond(Flag);
           end;
    end;
   
begin
   InsertParameter('visc_40', Tarray[v40c].result, tarray[v40c].flag);
   InsertParameter('visc_100',Tarray[v100c].result, tarray[v100c].flag);
   InsertParameter('water',  tarray[h20].result,tarray[h20].flag);
   InsertParameter('SOOt',   tarray[soot].result, tarray[soot].flag);
   InsertParameter('fuel',   tarray[fuel].result, tarray[fuel].flag);
   InsertParameter('glycol', tarray[gly].result, tarray[gly].flag);
   InsertParameter('FE',     tarray[fe].result, tarray[fe].flag);
   InsertParameter('CR',     tarray[cr].result, tarray[cr].flag);
   InsertParameter('PB',     tarray[pb].result, tarray[pb].flag);
   InsertParameter('CU',     tarray[cu].result, tarray[cu].flag);
etc., etc....

Open in new window

rfwoolfCommented:
Okay well it could be as simple as this:
      With dm.spUpdateTests.Parameters do
           begin
             if GetCond(Flag) = 99 then
               ParambyName(PName).Value := ''
             else
               ParambyName(PName).Value := GetCond(Flag)
             ParamByName(FName).Value := GetCond(Flag);
           end;
The problem with the above is the GetCond is being executed twice, which is amateur programming.
Better would be to put in a variable so that it only runs once, like this:

    procedure InsertParameter (tc, result, FLAG : string );
    var  
      pName,
      fName,
      GetCondResult : String;
    begin
      PName  := '@'+tc;
      FName := PName +'_F';
      With dm.spUpdateTests.Parameters do
           begin
             GetCondResult := GetCond(Flag);
             If GetCondResult = '99' then GetCondResult := '';
             ParambyName(PName).Value := GetCondResult;
             ParamByName(FName).Value := GetCond(Flag);
           end;
    end;

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rfwoolfCommented:
And just reading up on epasquier's coding, that will also do the job, except he left out the assignment of the FName, e.g.
  ParamByName(FName).Value := Cond; //in his code he has declared Cond as a variable.
zberg007Author Commented:
Thank you rfwoolf... I applied your better solution so it only runs once and went to compile it and got this error:

[Error] InTests.inc(32): Incompatible types: 'String' and 'Integer'

Thanks again, this is progress.... do you know what to do here on this error?
rfwoolfCommented:
It would help to know the line number.
I think it could be this line:
ParambyName(PName).Value := ''
you could try
ParambyName(PName).Value := nil
or
ParambyName(PName).Value := -1
etc.

zberg007Author Commented:
Sorry, Line 32 is this in my code:

            GetCondResult := GetCond(Flag);

this is where it threw the error.

Thanks
rfwoolfCommented:
Woops instead of
ParambyName(PName).Value := nil
you could also try
ParambyName(PName).Value := null
--epasquiers code above was good but with 1 small mistake like I explained, so here is it corrected:
procedure InsertParameter (tc, result, FLAG : string );
var 
 pName, fName : String;
 Cond:Integer;
begin
 PName  := '@'+tc;
 FName := PName +'_F';
 With dm.spUpdateTests.Parameters do
  begin
   Cond := GetCond(Flag);
   if Cond = 99 Then
     ParambyName(PName).Value := Null
   else
     ParambyName(PName).Value := Cond;

   ParamByName(FName).Value := Cond;
  end;
end;

Open in new window

rfwoolfCommented:
>>Sorry, Line 32 is this in my code:
>>  GetCondResult := GetCond(Flag);
Okay I made a mistake, in your declaration of GetCondResult, change it from:
  GetCondResult : String;
to
  GetCondResult : Integer;
zberg007Author Commented:
I ended up doing this:

GetCondResult : Variant;

and it compiled error free, then I ran a test. It almost works, however it is overwriting a valid Flag value from e.g. 137; to a value of 2.

This is I think because we are telling it to GetCondResult to be the same as GetCond(Flag), which is almost true, but we only want to only overwrite when it is 99.

I did try the last code you sent over with the correction from epasquier. Here it does error out on line 50; which is this:
ParambyName(PName).Value := Null

[Error] InTests.inc(50): Undeclared identifier: 'Null'

Thanks again...
rfwoolfCommented:
>>from e.g. 137; to a value of 2.
Well your value for A is 2: Case c[1] of  'A':  result  := 2;
so maybe that's what's doing it???

Well you can try Null, nil, '', -1, 0 or whatever. Normally when something is .value you can pass it a variant, and Null is usually accepted as a variant,
you can also try clear the value, e.g.
ParambyName(PName).clear;
zberg007Author Commented:
Yes, you're right, that's what it's doing as you illustrate:
>>Well your value for A is 2: Case c[1] of  'A':  result  := 2;
>>so maybe that's what's doing it???

Again I think it's coming from here:
GetCondResult := GetCond(Flag);

We really don't want GetCondResult from the GetCond(Flag); we want it from the function called GetCond, which are lines 1 through 17 in my pasted in code from today.

When we include the (Flag) we're actually picking up flag value that is to be inserted in the database as in my code beginning on line 32, like below:

begin
   InsertParameter('visc_40', Tarray[v40c].result, tarray[v40c].flag);
   InsertParameter('visc_100',Tarray[v100c].result, tarray[v100c].flag);
   InsertParameter('water',  tarray[h20].result,tarray[h20].flag);

So how do we get the GetCond results that are of 99 only and not overwrite the existing .result value, with the .flag value from the "InsertParameter('visc_40', Tarray[v40c].result, tarray[v40c].flag);" ?

Hope this is clear. I know it's a bit confusing. Thanks again for your efforts!  
Emmanuel PASQUIERFreelance Project ManagerCommented:
Hey guys, from what I'm reading your are turning around in circles...
It would seem that I only missed the default storage of result in PName parameter when condition value is not 99

Otherwise, I'm still not sure if you need null value or empty string in case of cond=99.

procedure InsertParameter (tc, result, FLAG : string );
var 
 pName, fName : String;
 Cond:Integer;
begin
 PName  := '@'+tc;
 FName := PName +'_F';
 With dm.spUpdateTests.Parameters do
  begin
   Cond:=GetCond(Flag);
   ParamByName(FName).Value := Cond;
   if Cond=99 
     Then ParambyName(PName).Value := Null // or '' I still don't know what you need there exactly
     Else ParambyName(PName).Value := result
  end;
end;

Open in new window

Emmanuel PASQUIERFreelance Project ManagerCommented:
about that [Error] InTests.inc(50): Undeclared identifier: 'Null'

you need to include Variants unit
zberg007Author Commented:
Hey guys, I used a variation of epasquier's code and it works like a charm! Here it is:

procedure InsertParameter (tc, result, FLAG : string );
var
 pName, fName : String;
 Cond:Integer;
begin
 PName  := '@'+tc;
 FName := PName +'_F';
 With dm.spUpdateTests.Parameters do
  begin
   Cond := GetCond(Flag);
   if Cond = 99 Then
     ParambyName(PName).Value := ''
   else
     ParambyName(PName).Value := result;

   ParamByName(FName).Value := GetCond(Flag);
  end;
end;

Thank you both for this solution, you both played a significant role in solving.

Thanks once again.
function GetCond (c : string) : Integer;   {X}
begin
   if length (c) = 0 then
     begin
       result := -1;
       exit;
     end;
   CASE C[1] OF
      'N':  result  := 0;
      'A':  result  := 2;
      'C':  result  := 4;
      'S':  result  := 4;
      'X':  result  := 99;
   else
       result := -1;
   end;
end;

procedure InsertParameter (tc, result, FLAG : string );
var
 pName, fName : String;
 Cond:Integer;
begin
 PName  := '@'+tc;
 FName := PName +'_F';
 With dm.spUpdateTests.Parameters do
  begin
   Cond := GetCond(Flag);
   if Cond = 99 Then
     ParambyName(PName).Value := ''
   else
     ParambyName(PName).Value := result;

   ParamByName(FName).Value := GetCond(Flag);
  end;
end;

Open in new window

Emmanuel PASQUIERFreelance Project ManagerCommented:
May I ask you why you are using a variation, while your code do exactly the same but less effectively ?

You are calling twice GetCond(Flag), why not use the Cond variable that was introduced exactly for the purpose of not calling twice the function ?

Have you tried the code I gave you as I posted it, or, as I think, have you tried to include it piece by piece, along with rfwoolf pieces ? Should you have tested the full code I gave @  02:15 AM, you would have noticed that it was doing almost  all you needed. You could even have found the last missing part by yourself and terminated that problem hours before.

Note that I don't complain about your wish to close the question as you say, nor want to reduce rfwoolf merit. I really say that so that you understand how to be more effective next time.

Regards,

E.P.

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.