By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
438,348 Members | 1,397 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 438,348 IT Pros & Developers. It's quick & easy.

Problem creating while Loop listing each occurance of a number in a string

P: 61
Hi,

I created a while-loop which will basically go through each number in a string and list the positions of the desired number.

For example suppose I have a string sa "12123124" and I want to list all the positions of "1" the output should be 0, 2 and 5.

My work out below is:
Expand|Select|Wrap|Line Numbers
  1. <html>
  2.     <body>
  3.         <?php
  4.             $number = "12123124";
  5.             $posFirst = 0; // Computer counts from 0.
  6.             $posLast = strlen($number)-1; // Since we are counting from 0, we need to 
  7.                                           // adjust the last position accordingly
  8.  
  9.             While($posFirst <= $posLast)
  10.             {
  11.                 $posFirst = strpos($number, "1", $posFirst);
  12.                 echo $posFirst."<p>";
  13.                 $posFirst = $posFirst+1;
  14.  
  15.  
  16.             }
  17.  
  18.         ?>
  19.     </body>
  20.  
  21. </html>
  22.  
The output I get is an infinite loop and I don't get what's causing it to loop forever.

0

2

5

2

5

2

5

2

5

2

5

2

Any idea would be appreciated. Thanks.
Sep 23 '08 #1
Share this Question
Share on Google+
12 Replies


Dormilich
Expert Mod 5K+
P: 8,639
It's the last cycle. In the incrementation $posFirst (which is at that moment: false) is set to 1 (false +1 = 1), you could either break out (if (is_boolean($posFirst)) break;) or use preg_match_all() with the PREG_OFFSET_CAPTURE flag instead of the while loop.

regards
Sep 23 '08 #2

P: 61
It's the last cycle. In the incrementation $posFirst (which is at that moment: false) is set to 1 (false +1 = 1)
I didn't get it. The increment in line 13 merely increments the value. So $posFirst was initialised to 0 then it became 1 after first run. Why is it false + 1 = 1?
Sep 23 '08 #3

Atli
Expert 5K+
P: 5,058
Yea. The problem is that if the strpos function doesn't find a match, it returns false. Which PHP will convert into 1 when you try to compare it with another integer.

If I were doing this, I would simply check if the return value of that function was false.
Like:
Expand|Select|Wrap|Line Numbers
  1. $position = -1;
  2. while($position = strpos($heystack, $needle, $position + 1))
  3. {
  4.   echo "Found at $position<br />";
  5. }
  6.  
Sep 23 '08 #4

Dormilich
Expert Mod 5K+
P: 8,639
If I were doing this, I would simply check if the return value of that function was false.
definitely more elegant than my solution.... *sigh*
Sep 23 '08 #5

P: 61
Yea. The problem is that if the strpos function doesn't find a match, it returns false. Which PHP will convert into 1 when you try to compare it with another integer.

If I were doing this, I would simply check if the return value of that function was false.
Like:
Expand|Select|Wrap|Line Numbers
  1. $position = -1;
  2. while($position = strpos($heystack, $needle, $position + 1))
  3. {
  4.   echo "Found at $position<br />";
  5. }
  6.  
Ok so, you intially set the value of $position to -1.

In the first run you are searching from position 0 ($position + 1, so -1 +1 = 0) and it found a value and prints it.

I am kind of lost what happens in the second pass through the while loop. Because you are not using condition checking == just =. So how does the computer know when to break off?

I get how you say it returns a false like that php link in your post says
Returns the position as an integer. If needle is not found, strpos() will return boolean FALSE.
Sep 23 '08 #6

P: 61
Actually sorry guys ignore me.

I forgot that a variable in PHP can take different values like $var can be set to take string when you say

$var = "hello";

but later becomes a boolean if you say $var = FALSE or something like that. So after strpos() finishes searching the string it returns a boolean false. So the $position in the while loop of Atli's code becomes a boolean (false more specifically) and hence it breaks out.

I couldn't get how it was set to take string earlier and now taking boolean FALSE all of a sudden. Blame it on too much C coding.

Thanks for your help Atli & Dormilich.
Sep 23 '08 #7

P: 25
I thought this was an interesting problem, and I played with it some.

First I added an "echo" at the beginning of the loop:
Expand|Select|Wrap|Line Numbers
  1. while($posFirst <= $posLast) {
  2.    echo $posFirst."-->";   //$posFirst value before the call to strpos()
  3.    $posFirst = strpos($number, "1", $posFirst);
  4.    echo $posFirst."<p>\n";   //$posFirst value AFTER the call
  5. }
  6.  
