PHP "for" loop issue - php

Simple question:
Why is this:
for($k=1;$k<=10;$k+2) { }
giving an infinite loop? When I change $k+2 by $k++, it works fine.
How can I correct it? (I can't change the 10 for an impair number because I need this function to work either with a pair or impair value at that place)

$k+2
This won't change $k's value, so it never get's higher than 10. Probably you meant:
$k+=2
Which will increase $k by two each time the expression get's evaluated (at the end of each for-loop).

for($k=1;$k<=10; $k = $k+2) { }
or
for($k=1;$k<=10; $k += 2) { }

it is infinite loop because $k is not updated, try this instead
for($k = 1; $k <= 10; $k = $k + 2) {}
or
for($k = 1; $k <= 10; $k += 2) {}
Reference: PHP operators

Related

What does this for-loop mean?

I've stumbled upon a syntax in a code example I have never seen in for-loops before in PHP.
What does this do? WHY should I use this?
for(;$i<$max;){
$i++;
//code..
}
I could figure out that it was not the same as
for($i=0;$i<$max;$i++) {
//code...
}
I don't understand the difference between the two examples above.
If for being more specific about my thoughts.
If we have this code (taken from a solution from adventofcode):https://www.reddit.com/r/adventofcode/comments/kdf85p/2020_day_15_solutions/
<?php
$cap = 2020;
$bits = [5,1,9,18,13,8,0];
$i=0;
$time = [];
foreach($bits as $bit) {
$i++;
$time[$bit] = $i;
$say = 0;
}
for(;$i<$cap-1;){
$i++;
if(isset($time[$say])) {
$last = $time[$say];
}
else {
$last = $i;
}
$time[$say] = $i;
$say = $i - $last;
}
echo $say;
?>
and compare that to:
<?php
$cap = 2020;
$bits = [5,1,9,18,13,8,0];
$i=0;
$time = [];
foreach($bits as $bit) {
$i++;
$time[$bit] = $i;
$say = 0;
}
for($i=0;$i<$cap-1;$i++){
if(isset($time[$say])) {
$last = $time[$say];
}
else {
$last = $i;
}
$time[$say] = $i;
$say = $i - $last;
}
echo $say;
?>
I get different results in $say.(376 in first example and 38 in last example).
Why do I get different values?
Well based on the PHP docs:
https://www.php.net/manual/en/control-structures.for.php
for loops are the most complex loops in PHP. They behave like their C
counterparts. The syntax of a for loop is:
for (expr1; expr2; expr3)
statement
While:
Each of the expressions can be empty or contain multiple expressions
separated by commas.
So it's just a way to "save code" when your first expression of the for-loop is "obvious", So instead of mentioning the default obvious expression - you just "skip" it.
According to your example:
for(;$i<$cap-1;)
we skipped the first expression (expr1) as $i has been already defined as 0 ($i = 0;) earlier in the code block so it's "skippable". Doesn't affect the code.
But, The third expression:
At the end of each iteration, expr3 is evaluated (executed).
Since we don't mention it in the loop, we are responsible to handle the "increasement" (in this case) of $i in the loop itself.
However - the main difference in the code is that if you mention the third expression - it's evaluated at the end of each iteration but in the code block (your example) - we increase the $i variable at the beginning of the code.
The main difference between the two blocks (assuming $i is initialised to 0 before the for(;$i<$max;){ loop) is that the first loop increments $i before running the loop code, where the second loop increments $i after running the loop code. As a trivial example:
function code($i) {
echo "$i\n";
}
$max = 3;
$i = 0;
for(;$i<$max;){
$i++;
code($i);
}
for($i=0;$i<$max;$i++) {
code($i);
}
The output of the first loop is:
1
2
3
while the output of the second loop is:
0
1
2
Note (as pointed out by #IMSoP), the condition clause is executed at the beginning of the loop, and can have side-effects, so you could also emulate the first loop with this code:
for($i=0;$i++<$max;) {
code($i);
}
C-style for loops are a rather peculiar piece of syntax. They actually consist of three expressions, any of which can do anything you like, or even be empty:
An expression to execute for its side effects once before the loop begins
An expression to evaluate at the beginning of each iteration, to see if the loop should terminate
An expression to execute for its side effects at the end of each iteration
The most common way to use them is:
Initialise a counter of some sort
Check if the counter has reached some value
Increment or decrement the counter
But those aren't built into the language at all, and leaving one of the expressions out doesn't apply any default behaviour, it just does nothing - except that leaving the second expression empty always evaluates to true.
So, for instance:
for(;true;) is an infinite loop: it does nothing, checks true, and does nothing again
for(;;) is the same infinite loop, because the empty expression in the middle is considered true
for($i=0;;) is just the same infinite loop, but with $i initialised to 0 before running it
for(;true;foo()) is the same loop, but with the function foo() run at the end of every iteration
In your case, the loop is for(;$i<$max;) which breaks down to:
Before starting the loop, do nothing
At the beginning of each iteration, terminate if the expression $i<$max happens to be false
At the end of each iteration, do nothing
It doesn't do anything to control what values $i and $max have before or during the loop.
In fact, it's just the same as while($i<$max) and would probably be much clearer if written that way.
The example shown seems to have ended up that way because the author wanted to move the $i++ to the beginning of each iteration, rather than the end (although why they also left out the $i=0 I'm not sure). But the for syntax supports that too! You can actually include multiple expressions with a comma between in any of the three positions; if they're in the second position, the last one is what determines if the loop exits.
So you can do this:
for($i=0; $i++,$i<=$max; )
Now, $i will be incremented at the beginning of the loop; since it will be incremented before the test, you have to also adjust the condition from < to <= to make sure it runs for one more iteration.
For that particular case, there's another way as well: incrementing a variable returns a value. If you write ++$i it returns the value after incrementing, and if you write $i++ it returns the value before incrementing. So both of these would also work:
for($i=0; ++$i <= 10; ) echo $i, PHP_EOL;
for($i=0; $i++ < 10; ) echo $i, PHP_EOL;
In your first example, $i is registered somewhere before. so $i can be 0 or other zero, because if you use code like
for(;$i<$max;){
$i++;
//code..
}
you got error Undefined variable $i in and later $i is registered.
/* example 1 */
for ($i = 1; $i <= 10; $i++) {
echo $i;
}
/* example 2 */
for ($i = 1; ; $i++) {
if ($i > 10) {
break;
}
echo $i;
}
/* example 3 */
$i = 1;
for (; ; ) {
if ($i > 10) {
break;
}
echo $i;
$i++;
}
https://www.php.net/manual/en/control-structures.for.php
what is your point?

Can i use divide in loop for PHP?

Can i use divide in loop for PHP ?
I write code like that but not work.
<?PHP
for ($k=100;$k>2;$k/2)
{echo $k;}
?>
That should be $k = $k / 2, or $k /= 2.
As pointed out in the comments, you could also use a bit shift operation $k >>= 1.
Try with:
for ($k=100;$k>2;$k = $k/2) {
echo $k;
}

Multiply in while()

I need to multiply variables, but the amount of them is not always the same, is there any function to do so, or how to solve this?
$string = "abc";
$amn = strlen($string);
$i = 1;
while ($i <= $amn) {
$comb[$i] = $i;
$i++;
}
It will save numbers 1, 2, and 3 into variable $comb[$i], and i need to multiply them between each other $comb[1]*$comb[2]*$comb[3]. Thank you in advance.
there is one function array_sum (http://php.net/manual/de/function.array-sum.php). This sums your array. If you need the product use array_product.
BR,
TJ
What about this:
$product = 1;
while($i <= $amn){
$product = $product*$i;
$i++;
}
This computes the factorial n!, which is 1*2*3*4*5*...*n (you can leave out the multiplication by one, because it is actually a nop).
You could also use a for loop, to make things more compact:
$product = 1;
for($i = 2; $i <= $amn; $product *= $i++);
first of all, since you're working with an index, running a loop a given ammount of time, a for loop is more sutable here, it manages the scoping of the index variable $i and makes for more readable code.
for($i=1;$i<=strlen($str);$i++){
$comb[$i]=$i;
}
now to multiply each of them:
$product = 1;
foreach($com as $key => $value){
$product*=$value;
}
If what you're trying to do is to just compute a factorial, you don't even need to make an array:
function factorial($num){
$fac = 1;
for($i=2;$i<=$num){
$fac*=$i;
}
}

These Loops are Not Working Properly

I have been working with the same loop for a couple days now, and it still won't work the way I want it to. I have tried both for, foreach and while and it still refuses to work.
The code that won't work is simply:
if(!empty($_POST['submit'])){
$d = count($_POST['deleteT']);
for ($pi = 1; $pi <= $d; $pi++) {
echo "Banned ".$_POST['deleteT'][$pi]."</br>";
}
}
If deleteT has two values: 'Bob' and 'Joe' it will print:
Banned Joe
Banned
Does anyone have any insight into why this is going on?
Start your loop index with $pi = 0; and only loop while $pi < $d.
I think one of your problems is in your count statement, then with the <= condition in the for loop.
If you use count(), then just use <. Example:
$c = count($my_array);
for ($i = 0; $i < $c; $i++) {
// do stuff
}
That said, an easier way to iterate over an array is with foreach. Like this:
foreach ($my_array as $key => $val) {
// do stuff with $val or $key
}

How to move a step back in foreach loop?

How do i move a step back in a foreach loop?
Say i have something like this:
Do something for the first run. If b == 1, do something again. See code below.
$i = 0;
foreach ($a as $b) {
if ($i == 0) {
//something
}
if ($b == '1') {
$i = 0;
}
$i++;
}
The problem is, when $b == 1, it is setting $i = 0 but not running the instructions inside.
Any better way to overcome this if it's not possible to step back?
Update:
Thanks guys for the response. Sorry i wan't clear when i typed this.
But I'd managed to achieve what i want by putting the loop in a function and do some conditional checks and pass arguments before calling it.
Not sure if this is a typo, but you have if ($i = 0) instead of if ($i == 0). Possibly your problem is there?
Perhaps another option would be just doing:
if ($b == '1') {
// do something?
}
Final option would be to do a regular for loop and decrement the counter if a condition exists:
for ($x = 0; $x < count($thing); $x++) {
if($thing[$x] == '1') {
$x -= 1;
}
}
are you sure that $i is getting set to 0 in the loop, it is quite possible it is always 0 (because that is what it is set to before the loop)

Categories