Notlar:
- İşlev nerede bulduğu bilgisini döndürdüğüne göre 'return 0' yanıltıcı olacaktır. Bulunmadığında uint.max özel değeri döndürülebilir.
1.5) Konum gibi bilgiler için size_t daha uygun oluyor çünkü .length gibi nitelikler de o türdeler. uint veya int kullanmak istediğimizde hep öyle tür uyumsuzluklarıyla karşılaşıyoruz. O yüzden dönüş türü size_t olabilir.
-
Eğer bitUzunluk'un 32'den uzun olması bir hata ise işlev onu hata atarak baştan reddetmelidir. Bu tam std.exception.enforce'a göre bir denetim.
-
bitUzunluk'un denetimi uzunluk denetiminden önce uzunluk'un değerinin ayarlanması gibi bazı işlemler de var. Bence işlevin giriş koşullarının en başta yapılması daha temiz olur. (Hem de aslında sıfır kabul edilse de uzunluk'a yapılan iki atama işleminin masrafından kurtulunmuş olunur.)
-
Dilimleri 'ref' olarak geçirme konusunu konuşmuştuk. İşlev ancak çağıran taraftaki dilimde yapısal bir değişiklik yapacaksa 'ref' olarak almalıdır. (Burada "yapısal değişiklik" derken dilime eleman ekleme, eleman çıkartma, veya yepyeni elemanlara eriştirme gibi işlemleri kastediyorum. Yoksa asıl elemanları dilimler yoluyla değiştirebileceğimizi biliyoruz.)
Bunun dışındaki durumlarda dilimler rahatça değer olarak geçirilmelidirler. Hem zaten yalnızca iki üyeden oluşurlar (elemanları gösteren gösterge ve eleman adedi) hem de aslında değer olarak gönderildiklerinde işlev içindeki kullanımları 'ref' daha hızlı olur! :) (Çünkü 'ref' parametreler perde arkasında gösterge olduklarından dilim kullanılırken o gösterge üzerinden zıplanır.)
-
Aldığı dilimde değişiklik yapmayacağı için parametreyi 'const' olarak işaretleyebilir. Böylece değişebilen 'immutable' olan dilimlerle de çağrılabilir.
-
Yine for yerine foreach öneririm. Böylece i gibi değişken de gerekmemiş olur.
7)Bir grup kodun '// Maske oluşturuyoruz...' gibi açıklamalarla açıklanma gereği duyulmuşsa, o kodun maskeOluştur() gibi bir işleve taşınmalarının zamanı gelmiş demektir.
Bu konu "İşlevler" bölümünde ayrı bir başlık halinde de var:
http://ddili.org/ders/d/islevler.html
-
printf güvensizdir (programcı düzen belirteçlerini yanlış verebilir) ve yeteneksizdir (yalnızca temel türleri destekler).
-
Sonunda etkin kullanımını anladığımızı düşündüğümüz immutable anahtar sözcüğünü de serpiştirebiliriz. (Doğrusu çok uzun olduğu için beni biraz rahatsız ediyor. :( )
Bütün bunlara uygun olarak ve kendi sevdiğim gibi bol boşluklu olarak :):
import std.exception;
uint maskeOluştur(size_t uzunluk)
{
uint maske = 1;
foreach (i; 0 .. uzunluk) {
maske <<= 1; // sola bir bit kaydır
maske |= 1; // açılan yere 1 bitini yerleştir: 0 => 1
}
return maske;
}
size_t bitBul(int bitUzunluk, uint arananBitler, const ubyte[] veri) {
enforce (bitUzunluk <= 32, "Bit uzunluğu 32'den fazla olamaz");
immutable int uzunluk = (bitUzunluk == 0
? 32
: bitUzunluk);
immutable uint maske = maskeOluştur(uzunluk);
// Verileri alırken maskeliyoruz...
ushort kafa = 0;
foreach (i; 0 .. (veri.length * veriBitleri)) {
kafa <<= 1;
// [Ali] bitTest() size_t olarak alsaydı bu cast'e gerek kalmazdı.
// size_t türü ile ilgili söylediklerim bu gibi durumlarda
// ortaya çıkıyor.
if (bitTest(veri, cast(uint)i)) kafa |= 1;
kafa &= maske;
if (kafa == arananBitler) return i * veriBitleri;
}
return 0;
}
void main() {
ubyte[] veriler = [ 137, 1, 0]; // 0000_0000_1000_1001_0000_0001_0000_0000
//ushort aranan = 0b1000_1001_0000_0001; // dec(35073)
ushort aranan = 0b1001_0000_0001; // dec(2305)
writefln("Aranan %d, şurada bulundu: %d", aranan, bitBul (12, aranan, veriler));
}
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]