Amiga C

5. Bölüm

Erdem Taylan

Geçen ay, bu ayki konumuzun diziler ve fonksiyonlara giriş olacağını belirtmiştim. O halde haydi dizileri incelemeye başlayalım.

DİZİLER

Basic'ten hatırlayacağınız gibi diziler, aynı türden birçok değişkeni bir tablo halinde bellekte tutmaya ve gerektiğinde, bu tablodan bazı parametreler (satır ve sütün numarası) verilerek değişkenleri kullanabilmeye yaramaktadır. Hemen hemen aynı dizi kavramı C dilinde de bulunmaktadır. Dizileri incelemek amacıyla geçen aylarda yaptığımız programların tümü gibi olan bir program yazalım. Bu program, girişindeki her rakamı, boşluk, tab, yeni satır karakterlerini ve bunların dışındaki karakterlerin sayısını saymaya yarayan bir program. Programın yazımı için lütfen birinci kutudaki adımları izleyin.

Programdaki;

int nba[10];
satırı, nba değişkeninin 10 elemandan oluşan veya boyutu 10 olan bir dizi olduğunu belirtir. C dilinde dizi indisleri sıfırdan başlar. Bu durum Basic ve Fortran gibi dillerin indis başlangıç değeri olan birden farklıdır. Yani nba dizisinin elemanları nba[0], nba[1], nba[2], ... , nba[9] adlı elemanlardır. Zaten for döngüsünden de bu durum anlaşılabilmcktedir. Çünkü for döngüsü sıfırdan ona kadar (on hariç) için çalışmaktadır.

Bir indis herhangi bir tamsayı değer olabilir. Dolayısıyla indis herhangi bir sabit sayı olabileceği gibi (nba[1]), herhangi bir tamsayı değişken de olabilir (nba[i]).

Program büyük ölçüde rakamların karakter olarak ifade edilmelerine bağlıdır. Örneğin:

if(c>='0'&&c<='9')
satırı, girişteki karakterin rakam olup olmadığını belirler. Eğer karakterse, nümerik değer karakterin değerinden '0' karakterinin değeri çıkarılarak bulunur. Böylece dizideki gerekli indis hesaplanmış olur ve program bu indisteki sayıyı bir artırma işlemini gerçekleştirmek için kullanır. Doğal olarak bu, ancak '0', '1', v.b. karakter değerlerinin pozitif ve birbirlerini izler şekilde olmaları sayesinde gerçekleşebilir. Bu varsayımlar, hemen hemen kullanılan bütün karakter setleri için doğrudur.

C dilinde tanım olarak, eğer karakterler ve tamsayılar arasında bir aritmetik işlem yapılıyorsa, bütün karakterler tamsayı kodlarına çevrilir ve işlem ondan sonra yapılır. Bu demektir ki, karakterler aritmetik işlemlerde birer tamsayıdan başka bir şey değildir. Bu oldukça doğal ve kullanışlıdır. Örneğimizdeki c-'0' aslında değeri sıfır ile dokuz arasında oynayan ve c karakterinin aldığı rakama göre değişen bir tamsayıdır. Böylece bir dizi indisinin sadece tamsayı olabileceği kuralı da sağlanmış olur. Çünkü, c-'0' değeri daha sonra nba dizisine indis olarak verilmektedir.

Girişteki karakterin türü:

if(c>='0'&&c<='9')
	++nba[c-'0'];
	else if(c==' '||c==''||c='\t') 
		++nb;
	else 
++nd;
testinde belirlenmektedir. Yazılış biçimi olarak:
if (koşul) 
	komutlar 
	else if(koşul) 
	 komutlar
		else
		   komutlar
yazımı, programlarda birkaç yönden test edilmesi gereken durumlarda oldukça sık kullanılmaktadır. Bu tür bir yazımın çalışma ilkesi şöyledir: Önce ilk koşul kontrol edilir. Eğer bu doğruysa, hemen sonraki komut veya komutlar grubu (komutlar grubu süslü parantezler içinde olmalıdır) çalıştırılır ve program testten çıkarak çalışmasına devam eder. Eğer bu koşul doğru değilse, ikinci koşul kontrol edilir, ikinci koşul doğruysa program ikinci if'ten sonraki komut ya da komutları çalıştırır ve testten çıkılarak programın çalışması devam ettirilir. Eğer ikinci koşul da yanlışsa, program ikinci else'den sonraki komut veya komutlar grubunu çalıştırır ve test bilmiş olur. İkinci else ve üçüncü komutlar bölümü yoksa (bu bölümler isteğe bağlıdır), hiçbir işlem yapılmadan testten çıkılır. Programlarınızın içinde islediğiniz kadar
else if( koşul) 
  komutlar
bölümü bulunabilir. Fakat benim size tavsiyem, buradakinden daha fazlasını kullanmamanız. Çünkü bu, programınızın anlaşılabilirliğini azaltacaktır.

FONKSİYONLAR