and got this output:
0-->0<p>1-->2<p>3-->5<p>6--><p>1-->2<p>3-->5<p>6--><p>1-->2<p>
which displays in browser as:
0-->0
1-->2
3-->5
6-->
1-->2
3-->5
6-->
1-->2
So, calling strpos with 0 returns 0. Adding 1 gives you 1.
2nd time in the loop: calling strpos with 1 returns 2. Adding 1 gives you 3.
3rd time in the loop: calling strpos with 3 returns 5. Adding 1 gives you 6.
4th time in the loop. calling strpos with 6 returns false. Adding 1 gives you 1 !!!
5th time in the loop: calling strpos with 1 returns 2. Adding 1 gives you 3.
and so on...

I was wondering if ++ acts differently, and it does! Replacing the last line in the loop with:
$posFirst++;
gives the following output:
0-->0
1-->2
3-->5
6-->
-->0
1-->2
So, using ++ operator on false yields false, but adding 1 to false makes a 1.
Sep 23 '08 #8

Atli
Expert 5K+
P: 5,058
There is a bug in my previous code! (Hard to believe... I know :P)
But first, let me explain.

In a conditional statement, like a while or a if statement, PHP will look for a TRUE value, which is basically the same as comparing everything inside the while with TRUE.

So:
Expand|Select|Wrap|Line Numbers
  1. // This:
  2. while(true)
  3. // Is exactly like doing
  4. while(true == true)
  5.  
  6. // And this
  7. while(strpos($h, $n))
  8. // Is exactly like
  9. while(strpos($h, $n) == true)
  10.  
And, being both very smart and a bit annoying, PHP will consider any number above 0 and any non-empty string to be TRUE, but evaluating NULL, 0 and "" as FALSE.

So, strpost, returning a number when it finds a match and FALSE when it doesn't, will be considered TRUE when it finds a match...

With one exception (which is what I overlooked in my previous code).
When it finds a match at the first index (0), it returns 0, which will be evaluated as FALSE, ending the loop prematurely.

So to fix that, we just look for a boolean value rather than FALSE.
Like:
Expand|Select|Wrap|Line Numbers
  1. $position = -1;
  2. while(!is_bool($position = strpos($heystack, $needle, $position + 1)))
  3. {
  4.     echo "Found at $position<br />";
  5. }
  6.  
Sorry about that. Was eating when I wrote my first post :P
Sep 23 '08 #9

P: 61
And, being both very smart and a bit annoying, PHP will consider any number above 0 and any non-empty string to be TRUE, but evaluating NULL, 0 and "" as FALSE.
Yeah it did terminate after printing zero but I thought there was something wrong with my syntax in while loop which is causing it to terminate at 0. Thanks for clarifying.
Sep 23 '08 #10

P: 61
that code works fine. Had a little trouble getting my head around that is_bool() becuase at first it looked like this:

is_bool(FALSE) is TRUE but digging a little deeper, is_bool looks at the type of variable not the content of the variable.

For a first timer dealing with is_bool() function it can be a little tricky! Kind of like a brain teaser.
Sep 23 '08 #11

Dormilich
Expert Mod 5K+
P: 8,639
What happens when strpos returns a FALSE after finishing searching the string for $needle? Because logically when it $position will then be FALSE and

!is_bool(FALSE) is same as TRUE and hence it'll dig again into the loop.
er no, is_bool() checks for a boolean type, so both true and false return true as result, which is negated and therefore it breaks the loop.

regards
Sep 23 '08 #12

Atli
Expert 5K+
P: 5,058
that code works fine. Had a little trouble getting my head around that is_bool() becuase at first it looked like this:

is_bool(FALSE) is TRUE but digging a little deeper, is_bool looks at the type of variable not the content of the variable.
Yea I can see why it could be confusing at first :)
It's in a series of "is_*" functions that check for all sorts of variable types.

Can be a little difficult to use cause PHP is so good at converting the types for you.
Like using is_int() to check numbers from user input will not work, because user input is always a string. But using numbers from user input in math works fine because PHP just converts it when it needs to.

It's very smart, but potentially very annoying :)
Sep 23 '08 #13

Post your reply

Sign in to post your reply or Sign up for a free account.