Jump to content

Simple math problem.


soupi

Recommended Posts

I am trying to learn PHP, how would I start this?

 

Given an input of an expression consisting of a string of letters and operators (plus sign, minus sign, and letters. IE: ‘b-d+e-f’) and a file with a set of variable/value pairs separated by commas (i.e: a=1,b=7,c=3,d=14) write a program that would output the result of the inputted expression.

For example, if the expression input was ("a + b+c -d") and the file input was ( a=1,b=7,c=3,d=14) the output would be -3.

 

i know how to do it in JAVA but am stummped on PHP

 

 

Thank you guys

Edited by soupi
Link to comment
Share on other sites

// the contents from the file
$input = 'a=1,b=2,c=3,d=4';

// the expression
$expression = 'a + b - c * d';

// put all variables into $variables
parse_str(str_replace(',', '&', $input), $variables);

foreach ($variables as $variable => $value) {
// replace the variables in $expression with their values
$expression = str_replace($variable, $value, $expression);
}

// assuming this is from a trusted source meaning you or your teacher.
eval('?><?php echo ' . $expression . ';');
Edited by ignace
Link to comment
Share on other sites

so would it look like this for 4 numbers?

<?php

$myString = 'a=1,b=2,c=3,d=4';

$expression = 'a + b - c * d';

// put all variables into $variables
parse_str(str_replace(',', '&', $myString), $variables);

foreach ($variables as $variable => $value) {
  // replace the variables in $expression with their values
  $expression = str_replace(

   if ($_GET['calc'] == "yes") 
 { 
 $a = $_GET['a']; 
 $b = $_GET['b']; 
 $c = $_GET['c']; 
 $d = $_GET['d']; 
 $total = $a+$b+$c+$d;);
}

eval('?><?php echo ' . $expression . ';');

?>

Edited by soupi
Link to comment
Share on other sites

This code will do what you are trying to do. I have modified ignace's example.

<?php

$expression = 'a + b + c - d';   // default expression
$input      = array( 'a' => 1,    
                     'b' => 7,
                     'c' => 3,
                     'd' => 14); // default input values

$total = 0;
$sum   = '';

// when form has been submitted. 
// Override default expression and input values
if(isset($_POST['Calculate']))
{
    $input      = $_POST['input'];
    $expression = $_POST['expression'];
}

// make sure the users expression is safe to use
if(preg_match('#^[a-z+-\s]+$#i', $expression))
{
    $sum = $expression;
    foreach ($input as $char => $value) {
        // replace the variables in $expression with their values
        $sum = str_replace($char, $value, $sum);
    }
 
    eval('?><?php $total = ' . $sum . ';'); // perform the calculation
}
else
{
	// display this message if the entered expression is invalid
	echo '<b>Expression invalid can only contain letters and math operators (+ or -)</b>';
}

?>

<form action=""  method="post"> 
    Number A: <input type="text" name="input[a]" value="<?php echo $input['a']; ?>" size=3> <br/>
    Number B: <input type="text" name="input[b]" value="<?php echo $input['b']; ?>" size=3> <br> 
    Number C: <input type="text" name="input[c]" value="<?php echo $input['c']; ?>" size=3> <br> 
    Number D: <input type="text" name="input[d]" value="<?php echo $input['d']; ?>" size=3> <br>
    <br>
    Expression: <input type = "text" name = "expression" value="<?php echo $expression ?>">  = <?php echo $total; ?><br>
    Sum: <?php echo $sum; ?><br>
    <input type="submit" name="Calculate" /> 
</form>
Edited by Ch0cu3r
Link to comment
Share on other sites

I don't think the posted solution matches the requirements. From the OP:

 

Given an input of an expression consisting of a string of letters and operators (plus sign, minus sign, and letters. IE: ‘b-d+e-f’) and a file with a set of variable/value pairs separated by commas (i.e: a=1,b=7,c=3,d=14) write a program that would output the result of the inputted expression.

For example, if the expression input was ("a + b+c -d") and the file input was ( a=1,b=7,c=3,d=14) the output would be -3.

The instructions say to let the user input an expression. So your form should only have 1 text field, not 4. Then you are supposed to evaluate that expression, swapping out the variables they specified (e.g. "a" or "b") with values from a text file.

 

So, IOW:

 

1) create a text file with like "a=1,b=7,c=3,d=14" in it.

2) write code for a form to let the user enter in an expression, e.g. "a+b" or "c-d+a"

3) write code that swaps those letters out to be the values from the text file (step 1). So for example "c-d+a" would be converted to "3-14+1".

