Bilgisayar programlama III Fonksiyonlar
Fonksiyon C deki program modülleridir Verilen girdilere göre bir çıktı üreten veya işlem gerçekleştiren manalı, isimlendirilmiş kod parçasıdır. Kullanıcı tanımlı işlemler ve kütüphane fonksiyonlarını birlikte kullanmayı sağlar. C standard kütüphanesi birçok hazır fonksiyona sahiptir. Fonksiyon Çağırma Fonksiyon ismi ve argümanları kullanılarak çağrılır. Fonksiyonlar İşlem veya değişimle gerçekleştirilir. Fonksiyon sonuç döndürebilir. Fonksiyon çağırma sırası: Ana program görevlerin tamamlanmasını ister. Çalışan fonksiyon bilgi alır, işlem yapar ve sonuç döndürür Bilgi gizleme(information hiding): çağıran ayrıntıları bilmez
Fonksiyonlar Modüler (anlamlı parçalardan oluşan) tasarım sağlar Fonksiyon içindeki tüm değişkenler yereldir (local variables) Sadece fonksiyon içinde geçerli Değişkenler Fonksiyonlara bilgi geçişi için kullanılır. Kapsamları fonksiyon içinde yerel değişkenler gibidir. Fonksiyonların yararları Böl ve yönet Küçük parçalar daha kolay tasarlanıp gerçekleştirilebilir Tekrar kullanım Detayları gizleme Kod tekrarını azaltma
Fonksiyon Tanımı Dönüş_türü fonksiyon ismi ( ) parametre_türü1 parametre_ismi1, parametre_türü2 parametre_ismi2, Fonksiyon ismi değişken ismindeki kurallar geçerlidir. Dönüş türü (Return-value-type): sonuç veri türü Varsayılan dönüş türü int tir void fonksiyonun değer döndürmediğini gösterir. Parametre listesi: değişken tanımları virgülle ayrılarak yazılır int hariç tüm türler harici olarak belirtilmelidir.
Fonksiyon çağırma hiyerarşisi (Patron Çalışan) main worker1 worker2 worker3 worker4 worker5
Örnek Bir fonksiyon int topla(int x, int y) { int sonuc; sonuc = x + y; return sonuc; }
Fonksiyon Dönüş Değeri Hiçbir değer dönmeyecekse return; Son süslü paranteze erişildiğinde ( } ) Bir değer dönecekse return ifade;
Fonksiyon Parametreleri Fonksiyon parametreleri klasik ve modern olmak üzere iki türlü tanımlanabilir. Örneğin aşağıdaki fonksiyon kendisine parametre olarak gelen tamsayının faktoriyelini gönderir. Bu fonksiyonun parametresi (n): int faktoriyel(n) /* kalsik biçim */ int n { int i=1, f=1; while(i<=n) f *= i++; return f; } şeklinde yada: int faktoriyel(int n) /* modern biçim */ { int i=1, f=1; while(i<=n) f *= i++; } return f;
İleriye yönelik tanımlama (forward decleration) Bir fonksiyon dosya içinde kullanıldığı noktadan önce tanımlanmış olmalıdır. (Nesneye yönelik olmadığından metot tanımı java daki gibi herhangi noktada yapılamaz.) Fonksiyonun sadece tanımı isim ve parametre listesinin kullanılmadan önce yazılmasına İleriye yönelik tanımlama (forward decleration) denir. Sadece int argüman alan fonksiyonlar varsayılan değerden dolayı tanımlanmasa da çalışabilir. Yapılışı Fonksiyon tanımı(); Herhangi metot } Fonksiyon gerçekleştirme (){. }
İleriye yönelik tanımlama örneği #include <stdio.h> void PrintSomeChar(char c); main (){ PrintSomeChar( a ); } void PrintSomeChar(char c){ printf("%c", c ); }
İleriye yönelik tanımlama Sadece int değişken içeren fonksiyon tanımları otomatik yapılır. Bu yüzden ileriye yönelik tanımlama gerektirmezler.
Kütüphane Kullanımı Sık kullanılan fonksiyonlar kütüphanelere taşınabilir. Kütüphane dosyaları başlık dosyası (header file ) olarak isimlendirilir ve *.h uzantılıdır Fonksiyonun tanımı kütüphane dosyasında yapılır. Gerçekleştirilmesi kütüphane dosyasından erişilebilen bir dizinde ayrı bir *.c uzantılı dosyada yapılır. Kütüphane include edilmelidir. Fonksiyon yine ayrı bir dosyadan çağrılır. Kütüphane include edilmelidir.
Kütüphane tanımı Çağırma *.c #include "tanım.h" void ametot(){ afunction (int x, int y); } Çağırma *.c #include "tanım.h" void ametot(){ afunction (int x, int y); } Tanım *.h #include "tanım.h" gerçekleştirme *.c void afunction (int x, int y){ } Çağırma *.c #include "tanım.h" void ametot(){ afunction (int x, int y); }
mykutuphane.h #define MYKUTUPHANE_H_ int topla(int a,int b); myimplemente.c #include "mylib.h" int topla(int a,int b); { return a + b; } mycall.c #include "mylib.h" main{ printf ("%d", topla(int a,int b)); } Kütüphane örnek
Kütüphane referans Standart kütühaneler <> arasında yazılır. #include <stdio.h> Özel başlık dosyaları "" c dosyaları ile aynı veya erişilebilir klasör yolunda saklanır içinde #include "mylib.h" şeklinde yazılır.
Bellek sınıfları Değişken ve fonksiyonların bellek sınıfları onların yaşam sürelerini, etki alanlarını, saklandıkları bölgeleri ve ilklenme yolunu belirler. auto Değişkenler register değişkenler static değişkenler extern değişkenler
auto bellek sınıfı Ön ek almamış bütün değişkenler bu türdür. Otomatik değişkenler, içinde bulundukları blok yürütüldüğü sürece yaşarlar yani bloktan önce veya sonra mevcut olmazlar. auto kullanmanın aslında gerçek bir anlamı yoktur, çünkü bloklar içinde tanımlanmış değişkenler için bellek sınıfı belirtilmediği zaman, otomatik oldukları varsayılır. Örnek: Aşağıdaki yazımlarda derleyici için bir farklılık yoktur. auto int i; int i
register bellek sınıfı Eğer bir değişken register sınıfından tanımlanmışsa, derleyici onu makinenin hızlı bellek yazmaçlarına yerleştirmeye çalışır register bellek sınıfı auto bellek sınıfı ile yakından ilgilidir. Bu iki sınıf için etki alanı ve yaşam süresi kuralları aynıdır, ve register, tıpkı auto gibi, fonksiyonlar dışında anlamsızdır. register bildirimi derleyiciye sadece bir öneri özelliği taşır. hızlı bellek yazmaçlarına yerleştirilmeyebilir Ana bellekte depolanmayabilecekleri için, register değişkenlerine tekli & işleci uygulanamaz. Ayrıca, diziler gibi karmaşık tipten bazı veriler register olamazlar; ancak bu sistemden sisteme değişebilir. Örnek register int i; register char kar, x;
Register bellek sınıfı register bellek sınıfından en iyi şekilde yararlanmak için, az sayıda değişken bu tipte tanımlanabilir. Bunlar en çok kullanılanlar olmalıdır. (Örneğin döngü sayaçları.) Mümkün olduğu kadar kullanıldıkları program koduna yakın tanımlanabilmeleri için de blok içine alınırlar. Fonksiyon parametreleri de register bellek sınıfından tanımlanabilirler.
static bellek sınıfı Değişkenler ve Fonksiyonlar Kullanıldığı yere bağlı olarak static anahtar sözcüğünün iki değişik anlamı vardır. Blok içinde Fonksiyon ve değişken tanımları öncesinde
Blok içinde static kullanımı Blok içinde, static kalıcı anlamına gelir. Yani, blok içinde değişkenlerin tanımlarının önüne static anahtar sözcüğü kullanılırsa, bu değişkenlerin değerleri blok sona erdiğinde yok olmazlar. Blok dışına çıkıldığında değişkenler erişilmez hale gelir, fakat blok tekrar işletilirse, blok sona erdiği zamanki değerleriyle programın yürütülmesine katılırlar. Diğer bir deyişle, bu bağlamda static auto nun tersidir. Fonksiyon parametreleri olarak kullanılan değişkenler static olamaz.
Static örnek void fark (void) { static int deger; int yeni_deger; scanf("%d", ¥i_deger); printf("bu deger son seferden %d birim farklidir.\n", deger - yeni_deger); deger = yeni_deger; } Tanım kısmı bir defa çalışır. Değer ilk fonksiyon çalıştığında atanır. Fonksiyondan çıkınca değer kaybolmaz. Tekrar çağrıldığında aynı değeri alır.
static anahtarının ikinci kullanımı Bir fonksiyon veya küresel bir değişken tanımının önüne yazıldığı zaman, static gizli anlamına gelir. Yani, bu fonksiyon veya değişken (ayrıca derlenmiş yada derlenecek) başka dosyalara tamamen yabancı olacaktır; diğer bir deyişle, bu dosyalar static değişken veya fonksiyona erişemeyeceklerdir. int fonk_1 (...) { fonk_1 in gövdesi } static double z; static int fonk_2 (...) { fonk_2 in gövdesi } int main (...) { main in gövdesi } Fonksiyona ve değişkene sadece aynı dosyadan erişilebilir. Diğer dosyalardan erişilemez.
extern bellek sınıfı Tanım ve beyanı (define and declare) birbirinden ayırır. Kullanımı: C' de uzun programların derlenmesi için programlar, dosyalar halinde bölünür. Dosyalar sonradan birleştirileceğinden,bir dosya için geçerli değişkenlerin diğer dosyalar içinde geçerli hale gelmesi için,dosyaların başına diğer dosyaların global değişkenleri yazılır ve başına ". extern" getirilir. Global değişken ve fonksiyonlar için varsayılan anahtar kelimedir. Anlamlı bir yerde extern anahtar sözcüğünü ve arkasına değişkenin bildirimi yazılır. Diğer dosyalardan değişkenlere bu tür bir erişim sağlamak için, değişkenin özgün tanımının static olmaması gerekir. http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
Extern bellek sınıfı Her küresel değişkenin tam bir tane extern olmayan tanımı ve birtakım extern bildirimleri vardır. extern kullanılmamış ( özgün )tanım, değişken için bellekten bir bölgenin ayrıldığı tek yerdir. Diğer bildirimler ise, bu değişkenin tanımının başka bir yerde bulunduğunu, tipinin ise belirtildiği gibi olduğunu derleyiciye anlatmak içindir. Diğer bir deyişle, extern bildirimi değişken için yer ayrılmasına neden olmaz.
Makro Fonksiyon Tanımlaması Başlık dosyalarında, bol miktarda makro fonksiyon uygulamalarına rastlanır. Makro tanımlaması #define önişlemci komutu kullanılarak yapılır. Örneğin aşağıdaki makro fonksiyonlar geçerlidir. #define kare(x) (x)*(x) #define delta(a,b,c) ((b)*(b)-4*(a)(c)) #define yaz() puts("devam etmek için bir tuşa basın...") Bu şekilde tanımlanan fonksiyonların kullanımı diğerleri gibidir. Yalnızca programın başında tanımlanır. Ancak, bu tanımlamalarla fonksiyon bellekte bir yer işgal etmez
extern bellek sınıfı her küresel değişkenin tam bir tane extern olmayan tanımı ve birtakım extern bildirimleri vardır. extern kullanılmamış ( özgün ) tanım, değişken için bellekten bir bölgenin ayrıldığı tek yerdir. Diğer bildirimler ise, bu değişkenin tanımının başka bir yerde bulunduğunu, tipinin ise belirtildiği gibi olduğunu derleyiciye anlatmak içindir. Diğer bir deyişle, extern bildirimi değişken için yer ayrılmasına neden olmaz. Bir değişkenin özgün tanımıyla extern bildirimlerinde farklı tiplerin belirtilmesi istenmeyen şeylerin oluşmasına neden olabilir. Hem tanım hem de bildirim aynı dosyada ise derleyici hatayı bulabilecektir, fakat eğer farklı dosyalarda ise hata bulunamayabilir. Bazı modern derleyiciler yukarıdaki hataları yakalayabilmektedir.
İlk değer verme Otomatik sınıfından olan değişkenler ait oldukları blokla beraber ortaya çıkarlar ve sonra yok olurlar. Yazmaç sınıfı değişkenler otomatikler gibidir; tek farkları yazmaçlara yerleştirilmelerinin söz konusu olmasıdır. Statik (static) yerel değişkenler değerlerini asla yitirmezler, oysa aynı sınıftan olan küresel değişkenler ve fonksiyonlar kendi dosyalarında gizli kalırlar. Statik (static) olmayan küresel değişkenler ve fonksiyonlar dördüncü ve son bellek sınıfını oluştururlar, bunlara dışsal adı verilir ve programın herhangi bir yerinden kullanılabilirler. Programcı tarafından, aksi belirtilmediği sürece dışsal ve static bellek sınıfından olan değişkenler sıfıra ilk değerlenir. auto ve register sınıfından olan değişkenlerin ilk değerleri belirsizdir.
Overloading ve C C fonksiyon overload edilmesine izin vermez. C++ overloading kullanılabilir. C fonksiyonlarını C++ dan çağırmak için extern anahtarı kullanılmalıdır.
Öz Yineleme (Çağrı) - recursion Fonksiyon kendi kendisini çağırabilir. Böylesi bir fonksiyon İlk değer Başlatma koşulu Devam koşulu Bitiş koşulu içermelidir
Öz yineleme Örnek fakt (int n) { int i = 1; while (n) i *= n--; return i; } Yukarıdaki klasik Faktöriel işlemini öz yinelemeli yazınız.
Öz yinelemeli factorial long factorial(long N) { if( N < 2 ) return N; else return N*factorial(N - 1); }
Öz yineleme Öz yinelemeli fonksiyonlar yığıttan çok yer harcarlar. Bir int değişkenin iki bayt, dönüş adresinin de dört bayt kapladığını varsayalım. Bu durumda, fakt(i) şeklinde bir çağrı yığıtta 6 (i+1) bayt kullanacaktır. Örneğin, fakt(6) için 42 bayta gereksinimimiz olacaktır. Diğer taraftan, fakt ın döngü temelli (yani ilk verilen) uyarlaması yığıttan 4 (dönüş adresi için) + 2 (n için) + 2 (i için) = 8 bayt kullanacaktır. Öz yinelemeli fonksiyonun bellek üzerinde daha fazla talepte bulunduğu açıktır. Ayrıca, yerel değişkenlerin ve dönüş adresinin yığıta itilip geri alınması işlemci zamanı da harcar. Döngü temelli fonksiyonlar genellikle öz yinelemeden daha verimlidir. Yinelemeli tüm fonksiyonların döngü temelli eşleniği olduğu ispatlanmıştır. Eşdeğer bir yinelemeli algoritması çok karmaşıksa Öz yinelemeli kullanımı tercih edilebilir
Math Kütüphanesi fonksiyonları Math Kütüphanesi fonksiyonları Genel matematiksel hesaplamalar için kullanılır #include <math.h> Fonksiyon Çağırma Formatı Functionİsmi( argumanlar ); Eğer birden fazla argüman varsa virgül kullanılır. printf( "%.2f", sqrt( 900.0 ) ); Karekök alma fonksiyonunun çağrılması sqrt Tüm matematiksel fonksiyonlar double dönüş türüne sahiptir. Argümanlar sabit, değişken veya hesaplama ifadesi (expression) olabilir.
Bazı Örnek Fonksiyonlar sqrt( x ) x in katesi sqrt( 900.0 ) is 30.0 sqrt( 9.0 ) is 3.0 exp( x ) e x exp( 1.0 ) is 2.718282 exp( 2.0 ) is 7.389056 log( x ) Doğal logaritma (e) log( 2.718282 ) is 1.0 log( 7.389056 ) is 2.0 log10( x ) logarithm x (10) log10( 1.0 ) is 0.0 log10( 10.0 ) is 1.0 log10( 100.0 ) is 2.0 fabs( x ) x in mutlak değeri fabs( 5.0 ) is 5.0 fabs( 0.0 ) is 0.0 fabs( -5.0 ) is 5.0 ceil( x ) x i üst tamsayıya tamamlama ceil( 9.2 ) is 10.0 ceil( -9.8 ) is -9.0 floor( x ) x i alt tamsayıya tamamlama floor( 9.2 ) is 9.0 floor( -9.8 ) is -10.0 pow( x, y ) x in y. kuvveti (x y ) pow( 2, 7 ) is 128.0 pow( 9,.5 ) is 3.0 fmod( x, y ) x/y işleminin kalanı (float) fmod( 13.657, 2.333 ) is 1.992 sin( x ) Sin(x)( x : açısal) sin( 0.0 ) is 0.0 cos( x ) Cos(x) (x : açısal) cos( 0.0 ) is 1.0 tan( x ) tan (x) (x in radians) tan( 0.0 ) is 0.0
Rastgele numara oluşturma rand fonksiyonu <stdlib.h> kütüphanesi include edilmelidir. 0 ve RAND_MAX (en büyük 32767) arasında rastgele bir numara döndürür i = rand(); Rastgele gibi görünür. Rastgele numara kümesini önceden belirler Fonksiyon çağırıldığında hep aynı kümeyi döndürür. Aralık 1 ve n arasıda bir rastgele numara için 1 + ( rand() % n ) rand() % n ifadesi 0 ve n 1 arasında rastgele bir sayı döndürür Bir eklenerek 1 ve n aralığındaki sayılara ulaşılabilir. 1 + ( rand() % 6) 1 ve 6 arasındaki sayılar
Her fonksiyon çağrısında farklı ratsgele sayılar üretmek srand fonksiyonu <stdlib.h> integer bir değer alır ve bundan yola çıkarak "random" bir aralığa atlar. srand( seed ); srand( time( NULL ) );/*load <time.h> */ time( NULL ) Programın compile zamanını saniye olarak alır Seed değerini üzerinden rastgelelik sağlar.
2 Shifted, scaled integers produced by 1 + rand() % 6 */ 3 #include <stdio.h> 4 #include <stdlib.h> 5 6 /* function main begins program execution */ 7 int main() 8 { 9 int i; /* counter */ 10 11 /* loop 20 times */ 12 for ( i = 1; i <= 20; i++ ) { 13 14 /* pick random number from 1 to 6 and output it */ 15 printf( "%10d", 1 + ( rand() % 6 ) ); 16 17 /* if counter is divisible by 5, begin new line of output */ 18 if ( i % 5 == 0 ) { 19 printf( "\n" ); 20 } /* end if */ 21 22 } /* end for */ 23 24 return 0; /* indicates successful termination */ 25 26 } /* end main */ fig05_07.c
Kaynaklar http://www.kadifeli.com/fedon/stdcprtr.php?4_3_1 http://www1.gantep.edu.tr/~bingul/c/index.php?ders= 8
Sorular