为什么此代码不简单地将字母A打印到Z?


435
<?php
for ($i = 'a'; $i <= 'z'; $i++)
    echo "$i\n";

此代码段给出以下输出(换行符由空格代替):

abcdefghijklmnopqrstu vwxyz aa ab ac ad ae af ag ah ai aj ak al am ao a a a ap aq ar as at au av aw ax ay az ab ba bb bc bd be bf bg bh bi bj bk bb bm bn bp bq bq bs bw bx by bz ca cb cc cd ce cf cg ch ci cj ck cl cm cn co cp cq cr cs ct cu cv cw cx cy cz cz da db dc dd d df dg dh di dj dk dl dm dn do dp dq dr ds dt du dv dw dx dy dz ea eb ed ee ef,例如eh e ek e e e e e e e e e e e e e e e e e e e E E E V E V V Ev C ...


31
即使语法试图说服您相反,PHP也不是C。
joni 2010年

3
这对我有用,但变化很小:for($ i ='a'; $ i!='aa'; $ i ++){echo“ $ i \ n”; }
超现实主义之梦

2
关于PHP不是C的评论是最热烈的,例如:在c:char c ='a';中。与php:中的不同$c = 'a';,要点是C中有char(character 1 symbol)类型,但PHP中没有,如果U告诉PHP- $c = 'a';表示这是一个只有1个字符的字符串。这就是为什么U无法在PHP中充分循环28个字符。我希望每个程序员都可以学习低级语言和强类型,而不会忘记数学实践,这将有助于他们变得更强大。
亚瑟·库什曼

哇,真的很棒,但是为什么它没有停在“ z”位置
Prasanth Bendra

有关使用等式(==!=)获得预期终点的方法,请查看有关相关问题的答案
IMSoP 2013年

Answers:


342

文档

当处理字符变量而非C的算术运算时,PHP遵循Perl的约定。

例如,在Perl 'Z'+1变成'AA',而用C 'Z'+1变成'['ord('Z') == 90ord('[') == 91)。

请注意,字符变量可以递增但不能递减,即使如此,仅支持纯ASCII字符(az和AZ)。

来自评论:-
还应该注意的<=是,按字典顺序比较'z'+1 ≤ 'z'。(因为'z'+1 = 'aa' ≤ 'z'。但这'za' ≤ 'z'是第一次比较不正确。)$i == 'z'例如,中断时间将起作用。

这里的例子


哈..那太疯狂了!我一直在用,ord()所以我从来没有注意到这一点。
mpen

68
为了完整起见,您还应该添加“ <=”是字典比较,因此'z'+ 1≤'z'。(因为'z'+ 1 ='aa'≤'z'。但是'zz'≤'z'是第一次比较错误。)例如,当$ i =='z'有效时将中断。
ShreevatsaR

6
正如ShreevatsaR所说,麻烦的是比较器,而不是算术,不要专注于++运算符
slf 2010年

10
@ShreevatsaR:实际上,“ yz” +1 =“ za”。未通过第一比较是“ZA” <=“Z”
米兰Babuškov

2
谢谢你们的评论!是的,关键是'aa'字典上小于'z',这就是循环继续的原因。它停止于,'yz'因为'za'大于z。检查此示例
CMS 2010年

123

因为一旦达到“ z”(这是您范围内的有效结果,$ i ++便将其递增到顺序的下一个值),则下一个值将为“ aa”;并且按字母顺序,“ aa”小于“ z”,因此永远不会满足比较

for ($i = 'a'; $i != 'aa'; $i++) 
    echo "$i\n"; 

55
'z'++ ='aa',但'aa'<'z'很奇怪。这种逻辑不是很好。
马修·维尼斯

19
@Matthew:按字母顺序排列。首先是'aa',因此它比字符串'z'少。循环终止于“ zz”,因为它的字母顺序是“大于”(在“ z”之后)。您可以“增加”某些东西并获得较小的价值,这是不合逻辑的,但是按字母顺序来说,这是合乎逻辑的。
eldarerathis

2
字符增量器是Perl逻辑(请参阅文档中CMS的引文)。比较'aa'<'z'是标准字符串比较逻辑。并不奇怪,一旦您了解了如何使用它……从这里的答案中,很多人都不会。
Mark Ba​​ker