4) write code to evaluate the expression and output the result. e.g. "c-d+a" would, based on the #1 output "-10"

 

So basically the accepted answer here asks for all input from the user, instead of pulling the values from a file.

Link to comment
Share on other sites


<html>
<head>
</head>
<body>
<?php

// get the values from the file and convert to an associative array
$data = file_get_contents('test.txt');
parse_str(implode('&',array_map('trim',explode(',',$data))),$vars);

// allowed vars (based on what is in file
$allowedVars = array_keys($vars);

// allowed operators
$allowedOpers = array('-','+','*','/');

?>
Allowed Variables: <?php echo implode(',',$allowedVars); ?> <br/>
Allowed Operators: <?php echo implode(',',$allowedOpers); ?> <br/>

Current Variable Values:<br/>
</pre>
<?php print_r($vars); ?>
</pre>

<form action = "" method = "POST">
Expression: <input type = "text" name = "expression" size=20> <br/>
<input type="hidden" name="calc" value ="yes">
<input type = "submit" name = "Calculate"/>
</form>

<?php
if (isset($_POST['expression'])&&trim($_POST['expression'])!='') {

// strip whitespace to be more flexible
$expression = preg_replace('~\s*~','',$_POST['expression']);

// used to check if expression only contains expected operators and vars
$allowedFormat = '^['.implode('',array_merge($allowedOpers, $allowedVars)).']+$';

// also used to check for expected opers and vars
$aor = '['.implode('',$allowedOpers).']';
$avr = '['.implode('',$allowedVars).']';

$error = array();


// check if vars from input file are only letters. This is protection against the eval below!
if ( !preg_match('~^[a-z]+$~i',implode('',$allowedVars)) )
$error[] = 'invalid variables in input file';

// check if values from input file are only numbers or dots. This is protection against the eval below!
if ( !preg_match('~^[0-9.]+$~i',implode('',$vars)) )
$error[] = 'invalid values in input file';

// check for format in general
if ( !preg_match('~'.$allowedFormat.'~',$expression) )
$error[] = 'invalid variables or operators used';

// check if more than one oper or var listed in a row
if ( preg_match('~'.$aor.'{2,}|'.$avr.'{2,}~',$expression) )
$error[] = 'cannot have more than one operator or variable in a row';

// check if expression starts or ends in operator
if ( preg_match('~^'.$aor.'|'.$aor.'$~',$expression) )
$error[] = 'expression cannot start or end in an operator';

// if there are errors, display the errors
if (count($error)>0) {

// output errors
echo "Error(s):<br/>";
echo implode('<br/>',$error);

// if there are no errors, output the solution
} else {

// replace the vars with their values
$expression = preg_replace('~('.$avr.')~e','$vars[$1]',$expression);

// evaluate the expression
eval('$solution='.$expression.';');

// output the solution
echo $expression.' = '.$solution;

} // end if..else

} // end if $_POST
?>

</body>
</html>
Link to comment
Share on other sites

implode takes an array and mashes it together into a single string, with a specified delimiter.

 

explode takes a string and separates it into an array, using specified delimiter as what to separate the string by

 

$string = 'a-b-c'; // a simple string. we've got some letters delimited with a hyphen

$letters = explode('-',$string); // let's explode the string into an array of letters. 
// this is now the equivalent of:
$letters = array('a','b','c');

//Now let's put them back to the original string, but make the delimiter a colon:
$string = implode(':',$letters); // now the string is "a:b:c"

Link to comment
Share on other sites

 

This code will do what you are trying to do. I have modified ignace's example.

<?php

$expression = 'a + b + c - d';   // default expression
$input      = array( 'a' => 1,    
                     'b' => 7,
                     'c' => 3,
                     'd' => 14); // default input values

$total = 0;
$sum   = '';

// when form has been submitted. 
// Override default expression and input values
if(isset($_POST['Calculate']))
{
    $input      = $_POST['input'];
    $expression = $_POST['expression'];
}

// make sure the users expression is safe to use
if(preg_match('#^[a-z+-\s]+$#i', $expression))
{
    $sum = $expression;
    foreach ($input as $char => $value) {
        // replace the variables in $expression with their values
        $sum = str_replace($char, $value, $sum);
    }
 
    eval('?><?php $total = ' . $sum . ';'); // perform the calculation
}
else
{
	// display this message if the entered expression is invalid
	echo '<b>Expression invalid can only contain letters and math operators (+ or -)</b>';
}

?>

