string sınıfında silme işlemleri

Bu yazımızın konusu string sınıfında silme işlemleri
Standart string sınıfının erase işlevi 3 ayrı imzayla yüklenmiş:

Üç işlevi de ayrıntılı olarak inceleyeceğiz. Önce işlevlere şöyle genel olarak bir bakalım:

İşlevin geri dönüş değeri *this nesnesi. Yani işlevimiz üzerinde silme işlemi yapılan string nesnesinin kendisini döndürüyor. Bu işlev ile bir yazının dilediğimiz bir parçasını silebiliriz.  İşlevin birinci parametresi silinecek yazı parçasının başladığı yerin indisi, ikinci parametresi ise silinecek parçanın uzunluğu. İkinci parametre için varsayılan arguman kullanılırsa  verilen indisten  başlayarak yazının geri kalan tüm karakterleri siliniyor. Birinci parametreye varsayılan arguman geçildiğinde ise silme işlemi  0 indisinden başlatılıyor. İşlevin her iki parametre değişkeni de varsayılan arguman (default argument) aldığından aslında bu işlevi üç ayrı işlev olarak düşünebiliriz:

Birinci işlev ile yazının tamamını,
İkinci işlev ile yazının idx indisli karakterinden başlayan geri kalan kısmını,
Üçüncü işlev ile yazının idx indisli karakterinden başlayan len uzunluğundaki parçasını silebiliriz.
Aşağıdaki koda bakalım:

İkinci işlevimiz aslında STL kaplarındaki temel silme işlevlerinden biri. string‘in de tam uyumlu bir STL kabı olduğunu hatırlayalım.

Bu işlev ile herhangi bir adımlayıcı konumundaki karakter silinebilir:

Yukarıdaki kodda s string nesnesinin tuttuğu yazının ilk ve son karakterleri siliniyor.

Üçüncü işlevimiz de STL kaplarının hemen hepsinde olan bir silme işlemlerinden biri. Bu işlev kap içindek bir aralığı (range) siliyor.

Aşağıdaki kodda bir stringin tuttuğu yazının ilk ve son karakterleri dışındaki tüm karakterleri siliniyor:

Adımlayıcı parametreli silme işlevlerini geri dönüş değerleri yine adımlayıcı. Bu işlevler eğer en az bir karakter silinmiş ilk öğenin silme işleminden önceki konumunu döndürüyorlar:

Yukarıdaki kodda “kesin” yazısından silinen “esi” yazısının yerine ‘a’ karakteri ekleniyor.

Yazıdan tek bir karakter silmek için hem indis parametreli hem de adımlayıcı parametreli işlevler çağrılabilir.  string sınıfının adımlayıcıları random acces iterator kategorisinde olduğu için toplama çıkarma işlemleriyle adımlayıcı değerinden indis değerine indis değerinden adımlayıcı değerine geçilebilir. s bir string nesnesi olmak üzere s nesnesinin tuttuğu yazının  idx indisli karakterine ilişkin adımlayıcı

değerindedir. Yine iter, s stringinin tuttuğu yazıda bir konumu göstermek üzere bu konuma ilişkin karakterin indisi

değerindedir.

yazıdan istenen bir karakteri silmek

Yazıdan istenen belirli bir karakteri silmek için string sınıfının find işlevi ile karakter aranır. find işlevi, aranan karakter bulunursa aranan karakterin indisini döndürür. Aranan karakter bulunamaz ise işlevin geri dönüş değeri string::npos değeridir. Aranan karakterin bulunması durumunda string sınıfının size_type parametreli işleviyle ya da  adımlayıcı parametreli işleviyle yazıdan bulunan karakter silinebilir.

Yazıdan belirli değerdeki tüm karakterleri silmek ya da belirli koşulları sağlayan tüm karakterleri silmek için remove – erase idiyomu kullanılabilir:

Aşağıdaki kodda ise yazıdaki tüm rakam karakterlerinin silinmesi için remove_if algoritması kullanılıyor:

STL’in remove, remove_if, unique isimli silme işlevleri gerçek silme işlemi yapmazlar.  Bu işlevler aldıkları aralık içinde yalnızca silinmemiş öğelerin bulunduğu bir aralık oluşturacak şekilde kap öğelerini yeniden konumlandırırlar. Bir kaptan öğe silmenin tek yolu kabın silme işlemi yapan üye işlevlerini çağırmaktır. Parametre değişkenleri adımlayıcı olan STL algoritmalarının kapların silme işlevlerini çağırması mümkün olmadığından gerçek silme işlemi yapmaları da mümkün değildir.  Bu işlevler geri dönüş değerleriyle “logic end” konumu döndürürler.  logic end konumu silinmemiş öğelerin yer aldığı aralığın end konumudur. Böylece bu algoritmalara çağrı yapan kodlar dilerlerse silinmesi istenen öğelere silinmiş muamalesi yaparak gerçek silme işlemi yapmadan silinmemiş öğeleri kullanabilir. Gerçek silme işlemi için string sınıfının aralık (range) parametreli erase işlevi (logic end – gerçek end) aralığıyla çağrılmalıdır.

Yazının tamamını silmek

Bir string nesnesini boşaltmanın yani string nesnesinin tuttuğu yazının tamamını silmenin birçok farklı yolu vardır:

Standart string kütüphanesinde yazının başındaki ya da sonundaki boşluk karakterlerini silecek trim işlevleri yok. Şimdilik bu işlevleri yazmayı birer çalışma sorusu olarak okuyucuya bırakıyorum:

ltrim işlevi yazının başındaki boşluk karakterlerini silecek.
rtrim işlevi yazının sonundaki boşluk karakterlerini silecek.
trim işlevi hem yazının başındaki hem de sonundaki boşluk karakterlerini silecek.

Necati Ergin

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

Bunlar da ilginizi çekebilir

string sınıfında silme işlemleri” için 3 yorum

  1. Selamlar,
    string s5 = “Necati”;
    cout << "s5 capacity :" << s5.capacity() << endl;
    cout << "s5 size :" << s5.size() << endl;
    s5.clear();
    cout << "s5 capacity :" << s5.capacity() << endl;
    cout << "s5 size :" << s5.size() << endl;
    Yukarıda da yazının bir yerinde bahsettiğiniz gibi sadece kullanıcı tarafında silme(!) işlemi gerçekleştiriliyor. Arka planda memory managment söz konusu olduğunda string'in kapasitesi de düşürülmek istendiğinde ne yapılması gerekir Necati Bey.

    Not: s5.resize(5);
    s5.shrink_to_fit(); yapıldığında işe yaramadığı görüldü.

    1. Ne yazık ki bunu yapmanın garantili standart bir yolu yok.
      string sınıfının shrink_to_fit işlevine yapılan çağrı kapasiteyi büzmek konusunda bağlayıcı olmayan bir istek. Yani bu işlevin çağrılmasından sonra kapasite küçülmek zorunda değil. Ayrıca kapasitenin küçültülmesi durumunda bu işlem optimizasyon amacıyla geciktirilebilir. Ve son olarak kapasite büzme işlemi yeniden bellek edinimine neden olabilir. Ancak tipik olarak derleyicilerin hemen hepsi shirink_to_fit çağrısı karşılığında kapasiteyi büzüyor.
      Sizin verdiğiniz  örnekte muhtemelen sorun başka. Modern string implementasyonlarının çoğunda küçük yazı işlemlerinin daha verimli bir şekilde yapılabilmesi için string nesneleri doğrudan kendi içlerinde bir gösterici ve uzunluk tutan veri öğelerinin dışında bir de belirli uzunlukta (örneğin 16 karakterlik) bir bellek alanı tutuyorlar. Böylece küçük yazı işlemlerinde dinamik bir bellek alanı edinmeye gerek kalmıyor. Şu kodu derleyicinizde derleyip çalıştırın:

      Muhtemelen ekran çıktısı 24 olacak. Yani aslında küçük yazılar için bir dinamik bellek edinimi söz konusu değil.
      Bir de kapasitenin büzülüp büzülmediğini şu kodla test edin:

      1. shrink_to_fit işleviyle kapasiteyi küçültemiyorsanız bir de takas hilesini deneyebilirsiniz:

Bir Cevap Yazın

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

Kod Eklemek İçin Okuyun