neylitalo Posted January 5, 2008 Share Posted January 5, 2008 I observed this behavior when running a for() loop on letters, like this: <?php for($a = "A"; $a <= "Z" ; $a++) { echo $a; } ?> After it runs through the entire alphabet (A-Z), then it starts in on pairs of letters. AA, AB, AC, all the way to AZ. And once it's done with A, it goes on to BA, BB, BC, and so on, to BZ. Then it loops through all of the other letters similarly. The "quirk" (if the whole thing isn't one big quirk) is at the end: It stops at YZ. It doesn't go on to ZA. I tested this: <?php for($a = "A"; $a <= "Y"; $a++) { echo $a; } ?> It runs through the alphabet, but only up to Y, and stops there, no pairs of letters. I suspect this may be a "bug" in PHP itself, but does anybody have a logical explanation for this behavior? Quote Link to comment https://forums.phpfreaks.com/topic/84591-solved-for-construct-with-letters/ Share on other sites More sharing options...
PFMaBiSmAd Posted January 5, 2008 Share Posted January 5, 2008 LOL, I wrote some code just like that a while ago. Here is what I think is happening. This is similar to when you sort the strings "10" and "2". "10" will come before "2", because the sort (comparison) is operating character by character, left to right. The comparison operator <= is not comparing the strings, it is comparing the values on both sides as an array of characters. For values A..Z, $a only contains one element $a[0], but because the comparison uses the "=" condition too, it means that $a will be incremented to AA on the next comparison. Once $a increments from Z to AA, $a now has two elements $a[0] and $a[1]. The "Z" is probably promoted to a two element string "Znull" for the comparison as well. As long as $a[0] is <= "Z" the comparison is still true. That gets you from AA to YZ. When this increments to ZA, $a[0] is now equal to "Z" (or the first array element of "Znull") and the comparison then checks the $a[1] element to see if the less-then "<" part of the comparison is true or false. Since the $a[1] element is no longer less-than or equal "<=" to the second element of "Z" or "Znull", the comparison is finally false. I recommend making an array of the characters A to Z using a range() function and then using a foreach() loop to iterate over that array of characters. Edit: In case you tried $a < "AA". It won't work for the same reason. When $a[0] becomes "B", that is greater than the first element of "AA" and the comparison is false. Quote Link to comment https://forums.phpfreaks.com/topic/84591-solved-for-construct-with-letters/#findComment-431081 Share on other sites More sharing options...
PFMaBiSmAd Posted January 5, 2008 Share Posted January 5, 2008 For the code to use a for() loop and work, it would need to be as follows (tested) - for($a = "A"; strcmp(str_pad($a, 2, " ",STR_PAD_LEFT),"AA") < 0 ; $a++) An array of letters and a foreach() loop is starting to look pretty good and would have much faster speed too. Quote Link to comment https://forums.phpfreaks.com/topic/84591-solved-for-construct-with-letters/#findComment-431097 Share on other sites More sharing options...
kenrbnsn Posted January 5, 2008 Share Posted January 5, 2008 The following doesn't solve the OP's original query, but gives the results that were mentioned: <?php $az = range('A','Z'); for ($i = 0;$i<count($az);$i++) for ($j=0;$j<count($az);$j++) echo $az[$i] . $az[$j] . "\n"; ?> Ken Quote Link to comment https://forums.phpfreaks.com/topic/84591-solved-for-construct-with-letters/#findComment-431114 Share on other sites More sharing options...
PFMaBiSmAd Posted January 5, 2008 Share Posted January 5, 2008 I am pretty sure he wanted just A - Z but attempting to use the comparison $a <= "Z" does not directly work for strings. Quote Link to comment https://forums.phpfreaks.com/topic/84591-solved-for-construct-with-letters/#findComment-431116 Share on other sites More sharing options...
neylitalo Posted January 5, 2008 Author Share Posted January 5, 2008 For values A..Z, $a only contains one element $a[0], but because the comparison uses the "=" condition too, it means that $a will be incremented to AA on the next comparison. This doesn't make sense to me. Why should the = make it increment to AA, and not stop at Z? After all, I didn't tell it "<= 'ZZ'", I said "<= 'Z'". By all logic, it should stop at Z, not go on to AA. And if we sidestep that point of logic, why does it stop at YZ? Why not go to ZA? Quote Link to comment https://forums.phpfreaks.com/topic/84591-solved-for-construct-with-letters/#findComment-431167 Share on other sites More sharing options...
PFMaBiSmAd Posted January 5, 2008 Share Posted January 5, 2008 For() loops execute the third parameter at the end of the loop. So, when $a is a "Z", $a <= "Z" is true, the code in the loop executes, then $a++ makes $a into an "AA" and that is what is used in the next comparison. Since the leading character in $a is still less than "Z", the comparison is true and the loop continues. As to why it stops at "YZ", read what I wrote a couple of more times. The leading character in $a (for "AA" to "YZ") is less than "Z" until $a is "ZA". It is only then that the comparison looks at the second character in $a and finds that the "A" in "ZA" is no longer <= to the second character in "Z" because "Z" does not contain a second character. Quote Link to comment https://forums.phpfreaks.com/topic/84591-solved-for-construct-with-letters/#findComment-431253 Share on other sites More sharing options...
neylitalo Posted January 7, 2008 Author Share Posted January 7, 2008 As to why it stops at "YZ", read what I wrote a couple of more times. The leading character in $a (for "AA" to "YZ") is less than "Z" until $a is "ZA". It is only then that the comparison looks at the second character in $a and finds that the "A" in "ZA" is no longer <= to the second character in "Z" because "Z" does not contain a second character. That's exactly what I was looking for, and the whole thing even makes sense, in a twisted sort of way. Thanks. Quote Link to comment https://forums.phpfreaks.com/topic/84591-solved-for-construct-with-letters/#findComment-432252 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.