standart giriş akımının tamponunun boşaltılması

C öğrenmekte olanların en çok sorduğu sorulardan biri bu? Standart giriş akımının tamponunu (buffer) nasıl boşaltabilirim? Soruya soruyla yanıt verelim: Neden standart giriş akımının tamponunu boşaltmak istiyorsunuz? Tipik senaryo şu: scanf ya da fgets işlevi ile bir giriş işlemi yapılır. Alınan karakterlerden bir kısmı kullanılır ama kullanılmayan karakterler tampon alanında kalır. Daha sonra çağrılacak başka bir giriş işlevinin önceki giriş işleminden kalabilecek çöpleri kullanması istenmez. Aşağıdaki koda bakalım:

Programı derleyip çalıştırdığınızda isminizi girebiliyor musunuz?

Aslında çoğu zaman çözüm giriş işleminin kontrollü bir şekilde yapılmasıdır. Yazının sonunda bu noktaya geri döneceğiz. Peki, standart girişi akımının tamponunda neden karakterler kalır? Farklı senaryolar söz konusu olabilir:
Giriş standart scanf işleviyle yapılmıştır ve (muhtemelen giriş scanf işleviyle yapılmamalıdır)

i) scanf tampondaki karakterlerden bir kısmını kullanır ama tampona giren fazladan karakterleri kullanmaz. Kullanılan karakterler tampondan çıkartılırken kullanılmayanlar tamponda kalır.
ii) Giriş scanf işlevinin istediği formatta değildir. scanf bu karakterle işini göremez. Karakterlere hiç dokunmaz, karakterler tamponda kalır.

Giriş standart fgets işleviyle yapılmıştır:

Kullanıcı girişi n değerine eşit ya da n değerinden daha fazla karakter içermektedir. Fazladan girilen karakterler tamponda kalır.

C’de giriş akımının tamponunu boşaltmanın standart bir yolu yok. Şimdi programcıların kullandıkları çok popüler olan bazı seçenekleri inceleyelim:

Bu yaygın bir idiyom. Standart giriş akımı için dosya konum göstericisi (file pointer) başa alınıyor. Bu çağrı aşağıdaki gibi de yapılabilirdi:

Belirli sistemlerde bu işe yarayan bir çözüm olsa da standart giriş akımı etkileşimli bir aygıta ya da bir pipe, soket gibi konumlandırma yapılamayacak bir birime bağlanmış ise tampon boşaltılamayabilir.

Ne yazık ki bu da çok yaygın bir idiyom. Standart fflush işleviyle standart giriş akımının tamponunu boşaltıyoruz. Ancak sistemlerin çoğunda bu çağrı iş görse de standartlara göre kod doğru değil. fflush işlevi çıkış akımları için hizmet veren bir işlev. Bir giriş akımı için kullanıldığında fflush işlevinin davranışı tanımlı değil.

Madem tamponu boşaltmanın standart bir yolu yok, biz onu kendi yazacağımız bir kod ile boşaltalım:

Standart giriş akımının tamponunda olan karakterlerin hepsini (standart giriş akımının tamponunda karakter olduğu sürece) temizliyoruz. Birçok noktada bu kodu yinelemek yerine bu işi yapan bir işlev tanımlayabiliriz:

Bu da iyi bir çözüm olarak görünmüyor. Kodlayıcı giriş işlemleri yapıldıkça flushline işlevini çağırmak durumunda kalacak. Bu da çok büyük olasılıkla beliri bir yerde gerçek kullanıcı girişinin de flushline işlevi tarafından yanlışlıkla giriş akımının tamponundan çıkartılması yani veri kaybedilmesi sonucunu doğuracak.
Başta da söylediğimiz gibi sorun tamponu boşaltmak istememizde değil, onu neden boşaltmak istediğimizde. Çözüm ne mi? Ya scanf işlevini hiç kullanmayın ya da yalnızca onu kullanın. scanf isminin de söylediği gibi (scan format) bir formatlı giriş işlevi. Çağırıcısından formatlı bir giriş bekliyor. Eğer standart giriş akımından gelecek karakterler için belirli bir format öngörülüyor ise giriş scanf ile yapılabilir. Ancak böyle bir durum söz konusu değilse giriş işlemini fgets ya da benzeri bir işlevle gerçekleştirip standart giriş akımından alınan yazıyı kendi beklentimiz doğrultusunda işlemek daha iyi bir seçenek olabilir. Eğer girişin scanf işleviyle yapılması zorunlu ise tüm giriş işlemlerinin uygun bir formatlamayla scanf işleviyle ele alınması daha iyi bir seçim olacaktır.

Necati Ergin

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

Bunlar da ilginizi çekebilir

standart giriş akımının tamponunun boşaltılması” için 2 yorum

  1. Hocam selamlar
    “Kodlayıcı giriş işlemleri yapıldıkça flushline işlevini çağırmak durumunda kalacak. Bu da çok büyük olasılıkla beliri bir yerde gerçek kullanıcı girişinin de flushline işlevi tarafından yanlışlıkla giriş akımının tamponundan çıkartılması yani veri kaybedilmesi sonucunu doğuracak.” kısmını anlayamadım. Bir senaryoda örnek kodla veri kaybolma kısmını açıklayabilir misiniz?

Bir Cevap Yazın

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

Kod Eklemek İçin Okuyun