soupi Posted October 25, 2013 Share Posted October 25, 2013 (edited) 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 October 25, 2013 by soupi Quote Link to comment Share on other sites More sharing options...
ignace Posted October 25, 2013 Share Posted October 25, 2013 (edited) // 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 October 25, 2013 by ignace Quote Link to comment Share on other sites More sharing options...
soupi Posted October 25, 2013 Author Share Posted October 25, 2013 (edited) 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 October 25, 2013 by soupi Quote Link to comment Share on other sites More sharing options...
Ch0cu3r Posted October 28, 2013 Share Posted October 28, 2013 (edited) 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 October 28, 2013 by Ch0cu3r Quote Link to comment Share on other sites More sharing options...
soupi Posted October 28, 2013 Author Share Posted October 28, 2013 thanks C, so i entered letters abc and d and I should get 25 for the result, but im getting 0150? below are screen shots before and after clicking submit Before After Quote Link to comment Share on other sites More sharing options...
Ch0cu3r Posted October 28, 2013 Share Posted October 28, 2013 (edited) My code is a fully working example, you do not need to modify it. Your screenshot are from something else. What have you changed? Edited October 28, 2013 by Ch0cu3r Quote Link to comment Share on other sites More sharing options...
soupi Posted October 28, 2013 Author Share Posted October 28, 2013 i got it now, thanks alot Ch0cu3r Quote Link to comment Share on other sites More sharing options...
AbraCadaver Posted October 28, 2013 Share Posted October 28, 2013 // assuming this is from a trusted source meaning you or your teacher. Quote Link to comment Share on other sites More sharing options...
.josh Posted October 28, 2013 Share Posted October 28, 2013 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. Quote Link to comment Share on other sites More sharing options...
.josh Posted October 28, 2013 Share Posted October 28, 2013 <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> Quote Link to comment Share on other sites More sharing options...
soupi Posted October 28, 2013 Author Share Posted October 28, 2013 Thanks josh, may i ask what the implode and explode? Quote Link to comment Share on other sites More sharing options...
.josh Posted October 28, 2013 Share Posted October 28, 2013 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" Quote Link to comment Share on other sites More sharing options...
soupi Posted October 28, 2013 Author Share Posted October 28, 2013 thank you, that was a excellent example. Thanks alot, im starting to understand php little by little Quote Link to comment Share on other sites More sharing options...
soupi Posted October 28, 2013 Author Share Posted October 28, 2013 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 Quote Link to comment Share on other sites More sharing options...
soupi Posted October 28, 2013 Author Share Posted October 28, 2013 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 Quote Link to comment Share on other sites More sharing options...
.josh Posted October 28, 2013 Share Posted October 28, 2013 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. Quote Link to comment Share on other sites More sharing options...
soupi Posted October 28, 2013 Author Share Posted October 28, 2013 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> Quote Link to comment Share on other sites More sharing options...
.josh Posted October 28, 2013 Share Posted October 28, 2013 Okay well, as I mentioned previously, the accepted solution does not match the requirements you posted, so there's that... Quote Link to comment Share on other sites More sharing options...
soupi Posted October 29, 2013 Author Share Posted October 29, 2013 (edited) <?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 October 29, 2013 by soupi Quote Link to comment Share on other sites More sharing options...
.josh Posted October 29, 2013 Share Posted October 29, 2013 that is a whole new question and it's a javascript question, not a php question. Post a new question in the javascript forum. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.