i have this exercise from class, that we need to make script with a function that uses a given string as parameter in lowercase and i have to return that same string in uppercase, i already made that, but when it comes to the printing, it prints the letters in alphabetical order, and i cant figure out whats wrong, here's the code:
<html>
<head>
<title>Ejercicio 10</title>
</head>
<body>
<center><h1>Ejercicio 10 (FunciĆ³n 1)</h1></center>
<h1>
<center>
<form action="ejercicio10.php" method="post">
<input type="text" id="frase" name="frase" placeholders="Introduzca una frase para transformar a mayusculas"/>
<input type="submit" value="Enviar"/>
</form>
<?php
$frase = $_POST['frase'];
function mayusculas($frase) {
$longitud = strlen($frase);
$minusculas = array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","w","x","y","z"," ");
$mayusculas = array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","W","X","Y","Z"," ");
$numeroLetras = count($minusculas);
for ($i = 0; $i < $longitud + 1; $i++) {
for ($j=0; $j < $numeroLetras ; $j++) {
$resultado = strrpos($frase, $minusculas[$j], $i);
if($resultado !== FALSE){
print($mayusculas[$j]);
}
}
return null;
}
}
print(mayusculas($frase));
?>
</center>
</h1>
</body>
</html>
Alright for the sake of the exercise, here is what is happening.
You are using two loops. The outer loop iterates as many times as the length of the string, and the inner loop iterates through each letter A through Z.
Here is the correct working version, and then I will explain:
function mayusculas($frase) {
$longitud = strlen($frase);
$minusculas = array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","w","x","y","z"," ");
$mayusculas = array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","W","X","Y","Z"," ");
$numeroLetras = count($minusculas);
for ($i = 0; $i < $longitud + 1; $i++) {
for ($j=0; $j < $numeroLetras ; $j++) {
$resultado = strpos($frase, $minusculas[$j], $i);
if($resultado == $i && $resultado !== false) {
print($mayusculas[$j]);
break;
}
}
}
}
Your for loops are correct, it's what you are doing inside them that is not. The following needed to happen:
First, you should use strpos instead of strrpos. We are going through the letters in the word forward, not backwards.
When we check for false in the result, we also need to check that the position it found the letter is the position of the letter we are looking for (i.e. from the outer loop)
Once we find a matching letter at the correct position, you can output it. And then we want to STOP the inner loop iteration since we are done with that loop.
Finally, after the first iteration of the outer loop, you were returning null, which is incorrect. That stops the outer loop from moving on to the second letter. We need to let the looping run its course.
A final note, this is no where close to the best way to do this. I'm only highlighting for learning sake.
Another option if is unnecessary use the function strpos is:
In you PHP section:
$frase = $_POST['frase'];
function mayusculas($frase) {
$longitud = strlen($frase);
$minusculas = array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","w","x","y","z"," ");
$mayusculas = array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","W","X","Y","Z"," ");
$numeroLetras = count($minusculas);
for ($i = 0; $i < $longitud; $i++) {
for ($j=0; $j < $numeroLetras ; $j++) {
if($minusculas[$j] == $frase[$i]) {
print($mayusculas[$j]);
}
}
}
}
print(mayusculas($frase));
Using this loop for ($j=0; $j < $numeroLetras ; $j++) { and doing this $resultado = strrpos($frase, $minusculas[$j], $i); means you're basically looping on the $minusculas array only, which is in alphabetical order.
Another error you have in your code is if your string contains repetitive letters like hkgkh, it will only print GKH.
And a major issue you have in your code is the return null statement you have in the for ($i = 0; $i < $longitud + 1; $i++) { loop. This will only fun your loop for 1 iteration.
Related
I am supposed to write a program that:
takes in a positive integer from a html form
then in another php script, checks if this integer is a perfect number or not and print the result (result as in if integer is perfect or not).
A perfect number is a positive integer that is equal to the sum of all its factors EXCLUDING itself.
Problem I'm facing:
The code runs but for every positive number entered, I get the same output which is "Yes, XXX is a perfect number" even when the number isn't.
Could someone help me find the bug(s) in my code? I can't locate the problems in the code.
#html form
<!DOCTYPE html>
<html>
<body>
<form action="lab_2_3.php" method="POST">
Enter positive integer:
<input type="number" name="pos_num" min="1"/>
<input type="submit"/>
</form>
</body>
</html>
#php script
<!DOCTYPE html>
<html>
<body>
<?php
$pos_num = $_POST["pos_num"];
function get_factors($pos_num){
$myarray = array(); //creating new array
for ($i = 1; $i <= ceil(($pos_num ** 0.5)); $i++){
if ($pos_num % $i == 0){
$myarray[] = $pos_num; //appending array in php
}
return $myarray; }
}
function get_total($myarray){
$total_val = 0;
for ($j = 0; $j < count($myarray); $j++){
$total_val += $myarray[$j];
} return $total_val;
}
$a_list = get_factors($pos_num);
$check_if_perf = get_total($a_list);
if ($check_if_perf == $pos_num){
echo "Yes, $pos_num is a perfect number";
}
else{
echo "No, $pos_num is not a perfect number";
}
?>
</body>
</html>
I tried printing out some variables to see what exactly the function was working with:
function get_factors($pos_num){
$myarray = array(); //creating new array
$end = $pos_num ** 0.5;
print "$end\n";
for ($i = 1; $i <= $end; $i++){
print "$i: " . $pos_num % $i . "\n";
if ($pos_num % $i == 0){
$myarray[] = $i; //appending array in php
}
return $myarray; }
}
// ===>
3.1622776601684
1: 0
No, 10 is not a perfect number
From this, it was evident the for loop was not functioning as expected. So step one is to clean up the code and indenting. The error became obvious: misplaced end bracket.
function get_factors($pos_num)
{
$myarray = array(); //creating new array
for ($i = 1; $i <= $pos_num ** 0.5; $i++) {
print "$i: " . $pos_num % $i . "\n";
if ($pos_num % $i == 0){
$myarray[] = $i; //appending array in php
}
}
return $myarray;
}
// ==>
1: 0
2: 0
3: 1
No, 10 is not a perfect number
However, get_factors() does not correctly compute the factorials. The end limit, set by $pos_num ** 0.5 does not gather all the factorials. For example,
print 6 ** 0.5;
// ==>
2.4494897427832
To fix this, we want to get the first half of the factorials (inclusive of n/2)
function get_factors($pos_num)
{
$myarray = array(); //creating new array
for ($i = 1; $i <= $pos_num/2; $i++) {
if ($pos_num % $i == 0){
$myarray[] = $i;
}
}
return $myarray;
}
Now, putting all the code together in a standard format, with notes explaining why (I've also left some of the debugging commented out):
<?php
// testing...
// $_GET["pos_num"] = 496;
// always start out with PHP logic, never HTML.
// Deal with input:
// if submission is not destructive (ie, insert, update, delete), use GET.
// if submission changes data state, use POST. POST should always be followed
// with a redirect. (Post-Redirect-Get pattern)
if(isset($_GET["pos_num"])) {
$pos_num = $_GET["pos_num"];
$a_list = get_factors($pos_num);
$check_if_perf = get_total($a_list);
$is_perfect = ($check_if_perf == $pos_num); // boolean
}
// functional logic:
function get_factors(int $pos_num) : array
{
$myarray = array(); //creating new array
$end = $pos_num /2;
// $end = $pos_num ** 0.5;
// print "$end\n";
for ($i = 1; $i <= $end; $i++){
if ($pos_num % $i == 0){
$myarray[] = $i; //appending array in php
}
}
return $myarray;
}
function get_total(array $myarray) : int
{
$total_val = 0;
for ($j = 0; $j < count($myarray); $j++){
$total_val += $myarray[$j];
}
return $total_val;
}
// print_r(get_factors($pos_num));
// all done with logic, show presentation:
?>
<!DOCTYPE html>
<html>
<body>
<?php if(isset($_GET["pos_num"])): ?>
<div>
<?= $is_perfect
? "Yes, $pos_num is a perfect number"
: "No, $pos_num is not a perfect number"
?>
</div>
<?php endif; ?>
<form action="lab_2_3.php" method="GET">
Enter positive integer:
<input type="number" name="pos_num" min="1"/>
<input type="submit"/>
</form>
</body>
</html>
Working example: http://sandbox.onlinephpfunctions.com/code/d1e5823075c71272c67e09448e6302a4dffead39
Below is the code i tried, where count is showing improper.
Please help me to get where i am missing the logic.
I am attaching the code which i have tried so far.
PS Note:- I am not intended to use more built in function of php and so I created function for string length.
error_reporting(E_ALL);
$string = "ssddk";
function checkString($addinString, &$stringBK) {
if (empty(count($stringBK))) {
$stringBK[] = $addinString;
return false;
}
foreach ($stringBK as $key => $val) {
if ($addinString == $val) {
return true;
}
}
$stringBK[] = $addinString;
return false;
}
for ($i = 0; $i < checkstrlength($string); $i++) {
$count = 0;
for ($j = 0; $j < checkstrlength($string); $j++) {
if ($string[$i] == $string[$j]) {
if (checkString($string[$i], $stringBK)) {
continue 2;
}
$count++;
echo "Column => " . $string[$j] . " for count" .$count . "<br>";
}
}
}
function checkstrlength($string) {
$count = 0;
for ($i = 0; $string[$i] != ""; $i++) {
$count++;
}
return $count;
}
It gives below output ,
Column => s for count1
Column => d for count1
Column => k for count1
I am expecting it as ,
Column => s for count 2
Column => d for count 2
Column => k for count 1
Ok, there a couple of things to look at here.
The checkstrlength() has the below loop.
for ($i = 0; $string[$i] != ""; $i++) {
Formally speaking, we usually look at \0 terminating character in the string to terminate our loop. But in PHP, everything is a string. So, \0 is now a string to match on rather than a character match. Better, we do an isset check to stop our loop. So, code would look like:
for ($i = 0; isset($string[$i]); $i++) {
Second is your not caching the result which you got from checkstrlength(). Do it. Also, you can start the inner loop from $i itself. There is no need to go from start again. So, for loop would look like:
$length = checkstrlength($string);
for ($i = 0; $i < $length; $i++) {
for ($j = $i; $j < $length; $j++) {
Third is that there is no need of empty and count checks in checkString. This also reduces inbuilt function calls. You can simply loop over and return true if found. If not found, we are adding it anyway. So it would look like:
function checkString($addinString, &$stringBK) {
foreach ($stringBK as $key => $val) {
if ($addinString == $val) {
return true;
}
}
$stringBK[] = $addinString;
return false;
}
Now, in your nested loop, you add it to $stringBK outside of the inner loop, because there is no point in checking with the inner loop when chars match. This is because if some character was visited, why initialize the inner loop at all. Just have a check above and continue the search and count. Also note that you are having echo statements inside the inner loop which doesn't make sense because we haven't finished the count yet. Let's do and print it outside of the inner loop at the end. Snippet as follows:
for ($i = 0; $i < $length; $i++) {
$count = 0;
if (checkString($string[$i], $stringBK)) {
continue;
}
for ($j = $i; $j < $length; $j++) {
if ($string[$i] == $string[$j]) {
$count++;
}
}
echo "Column => " . $string[$i] . " for count : " .$count,PHP_EOL;
}
Final Code Demo: https://3v4l.org/4dpST
So I have a for loop that is decreasing...
for ($i=count($array); i>0; $i--;)
{
if(condition)
{DO SOMETHING like print the element in a decreasing manner}
if(enter ending iteration condition here after xth element) break;
}
that pretty much sums up my question. How do I formulate the ending iteration - let's say after 5 elements printed I want to stop the iteration.
$j = 0;
for ($i=count($array); $i>0; $i--)
{
if(condition)
{
DO SOMETHING like print the element in a decreasing manner;
$j++;
}
if($j > 4){
break;
}
}
Try to reverse the count of the loop. Instead of decreasing, try to increase so you will have a count of how many items are being printed.
<?php
for ($i = 0; $i < count($array); $i++)
{
if(condition)
{
/* DO SOMETHING like print the element in a decreasing manner */
}
/* replace (nth) with the needed number */
if($i === (nth)) break;
}
You could set the limit based on the count, like:
$loop_limit = 5;
$array_count = count($array);
$last = $array_count - $loop_limit;
for ($i = $array_count; $i >= $last ; --$i) {
if ( $i == $last ) {
//Do whatever you need at this point
}
//do the normal loop action
}
I have this code that for some reason it keeps in an infinite loop, when it is suppose to just print all possible substrings. This is part of the complete function. The purpose of the function is to return the indexes of the substring from string $str2 found in string $str1. Thanks a lot for the help.
$str1='QYDIKYTWNVPKIAPKS';
$str2='KYTWNVPKSS';
print($str1);echo"</br>";print($str2);echo"</br>";
function overlapping($str1,$str2) {
$peptide1 = str_split($str1);
$peptide2 = str_split($str2);
$longest_seq=array();
$len=count($peptide2)-1;
for ($i = 0; $i < count($peptide1); ++$i) {
for ($j = 0; $j < count($peptide2); ++$j) {
if ($peptide2[$j]==$peptide1[$i]){
$k=$j;
$start=$j;
$l=$i;
$tmp=array();
while ($peptide2[$k]==$peptide1[$l]){
array_push($tmp, $peptide2[$k]);
$substring=implode($tmp);
print $substring;
echo"</br>";
$k=$k+1;
$l=$l+1;
}
}
}
}
}
Maybe you have another idea of how to extract the index of a matching substring, I can also try that
You never check to insure that $k and $l are valid offsets. Check for it here :
while (isset($peptide2[$k]) && isset($peptide1[$l]) && $peptide2[$k]==$peptide1[$l]){
instead of
while ($peptide2[$k]==$peptide1[$l]){
I'm not sure if this has anything to do with your issue, but I always post-increment in my for loops.
for ($i = 0; $i < count($peptide1); $i++) {
// do stuff
}
what I want to do is run this for loop and within there is a foreach searching the positions. what I want to do is once there it returns false I want it to break and save the position of $i in a variable. I'm using simple_html_dom.php but I don't think that matters since this is more of a basic programming problem.
for($i = $0; $i < $20; $i++){
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false){
break;
}
}
//this is not valid, but essentialy this is what I want to do.
$stop = $i;
}
To break multiple levels in a loop you simply specify the levels, eg, break 2 - see the manual on break - http://www.php.net/manual/en/control-structures.break.php.
As such your code might work as
for($i = $0; $i < $20; $i++){
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false){
$stop = $i; // Set variable
break 2; // break both loops
// or alternatively force the outer loop condition to expire
//$i = 21; // Force the outer loop to exit
//break;
}
}
}
I have expanded to question to set $i = 21 to break the outer loop with a single break.
Untested code but syntax checked...
<?php
// Untested code...
// Assume that you WILL break out of the loops...
$currentForIdx = -1; // so we can test that 'for' loop actually ran
$quitLoops = false;
for($i = 0; $i < $20 && !quitLoops; $i++) {
$currentForIdx = $i; // in case we break out of the loops
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false) {
$quitLoops = true;
break;
}
}
}
// test $quitLoops and $currentForIdx to work out what happened...
?>
I havent tested this, but I would try something like this:
for($i = $0; $i < $20; $i++){
$stop = false;
foreach($html->find('div[class=cate_link]',$i) as $a){
if (strpos($a->plaintext,'+info') == false){
$stop = $i;
}
}
if ($stop !== false) {break;}
}