<form action=""  method="post"> 
    Number A: <input type="text" name="input[a]" value="<?php echo $input['a']; ?>" size=3> <br/>
    Number B: <input type="text" name="input[b]" value="<?php echo $input['b']; ?>" size=3> <br> 
    Number C: <input type="text" name="input[c]" value="<?php echo $input['c']; ?>" size=3> <br> 
    Number D: <input type="text" name="input[d]" value="<?php echo $input['d']; ?>" size=3> <br>
    <br>
    Expression: <input type = "text" name = "expression" value="<?php echo $expression ?>">  = <?php echo $total; ?><br>
    Sum: <?php echo $sum; ?><br>
    <input type="submit" name="Calculate" /> 
</form>

Hi is there another way t do this with out using the EVAL to get the sum?

I tried $total =$sum; but that didnt work

Link to comment
Share on other sites

implode takes an array and mashes it together into a single string, with a specified delimiter.

 

explode takes a string and separates it into an array, using specified delimiter as what to separate the string by

 

$string = 'a-b-c'; // a simple string. we've got some letters delimited with a hyphen

$letters = explode('-',$string); // let's explode the string into an array of letters. 
// this is now the equivalent of:
$letters = array('a','b','c');

//Now let's put them back to the original string, but make the delimiter a colon:
$string = implode(':',$letters); // now the string is "a:b:c"

<?php
$expression = '';   
$input      = array( 'a' => 5,    
                     'b' => 10,
                     'c' => 15,
                     'd' => 20); 
$total = 0;
$sum   = '';
// Override default expression and input values
if(isset($_POST['Calculate']))
{
    $input      = $_POST['input'];
    $expression = $_POST['expression'];
}
// make sure the users expression is safe to use
if(preg_match('#^[a-z+-\s]+$#i', $expression))
{
    $sum = $expression;
    foreach ($input as $char => $value) {
        // replace the variables in $expression with users values
        $sum = str_replace($char, $value, $sum);
    }
	
    eval('?><?php $total = ' . $sum . ';'); // calculation is being performed */
}
?>
<form action=""  method="post"> 
    Number A: <input type="text" name="input[a]" value="<?php echo $input['a']; ?>" size=3> <br/>
    Number B: <input type="text" name="input[b]" value="<?php echo $input['b']; ?>" size=3> <br> 
    Number C: <input type="text" name="input[c]" value="<?php echo $input['c']; ?>" size=3> <br> 
    Number D: <input type="text" name="input[d]" value="<?php echo $input['d']; ?>" size=3> <br>
    <br>
    Expression: <input type = "text" name = "expression" value="<?php echo $expression ?>">  = <?php echo $total; ?><br>
    Sum: <?php echo $sum; ?><br>
    <input type="submit" name="Calculate" /> 
</form>

Hi i tried it this way but is there another way to do this without using the eval to calculate the result?

its highlighted in red

Link to comment
Share on other sites

What do you mean by "it doesn't work" ? The only thing I see "wrong" with that code is that

 

Sum: <?php echo $sum; ?><br>
$sum contains the actual expression, not the evaluated expression result. So really, it should be echoing $total not $sum, which is a bit superfluous with it being output to the right of the expression already..

 

And what do you mean by "it's highlighted in red" ? I don't see anything highlighted in red.

 

But anyways, as to your actual question: "Can this be done without eval?". Yes, yes it can. And in general, it is highly advisable to NOT use eval, because it is a very dangerous thing. There is an expression out there for it: "eval is evil!" which rings throughout virtually all programming language circles. And for good reason. eval executes a string as php code, and you are putting user (and file, in my example) inputted code into it. Which means someone can send malicious code to your script to fuck all kinds of shit up. Which is why in all of the examples shown, precautions have been put in place to match for expected values.

 

