Amiga Dünyası sayı 6, sayfa 38

Bu sayfadaki yazılar

Sayfanın metni

Sayfa 38

DİLLER

Nerede kalmıştık? Aaaa, Evet! Fonksiyonları inceliyorduk. (Unutmadan dergi artık Amiga ile baskıya hazırlandığından "\" karakteri sorunu da kapanmış oldu.)

Son olarak, bir fonksiyonun kendisini çağıran fonksiyona bilgiyi geri gönderme metodlarını incelemiştik. Bu sayıda ise, fonksiyonların argümanlarıyla ilgili biraz teknik ve açıklayıcı bilgiden sonra karakter dizilerini inceleyeceğimizi belirteyim.

ARGÜMANLAR VE DEĞER OLARAK ÇAĞRILMALARI C dilindeki fonksiyonların en önemli parçası olarak gösterebileceğimiz argümanların, diğer dillere yabancı bir özellikleri var. Bu özellik diğer birçok dilin aksine, C'de argümanların değer olarak fonksiyona çağrılmaları. Değer olarak çağrılmayla anlatılmak istenen olgu şu: Bir fonksiyona bir argüman geçirildiğinde, o argümanın geçici bir kopyası alınır ve işlemler bu kopya üzerinde yapılır. Böylece argümanın kendisi değil, değeri işlemlere girer. Diğer birçok dilde ise argümanların adresleri fonksiyonlara geçirildiğinden, onlar üzerinde yapılan her işlem argümanın kendi değerini de etkiler. Diğer dillerin uyguladığı yönteme, adresle çağrılma denmekte.

Bu iki metod arasındaki en önemli fark, C dilinde hiçbir fonksiyonun argümanları üzerinde bir değişiklik yapamaması. Fonksiyonlar sadece o argümanın kopyası üzerinde değişiklik yapabildiklerinden, bir argüman fonksiyona hangi değerle yollandıysa (Yollayan kim mi? Tabii ki fonksiyonu çağıran diğer fonksiyon -hatırlarsanız C dilinde bütün programlar fonksiyonlardan oluşmaktaydı ve main bile aslında özel adlı bir fonksiyondu-), o değerle geri döner.

Değerle çağırma ilk bakışta anlamsız gibi görünse de genellikle programların daha kısa, daha az değişken kullanılarak yapılabilmesine olanak tanır. Çünkü fonksiyonlardaki argümanlar, değerlerinde bir değişme olacağı korkusu olmadan aynı isim altında kullanılabilirler. Örneğin aşağıdaki satırlarda power fonksiyonunun değer ile çağrılma yöntemini kullanan bir versiyonu bulabilirsiniz.

power(x,n) int x,n;

{

intp;

for(p=l;n>0;--n)

p=p*x; return(p);

}

Burada n adlı argümanın bir kopyası işlemlerde kullanılmıştır. İşlem sırasında, n sıfır olana kadar devamlı bir eksiltilmiştir. Dolayısıyla fonksiyonun içinde sayaç görevini üstlenmek için yeni bir değişken tanımlamaya gerek kalmamıştır. Çünkü fonksiyon n değişkeninin asıl değerini etkileyemeyeceğinden, n kullanılması değerin yitirilmesi gibi bir sonuca yol açmayacaktır.

Doğal olarak, gerektiğinde argümanlarının değerini değiştirebilecek fonksiyonlar yazmak da olasıdır. Değişkeni çağıran fonksiyona geçiren program parçası eğer değişken yerine, değişkenin adresini verirse (teknik olarak bir değişkenin adresine verilen isim pointer'dır (İng. gösterici)), program bu adres üzerinden giderek o değişken üzerinde değişiklik yapabilir. Doğal olarak eğer değişken yerine adresi yollanıyorsa fonksiyonda tanımlamalar sırasında o argüman bir değişkene pointer olarak tanımlanmalıdır. Herhangi bir fonksiyon, bir değişkenin adresini bilirse bu adres yardımıyla onun değeriyle dolaylı yoldan oynayabilir.

Eğer fonksiyon argümanlarından biri bir dizinin adıysa, fonksiyona girilen değer aslında o dizinin adresidir. Dolayısıyla fonksiyonlara geçirilen bir dizi için değer olarak çağrılma değil, adres ile çağrılma durumu geçerlidir. O zaman eğer fonksiyon dizinin elemanları üzerinde bir değişiklik yaparsa, değişiklikler dizinin elemanlarını etkileyerek değerlerini değiştirebilirler.

KARAKTER DİZİLERİ C dilinde en çok kullanılan dizi türü, belki de karakter dizileridir. Bu tür dizileri ve fonksiyonların onlar üzerindeki etkilerini görmek için, okuduğu satırlar içinden en uzun olanını seçen bir program hazırlayalım. Programın temel hatları oldukça kolay tasarlanabilir:

while(her satır daha varken)

if(o anki satır o ana kadarki en uzun satırdan daha uzunsa)

o satırı ve uzunluğunu sakla en uzun satırı ekrana yaz

Bu temel adımlardan da anlaşılabileceği gibi program parçalara kolaylıkla ayrılabilir. Bir parça yeni satırı okumakla, diğer bir parça onu test etmekle, bir sonraki onu bir yerde saklamakla ve kalan parçada işleyişi kontrol etmekle görevlendirilebilir.

Parçalar oldukça güzel bir biçimde birbirinden ayrılabildiğinden, programı parçalara ayırarak yazmak da oldukça iyi olacaktır. Bunun için önce girişteki bir sonraki satırı okuyan getline adlı bir fonksiyon -ki bu fonksiyon getchar fonksiyonunun genelleştirilmiş halidir- yazalım. Fonksiyonu başka programlarda da kullanabilmek için yazım sırasında fonksiyonun birkaç amaca uygulanabilir şekilde yazılmasına dikkat etmek gerekir. Bu fonksiyon en azından dosya bitimini sezebilmeli, daha genel olarak da okuduğu satırın uzunluğunu çağrıldığı yere geri gönderebilmelidir. Eğer yeni bir satır okuma sırasında dosya bitimi mesajı (EOF) alınırsa, program satır uzunluğu olarak sıfır'ı çağırana gönderecektir. Sıfır hiçbir zaman olası bir satır uzunluğu olamaz, çünkü bir satır en azından yeni satır karakterini ("\n") içermek zorundadır. Sadece "\n" karakterinden oluşan bir satırın uzunluğu bile bir olacaktır. Buradan da anlaşıldığı gibi karakterler arasında görülemeyen olanlar da sayılmaktadır ("\n"-yeni satır, "\t"-tab karakterleri gibi).

O ana kadarki en uzun satırdan daha uzun bir satır bulduğumuzda, o satırı mutlaka bir yerlere kaydetmeliyiz (burada kaydetmeyle diskete kaydetmek değil, bellekte bir bölgeye yerleştirme işlemini anlatmak istiyorum.). Bu gereklilik, copy isimli, görevi o anki en uzun satırı güvenilir bir yerde saklamak olan bir fonksiyon yardımıyla çözülebilir.

Son olarak tüm bu parçaların toplanacağı ve programın çalışmasının kontrol edileceği ana bir programa gerek duyulmaktadır.

Bu gerekliliklere göre yazılan programı birinci kutuda bulabilirsiniz.

Programdaki main ve getline fonksiyonları birbirleriyle bir çift argüman ve return komutuyla yollanan bir değer yardımıyla haberleşmektedir, getline fonksiyonunda, argümanlar

char s[]; int lim;

deklarasyonları ile tanımlanmaktadır. Burada birinci argüman bir dizi, ikinci argüman ise bir integer (Tk. tamsayı) olarak tanımlanmıştır, s dizisinin uzunluğu deklarasyonda yer almamıştır. Çünkü bu dizinin uzunluğu main fonksiyonunda belirlenmektedir, getline return komutunu main'e bir değer yollamak için kullanmaktadır. Görüldüğü gibi bazı fonksiyonlar bazı yararlı değerleri çağırıcılarına yollarken, copy fonksiyonu örneğinde olduğu gibi sadece yaptığı iş için kullanılan ve kullanışlı hiçbir değeri çağırana göndermeyen fonksiyonlar da vardır.

getline fonksiyonu 0 karakterini (null karakteri ki bu karakterin değeri sıfırdır), yarattığı dizinin sonuna; dizinin bittiğini belirtmek için koymaktadır. Bu metodu C compiler'ının kendisi de kullanmaktadır. Öyle ki, eğer compiler programın içinde;

Klavyeyle gezinmek için ← ve → tuşları.