7. Bölüm
Erdem Taylan
Merhaba... Geçen ayki yazımın sonunda, bu ay external (Tk. dışsal) değişkenleri inceleyeceğimizi belirtmiştim. Şimdi, hazırsanız kaldığımız yerden devam edelim.
Önce altıncı sayının gözünüzün önünde olmasını sağlayın. Çünkü arada sırada bakmanız gerekecek.
Geçen ay birinci kutuda verilen programı incelerseniz, main fonksiyonundaki değişkenlerin (len. max. line vb.) sadece main'e özel veya onun içinde (İng. local) geçerli olduğunu farkedebilirsiniz. Başka hiçbir fonksiyon onlara direkt olarak ulaşamaz. Bu durum, diğer fonksiyonlar için de geçerlidir. Örneğin getline fonksiyonundaki i değişkeni ile copy fonksiyonundaki i, tamamen bağımsızdır ve birbirleriyle hiçbir ilişkileri yoktur. Her lokal değişken, içinde bulunduğu fonksiyonun çağrılması ile ortaya çıkar ve fonksiyondan çıkıldığında ortadan kaybolur. Dolayısıyla bu tür değişkenlere C dilinde otomatik değişkenler adı verilir.
Fonksiyonların çağrılıp bitişiyle otomatik değişkenler de ortaya çıkıp yok olduklarından, bu tür değişkenler fonksiyon her çağrıldığında yeniden eşlenmelidirler. Eğer bu değişkenler bir eşleme ile değere eşlenmezlerse, değerleri tahmin edilemeyen bir değer olabilir.
Otomatik değişkenlere bir alternatif olarak external (Tk. dışsal) olan değişkenler tanımlamak da olasıdır. Bu tür değişkenler, istenen her fonksiyon tarafından değiştirilebilir ve değerleri her zaman son işlemden sonraki halde kalır (Doğal olarak yeni bir işlem bu değeri değiştirebilir).
External değişkenler, mutlaka tüm fonksiyonların dışında tanımlanmalıdır. Bu tanımlama işlemi sonunda, değişkenler için bir bellek alanı da ayrılır. Değişken, onu kullanmak isteyen her fonksiyonun içinde de tanımlanmalıdır. Tanımlama işlemi, değişkenin başına extern deklerasyonunun yazılması ile yapılır. External değişkenleri daha iyi anlamak için, 6. sayıdaki 2. kutudaki en uzun satır programını line, save ve max değişkenlerini external değişken olarak kullanıp yeniden yazalım. Programın listesini kutu 1'de bulabilirsiniz.
main, getline ve copy fonksiyonlarındaki external değişkenler programın başındaki:
char line[MAXLINE]; char save[MAXLINE]; int max;satırları ile tanımlamaktadır. Bu tanımlamalarda, değişkenin bir türü verilmek zorundadır. Farkettiyseniz, external değişken tanımlamaları aynen otomatik değişken tanımlamaları gibidir. Bir fonksiyon, bir external değişkeni kullanmadan önce mutlaka değişkenin adını ve türünü bilmelidir. Bunu yapmanın bir yolu, değişken tanımlamasının başına extern yazarak onu fonksiyona tanıtmaktır ki, biraz önce de söylediğim gibi; bu işlem, extern ön eki hariç otomatik değişkenlerin tanımlanmasıyla aynıdır.
Bazı durumlarda (ki sizin yapacağınız birçok kısa program için bu geçerli) extern tanımlamaları yazılmayabilir. Hatırlayacağınız gibi, C dilinde bir program birçok parçadan oluşabilir ve bu bu parçalar ayrı ayrı compile edilip sonuçta birleştirilebilir. Eğer external değişken bir fonksiyonda kullanılmadan önce o program parçasında tanımlanmışsa, exter kelimesinin yazılmasına gerek yoktur. Dolayısıyla, program örneğimizdeki main, getline ve copy'deki extern tanımlamalarına aslında gerek yoktur. Eğer biz main'i ayrı, getline'ı ayrı, copy'yi ayrı compile etseydik, bu deklerasyonlar gerekli olacaktı. Tanımlayacağınız external değişkenleri, programın başında hiçbir fonksiyon onları kullanmadan tanımlamanız, programın anlaşılabilirliği açısından yararlı olacaktır.
Bu arada tanımlama (İng. declaration) ve eşleme (İng. definition) kelimelerinin arasındaki farkın anlaşılması oldukça önemli. Eşleme, bir değişken için bellekte bir yer ayrılmasına sebep olan işlem (a=3;); tanımlama ise, bir değişkenin sadece türünün tanımlanması, yani onun için bellekte bir yer ayrılmaması (int,a;) demektir.
Dikkat edileceği gibi, her değişkeni external yapmak sanki daha kolay gibi gözükmekte. Fakat aslında external değişkenlerin önemli dezavantajları var. Örneğin siz istemezseniz bile onlar hep oradadırlar. Bu programınızın kullanacağı belleği artırır. Ayrıca birbirinden bağımsız yapılabilecek fonksiyonlar external değişken kullanımı ile birbirine bağlanmakta, bu da fonksiyonların başka programlarda kullanılma şansını azaltmaktadır. Ayrıca uzun programlarda programın değiştirilmesi de daha zorlaşır. Böylece yazı dizimizin ilk bölümü olan C diline girişi bitirmiş olduk. Bu aşamada elinizden geldiği kadar çok alıştırma yapın (Aklınıza ne geliyorsa programlamaya çalışın). İkinci kutuda sizlere yardımcı olmak amacıyla birkaç örnek veriyorum. Başaramazsanız dergiye yazın, cevaplandıralım.
Yazı dizimiz bundan sonra daha hızlı bir şekilde C'nin derinliklerine doğru hareket edecek. Gelecek sayıda buluşmak üzere.
KUTU 1 1> Aşağıdaki programı yazıp Ram Disk'e kaydedin. /* K&R'ın kitabından alınarak Amiga'ya uyarlanmıştır. */ #define EOF-1 #define MAXLINE 1000 int max; /*O ana kadarki en büyük uzunluk*/ char line[MAXLINE]; /*O anki satır*/ char save[MAXLINE]; /*O ana kadar en uzun satır*/ main() { int len; /"O anki satır uzunluğu*/ extern int max; extern char save[]; max=0; while ((len=getline())>0) if (len>max) { max=len; copy(); } if(max>0) printf("%s",save); } getline() { int c; int i; extern char line[]; for(i=0;i<lim-1&&(c=getchar())!=EOF&&c!='\n';++i) line[i]=c; if (c=='\n') { line[i]=c; ++i; } line[i]='\0'; return(i); } copy() { int i; extern char line[], save[]; i=0; while((save[i]=line[i])!='\0') ++i; } 2> Şimdi programı "cc ram:program-ismi.c" ile compile edin. 3> Şimdi de "ln ram:program-ismi.o lc" ile link edin. 4> Programı çalıştırmak için ram:program-ismi yazın. Bu durumda program sizin klavyeden girdiğiniz karakterler üzerinde işlem yapacaktır. Bu moddan çıkmak için Ctrl-\ (Control ve ters bolü tuşlarına birlikte) tuşlarına basmalısınız. Eğer programa bir text dosyasından redirection (Tk. yeniden yönlendirme) verirseniz program text dosyasının bitimiyle beraber size yaptığı işlemlerin sonuçlarını yazacaktır.
KUTU 2 1> Girişindeki karakterleri çıkışına kopyalarken, rasladığı birden fazla boşluktan oluşan topluluğu, tek bir boşluk ile değiştiren bir program yazın. 2> Girişindeki kelimelerin uzunluklarını sayarak daha sonra o uzunlukla kaç kelime olduğunu yazan bir program yazın. (Örneğin, 3 tane iki harfli, 8 tane 3 harfli vb.) Programın çıktısı aşağıdaki gibi olmalıdır: Harf Sayısı Kelime Adedi 2 5 3 8 ... ... 3> Girişindeki dosyayı, küçük harflerden oluşan bir dosyayı çeviren bir program yazın. Program, küçült(c) isimli bir fonksiyon kullansın, ki bu fonksiyon eğer c bir harfse, onun küçük harf kodunu programa yollasın; harf değilse (rakam, yeni satır vb.), karakteri aynen programa geri yollasın. 4> Girişindeki dosyadaki boşlukları ve tabları silen bir program yazın. Eğer dosyada tamamıyla boş bir satır varsa, o satır da silinsin. 5> Daha önceden yazdığımız en en uzun satır programının main fonksiyonunu, satırların ve dosyanın uzunluğunda bir sınır olmayacak şekilde yeniden yazın. 6> Girişindeki dosyadaki tüm lab (\t) karakterlerini belirli uzunluktaki boşluklarla (örneğin her tab için 3 boşluk) değiştiren bir program yazın. 7> Bir C programındaki tüm comment (Tk. Açıklama) yok eden bir program yazın. 8> Bir C programındaki parantez, süslü parantez ve köşeli parantez eksikliklerinden doğan hataları bulan bir program yazın, bu arada eğer program çift tırnak ("), tek tırnak (') ve comment işaretlerini (/*) de kontrol ederse iyi olur. (Bu program tam anlamıyla yapıldığında size biraz zor gelebilir.) Başarılar.........