next ve prev algoritmaları

C++11 standartları ile kapatılan eksikliklerden biri de next ve prev algoritmaları. Adımlayıcılar (iterator) üzerinde çalışan bu algoritmaları anlayabilmek için önce ihtiyaç noktasını görmemiz gerekiyor. Elimizde aşağıdaki gibi bir kap olsun:

Bu kabın tuttuğu tüm öğeler üstünde bir algoritmayı koşturmak için begin ve end işlevlerinden alacağımız adımlayıcıları kullanmamız gerekir, değil mi?

Yukarıdaki deyimde standart for_each algoritmasıyla ivec isimli vector nesnesinde tutulan tamsayıların hepsini iki katına çıkartmış oluyoruz.

Peki ya, vector‘ün tüm öğeleri için değil de belirli bir aralığı üstünde bir algoritmayı koşturmak istersek ne yapacağız? Bu amaçla adımlayıcı aritmetiğinden faydalanabiliriz. Örneğin ilk ve son öğe haricindeki tüm öğeleri içeren aralık üstünde işlem yapmak istediğimizi düşünelim:

Eğer kabımız bir vector ise bu işlemde bir sorun yok. Çünkü vector kabının adımlayıcıları tamsayı ile toplama arayüzünü de sunan “random acces iterator” kategorisinde.

gibi bir ifadeyle ivec kabında tutulan n indisli öğenin konumunu tutan bir adımlayıcı elde edebiliyoruz.

Peki kabımız bir list nesnesi olsaydı?

kodumuz geçerli değil. Çünkü “bidirectional iterator” kategorisinde  olan list sınıfının adımlayıclarının arayüzünde toplama işlemi yok. Şöyle bir kod yazabiliriz:

<iterator> başlık dosyasında bulunan next ve prev algoritmaları bu tür durumlarda işimizi bir hayli kolaylaştırıyor. Şimdi her iki algoritmayı da inceleyelim:

İşlevimiz birinci parametresi bir adımlayıcı istiyor. İşlevin değerle çağrıldığına (call by value) dikkat edin. İşlevin 2. parametresine belirlenen adımlayıcı konumundan kaç sonraki konumu elde etmek istiyorsak o tamsayıyı geçiyoruz. İkinci parametrenin varsayılan argüman olarak 1 değerini aldığını görüyorsunuz. Yani ikinci parametreye bir arguman gönderilmez ise işlevden geri dönüş değeri olarak bir sonraki öğenin konumunu tutan bir adımlayıcı elde ediyoruz. iter, “forward iterator” arayüzüne sahip bir adımlayıcı olmak üzere

ifadesi ile iter konumundan bir sonraki öğenin konumunu elde ediyoruz.

ifadesi ile iter konumundan n sonraki öğenin konumunu elde ediyoruz.

next işlev şablonunun gerçekleştirimi aşağıdaki gibi olabilir:

Standart advance algoritmasının referans yoluyla aldığı adımlayıcıyı n pozisyon ilerlettiğini hatırlayalım. Eğer n negatif bir tamsayı ise işleve gönderilen adımlayıcı n pozisyon eksiltiliyor.

Gelelim prev algoritmasına. Bu algoritma ile bir adımlayıcı konumundan n önceki konumu elde ediyoruz:

Adımlayıcılar üzerinde eksiltme işlemi yapabilmek için adımlayıcının en az “bidirectional iterator” kategorisinde olması gerekiyor. iter, “bidirectional iterator” arayüzüne sahip bir adımlayıcı olmak üzere

ifadesi ile iter konumundan bir önceki öğenin konumunu elde ediyoruz.

ifadesi ile iter konumundan n önceki öğenin konumunu elde ediyoruz..

next ve prev algoritmalarını kullanarak bir kap içinde tutulan öğelerin herhangi bir aralığı üstünde işlem yapabiliriz. Daha önce yazdığımız geçersiz koda geri dönelim:

Yukarıdaki kodda

ifadesi ile ilist kabında tutulan ikinci öğenin konumunu

ifadesi ile kapta tutulan son öğenin konumunu elde ediyoruz. for_each algoritmasıyla ilist listesindeki ilk ve son öğe haricindeki tüm öğeleri 2 katına çıkartmış olduk.

next ve prev algoritmalarıma geçersiz bir adımlayıcı konumunun geçilmesi çalışma zamanı hatasına neden oluyor. Eksiltme ya da artırma sonucu geçersiz bir konumun elde edilmesi yine çalışma zamanı hatası. Her iki durumda da bir hata nesnesi (exception) gönderilmediğini hatırlatalım.

Necati Ergin

C ve Sistem Programcıları Derneğinde eğitmen olarak çalışıyor.

Bunlar da ilginizi çekebilir

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Kod Eklemek İçin Okuyun