ทำไมรหัสนี้ไม่พิมพ์ตัวอักษร A ถึง Z


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

ตัวอย่างนี้ให้ผลลัพธ์ต่อไปนี้ (บรรทัดใหม่จะถูกแทนที่ด้วยช่องว่าง):

abcdefghijklmnopqrstu vwxyz aa ab ac โฆษณา ae af ag ai aj ak อัลฉันเป็น ao ap aq ar เป็นที่ au av aw ขวาน ay az บา bc bd เป็น bf bg bh bh bh bb bn bn bw bx โดย bz ca cb cc cd ce cf cg ci cj ck cl cm cn co cp cq cq cs ct ct ct ct cv cw cw cx cx cs c d da dd df dg dh d d d d d d d d d d d d d d du dv dw dx dy dz ea eb ec ed ee ef เช่น eh ei ej ek el em en eo ep eq er es et eu ev ew ex ... ไปที่ yz


31
PHP ไม่ใช่ C แม้ว่าไวยากรณ์พยายามโน้มน้าวคุณในทางตรงกันข้าม
joni

3
สิ่งนี้ใช้ได้กับฉันด้วยการเปลี่ยนแปลงเล็กน้อยมาก: สำหรับ ($ i = 'a'; $ i! = 'aa'; $ i ++) {echo "$ i \ n"; }
Surreal Dreams

2
ความคิดเห็นเกี่ยวกับ PHP นั้นไม่ใช่ C - เป็นตัวอย่างที่ดีที่สุด: ใน c: char c = 'a'; ไม่เหมือนกับใน php: $c = 'a';ประเด็นคือใน C มีประเภทของถ่าน (สัญลักษณ์ 1 ตัวอักษร) แต่ไม่ใช่ใน PHP ถ้าคุณบอก PHP $c = 'a';- หมายความว่านี่เป็นสตริงที่มีอักขระเพียง 1 ตัว นั่นเป็นสาเหตุที่ U ไม่สามารถวนซ้ำ 28 ตัวอักษรใน PHP อย่างเพียงพอ ฉันหวังว่าโปรแกรมเมอร์ทุกคนจะได้เรียนรู้ภาษาระดับต่ำและการพิมพ์ที่รัดกุมพร้อมกับมันโดยไม่ลืมเกี่ยวกับการฝึกฝนทางคณิตศาสตร์ซึ่งจะช่วยให้พวกเขาแข็งแกร่งขึ้น
Arthur Kushman

ว้าวนั่นเจ๋งจริงๆ แต่ทำไมมันไม่หยุดที่ "z"
Prasanth Bendra

สำหรับวิธีการรับ end-point โดยคาดว่าจะใช้ความเท่าเทียมกัน (ก==หรือ!=) ตรวจสอบคำตอบนี้ไปคำถามที่เกี่ยวข้อง
IMSoP

คำตอบ:


342

จากเอกสาร :

PHP เป็นไปตามแบบแผนของ Perl เมื่อจัดการกับการดำเนินการทางคณิตศาสตร์กับตัวแปรตัวอักษรและไม่ใช่ของ C

