Mengapa alfabet terpecah menjadi beberapa rentang dalam kode C ini?

161

Di perpustakaan khusus saya melihat implementasi:

inline int is_upper_alpha(char chValue)
{
    if (((chValue >= 'A') && (chValue <= 'I')) ||
        ((chValue >= 'J') && (chValue <= 'R')) ||
        ((chValue >= 'S') && (chValue <= 'Z')))
        return 1;
    return 0;
}

Apakah itu telur Paskah atau apa keunggulan vs metode C / C ++ standar?

inline int is_upper_alpha(char chValue)
{
    return ((chValue >= 'A') && (chValue <= 'Z'));
}
Vladimir Ch.
sumber
Perhatikan bahwa dalam EBCDIC, kisaran karakter untuk huruf kecil datang sebelum rentang karakter untuk huruf besar, dan keduanya datang sebelum digit - yang persis kebalikan dari urutan dalam pengkodean berbasis ASCII (seperti 8859- x series, atau Unicode, atau CP1252, atau ...).
Jonathan Leffler
1
Catatan: jika 'J' - 'I'dan 'S' - 'R'keduanya sama 1, maka saya berharap pengoptimal yang masuk akal akan mengubah yang pertama di yang kedua.
Matthieu M.

Jawaban:

214

Penulis kode ini mungkin harus mendukung EBCDIC di beberapa titik, di mana nilai-nilai numerik dari huruf non-contiguous (ada kesenjangan antara I, Jdan R, Sseperti yang bisa Anda tebak).

Perlu dicatat bahwa C dan C ++ standar satunya jaminan bahwa karakter 0untuk 9memiliki nilai numerik bersebelahan justru karena alasan ini, sehingga tak satu pun dari metode ini adalah ketat standar sesuai.

Musim dingin
sumber
64
WTF sebenarnya adalah mengapa tidak penulis asli dimasukkan ke dalam komentar: // In the EBCDIC coding, the alphabet has gaps between these values. See URL: xxxx for details. Maka Anda bahkan tidak perlu mengajukan pertanyaan. Anda memiliki jawaban untuk kode tersebut.
abelenky
66
@abelenky Jika kode ini awalnya untuk sistem di mana ebcdic biasanya digunakan mungkin sudah tampak jelas pada saat itu dan tidak memerlukan komentar, sayangnya hal-hal yang tampaknya baik-baik saja dalam kode lama tampak aneh sekarang.
Vality
26
@abelenky: WTF yang sebenarnya adalah mengapa penulis aslinya tidak menggunakan fungsionalitas standar, yaitu return ( isalpha( chValue ) && isupper( chValue ) )...
DevSolar
4
@ Damon: Bukan itu masalahnya. Anda mungkin harus memproses pengkodean "alien" bahkan pada sistem yang tidak menggunakan pengkodean itu secara asli. Jadi Anda mengatur lokal Anda ke pengkodean yang diberikan, dan kemudian Anda harus tetap bersilang bahwa pemrogram benar-benar menggunakan fungsi standar daripada melakukan pengkodean "pintar" seperti di atas, berpikir dia tahu setiap pengkodean programnya akan pernah menemukan ...
DevSolar
6
Jika ditulis untuk mendukung EBCDIC dari tahun 1970-an, apakah isalpha dan bahkan lebih ANSI atau didukung oleh mayoritas kompiler saat itu?
nickalh
54

Sepertinya itu mencoba untuk menutupi EBCDIC dan ASCII. Metode alternatif Anda tidak berfungsi untuk EBCDIC (memiliki positif palsu, tetapi tidak ada negatif palsu)

C dan C ++ memang membutuhkan yang '0'-'9'berdekatan.

Perhatikan bahwa panggilan perpustakaan standar yang tahu apakah mereka berjalan di ASCII, EBCDIC atau sistem lainnya, sehingga mereka lebih portabel dan mungkin lebih efisien.

MSalters
sumber
5
std::isupper sebenarnya menanyakan lokal C global yang saat ini diinstal.
Lingxi
1
Ya kamu benar. Metode ini ditulis untuk menutupi kedua penyandian. Terima kasih atas jawabannya!
Vladimir Ch.
4
@ Lingxi: Benar, tetapi itu tidak berarti Anda dapat mengubah lokal dari ASCII ke EBCDIC. 'A'harus tetap 'A'terlepas dari lokal. ASCII ke UTF-8, itu mungkin saja terjadi.
MSalters
2
@ Lingxi: std::isupperkueri global C global yang saat ini diinstal, ya, tetapi fase kompilasi yang menafsirkan literal karakter tidak.
Lightness Races di Orbit
1
@ Lingxi - Hanya catatan cepat. Masih dipertanyakan apakah std::isupperbenar-benar dibutuhkan dalam banyak kasus. Itu menghormati lokal yang digunakan untuk input dari pengguna. Tetapi ketika mem-parsing file, berinteraksi dengan basis data Anda biasanya mengharapkan beberapa lokal lain. Terlebih lagi, setidaknya di Linux, panggilan lokal terkait ini sangat lambat - misalnya std::isalphapanggilan dynamic_cast dua kali untuk "menemukan" implementasi lokal yang tepat sebelum benar-benar membandingkan satu karakter.
ibre5041