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!

saving math operators in scalars help needed

Status
Not open for further replies.

jackz15

Programmer
Joined
Jun 28, 2006
Messages
103
Location
US
hi i want to be able to save operators in scalars in such a form:
if($something $operator $another_thing){
do something
}
if
$something=5;
$operator="=";
$another_thing=2;
so translated:
if(5=2){
do something
}
is this possible to do? cause i cannot do it in the format above, is there a way?
 
yep.
Use "eval"
Code:
if(eval "$something $operator $another_thing") {
    # Do something here
}


Trojan.
 
. . . always remembering that `=' is the assignment operator and `==' is for numeric comparison.

Of course, the usual caveats about using eval apply too: you've to be very careful where the values of those scalars come from, otherwise you could be allowing user to execute arbitrary Perl code, which is never a good idea.
 
haha, i AM allowing the user to execute Perl code only allowing them if statements used in a calculator
 
haha, i AM allowing the user to execute Perl code only allowing them if statements used in a calculator but nevertheless thanks for reminding me on that, i did use '=' instead of '==' but the code itself still works.
 
sorry about the double post, something went wrong...
 
jackz15 said:
i did use '=' instead of '==' but the code itself still works.
I'm glad it does, but it shouldn't, have you tested your $operators.

When you say a calculator, this isn't a web calculator by any chance?

Code:
if($something $operator $another_thing){
You're simply testing the result of the operation, not equivalence of the two variables
Code:
if (eval($something $operator $another_thing)){
this is testing the result of an eval statement, rather than what's inside it.

Care to post your code,
--Paul

Paul
------------------------------------
Spend an hour a week on CPAN, helps cure all known programming ailments ;-)
 
To avoid that sort of functionality of someone perhaps submitting bogus $operators, you could simply case the operator to use a function.

Code:
if ($operator eq '+') {
  $result=add($thing, $anotherthing);
} else if ($operator eq '-') {
  $result=subtract($thing, $anotherthing);
} else if ($operator eq '*') {
  $result=multiply($thing, $anotherthing);
} else if ($operator eq '/') {
  $result=divide($thing, $anotherthing);
}
sub add {
  return $_[0]+$_[1];
}
sub subtract {
  return $_[0]-$_[1];
}
sub multiply {
  return $_[0]*$_[1];
}
sub divide {
  return $_[0]/$_[1];
}

HTH

Paul
------------------------------------
Spend an hour a week on CPAN, helps cure all known programming ailments ;-)
 
just a typo on Pauls part:

this: else if
should be: elsif

if it's a real simple calculator a hash of anonymous subs will work:

Code:
my $var1 = 100;
my $var2 = 50;
my $operator = '/';
my %coms = (
   '+' => sub {$var1 + $var2},
   '-' => sub {$var1 - $var2},
   'x' => sub {$var1 * $var2},
   '/' => sub {$var1 / $var2},
);
print $coms{$operator}->();

but if you are doing more complex algebra type stuff you may have to stick with eval, but the entered data should be validated and use taint mode.
 
For a demonstration of what they're talking about, say you have this code:

Code:
my $eqn = "2 + 2 * 4";

my $result = eval($eqn);

print "$eqn = $result\n";
# "2 + 2 * 4 = 10"

If $eqn is defined by the user (e.g. through a web form if used as a web calculator), there's nothing stopping them from doing this:

Code:
$eqn = "unlink (glob('C:/Windows'))"

Which, if on a Win32 machine, would delete files in the Windows folder.

So if you put a variable that is user-defineable into an eval statement, you run the risk of that user telling Perl to run *ANY* command Perl can do, which can seriously screw you over.

Here's a code for a calculator I wrote once which used eval, but didn't allow hacking like this:

Code:
if ($eqn =~ /[^0-9\+\-\/\*]/) {
   print "Invalid operators: use only numbers, +, -, /, or *\n";
}
else {
   print "$eqn = " . eval($eqn) . "\n";
}

That way, if they try anything funny, it won't eval $eqn. Also note that I allowed the forward slash / but not the back slash \, as the \ has special significance in Perl and can be used to execute code using escape codes (eg "\049" type of strings can be interpreted into text, so commands like "unlink" can be spelled out using \'s and numbers).

So, be sure to be as strict as possible on any variables being sent into eval.
 
thanks for all your replies, the operator that i needed here is just comparison operator > < == >= <=. I have a huge hash already with all the other operators. To answer paul:
I am just testing if $something $op $sanotherthing(5>4), if thats true, then continue with the operatiom, else don't continue.
Btw my calulator is basically a reverse Polish calculator, where the numbers go first then the operation(i.e 4 5 + ...this adds 4 and 5 and pushes it in an array).
And for kirsle,
In my program everything that is entered MUST exist in my hash of operations, be a userdefined variable(MUST be numbers), or be numbers, if there are ANY letters in the numbers then the program returns an error. So I cannot set something to unlink (glob('C:/Windows')). Thanks again for everything
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top