Bu konuyu daha önce de konuştuk. string'in ve wstring'in elemanlarına doğrudan erişmek, sırasıyla UTF-8 ve UTF-16 kodlamalarının kod birimlerini verir. Oysa çoğu durumda harflerin kendilerini isteriz. İşin kötüsü, bu tür yanılgılar sonraki bir zamana kadar gözden kaçabilir.
Elimizde şöyle bir dizgi varsa:
string dizgi = "abcçd";
Oradaki ç iki char'dan oluştuğu için dizgi içinde alıştığımız gibi ilerlemek sorun oluyor.
D'de string ve wstring'e "dar karakter dizgisi" anlamında NarrowString deniyormuş (veya Phobos gelişirken onlara da bu yeni isim verilmiştir; emin değilim :)). Dar olmaları, dstring gibi 32 bit değil, sırasıyla 8 bit ve 16 bit olmalarından geliyor. İstenirse şablon yazarken isNarrowString ile hangi tür bir dizgiyle ilgilendiğimizi bilebiliyoruz. (isNarrowString, std.traits modülünde tanımlı.)
Örneğin yalnızca dstring ile çalışabilen bir algoritma bunu isNarrowString ile kısıtlayabilir:
import std.traits;
void foo(T)(T dizgi)
if (!isNarrowString!T) /* <-- "NarrowString değil ise" anlamında */
{
/* ... */
}
void main()
{
foo("bir dstring"d);
/* Bunlar derlenemezler çünkü foo() "narrow string" kabul etmiyor */
// foo("bir wstring"w);
// foo("bir string"c);
}
Neyse... asıl konu o değil. Ben dizgilerle ilgili küçük bir deneme daha yaptım ve dizgi elemanlarına erişme konusunda "stride ile foreach" yöntemini en uygun buldum:
import std.stdio;
import std.range;
void main()
{
string dizgi = "abcçd";
for_ile_indeks_kullanarak(dizgi);
foreach_ile_normal_olarak(dizgi);
for_ile_InputRange_gibi(dizgi);
foreach_ile_stride_kullanarak(dizgi);
}
void for_ile_indeks_kullanarak(string dizgi)
{
writeln();
writeln("for, Unicode kod birimlerine eriştirir:");
for (int i; i != dizgi.length; ++i) {
writeln(" ", dizgi[i]);
}
/* asıl dizgi tükenmez */
assert(!dizgi.empty);
}
void foreach_ile_normal_olarak(string dizgi)
{
writeln();
writeln("foreach, Unicode kod birimlerine eriştirir:");
foreach (karakter; dizgi) {
writeln(" ", karakter);
}
/* asıl dizgi tükenmez */
assert(!dizgi.empty);
}
void for_ile_InputRange_gibi(string dizgi)
{
writeln();
writeln("for ile InputRange aralığı gibi kullanınca"
" asıl karakterlere eriştirir:");
for ( ; !dizgi.empty; dizgi.popFront()) {
writeln(" ", dizgi.front);
}
writeln("Ama DİKKAT: Aralığın kendisi tükenir!");
writeln("Kalan uzunluğu: ", dizgi.length);
}
void foreach_ile_stride_kullanarak(string dizgi)
{
writeln();
writeln("foreach ve stride() en uygunu:");
foreach (karakter; stride(dizgi, 1)) {
writeln(" ", karakter);
}
/* asıl dizgi tükenmez */
assert(!dizgi.empty);
}
stride, dizgiyi Unicode karakterini oluşturan adımlar halinde ilerler. ASCII harflerde tek adım, ç için 2 adım, vs. stride'ın ikinci parametresi "harf adımı uzunluğunu" belirliyor. Örneğin stride(dizgi, 2) yazsaydık a, c, ve d'yi görürdük.
Çıktısı:
'for, Unicode kod birimlerine eriştirir:
a
b
c
?
?
d
foreach, Unicode kod birimlerine eriştirir:
a
b
c
?
?
d
for ile InputRange aralığı gibi kullanınca asıl karakterlere eriştirir:
a
b
c
ç
d
Ama DİKKAT: Aralığın kendisi tükenir!
Kalan uzunluğu: 0
foreach ve stride() en uygunu:
a
b
c
ç
d
'
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]
Permalink
Reply