C Programlama Dili'ne Giriş

  Dersler
* Önsöz

* Giriş
* Veri Tipleri, Değişkenler
* Operatörler
* Temel G/Ç Fonksiyonları
* Temel Kütüphane Fonksiyonları
* Karşılaştırma Deyimleri
* Döngüler
* Fonksiyonlar I
* Fonksiyonlar II
* Diziler
* Gösterici (Pointer) Kavramı
* Katarlar (Stringler)
* Dinamik Bellek Yönetimi
* Gösterici Uygulamaları
* Yapılar ve Birlikler
* Dosya Yönetimi
* Bit Düzeyinde Çalışmak
* Port Denetimi
* Grafik Kullanımı
* C Makroları

* Kısaca C++
* Derleme Seçenekleri
* Tarih-Saat Fonksiyonları
* Monte-Carlo Yöntemleri
* Fortran ve C

* Yararlanılan Kaynaklar

  C/C++ Derleyicileri
* Dev-C++
* Salford (silversoft FTN95)
* GCC
* Turbo C
* Eclipse IDE
* NetBeans IDE

  Dış Bağlantılar
* programlama.com
* C Programcıları Derneği

* C (wikipedia)
* C++ (wikipedia)
* cplusplus.com
* koders.com
* Hot scripts

 

Ders 9: Fonksiyonlar II (Alt programlar)

##################-- (%90)

En son güncelleme: Wed, 30 Nov 2011 13:22:02 +0200

Giriş

Bu kısımda, esnek argümanlı fonksiyonlar, main() fonksiyonu ve komut satırından main() fonksiyonuna parametre aktarımı incelenektir.


9.1   Esnek Argümanlı Fonksiyonlar

Aşağıdaki gibi üçüncü dereceden bir polinom düşünelim:

P(x) = a + bx + cx2 + dx3
burada a, b, c, d katsayıları gerçel sayı sabitleridir. Bu polinomu temsil eden en basit fonksiyon şöyle tanımlanabilir.
      double p(double x, double a, double b, double c, double d)
      {
         double p = a + b*x + c*x*x + d*x*x*x;
         return p;
      }

Buna göre, x = 1.7'de, P(x) = 1 - 2x değerini hesaplamak için bu fonksiyon aşağıdaki: gibi çağırılmalıdır:

      sonuc = p(1.7, 1.0, -2.0, 0.0, 0.0);
Burada, kullanılmayan katsayılar için 0.0 değeri mutlaka fonksiyona geçirilmelidir. Kullanılmayan argumanlar geçirilmeden de fonksiyonu çağırmak mümkündür. C++ ve Fortran 90'da olduğu gibi, C Programlama Dili kullanıcılarına argümanları esnek olarak geçirme imkanı verir. Bunun anlamı, belli kurallar sağlandığında, p() fonksiyonu aşağıdaki gibi çağrılabilmesidir:
              /*  x  a     b  */
      sonuc = p(1.7, 1.0, -2.0);
Esnek argümanlar için iki temel kural vardır:
  • Esnek argümanlar kullanımı isteğe bağlıdır.
  • Esnek argümanları oluşturan küme ardışık olarak listeye eklenmelidir.
Bu türden argümanlar, aşağıdaki gibi, fonksiyonun parametre listesi kısmında ... ile belirtilir.
      double p(double x, int n, ...)
      {

      }

Esnek Argumanlı Fonksiyon tanımlaması yapabilmek için stdarg.h kütüphanesinde üç tane makro fonksiyon tanımlanmıştır. Bu fonksiyonlar Tablo 9.1'de listelenmiştir.

Tablo 9.1: stdarg.h'te tanımlı tip ve makro fonksiyonlar
Tip / Fonksiyon Açıklama
va_list Ardışık esnek argümalar için tip belirleyici
va_start(ap, n) va_list tipinde bildirilmiş ap göstericisi için bellekten n elemanlı yer ayırır.
va_arg(ap, tip) Veri tipi tip ile belirlenmiş küme elemanlarına eriştirir.
va_end(ap) va_list tipinde bildirilmiş ap göstericisi için bellekten bölgeyi boşaltır.

Bu kurallar ışığında, p() fonksiyonunun genel kullanımı Program 9.1'de gösterilmiştir. p(), kendisine parametre olarak gelen x, n ve ai katsayılarına göre