C dilindeki fonksiyon kavramı, Basic'teki subrutinlere benzer. Bir fonksiyon, bazı hesaplamaların programdan bağımsız bir yerde yapılabilmesine olanak tanıyan bir yapıdır. Fonksiyonların asıl amacı, karışık ve uzun problemlerin daha kolay ve kısa olan parçalara bölünmesi ve bütün parçaların birleştirilmesiyle kısa, hızlı, daha kolay bir yoldan çözülebilmesidir. Uygun düzenlenmiş fonksiyonlarla, bir işin nasıl yapıldığı önemsenmeyebilir. Yani, sadece sonuç olarak neyin gerçekleştiğini bilmek yeterlidir. C dili fonksiyonları iyi, kolay, uygulanma alanı çok ve kullanım faydaları fazla olacak bir şekilde işleyebilmek için dizayn edilmiştir. C dilinde, sadece birkaç satırdan oluşan fonksiyonlar oldukça sık görülecektir. Bunların amacı, programın daha rahat anlaşılmasını sağlamak, daha sonra program üzerinde yapılacak değişikliklerin kolaylıkla yapılabilmesi olanağını vermek ve bir fonksiyonun birden çok programda kullanılabilmesini sağlamaktır.

Şu ana kadar bizim için daha önceden hazırlanmış olan printf, getchar, putchar gibi fonksiyonları kullandık. Fakat hiç kendi yazdığımız bir fonksiyonu kullanmadık. Sanırım artık bunun zamanı geldi. Örnek olarak, C dilinde üs alma operatörü olmadığı için, verilen bir sayının tamsayı üssünü alan bir power(m,n) fonksiyonu yazmayı seçtik. Tabii ki bu fonksiyon, tüm üs alma işlemlerini yapamamaktadır. Çünkü üs değeri olarak sadece tamsayılar verilebilmektedir.

Şimdi, ikinci kutudaki ana programı ve altındaki power fonksiyonunu yazarak kutudaki adımlar yardımıyla programı çalışır hale getirin.

Programdaki main fonksiyonu, sadece power fonksiyonunu test etmek için kullanılmıştır. Çünkü bütün C programlarında programın çalışabilmesi için bir yerde mutlaka main fonksiyonu olmalıdır.

C dilindeki tüm fonksiyonlar aynı düzende yazılırlar:

fonksiyon-adı(eğer varsa argüman adları) 
  eğer varsa argüman tanımlamaları
{
  tanımlamalar 
  komutlar
}
	power fonksiyonu,

printif("%d &d %d",i,power(2,i),power(3,i));
satırında, iki defa çağrılmaktadır. Her çağrılmada, power fonksiyonuna iki tane argüman geçirilmektedir ve power fonksiyonu da sonuçla ana fonksiyona (main'e) bir sayıyı geri göndermektedir. power fonksiyonunun geri gönderdiği sayı, bir tamsayı olduğundan, printf'de %d yardımıyla basılabilmekledir. Doğal olarak C dilinde her fonksiyon mutlaka tamsayı bir değeri geri göndermek zorunda değildir. Fakat bunlarla ilgili bilgileri daha sonraki sayılarda size vereceğim.

power fonksiyonundaki argümanlar doğru olarak tanımlanmalıdırlar ki program tarafından doğru olarak kullandabilsin. Bu işlem;

int x,n;
satırı ile yapılmakladır. Argüman tanımlamaları, fonksiyon adı ve açma süslü parantezi ({) arasında yeralmalı ve her tanımlamanın sonuna, noktalı virgül konmalıdır. power'ın argümanları için kullanılan isimler (x, n) tamamen o fonksiyona aittir ve başka fonksiyonlar içinde bir karışıklık yaratmadan kullanılabilir. Bu aynı zamanda fonksiyonun içindeki i, p gibi değişkenler için de geçerlidir. Yani main fonksiyonundaki i değişkeni ile, power fonksiyonundaki i değişkeninin birbiri ile hiçbir ilgisi yoktur ve bu durum programın işlemesi açısından bir karışıklık yaratmaz.

power'ın hesapladığı değer, fonksiyona bir return komutu yardımıyla gönderilmektedir, return fonksiyonunun parantezleri içinde, herhangi bir ifade bulunabilir. Bir fonksiyon, mutlaka bir sayı geri göndermek (İng. return) zorunda değildir. Parantezleri içinde hiçbir ifade bulunmayan retum komutu, kontrolün çağırıcı fonksiyona dönmesini (doğaldır ki hiçbir değeri olamayan bir değerle) sağlar. Çağırıcı fonksiyona dönmenin bir başka yolu da, return komutu yazılmadan süslü parantez ile kapatmaktır.

Bu aylık da bu kadar. Gelecek ay fonksiyonların ve programımızın incelenmesine devam edeceğiz. Hogçakalın.


KUTU l 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 main() { intc,i,nb,nd; int nba[10]; nb=nd=0; for(i=0;i<10;++i) nba[i]=0; while((c=getchar())!=EOF) if(c>='0'&&c<='9') ++nba[c-'0']; else if(c==' '||c==''||c=='\t') ++nb; else ++nd; printf("basamaklar ="); for(i=0;i<10;++i) printf(" %d",nba[i]); printf("beyaz karakterler = %d",nb); printf(", diğerleri = %d",nd); } 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> Aşağıdaki programı yazıp, Ram Disk'e kaydedin. /* K&R'ın kitabından alınarak Amiga'ya uyarlanmıştır. */ main() { int i; for(i=0;i<10;++i) printf("%d %d %d",i,power(2,i),power(3,i)); } power(x,n) int x,n; { int ,,p; p=1; for(i=1;i<=n;++İ) p=p*x; return(p); } 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.