Amiga C

29. Bölüm

Cenker Özkurt

Herkese selam! Bu aydan itibaren, Amiga intuition library üzerinde çalışmaya başlayacağız. Fakat bu ay intuition library'e geçmeden önce, özellikle yeni başlayan okuyucularımız için genel bir C tekrarı yapmayı düşündüm. Bunun amacı, geçmiş konularımıza bir göz atmak ve varsa eksiklerimizi kapatmak. Geçmiş konularımız derken, özellikle genel C dilinden bahsediyorum. C'nin genel yapısı, değişkenler, structure'lar, fonksiyonlar ve pointer'lar bu ayki tekrarlarımızı oluşturuyor.

Evet, şimdi tekrarımıza başlayabiliriz. C'de tekrar yaparken oldukça temelden ve kısa örneklerle ilerleyeceğiz. Bu arada yazımızı takip edenler, bu sayıda böyle bir yazı beklemiyorlardı sanırım. Fakat yeni başlayan arkadaşları da biraz olsun düşünmek lazım. Çünkü biliyorsunuz gelecek sayıda yeni bir konuya başlayacağız. En azından onlar da program hakkında az da olsa yorum yapabilsinler.

İlk olarak C'nin genel yapısını bir yorumlayalım isterseniz. Bu arada (Amiga Dos hariç) işletim sisteminin C dilinde yazıldığını tekrar hatırlatalım. Bu nedenle, böyle bir alette C diliyle çalışmak oldukça rahat oluyor. C'nin genel yapısını, kısaca modüler olarak tanımlayabiliriz. Rutin veya modüller bir kere hazırlandıktan sonra, devamlı kullanılabiliyor.

Amiga'nın rom'unu da aynı şekilde kullanabiliyoruz. Bildiğiniz gibi, Amiga Sistemi derken bu ROM'dan bahsediyoruz. Ayrıca Amiga sistemi Library'ler olarak kütüphanelere ayrılmış. Gelecek aydan itibaren, intuition library ile library'leri incelemeye başlayacağız.

Evet, şimdi C'nin genel yapısındaki değişkenler. C dilinde, birkaç veri tipi vardır. Bunlar:

char	 	-> 1 byte
int	 	-> 2 byte
short int 	-> 2 byte
long int	-> 4 byte
unsigned int	-> 2 byte
float		-> 4 byte
double  	-> 8 byte
Veri tiplerini C disketinizde #include dosyaları içerisinden 'exec/types.h' directory'sinden bulabilirsiniz. Bazı Macro değişken tipleri de burada tanımlanmıştır. Örneğin, APTR, BYTE, UBYTE gibi. Bu değişkenler, temel olarak yukarıda verdiğim tiplerden üretilir.

C'de bir değişken tanımlaması şöyle yapılır:

main()
{
  int a,b;

  a=5; b=a*5;
  printf("a=%d b=%d\n",a,b);
}
Yukarıda kısa bir C programı görüyorsunuz. main(), C'nin temel fonksiyonudur. Program her zaman için ilk olarak bu fonksiyona sıçrar.

Bu nedenle, her programda main() fonksiyonu bulunmalıdır.

main()
{
  int a;
  charc='a';

  printf("a=%d c=%c\n",a,c);
}
Bu örnekte, bir integer (tamsayı) ve char (karakter) tipinde iki veri tipi görüyorsunuz. Veri tanımlarken veri atama da yapılabiliyor, char c='a' buna bir örnek. Printf() fonksiyonu ise temel fonksiyonlardan ve ekrana bilgi göndermemizi sağlıyor. Tırnak işaretleri arasında yazılacak formu saptıyoruz. % işareti, bir komut niteliğinde ve arkasındaki karakter veri tipinin formunu belirliyor.

Bu formlar şöyle:

