Tại sao mã này không chỉ đơn giản là in chữ A đến Z?


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

Đoạn mã này cung cấp đầu ra sau (dòng mới được thay thế bằng dấu cách):

abcdefghijklmnopqrstu vwxyz aa ab ac ad ae af ag ah ai aj ak al am a a a a a a a a a a a a a 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 cyx du dv dw dx dy dz e eb e ed ee ef vd eh ei ej ek el em en eo ep eq er es et eu ev ew ex ... on to yz


31
PHP không phải là C, ngay cả khi cú pháp cố gắng thuyết phục bạn ngược lại.
joni

3
Điều này hoạt động với tôi với một thay đổi rất nhỏ: for ($ i = 'a'; $ i! = 'Aa'; $ i ++) {echo "$ i \ n"; }
Giấc mơ siêu thực

2
Nhận xét về PHP đó không phải là C - là quan trọng nhất, ví dụ: in c: char c = 'a'; không giống như trong php : $c = 'a';, điểm là trong C có loại char (ký hiệu 1 ký tự), nhưng không phải trong PHP, nếu U nói với PHP $c = 'a';- có nghĩa đây là một chuỗi chỉ có 1 ký tự. Đó là lý do tại sao U không thể lặp qua 28 ký tự đầy đủ trong PHP. Tôi hy vọng mọi lập trình viên sẽ học các ngôn ngữ cấp thấp và gõ mạnh cùng với nó, mà không quên các thực hành Toán học, điều này sẽ giúp họ mạnh hơn.
Arthur Kushman

Wow điều đó thật tuyệt, Nhưng tại sao nó không dừng lại ở "z"
Prasanth Bendra

Để biết cách lấy điểm cuối dự kiến ​​bằng cách sử dụng đẳng thức ( ==hoặc !=), hãy xem câu trả lời này cho một câu hỏi liên quan .
IMSoP

Câu trả lời:


342

Từ các tài liệu :

PHP tuân theo quy ước của Perl khi xử lý các phép toán số học trên các biến ký tự chứ không phải C's.

Ví dụ: trong Perl 'Z'+1biến thành 'AA', trong khi ở C 'Z'+1biến thành '['( ord('Z') == 90, ord('[') == 91).

Lưu ý rằng các biến ký tự có thể được tăng nhưng không giảm và thậm chí chỉ có các ký tự ASCII đơn giản (az và AZ) được hỗ trợ.

Từ Nhận xét: -
Cũng cần lưu ý rằng đó<=là một so sánh từ điển, vì vậy'z'+1 ≤ 'z'. (Vì'z'+1 = 'aa' ≤ 'z'. Nhưng đây'za' ≤ 'z'là lần đầu tiên so sánh là sai.)$i == 'z'Chẳng hạn,khi nàothì sẽ hoạt động.

Ví dụ ở đây .


Hah..thật điên rồ! Tôi đã luôn luôn sử dụng ord()vì vậy tôi không bao giờ nhận thấy điều này.
mở

68
Để đầy đủ, bạn cũng nên thêm rằng "<=" là so sánh từ vựng, vì vậy 'z' + 1 'z'. (Vì 'z' + 1 = 'aa'≤'z'. Nhưng 'zz'≤'z' là lần đầu tiên so sánh là sai.)
ShreevatsaR

6
như ShreevatsaR đang nói, đó là bộ so sánh, không phải số học là vấn đề, đừng tập trung vào toán tử ++
slf

10
@ShreevatsaR: thực sự, 'yz' + 1 = 'za'. Sự so sánh đầu tiên thất bại là 'za' <= 'z'
Milan Babuškov

2
Cảm ơn vì lời bình luận các chàng trai! Yeah, điểm mấu chốt là 'aa'tự từ điển nhỏ hơn 'z', đó là lý do tại sao vòng lặp tiếp tục. Và nó dừng lại 'yz''za'lớn hơn z. Kiểm tra ví dụ này .
CMS

123

Vì một khi đạt được 'z' (và đây là kết quả hợp lệ trong phạm vi của bạn, $ i ++ sẽ tăng nó lên giá trị tiếp theo trong chuỗi), giá trị tiếp theo sẽ là 'aa'; và theo thứ tự abc, 'aa' là <'z', do đó, sự so sánh không bao giờ được đáp ứng

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

55
Thật kỳ lạ khi 'z' ++ = 'aa', nhưng 'aa' <'z'. Logic đó không chảy rất tốt.
Matthew Vines

19
@Matthew: Bảng chữ cái chúng. 'aa' sẽ đến trước, do đó, nó "ít hơn" chuỗi 'z'. Vòng lặp kết thúc tại 'zz' vì nó theo thứ tự "lớn hơn" (đến sau) 'z'. Điều đó là phi logic theo nghĩa là bạn có thể "tăng" một cái gì đó và nhận được một giá trị nhỏ hơn, nhưng nó hợp lý theo nghĩa chữ cái.
eldarerathis

