Mengapa kode ini tidak hanya mencetak huruf A hingga Z?

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

Cuplikan ini memberikan output berikut (baris baru diganti dengan spasi):

abcdefghijklmnopqrstu vwxyz aa ab ac ad ae af ag ah ai aj ak al am a ao ap aq ar as at au av aw ax ay az ba bb bc bd menjadi bf bg bh bi bj bk bl bm bn bo bp bq b bb bt bt bw bx oleh bz ca cb cc cd ce cf cg ch ci cj ck cl cm cn co cp cq cs ct cu cv cw cx cz cy dz dc dd de df dg dh di dj dk dl dm dn do dp dq dr ds dt du dv dw dx dy dz ea eb ec ed ee ef eg eh ei ej ek el em en eo ep eq er es et eu ev ew ev ... on to yz

Milan Babuškov
sumber
31
PHP bukan C, bahkan jika sintaks mencoba meyakinkan Anda sebaliknya.
joni
3
Ini bekerja untuk saya dengan perubahan yang sangat kecil: untuk ($ i = 'a'; $ i! = 'Aa'; $ i ++) {echo "$ i \ n"; }
Surreal Dreams
2
Komentar tentang PHP itu bukan C - adalah yang paling tajam, contoh: di c: char c = 'a'; tidak sama dengan di php:, $c = 'a';intinya adalah bahwa di C ada tipe char (karakter 1 simbol), tetapi tidak dalam PHP, jika U tell PHP $c = 'a';- berarti ini adalah string dengan hanya 1 karakter. Itu sebabnya Anda tidak dapat mengulang melalui 28 karakter secara memadai di PHP. Saya harap setiap programmer akan belajar bahasa tingkat rendah dan mengetik dengan kuat, tanpa melupakan praktik Matematika, yang akan membantu mereka menjadi lebih kuat.
Arthur Kushman
Wow itu sangat keren, Tapi mengapa itu tidak berhenti di "z"
Prasanth Bendra
Untuk mendapatkan titik akhir yang diharapkan dengan menggunakan kesetaraan ( ==atau !=), periksa jawaban ini untuk pertanyaan terkait .
IMSoP

Jawaban:

342

Dari dokumen :

PHP mengikuti konvensi Perl ketika berhadapan dengan operasi aritmatika pada variabel karakter dan bukan C.

Misalnya, di Perl 'Z'+1berubah menjadi 'AA', sedangkan di C 'Z'+1berubah menjadi '['( ord('Z') == 90, ord('[') == 91).

Perhatikan bahwa variabel karakter dapat bertambah tetapi tidak dikurangi dan meskipun demikian hanya karakter ASCII biasa (az dan AZ) yang didukung.

Dari Komentar: -
Perlu juga dicatat bahwa itu<=adalah perbandingan leksikografis, jadi'z'+1 ≤ 'z'. (Sejak'z'+1 = 'aa' ≤ 'z'. Tapi'za' ≤ 'z'adalah pertama kali perbandingannya salah.) Melanggar kapan$i == 'z'akan berhasil, misalnya.

Contoh di sini .

CMS
sumber
Hah..itu gila! Saya selalu menggunakan ord()jadi saya tidak pernah memperhatikan ini.
buka
68
Untuk kelengkapan, Anda juga harus menambahkan bahwa "<=" adalah perbandingan leksikografis, jadi 'z' + 1 ≤ 'z'. (Karena 'z' + 1 = 'aa'≤'z'. Tapi 'zz'≤'z' adalah yang pertama kali perbandingannya salah.) Melanggar ketika $ i == 'z' akan bekerja, misalnya.
ShreevatsaR
6
seperti yang dikatakan ShreevatsaR, ini adalah komparatornya, bukan aritmatika yang menjadi masalah, jangan fokus pada operator ++
slf
10
@ShreevatsaR: sebenarnya, 'yz' + 1 = 'za'. Perbandingan pertama yang gagal adalah 'za' <= 'z'
Milan Babuškov
2
Terima kasih atas komentar kalian semua! Ya, kuncinya adalah bahwa 'aa'secara leksikografis lebih kecil daripada 'z', itu sebabnya loop berlanjut. Dan itu berhenti 'yz'karena 'za'lebih besar dari z. Lihat contoh ini .
CMS
123

Karena setelah 'z' tercapai (dan ini adalah hasil yang valid dalam rentang Anda, $ i ++ menaikkannya ke nilai berikutnya secara berurutan), nilai berikutnya akan menjadi 'aa'; dan menurut abjad, 'aa' adalah <'z', jadi perbandingannya tidak pernah terpenuhi

for ($i = 'a'; $i != 'aa'; $i++) 
    echo "$i\n"; 
Mark Baker
sumber
55
Aneh bahwa 'z' ++ = 'aa', tetapi 'aa' <'z'. Logika itu tidak mengalir dengan baik.
Matthew Vines
19
@ Matius: Alfabetkan mereka. 'aa' akan didahulukan, jadi itu "kurang dari" string 'z'. Loop berakhir pada 'zz' karena itu abjad "lebih besar dari" (datang setelah) 'z'. Ini tidak logis dalam arti bahwa Anda dapat "meningkatkan" sesuatu dan mendapatkan nilai yang lebih rendah, tetapi itu logis dalam arti abjad.
eldarerathis
2
Incrementor karakter adalah Perl logika (lihat kutipan CMS dari dokumen). Perbandingan 'aa' <'z' adalah logika perbandingan string standar. Tidak aneh, begitu Anda mengerti cara menggunakannya ... dari jawaban di sini, banyak orang tidak.
Mark Baker
5
@eldarerathis Oh, saya benar-benar mengerti cara kerjanya. Saya merasa aneh pada saat bersamaan.
Matthew Vines
2
Ini sangat berguna bagi saya, bermain-main dengan kolom Excel yang mengikuti seri logis yang sama
Mark Baker
97