ตัวอย่างเช่นใน Perl 'Z'+1จะกลายเป็น'AA'ในขณะที่ใน C 'Z'+1กลายเป็น'['( ord('Z') == 90, ord('[') == 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

10
@ShreevatsaR: อันที่จริงแล้ว 'yz' + 1 = 'za' การเปรียบเทียบครั้งแรกที่ล้มเหลวคือ 'za' <= 'z'
Milan Babuškov

2
ขอบคุณสำหรับความคิดเห็นพวก! ใช่ประเด็นสำคัญก็คือ'aa'มันมีขนาดเล็กกว่าพจนานุกรม'z'ซึ่งเป็นสาเหตุที่วงยังคง และมันก็หยุด'yz'เพราะมีค่ามากกว่า'za' zตรวจสอบตัวอย่างนี้
CMS

123

เนื่องจากเมื่อถึง 'z' (และนี่คือผลลัพธ์ที่ถูกต้องภายในช่วงของคุณการเพิ่ม $ i ++ จะเพิ่มไปยังค่าลำดับถัดไป) ค่าถัดไปจะเป็น 'aa'; และตัวอักษร 'aa' คือ <'z' ดังนั้นการเปรียบเทียบจึงไม่เคยพบกัน

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

55
มันแปลกที่ 'z' ++ = 'aa' แต่ 'aa' <'z' ตรรกะนั้นไหลไม่ดีนัก
Matthew Vines

19
@ Matthew: เรียงตามตัวอักษร 'aa' จะมาก่อนดังนั้นจึงเป็น "น้อยกว่า" สตริง "z" การวนซ้ำจะสิ้นสุดที่ 'zz' เนื่องจากตัวอักษร "มากกว่า" (มาหลังจาก) 'z' มันไร้เหตุผลในแง่ที่ว่าคุณสามารถ "เพิ่ม" บางสิ่งบางอย่างและรับค่าที่น้อยกว่า แต่มันสมเหตุสมผลในแง่ของตัวอักษร
eldarerathis

2
ตัวเพิ่มอักขระคือตรรกะลอจิก (ดูเครื่องหมายคำพูดของ CMS จากเอกสาร) การเปรียบเทียบ 'aa' <'z' เป็นตรรกะการเปรียบเทียบสตริงมาตรฐาน ไม่แปลกเมื่อคุณเข้าใจวิธีใช้ ... จากคำตอบที่นี่ผู้คนจำนวนมากไม่
Mark Baker

5
@ Eldarathis โอ้ฉันเข้าใจได้อย่างแน่นอนว่ามันทำงานยังไง ฉันเพิ่งพบว่ามันแปลกในเวลาเดียวกัน
Matthew Vines

2
มันมีประโยชน์อย่างเหลือเชื่อสำหรับฉันเล่นกับคอลัมน์ Excel ที่เป็นไปตามชุดตรรกะเดียวกัน
Mark Baker

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 มากขึ้น :-) ไม่มีภาษาอื่นที่ฉันรู้ว่าในช่วงใด () ทำงานในลักษณะนี้ (ไม่แน่นอนว่า Haskell หรือ Python) Dijkstra ไม่ได้เขียนบางสิ่งเกี่ยวกับสิ่งนี้ใช่ไหม
ShreevatsaR

10
ความบ้าคลั่งอยู่ในความไม่สอดคล้องของ PHP range ('A', 'CZ') ทำงานต่างกันโดยสิ้นเชิงกับตัวเพิ่ม ++ และอาร์เรย์ผลลัพธ์จะมีค่าสามค่า: A, B และ C
Mark Baker

35

คนอื่นพูดแล้วว่าทำไม PHP ไม่แสดงสิ่งที่คุณคาดหวัง นี่คือวิธีที่คุณได้รับผลลัพธ์ที่คุณอาจต้องการ:

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

2
ไม่จำเป็น. คุณไม่จำเป็นต้องทำ ord () เลยเพียงแค่การเปรียบเทียบที่ถูกต้องเพื่อยุติลูป
Mark Baker

2
+1 เข้าใจได้มากขึ้นเมื่อไม่คุ้นเคยกับหนึ่งในฟีเจอร์ที่แปลกประหลาดของ PHP
lonesomeday

1
นี่เป็นตัวอย่างที่ดีของรหัสการทำเอกสารด้วยตนเอง มันเข้าใจได้ง่ายอย่างแม่นยำ b / c ใช้ค่าเลขลำดับแล้วแสดงตัวแปรเป็นอักขระ for-loop จะมีประสิทธิภาพมากกว่าหากการทดสอบค่าสูงสุดถูกกำหนดเพียงครั้งเดียวดังนี้: "สำหรับ ($ i = ord ('a'), $ max = ord ('z'); $ i <= $ สูงสุด; $ i ++) {"
slevy1


4

ลองรหัสนี้ ฉันคิดว่ารหัสนี้จะเป็นประโยชน์กับคุณ

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

แสดง 26 ตัวอักษรตามลำดับ




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
โปรดทราบว่านี่จะให้คุณกับ y ไม่ใช่ z
Mark Baker

DOH! ใช่จุดดี ฉันสามารถดูตรรกะที่อยู่เบื้องหลังทั้งการเพิ่มและการเปรียบเทียบ แต่แน่ใจว่าแปลกที่บางครั้ง $ a ++ <$ a
jon_darkstar

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

ว้าวฉันไม่รู้จริงๆเกี่ยวกับสิ่งนี้ แต่มันไม่ใช่รหัสขนาดใหญ่ที่คุณสามารถลอง echo "z" หลังจากวนรอบเครื่องหมายถูกต้องฉันใช้วิธีการของเขา แต่ถ้าคุณต้องการทางเลือกนี่อาจจะลองก็ได้

<?php
for ($i = "a"; $i = "y"; $i++) {
    echo "$i\n";
    if ($i == "z") {}
}
echo "z";
?>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.