2
Gia tăng ký tự là logic Perl (xem trích dẫn của CMS từ các tài liệu). So sánh 'aa' <'z' là logic so sánh chuỗi tiêu chuẩn. Không có gì lạ, một khi bạn hiểu cách sử dụng nó ... từ câu trả lời ở đây, rất nhiều người không biết.
Mark Baker

5
@eldarerathis Oh tôi chắc chắn hiểu nó hoạt động như thế nào. Tôi chỉ thấy nó kỳ quặc cùng một lúc.
Matthew Vines

2
Nó cực kỳ hữu ích đối với tôi, chơi xung quanh với các cột Excel theo cùng một chuỗi logic
Mark Baker

97

Những câu trả lời khác giải thích hành vi quan sát của mã được đăng. Đây là một cách để làm những gì bạn muốn (và đó là mã sạch hơn, IMO):

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

Đáp lại nhận xét / câu hỏi của ShreevatsaR về hàm phạm vi : Có, nó tạo ra "điểm cuối bên phải", tức là các giá trị được truyền cho hàm nằm trong phạm vi. Để minh họa, đầu ra từ đoạn mã trên là:

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
Có phạm vi () bao gồm điểm cuối phải không? Từ kinh nghiệm với các ngôn ngữ khác, điều đó cũng bất ngờ!
ShreevatsaR

1
@ShreevatsaR: Có, phạm vi () đưa ra điểm cuối "đúng", xem câu trả lời đã chỉnh sửa của tôi (và theo liên kết đến hàm) để biết thêm thông tin.
GreenMatt

1
Tôi có thể nói gì thêm điên rồ PHP hơn. :-) Không có ngôn ngữ nào khác mà tôi biết trong phạm vi () hoạt động theo cách này. (Chắc chắn là không, giả sử, Haskell hoặc Python.) Không Dijkstra viết gì về điều này?
ShreevatsaR

10
Sự điên rồ nằm trong sự không nhất quán của PHP. phạm vi ('A', 'CZ') hoạt động hoàn toàn khác với gia số ++ và mảng kết quả sẽ chỉ chứa ba giá trị: A, B và C.
Mark Baker

35

Những người khác đã nói tại sao PHP không hiển thị những gì bạn mong đợi. Đây là cách bạn nhận được kết quả mà bạn có thể muốn:

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

2
Không cần thiết. bạn hoàn toàn không cần thực hiện lệnh (), chỉ cần so sánh chính xác để chấm dứt vòng lặp
Mark Baker

2
+1 Dễ hiểu hơn nhiều khi không quen thuộc với một trong những tính năng lập dị hơn của PHP.
lonesomeday

1
Đây là một ví dụ tuyệt vời về mã tự viết tài liệu. Có thể dễ dàng hiểu chính xác b / c nó sử dụng các giá trị thứ tự và sau đó hiển thị biến dưới dạng một ký tự. Vòng lặp for sẽ hiệu quả hơn nếu thử nghiệm cho giá trị tối đa chỉ được xác định một lần như sau: "for ($ i = ord ('a'), $ max = ord ('z'); $ i <= $ max; $ i ++) {"
slevy1


4

Hãy thử mã này. Tôi nghĩ rằng mã này sẽ hữu ích cho bạn.

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

Hiển thị 26 chữ cái theo thứ tự.



2

Ngoài ra điều này có thể được sử dụng:

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

2

PHP có chức năng lặp các chữ cái và có thể vượt quá các ký tự đơn; phần còn lại sẽ được thực hiện theo cách này: aa ab ac ... zz, v.v.

Thử cái này:

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

0

Mặc dù các câu trả lời ở trên rất sâu sắc với những gì đang diễn ra và khá thú vị (tôi không biết nó sẽ hành xử như thế này và thật tốt để biết lý do tại sao.

Cách khắc phục dễ nhất (mặc dù có lẽ không có ý nghĩa nhất) sẽ chỉ là thay đổi điều kiện thành $ i! = 'Z'

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

4
Lưu ý rằng điều này sẽ chỉ cung cấp cho bạn một y, không phải z
Mark Baker

doh! vâng, điểm tốt. Tôi có thể thấy logic đằng sau cả tăng và so sánh, nhưng chắc chắn là lạ khi đôi khi $ a ++ <$ a
jon_darkstar

0

PHP không xem xét 'AA' ít hơn 'Z'. Cách tốt nhất để thực hiện điều này là:

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

abcdefghijklmnopqrstuvwxyz


0

Có lẽ mã này sẽ hoạt động. Thật dễ dàng và có thể hiểu được:

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

trong đó 26 là tổng số chữ cái trong bảng chữ cái.


-3

Wow Tôi thực sự không biết về điều này nhưng nó không phải là một mã lớn, bạn có thể thử echo "z" sau vòng lặp Mark is Hoàn toàn đúng Tôi sử dụng phương pháp của anh ấy nhưng nếu bạn muốn thay thế thì bạn cũng có thể thử

<?php
for ($i = "a"; $i = "y"; $i++) {
    echo "$i\n";
    if ($i == "z") {}
}
echo "z";
?>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.