5
@eldarerathis哦,我绝对知道它的工作方式。我只是觉得同时很奇怪。
马修·维尼斯

2
对于我来说,这非常有用,它可以处理遵循相同逻辑序列的Excel列
Mark Ba​​ker,2010年

97

其他答案则说明了已观察到的已发布代码的行为。这是一种执行所需操作的方法(它是更干净的代码IMO):

foreach (range('a', 'z') as $i)
    echo "$i\n";

响应ShreevatsaR关于范围函数的评论/问题:是的,它会产生“正确的端点”,即,传递给该函数的值在范围内。为了说明这一点,上述代码的输出为:

a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z

2
range()是否包含正确的端点?从其他语言的经验来看,这也是意外的!
ShreevatsaR

1
@ShreevatsaR:是的,range()给出了“正确的”端点,有关更多信息,请参见我编辑过的答案(并点击指向该函数的链接)。
GreenMatt

1
我能说什么……更多的PHP疯狂。:-)我不知道在哪种range()以这种方式工作的其他语言。(当然不是,例如Haskell或Python。)Dijkstra没为此写点什么吗?
ShreevatsaR

10
疯狂在于PHP的不一致。范围(“A”,“CZ”)的工作原理完全不同的增量器++,将得到的阵列将只包含三个值:A,B和C.
马克贝克

35

其他人已经说过PHP为什么不显示您的期望。这是您可能想要的结果的方式:

<?php
for ($i = ord('a'); $i <= ord('z'); $i++)
    echo chr($i);
?>

2
不必要。您根本不需要执行ord(),只需进行正确的比较即可终止循环
Mark Ba​​ker,2010年

2
+1如果不熟悉PHP的一种更古怪的功能,则更容易理解。
lonesomeday

1
这是自我记录代码的一个很好的例子。b / c使用序数值然后将变量显示为字符,很容易准确地理解它。如果仅按以下方式一次确定最大值的检验,则for循环将更加有效:“ for($ i = ord('a'),$ max = ord('z'); $ i <= $ max; $ i ++){“
slevy1 2014年


4

试试这个代码。我认为这段代码将对您有所帮助。

$alphas = range('A', 'Z');
foreach($alphas as $value){
    echo $value."<br>";
}

依次显示26个字母。



2

也可以使用:

for ($i = 'a'; $i <= 'z'; $i=chr(ord($i)+1))
    echo "$i\n";

2

PHP具有循环字母的功能,并且可以超出单个字符;其余的将以这种方式完成:aa ab ac ... zz,依此类推。

尝试这个:

<?php
for ($i = 'a'; $i !== 'aa'; $i++)
    echo "$i\n";
?>

0

尽管以上答案对正在发生的事情很有洞察力,但非常有趣(我不知道它的行为会如此,很高兴知道为什么。

最简单的解决方法(尽管可能不是最有意义的)只是将条件更改为$ i!='z'

<?php
for ($i = 'a'; $i != 'z'; $i++)  
    echo "$i\n";
?>

4
请注意,这只会给您a到y,而不是z
Mark Ba​​ker

h!是的,很好。我可以看到增量和比较背后的逻辑,但可以肯定的是,有时$ a ++ <$ a
jon_darkstar 2010年

0

PHP认为'AA'小于'Z'。最好的方法是:

for($i = 'a'; $i != 'aa'; $i++) {
  echo $i;
}

abcdefghijklmnopqrstuvwxyz


0

也许这段代码会起作用。这很容易并且可以理解:

<?php
$ascii_val = ord("a");
for($i=$ascii_val;$i<$ascii_val+26;$i++){
echo chr($i)."\n";
}
?>

其中26是字母表中字母的总数。


-3

哇,我真的不知道,但是它不是很大的代码,您可以在循环后尝试回显“ z”。Mark是绝对正确的我使用了他的方法,但是如果您想要替代方法,也可以尝试

<?php
for ($i = "a"; $i = "y"; $i++) {
    echo "$i\n";
    if ($i == "z") {}
}
echo "z";
?>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.