Jawaban lain menjelaskan perilaku yang diamati dari kode yang diposting. Berikut adalah salah satu cara untuk melakukan apa yang Anda inginkan (dan itu adalah kode bersih, IMO):

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

Menanggapi komentar / pertanyaan ShreevatsaR tentang fungsi rentang : Ya, ini menghasilkan "titik akhir yang tepat", yaitu nilai yang diteruskan ke fungsi berada dalam kisaran. Sebagai ilustrasi, output dari kode di atas adalah:

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
GreenMatt
sumber
2
Apakah range () termasuk titik akhir yang tepat? Dari pengalaman dengan bahasa lain, itu juga tidak terduga!
ShreevatsaR
1
@ShreevatsaR: Ya, range () memberikan titik akhir "benar", lihat jawaban saya yang diedit (dan ikuti tautan ke fungsi) untuk info lebih lanjut.
GreenMatt
1
Apa yang bisa saya katakan ... lebih PHP kegilaan. :-) Tidak ada bahasa lain yang saya ketahui dalam kisaran mana () berfungsi seperti ini. (Tentu saja tidak, katakanlah, Haskell atau Python.) Bukankah Dijkstra menulis sesuatu tentang ini?
ShreevatsaR
10
Kegilaan ada dalam inkonsistensi PHP. range ('A', 'CZ') bekerja sangat berbeda dengan ++ incrementor, dan array yang dihasilkan hanya akan berisi tiga nilai: A, B dan C.
Mark Baker
35

Orang lain sudah mengatakan mengapa PHP tidak menunjukkan apa yang Anda harapkan. Inilah cara Anda mendapatkan hasil yang mungkin Anda inginkan:

<?php
for ($i = ord('a'); $i <= ord('z'); $i++)
    echo chr($i);
?>
Filip Ekberg
sumber
2
Tidak perlu Anda tidak perlu melakukan ord () sama sekali, hanya perbandingan yang benar untuk mengakhiri loop
Mark Baker
2
+1 Jauh lebih mudah dipahami jika tidak terbiasa dengan salah satu fitur PHP yang lebih eksentrik.
lonesomeday
1
Ini adalah contoh yang sangat baik dari kode dokumentasi diri. Ini mudah dipahami tepatnya b / c menggunakan nilai-nilai ordinal dan kemudian menampilkan variabel sebagai karakter. For-loop akan lebih efisien jika pengujian untuk nilai maksimum ditentukan hanya sekali sebagai berikut: "untuk ($ i = ord ('a'), $ max = ord ('z'); $ i <= $ maks; $ i ++) {"
slevy1
22

Kenapa tidak pakai saja range('a','z')?

bcosca
sumber
4

Coba kode ini. Saya pikir kode ini akan membantu Anda.

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

Tampilkan 26 huruf secara berurutan.

Chinmay235
sumber
2
<?php

$i = 'a';
do {
echo ($j=$i++),"\r\n";
} while (ord($j) < ord($i));

?>
Tuan Griever
sumber
2

Ini juga dapat digunakan:

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

PHP memiliki fungsi pengulangan huruf dan dapat melebihi karakter tunggal; sisanya akan dilakukan dengan cara ini: aa ab ac ... zz, dan seterusnya.

Coba ini:

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

Sementara jawaban di atas sangat memahami apa yang terjadi, dan cukup menarik (saya tidak tahu itu akan berperilaku seperti ini, dan bagus untuk melihat alasannya.

Perbaikan termudah (meskipun mungkin bukan yang paling berarti) adalah dengan mengubah kondisinya menjadi $ i! = 'Z'

<?php
for ($i = 'a'; $i != 'z'; $i++)  
    echo "$i\n";
?>
jon_darkstar
sumber
4
Perhatikan bahwa ini hanya akan memberi Anda a ke y, bukan z
Mark Baker
lakukan! ya, poin bagus. Saya dapat melihat logika di balik kenaikan dan perbandingan, tetapi sungguh aneh bahwa kadang-kadang $ a ++ <$ a
jon_darkstar
0

PHP tidak menganggap 'AA' kurang dari 'Z'. Cara terbaik untuk melakukannya adalah:

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

abcdefghijklmnopqrstuvwxyz

Renato Cassino
sumber
0

Mungkin kode ini akan berfungsi. Mudah & bisa dimengerti:

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

di mana 26 adalah jumlah total huruf dalam alfabet.

Pengecualian
sumber
-3

Wow saya benar-benar tidak tahu tentang ini tetapi itu bukan kode besar Anda dapat mencoba gema "z" setelah loop Mark Benar-Benar Benar Saya menggunakan metodenya tetapi jika Anda ingin alternatif maka ini juga dapat Anda coba

<?php
for ($i = "a"; $i = "y"; $i++) {
    echo "$i\n";
    if ($i == "z") {}
}
echo "z";
?>
Mohit Bumb
sumber