P(x,n) = a0 + a1x + a2x2 + ... + anxn

polinomu hesaplar. ai (i = 0, 1, 2, ..., n) katsayları esnek argüman olarak bildirilmiştir.

Program 9.1: Sonu -1 ile biten kümeyi ekrana yazar
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
/* 09prg01.c: Polinom hesabı */

#include <stdarg.h>
#include <stdio.h>
#include <math.h>

/* fonksiyon örneği */
double p(double, int, ...);


int main(void){

double x = 1.7;

   printf("x = %lf icin:\n",x);

   printf("p(x, 1,  1.0) = %lf\n", 
           p(x, 1,  1.0));

   printf("p(x, 2,  1.0, -2.0) = %lf\n", 
           p(x, 2,  1.0, -2.0));

   printf("p(x, 3,  1.0, -2.0, 0.2) = %lf\n", 
           p(x, 3,  1.0, -2.0, 0.2));

   printf("p(x, 4,  1.0, -2.0, 0.2, 1.1) = %lf\n", 
           p(x, 4,  1.0, -2.0, 0.2, 1.1));

   printf("p(x, 5,  1.0, -2.0, 0.2, 1.1, -0.6) = %lf\n", 
           p(x, 5,  1.0, -2.0, 0.2, 1.1, -0.6));

  return 0;
}

/* Verilen x, n ve ai katsayıları için, 
   P(x,n) = a0 + a1*x + a2*x^2 + ... + an*x^n polinomu hesaplar. 
   a0, a1, ..., an katsayları esnek arguman olarak bildirilmiştir. */
double p(double x, int n, ...)
{
   double a, t = 0.0;
   int i;

   /* arguman göstericisi; ag va_list tipinde */
   va_list  ag;

   /* ag için bellekten n adet hücre ayır */
   va_start(ag, n);

   for(i=0; i<n; i++)
   {
      /* herbir argumanı sırasıyla al */
      a = va_arg(ag, double);

      /* polinomun değerini hesapla */
      t += a*pow(x,i);
   }

   /* belleği boşalt */
   va_end(ag);

   return t;
}

ÇIKTI

x = 1.700000 icin:
p(x, 1,  1.0) = 1.000000
p(x, 2,  1.0, -2.0) = -2.400000
p(x, 3,  1.0, -2.0, 0.2) = -1.822000
p(x, 4,  1.0, -2.0, 0.2, 1.1) = 3.582300
p(x, 5,  1.0, -2.0, 0.2, 1.1, -0.6) = -1.428960

Program 9.2'de, argümanları esnek olarak bildirilmiş topla(int n, ...) fonksiyonu, n tane tamsayının sayının toplamını hesaplar.

Program 9.2: n tane sayının toplamını hesaplar
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
/* 09prg02.c
   n tane sayının toplamının hesaplanması */

#include <stdarg.h>
#include <stdio.h>


int topla(int, ...);

int main(void)
{
  printf("topla(2, 11,22)             = %d\n", topla(2, 11,22));
  printf("topla(3, 11,22,33)          = %d\n", topla(3, 11,22,33));
  printf("topla(4, 11,22,33,44)       = %d\n", topla(4, 11,22,33,44));
  printf("topla(5, 11,22,33,44,55)    = %d\n", topla(5, 11,22,33,44,55));
  printf("topla(6, 11,22,33,44,55,66) = %d\n", topla(6, 11,22,33,44,66,66));

 return 0;
}

/* Esnek argumanla tanımlanmış n tane tamsayının sayının
   toplamını gönderir */
int topla(int n, ...)
{
    va_list ap;
    int i, top = 0;

    va_start(ap, n);

    for (i=1; i<=n; i++)
        top += va_arg(ap, int);

    va_end(ap);
    return top;
}

ÇIKTI

topla(2, 11,22)             = 33
topla(3, 11,22,33)          = 66
topla(3, 11,22,33,44)       = 110
topla(5, 11,22,33,44,55)    = 165
topla(6, 11,22,33,44,55,66) = 242

Argüman sayısı bilidirilmeden de bir küme üzerinde işlem yapılabilir. Ancak bu durumda kümenin boyutu başka bir yöntemle hesaplanmalıdır. Program 9.3'de, argümanları esnek olarak bildirilmiş argyaz(int arg, ...) fonksiyonu, son elemanı -1 olan bir kümenin elemanlarını ekrana yazar. Kümenin sonu (yani boyutu) -1 ile belirlenmiş olur.