Despite all that.. coding it without eval would be significantly harder, and for a simple exercise such as this, I'd personally condone the use of it (again, provided you use the precautions to make sure you are only putting expected values into it). But if you were to go the non-eval route, it would basically involve stepping through the expression 1 character at a time, building a php string based on the input. What especially makes this hard is order of operations. You can't simply go from left to right, since order of operations may dictate that part(s) farther along in the string may get evaluated before other parts. It's not impossible, but it's a bit complex. I'm sorry but I'm not going to take the time to write that out for you (tbh we shouldn't have even done this much, seeing as how we generally don't do people's homework for them!). But if you want to pursue it, you will want to look into Object Oriented Programming. Particularly, using the Interpreter pattern. You can readily find "algebraic expression parsers" out there (example here: the actual code you'd have to write from it is relatively simple, but take a look at the php files in there, the code that's behind it!) but I doubt you will find anything that's watered down solely towards basic math operations without nesting or anything.

Link to comment
Share on other sites

Hey josh thanks for your insight, i followed it and solved it.

<?php
$expression = '';   
$input      = array( 'a' => 5,    
                     'b' => 10,
                     'c' => 15,
                     'd' => 20); 
$total = 0;
$sum   = '';
// Override default expression and input values
if(isset($_POST['Calculate']))
{
    $input      = $_POST['input'];
    $expression = $_POST['expression'];
}
// make sure the users expression is safe to use
if(preg_match('#^[a-z+-\s]+$#i', $expression))
{
    $sum = $expression;
	$input_letters = array();
	$input_operators = array();
	
	for ($i = 0; $i < strlen($expression) ; $i++) {
	if (($i % 2) == 0) {
	$input_letters[] = $expression[$i]; 
	} else {
	$input_operators[] = $expression[$i];
	}
	}
    //
	for ($i = 0 ; $i < sizeof($input_letters); $i++) {
	$value = $input[$input_letters[$i]];
	if ($i == 0) {
		$sum += $value;
	} else {
	if ($input_operators[$i-1] == '+') {
	$sum += $value;
	} else if ($input_operators[$i-1] == '-')  {
	$sum -= $value;
	}
	}
	}
} else {
echo "Error: expression not correct form";
}
?>
<form action=""  method="post"> 
    Number A: <input type="text" name="input[a]" value="<?php echo $input['a']; ?>" size=3> <br/>
    Number B: <input type="text" name="input[b]" value="<?php echo $input['b']; ?>" size=3> <br> 
    Number C: <input type="text" name="input[c]" value="<?php echo $input['c']; ?>" size=3> <br> 
    Number D: <input type="text" name="input[d]" value="<?php echo $input['d']; ?>" size=3> <br>
    <br>
    Expression: <input type = "text" name = "expression" value="<?php echo $expression ?>">  = 
<?php echo $sum; ?><br>
    Sum: <?php echo $sum; ?><br>
    <input type="submit" name="Calculate" /> 
</form>
Link to comment
Share on other sites

<?php
$expression = '';   
$input      = array( 'a' => 5,    
                     'b' => 10,
                     'c' => 15,
                     'd' => 20);
$total = 0;
$sum   = '';
// Override default expression and input values
if(isset($_POST['Calculate']))
{
    $input      = $_POST['input'];            //input being passed via POST method
    $expression = $_POST['expression'];        //expression being passed via POST method
}
// make sure the users expression is safe to use
if(preg_match('#^[a-z+-\s]+$#i', $expression))
{
    $sum = $expression;            //evaluates sum as expression
    $input_letters = array();    //puts letters into a array
    $input_operators = array(); //puts operators into a array
    
    
    for ($i = 0; $i < strlen($expression) ; $i++) { //gets string length
    if (($i % 2) == 0) {
    $input_letters[] = $expression[$i]; //getting the character for the position i
    } else {
    $input_operators[] = $expression[$i];
    }
    }
    //
    for ($i = 0 ; $i < sizeof($input_letters); $i++) { //size of= numbers (4)
    $value = $input[$input_letters[$i]]; //takes the value  from the letters
    if ($i == 0) {
        $sum += $value; //adds the sum if = 0
    } else {
    if ($input_operators[$i-1] == '+') { //checks to see if the operator is +
    $sum += $value;
    } else if ($input_operators[$i-1] == '-')  { //checks to see if the operator is -
    $sum -= $value;
    }
    }
    print_r($value);
    }
} else {    
echo "Error: expression not correct form"; //error message
}
?>
<form action=""  method="post">     <!--Form begins-->
    Number A: <input type="text" name="input[a]" value="<?php echo $input['a']; ?>" size=3> <br/>
    Number B: <input type="text" name="input[b]" value="<?php echo $input['b']; ?>" size=3> <br>
    Number C: <input type="text" name="input[c]" value="<?php echo $input['c']; ?>" size=3> <br>
    Number D: <input type="text" name="input[d]" value="<?php echo $input['d']; ?>" size=3> <br>
    <br>
    Expression: <input type = "text" name = "expression" value="<?php echo $expression ?>">  =
<?php echo $sum; ?><br>
    Sum: <?php echo $sum; ?><br>
    <input type="submit" name="Calculate" />
</form>
<script src="http://code.jquery.c...1.js"></script>
<script>
$( "form" ).submit(function( event ) {
var myExpression = $('[name="expression"]').val();
if $("$input_letters").validate({
minlength: 4
}
});
</script>

 in the code i provided, how would i add a  javascript on the bottom check to see that use entered four letters, if they enter more when submit is clicked, put a alert message saying you cant.

Edited by soupi
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.