%o   ->  oktal tamsayı
%d   ->  desimal tamsayı
%x   ->  hex tamsayı
%c   ->  karakter
%s   ->  karakter dizisi
%f   ->  float noktalı sayı
Bu formlar aynı zamanda sprintf(), cprintf() gibi temel C fonksiyonlarında da kullanılmaktadır.
main()
{
  char s[10];
  float pi=3.1415;
  
  strcpy(s,"0123456789");
  printf("s=%s pi=%f\n",s,pi);
}
Benzer şekilde,
main()
{
  char x[30];
  char s[10]="0123456789";
  float e=2.7;

  sprintf(x,"s=%s e=%f\n",s,e);
  printf("%s",x);
}
Buradaki sprintf() fonksiyonu, printf() fonksiyonu gibi çalışmaktadır. Aradaki fark, printf() sonucu ekrana yazarken, sprintf() verilen değişkene yazmaktadır. Yukarıdaki programda 'x', verilen değişkendir. Ve uzunluğu en azından toplam form kadar olmalıdır.

C'de fonksiyon kullanımı da şu oluyor:

main()
{
  int a;
  
  a=min(10,9);
  printf("min=%d\n",a);
}

min(a,b) 
int a,b;
{
  int r;
  
  if(a<b) return(a); else return(b);
}
Yukarıdaki örnek, bir fonksiyon kullanımını gösteriyor. min() fonksiyonu, iki sayı arasından en küçüğünü bularak geri dönüyor. return() fonksiyonu, burada alt rutinden (istersek) bir değer ile geri dönmemizi sağlıyor. Yukarıdaki örnekte, aynı zamanda if-else ikilisini gördük. Şimdi bunları ve diğerlerini başka örneklerle inceyelim.

switch() fonksiyonu, temel C fonksiyonlarındandır. İfadenin değerine göre birden fazla satıra dallanmamızı sağlar.

main()
{
  int c;

  printf("Cevabınız?\n");
  c=getchar();
 
  switch(c) {
     case 'e': printf("Evet\n");
	break;
     case 'h': printf("Hayır\n");
	break; 
     default: printf("Cevap hatalı\n");
	break;
  }
}
case, default ve break switch() ile birlikte kullanılır. case'den sonraki ifade, verilen ifade ile (burada c) karşılaştırılır. Eğer eşitse, hemen yanındaki komut satırı veya break'e kadar olan komut satırları işlenir. İfade case'de verilenlerden farklıysa, default satırına geçilir.

Sıra geldi 'while' ve 'for' temel C komutlarına. Her iki komut da, C'de döngü kurmamızı sağlar.

Bir örnekle inceleyelim:

main()
{
  int i=0;

  while(i<100) {
    printf("%d\n",i);
  }
}
while, yanında verilen ifadenin doğruluğu sürdükçe döngüye devam eder.
main()
{
  int i;
 
  for(i=0;i<100;i++) {
     printf("%d\n",i);
  }
}
while ile yapılan programı, for ile yukarı olduğu gibi yazmak mümkün. Burada i<100, ana ifadeyi oluşturmakta. Yani bu ifadenin doğruluğu sürene kadar döngü devam eder. Eğer ikinci ifade kullanılsa 'for', sonsuz döngüye girer.
for(;;) {
  ..
}
Bir sonsuz döngü (infinite) oluşturur.

Temel fonksiyonlardan en çok kullanılanlardan do-while'ı bir inceleyelim. Kullanımı, while komutuna benzer. Program bir defalık döngüye girerek cümleyi işler ve daha sonra while'dan sonraki ifadenin doğruluğuna göre döngüye devam eder. Eğer ifade yanlışsa, sonuç olarak do'dan sonraki cümleler bir defalık bile olsa işlenmiş olur.

Bir örnekle inceleyelim:

main()
{
  int i=0;

  do {
     printf("%d=\n",i);
  } while(i<100);
}
program 100'e kadar sürer.

Goto, C dilinde de kullanılmakta ve bildiğiniz gibi program içerisinde herhangi bir ifadeye bağlı olmadan verilen etikete (label) sıçramayı sağlar.