Program 9.3: Sonu -1 ile biten kümeyi ekrana yazar
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
/* 09prg03.c: Esnek argumanların yazdırılması  */

#include <stdio.h>
#include <stdarg.h>

/* herbiri int tipinde ve sonu -1 ile biten kümeyi ekrana yazar */
void argyaz(int arg, ...)
{
  va_list ap;
  int i;

  va_start(ap, arg);

  for (i = arg; i != -1; i = va_arg(ap, int))
    printf("%d ", i);

  va_end(ap);
  putchar('\n');
}

int main(void)
{
   argyaz(5, 2, 14, 84, 97, 15, 24, 48, -1);
   argyaz(84, 51, -1);
   argyaz(-1);
   argyaz(1, -1);

  return 0;
}

ÇIKTI

5 2 14 84 97 15 24 48
84 51

1


9.2   main Fonksiyonu

Ana program anlamına gelen main de bir fonksiyondur. C programlarının başlangıcı ve sonu bu fonksiyonla belirlenir. Buna göre, bir C (veya C++) programı sadece bir tane main içerebilir.

main fonksiyonu da geri dönüş değeri kullanabilir. main fonksiyonunun geri dönüş değerinin görevi, programın çalışması bittikten sonra sonucu işletim sistemine göndermektir. Program içinde return deyimi ile iletilen değer 0 olduğunda, bu işletim sistemi tarafından "program başarılı olarak sonlandı" olarak değerlendir. Başka bir deyişle,

     return 0;

program, kullanıcının talebi doğrultusunda (olumlu anlamda) "yapması gereken işi yaptı" mesajını işletim sistemine bildirilir. 0'dan farklı herhangi bir değer ise programın sorunlu sonlandığı anlamına gelecektir. Bu yüzden bütün C programlarımızın sonuna return 0; ilave ediyoruz.

Bazı programcılar main fonksiyonunun başına şey yazmaz.

     main()
     {
        ...
        return 0;
     }

Bu durumda geri dönüş değeri tamsayı (int) kabul edilir. Bu şekilde kullanımda, yeni tip derleyiciler uyarı (warning) mesajı verebilirler. Bu yüzden, aşağıdaki kullanımı tavsiye ediyoruz.

     int main()
     {
        ...
        return 0;
     }

Eğer ana programdan bir değer döndürülmeyecekse, main fonksiyonunun önüne aşağıdaki gibi void deyimi eklelenmelidir. Ancak bu bazı derleyiciler tarafından hata olarak yorumlanır. Bu nedenle, aşağıdaki kullanımlar pek tavsiye edilmez.

     void main()
     {
        ...
     }
yada
     void main(void)
     {
        ...
     }

9.3   main() Fonksiyonuna Parametre Aktarımı

 NOT
Bu ve sonraki kısımda (9.3) anlatılanlar Bölüm 10, 11 ve 16 okunduktan sonra daha iyi anlaşılacaktır. Ancak, konu akışını bozmamak için, bu konunun buraya konması uygun bulunmuştur.

Ana programa parametre aktarımı, derlenmiş (çalıştırılabilir) bir program komut satırından (işletim sistemi ortamından) çalıştırılacağı zaman yapılır. Parametre aktarımı, programın adı yazılıp bir boşluk bırakıldıktan hemen sonra yapılır. Parametreler, komut satırından sayısal olarak girilse bile program içinde karakter topluluğu (string) olarak gelir. Bu durumda, bu ifadeleri sayısal değerlere çeviren (atoi(), atol(), atof() gibi) fonksiyonlar kullanılır[1].

Genel kullanım biçimi:
          ...
          int main(arguman_sayısı, arguman_vektörü)
          int  arguman_sayısı;
          char *arguman_vektörü[];
          {
             .
             .
             .
             if(arguman_sayısı < ...){
                printf("Eksik parametre !\n");
                exit(1);
             }
             if(arguman_sayısı > ...){
                printf("Cok fazla parametre !\n");
                exit(1);
             }
             .
             ... arguman_vektörü[0] ... /* 1. eleman program adı  */
             ... arguman_vektörü[1] ... /* 2. eleman 1. parametre */
             ... arguman_vektörü[2] ... /* 3. eleman 2. parametre */
             .
         }

