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

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Alien
    New Member
    • Sep 2007
    • 61

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

    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:
    [code=php]
    <html>
    <body>
    <?php
    $number = "12123124";
    $posFirst = 0; // Computer counts from 0.
    $posLast = strlen($number)-1; // Since we are counting from 0, we need to
    // adjust the last position accordingly

    While($posFirst <= $posLast)
    {
    $posFirst = strpos($number, "1", $posFirst);
    echo $posFirst."<p>" ;
    $posFirst = $posFirst+1;


    }

    ?>
    </body>

    </html>
    [/code]

    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.
  • Dormilich
    Recognized Expert Expert
    • Aug 2008
    • 8694

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

    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($po sFirst)) break;) or use preg_match_all( ) with the PREG_OFFSET_CAP TURE flag instead of the while loop.

    regards

    Comment

    • Alien
      New Member
      • Sep 2007
      • 61

      #3
      Originally posted by Dormilich
      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?

      Comment

      • Atli
        Recognized Expert Expert
        • Nov 2006
        • 5062

        #4
        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:
        [code=php]
        $position = -1;
        while($position = strpos($heystac k, $needle, $position + 1))
        {
        echo "Found at $position<br />";
        }
        [/code]

        Comment

        • Dormilich
          Recognized Expert Expert
          • Aug 2008
          • 8694

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

          Originally posted by Atli
          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*

          Comment

          • Alien
            New Member
            • Sep 2007
            • 61

            #6
            Originally posted by Atli
            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:
            [code=php]
            $position = -1;
            while($position = strpos($heystac k, $needle, $position + 1))
            {
            echo "Found at $position<br />";
            }
            [/code]
            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.

            Comment

            • Alien
              New Member
              • Sep 2007
              • 61

              #7
              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.

              Comment

              • Marjeta
                New Member
                • Sep 2008
                • 25

                #8
                I thought this was an interesting problem, and I played with it some.

                First I added an "echo" at the beginning of the loop:
                Code:
                while($posFirst <= $posLast) {
                   echo $posFirst."-->";   //$posFirst value before the call to strpos()
                   $posFirst = strpos($number, "1", $posFirst);
                   echo $posFirst."<p>\n";   //$posFirst value AFTER the call
                }
                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.

                Comment

                • Atli
                  Recognized Expert Expert
                  • Nov 2006
                  • 5062

                  #9
                  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:
                  [code=php]
                  // This:
                  while(true)
                  // Is exactly like doing
                  while(true == true)

                  // And this
                  while(strpos($h , $n))
                  // Is exactly like
                  while(strpos($h , $n) == true)
                  [/code]
                  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:
                  [code=php]
                  $position = -1;
                  while(!is_bool( $position = strpos($heystac k, $needle, $position + 1)))
                  {
                  echo "Found at $position<br />";
                  }
                  [/code]
                  Sorry about that. Was eating when I wrote my first post :P

                  Comment

                  • Alien
                    New Member
                    • Sep 2007
                    • 61

                    #10
                    Originally posted by Atli
                    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.

                    Comment

                    • Alien
                      New Member
                      • Sep 2007
                      • 61

                      #11
                      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.

                      Comment

                      • Dormilich
                        Recognized Expert Expert
                        • Aug 2008
                        • 8694

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

                        Originally posted by Alien
                        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

                        Comment

                        • Atli
                          Recognized Expert Expert
                          • Nov 2006
                          • 5062

                          #13
                          Originally posted by Alien
                          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 :)

                          Comment

                          Working...