main()
{
  int i=0;

  for(;;) {
     printf("%d\n",i);
     i++;
     if(i==100) goto end;
  }
 end:
  printf("Program sonu\n");
}
Bu temel komutların dışında, C'de önişlem komutları vardır. Bunlardan #include <dosya.h>, program compile edilmeden önce verilen dosya.h ismindeki dosya, disketinizdeki 'include' directory'si içerisinden yüklenerek compile edilir ve sonra programa geri dönülerek ana program compile edilir. Bu önişlem komutu, özellikle structure yapı tanımlamaları ve macro tanımlamaları için kullanılır. #define ise, macro tanımlamak için kullanılan bir ön işlem komutudur.

Kullanımı ise şöyledir:

#define printfi(i) printf("%d\n",i); 
#define printfc(i) printf("%c\n",i);

main()
{
  int i=5;
  char c='a';

  printfi(i);
  printfc(a);
}
Örnekten de anlaşılacağı gibi, #define ile printf() fonksiyonları tanımlanmakta. Burada C compiler programı, printfi(i) gördüğü yerde printf("%d",i); varmış gibi davranmaktadır. Oldukça kullanışlı bir fonksiyon.

Structure'lar ise, C'nin getirdiği avantajlardan bir tanesi. C dilinde çok kullanılan struct komutu, yapı anlamına geliyor ve birden fazla değişkeni bir grup ismi altında toplamamıza yarıyor. Bu sayede program içerisindeki değişkenlere, kullanım yerlerini daha rahat ayırt ederek ulaşabiliyoruz. Böylece hem programımızın anlaşılırlığı artıyor, hem de planlarken değişkenleri daha yerli yerinde kullanabiliyoruz.

Sonuç olarak yapılar, verilerin daha iyi organize edilmesini sağlıyor.

Bir örnekle devam edelim:

struct grup {
   int a;
   int b;
   char string[10];
} d1;

main()
{
   d1.a=10;
   d1.b=20;
   d1.string="0123456789";

   printf("a=%d\n",d1.a);
   printf("b=%d\n",d1.b);
   printf("string=%s\n",d1.string);
}
Yukarıdaki programda 'grup' bir yapı ismi, d1 ise bu yapının değişkeni olarak tanımlanıyor. İçerisindeki veri tipleri ise, yapının elemanlarını oluşturuyor. Yapı içerisindeki veri tiplerine erişebilmek için 'd1.a' yazı şeklini kullanıyoruz. Bu arada yapı tanımlamaları main() dışında tanımlanmak zorunda. Bu nedenle, biz de yapı tanımlamasını main'den önce yaptık.

Bu ay son olarak, C dilinde 'struct' kadar önemli ve çok kullanılan bir fonksiyon olan 'Pointer' mantığını hatırlayacağız.

Pointer'lar (işaret değişkenleri), kısaca bir değişkenin kullandığı adresi gösterir. Aynı zamanda bu adres ile de oynamamız mümkün. Normal olarak biz bir değişkenin adresini öğrenmek istediğimizde, '&' işaretini kullanırız. Örneğin 'x' değişkenin hafızada bulunduğu adresi, 'px' değişkenine aktarmak istediğimizde, 'px=&x' yazarız. Fakat burada 'x' değişkeninin adresi ile oynamamız mümkün değildir. Bu adres sabittir. Eğer böyle bir ihtiyacımız varsa, buradaki 'x' değişkenini pointer değişken olarak kullanabiliriz.

Kullanımını inceleyelim:

main() 
{
  int *x;
  
  x=0xbfe001;
  printf("x=%d\n",*x);
}
Dikkat ettiyseniz, pointer tanımlamasını '*x' şeklinde yaptık. Bu değişkenin gösterdiği adresi 'x', adresteki değeri ise '*x'ten öğrenebiliriz. Yukarıdaki programdaki 'x=0xbfe001' komutuyla, x değişkenine hex olarak 0xbfe001 adresi tanımlanmıştır. Bundan böyle x değişkeni artık 0xbfe001 adresini gösterecektir. Bu adresteki değeri okumak için de, *x'e bakabiliriz.

Evet, bu ayki tekrarımız burada sona eriyor. Umarım sizi eski konulara götürerek fazla sıkmamışımdır. Fakat gelecek ay yeni şeyler öğrenmeye devam edeceğiz. Gelecek aya buluşmak üzere hepinize iyi günler...