Program 9.1, komut satırından girilen iki sayının toplamını hesaplar.

Program 9.1: Komut satırından girilen iki sayının toplamını hesaplar
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
/* topla.c
   Komut satırından girilen iki sayının toplamını hesaplar.
   Kullanımı:  topla sayı1 sayı2 */

#include <stdio.h>
#include <stdlib.h>

int main(int argsay, char *argvek[]){
    
    int toplam;

    if(argsay < 3){
      printf("Eksik parametre !\n");
      exit(1);
    }

    if(argsay > 3){
       printf("Cok fazla parametre !\n");
       exit(1);
    }

    toplam = atoi(argvek[1]) + atoi(argvek[2]);

    printf("Toplamlari %d\n",toplam);

  return 0;
}

Program 9.1, topla.c derlendikten sonra üretilen Windows ortamında üretilen topla.exe ve Linux ortamında üretilen topla dosyasının çalıştırılması şöyledir:

  • Turbo C 2.0 Derlecisi kullanılarak (topla.c programı C:\TC adlı dizinin altına kaydedildiği varsayılmıştır)

  • Dev-C++ Derlecisi kullanılarak (topla.c programı C:\Users\bingul\Desktop adlı dizinin altına kaydedildiği varsayılmıştır)

  • Linux gcc derleyicisi kullanılarak (topla.c programı /home/bingul/ adlı dizinin altına kaydedildiği varsayılmıştır)

Komut satırında yazılan dosya adı dahil toplam parametre sayısı 3 tür. Bunlar:

    topla          4            9
      |            |            |
      V            V            V
   argvek[0]    argvek[1]    argvek[2]
şeklindedir.

Program 9.1, komut satırından girilen iki sayının toplamını hesaplar. Bu programın daha gelişmiş hali Program 9.2'de verilmiştir. Program 9.2 çalıştırıldığında, komut satırından girilen iki sayı ve bir operatör bekler. Girilen operatöre göre beş aritmetik işlemden birinini yapıp sonucu ekranda gösterir. İnceleyiniz.

Program 9.2: Komut satırından girilen iki sayı ve bir operatör bilgisine göre 5 işlemden birini hesaplar
01: 
02: 
03: 
04: 
05: 
06: 
07: 
08: 
09: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
/* hesap.c: Komut satırından girilen iki sayı üzerinde 5 işlem yapar.

     Kullanımı: hesap <sayi1> <operator> <sayi2> */

#include <stdio.h>
#include <stdlib.h>

int main(int args, char **argv)
{
    int   s1, s2;
    float sonuc;
    char  op;

    if(args != 4){
      printf("Eksik veya fazla parametre !\n");
      printf("Kullanimi: hesap <sayi1> <operator> <sayi2>\n");
      return 1;
    }

    s1  = atoi(argv[1]);    /* 1. parametre: sayi1 */
    op =       argv[2][0];  /* 2. parametrenin ilk karakteri: operator */
    s2  = atoi(argv[3]);    /* 3. parametre: sayi2 */

    switch(op)
    {
         case '+': 
           sonuc = s1 + s2; break;
         case '-': 
           sonuc = s1 - s2; break;
         case '*': 
           sonuc = s1 * s2; break;
         case '/': 
           sonuc = (float) s1 / s2; break;
         case '%': 
           sonuc = s1 % s2; break;
         default:
          sonuc = 0.0;
          printf("Yanlis operator %c\n",op);
          printf("Operatorler: +, -, *, / veya %%\n");
    }

    printf("sonuc = %f\n",sonuc);

 return 0;
}

Program hesap.c adlı dosyada saklandığı varsayılırsa, programın Linux ortamındaki çıktısı şöyle olacaktır:


9.4   Komut Satırı Örnekleri

Aşağıda verilen iki program, Linux işletim sistemindeki cp ve wc komutlarının basit kaynak kodlarıdır:

  • cp (copy) komutu, bir text dosyasının kopyasını oluşturur.
    Kullanımı: cp kaynak_dosya hedef_dosya
    cp komutunun kaynak kodları

  • wc (word count) komutu, bir dosyanın kaç karakter, kelime satırdan oluştuğunu bulup ekrana yazar.
    Kullanımı: wc dosya_adı
    wc komutunun kaynak kodları


Powered by PHP