Algoritmalar ve Programlama I Ders 10: ALTPROGRAM KAVRAMI ve FONKSİYON Doç. Dr. Cemil Öz Algoritmalar ve Programlama I Ders 10: ALTPROGRAM KAVRAMI ve FONKSİYON SAÜ Bilgisayar Mühendisliği Dr. Cemil Öz
Çoğu problemin çözümünde genellikle uzun programlara ihtiyaç duyulmaktadır. Binlerce ifadeden oluşan bir programların yazılması ve anlaşılması oldukça zor bir işlemdir. Bu sebeple problemin daha kolay çözülebilen alt parçalarına (modül) ayrıştırılması işlemi yapısal programlamanın temel yaklaşımlarındandır. Programlama dillerinde her bir modülün (alt parça) bağımsız olarak ele alınmasını sağlayan ve alt program adı verilen birimler tanımlanır. Altprogramlar büyük ve karmaşık problemin çözümünde yapısal programlamanın etkin kullanımı için gerekli temel taşlarındandır. Altprogramlar bir kere yazılır ve program içerisinde bir yada daha çok yerde çağrılarak kullanılır.
Altprogram kullanmanın faydaları; Belirli bir işi yapan program parçasının, birden çok yerde değişik veriler için ayrı ayrı yazılmasını önlemek. Düşük düzeydeki ayrıntıları, program mantığının ana akışından uzaklaştırıp ayrı modüllere yerleştirerek, programın tasarlanmasını kolaylaştırmak ve okunulabilirliğini artırmak. Büyük bir programın, daha küçük ve yazılması daha kolay fonksiyonel parçalara bölünmesini sağlamak. Program yazma işinin birden çok programcı tarafından paylaşılmasına olanak sağlamak.
Programlama dillerinde genelde iki tür alt program kullanılır; Yordam (procedure, subrotine) Fonksiyon Yordam ve fonksiyon özünde birbirine çok benzeyen altprogramlardır. Programlama dillerinde genelde yordam fonksiyona göre daha genel amaçlıdır. Fonksiyonlar ana programa bilgi geri gönderirken, yordamlardan bu beklenmez. Ayrıca fonksiyonların argüman (işlenen değişken, parametre) kullanması gerekirken, yordam argümansız olarak kullanılabilir.
Yordamı küçük bir program parçası şeklindeki bir altprograma, fonksiyonu da hesaplamalarda matematiksel hesaplamalarda kullandığımız hesaplamalara benzer işlem yapan bir altprograma benzetebiliriz.
C/C++’ da altprogram kullanımı C/C++’ da fonksiyon kavramı yordam ve fonksiyonu ihtiva edebilecek şekilde geniş tanımlanmıştır. Yani C/C++’ da hem yordam hem de fonksiyon aynı yapı kullanılarak ifade edilir. C/C++’ da altprogramlar fonksiyon ile ifade edilir. Fakat kullanımı hem yordamı hem de fonksiyonu ifade edecek kadar geniştir. C/C++’ da fonksiyonlar parametreli ve değer döndürerek fonksiyon şeklinde ve parametreli veya parametresiz (void) olarak değer döndürmeden (void) yordam şeklinde kullanılabilir.
C/C++’ da altprogram kullanımı C/C++’ da her fonksiyonun bir adı, tipi (döndürdüğü tip) ve argüman/argümanları vardır. Fonksiyon adı C dilinin anahtar sözcüklerinden (if, do, for, vb.) olmamak koşulu ile istenildiği gibi verilebilir. Diğer yandan fonksiyon adının yapısal programlama mantığına uygun olarak yaptığı işle uygun ve hatırlatıcı olması beklenir. Fonksiyonun tipi kendisini çağırana göndereceği verinin tipini belirtir. Eğer bir fonksiyon kendisini çağırana hiçbir veri göndermeyecek ise (yordam ise) tipi void olmalıdır.
C/C++’ da fonksiyon tanımlanması ve bildirimi C/C++’ da bir fonksiyonun genel yapısı aşağıda gösterildiği gibidir; fonksiyon-tipi fonksiyon-adı (argüman listesi) argümanların tip bildirimleri { yerel değişken bildirimleri … işlemler; } Bir C/C++ programında fonksiyonlar ana fonksiyon olan main() fonksiyonundan önce veya sonra tanımlanabilir. Kullanılacak fonksiyon main() fonksiyonundan önce tanımlanır ise bu durumda fonksiyonun ön bildirimine ihtiyaç yoktur.
Fakat özellikle büyük boyutlu programlar oluştururken programın okunulabilirliği açısından main() fonksiyonundan önce ön bildirim yapıp fonksiyonu main() fonksiyonundan sonra tanımlamak daha uygundur. Argümanlar yerel değişkenlere benzerler ve sadece fonksiyon içerisinde tanınırlar. Bildirimi yukarıda olduğu gibi fonksiyon adının hemen altında yada fonksiyon parantezi içindeki argümanın önünde yapılabilir (formal bildirim). Fonksiyon altprogramı kendisini çağırana veri gönderecek ise (fonksiyon ise), “return” deyimi kullanarak sadece bir tane sonuç gönderebilir. Gönderilecek verinin tipini fonksiyon-tipi belirler.
Daha öncede bahsedildiği gibi eğer bir fonksiyon kendisini çağırana hiçbir veri göndermeyecek ise yordam şeklinde kullanılıyordur ve fonksiyon-tipi “void” olmalıdır. C/C++’ da bir fonksiyonun argümanı (formal parametresi) birden çok olabileceği gibi hiç de olmayabilir. Hiç parametre yok ise derleyicinin isteğine göre hiç parametre yazılmaz veya fonksiyon parantezi içine “void” yazılır. Bir fonksiyonun her çağrılmasında standart kütüphanenin (stdlib.h) va_start(), va_arg(), va_end() makro fonksiyonları kullanılarak farklı sayıda argüman parametre olarak kullanılabilir. Bu ders kapsamında bu konu ele alınmayacaktır.
Bir C/C++ programında fonksiyon çağırma işini aşağıdaki şekilde olduğu gibi ifade edebiliriz;
c/C++’ da fonksiyona parametre aktarımı C/C++’ da bir fonksiyonuna parametre aktarımı (argüman kullanımı) iki şekilde yapılabilir; Verinin değeri doğrudan aktarılabilir yani değer doğrudan parametre olarak kullanılabilir (değer ile çağırma – calling by value). Verinin adresi (değişken) aktarılabilir yani değişken parametre olarak kullanılabilir (adres ile çağırma – calling by reference). Bunun ile birlikte fonksiyon argümanların bir kısmı değer bir kısmı da değişken şeklinde olabilir.
Örnek C/C++’da fonksiyon tanımlanması, bildirimi ve parametre aktarımı ile ilgili basit bir örnek program; #include <stdio.h> #include <conio.h> int ekle(int, int); /* fonksiyon bildirimi – bazi derleyicilerde zorunlu */ /*ana fonksiyon*/ void main(void) { int x,y; clrscr(); printf("yedi eklenecek sayiyi girin: "); scanf("%d",&x); y=ekle(x,7); /* fonksiyonun cagrilmasi */ printf("sonuc = %d",y); getch(); } /* fonksiyon tanimlama*/ int ekle(a,b) int a,b; { int g; g=a+b; return g;
Örnek;C/C++’da değişkenler arası verileri yer değiştiren bir fonksiyon (yordam olarak) kullanılması ile ilgili basit bir örnek program; #include <stdio.h> #include <conio.h> void degistir(void); /* fonksiyon bildirimi – bazi derleyicilerde zorunlu */ int x,y; /*ana fonksiyon*/ void main(void) { clrscr(); printf("birinci sayiyi girin: "); scanf("%d",&x); printf("ikinci sayiyi girin: "); scanf("%d",&y); printf(" %d %d\n",x,y); degistir(); /* fonksiyonun cagrilmasi */ printf(" %d %d ",x,y); getch(); } /* fonksiyon tanimlama*/ void degistir(void) { int g; g=x; x=y; y=g; }
Görüldüğü gibi kullanılan altprogram parametre aktarmayan bir yordam şeklinde kullanıldığı için parametre aktarımı ve sonuçta değer döndürülmesi yapılmadı. Bu sebep ile x, y global değişken olarak kullanıldı. Değişkenlerin değer değiştirme işlemini daha etkin olarak yapabilmek için oluşturacağımız yordam fonksiyonuna parametre aktarımı yapmak gerekir. Fakat aktarım parametrelerine direkt olarak değer döndürülemeyeceği için, dolaylı olarak değer döndürmek gerekir. Bu sebep ile işaretçi değişkenler kullanmak gerekir.
#include <stdio.h> #include <conio.h> void degistir(int *, int *); /* fonksiyon bildirimi – bazi derleyicilerde zorunlu */ /*ana fonksiyon*/ void main(void) { int x,y; clrscr(); printf("birinci sayiyi girin: "); scanf("%d",&x); printf("ikinci sayiyi girin: "); scanf("%d",&y); printf(" %d %d\n",x,y); degistir(&x,&y); /* fonksiyonun cagrilmasi */ printf(" %d %d ",x,y); getch(); } /* fonksiyon tanimlama*/ void degistir(int *a, int *b) { int g; g=*a; *a=*b; *b=g;
Altprogramın yan etkileri Bir programın değişken değerlerini istenmeyen bir biçimde değiştirmesine yan etki denilir. Bu durumda çoğu zaman istenmeyen sonuçlar doğurabilir. Yan etkiden kaçınmak için çok önemli bir neden yoksa yordam yada fonksiyonda global (genel) değişken kullanılmamalıdır. Mümkün olduğunca program modülleri arasındaki iletişim parametre aktarımı ile yapılmalıdır.
Örnek ;Yan etkinin beklenmedik sonuçlara nasıl yol açacağını görmek için aşağıdaki C/C++ programını örnek olarak inceleyebiliriz; #include <stdio.h> #include <conio.h> int f(int); int x; void main(void) { clrscr(); x=0; printf("%d\n",f(0)); getch(); } int f(int y) { int g; g=x+y; x++; return g; program çıktısında üç değerinde aynı olacağı sanılsa da bu bir yanılgıdır. “f” fonksiyonu “x” global değişkeninin değerini değiştirdiği için aynı olması beklenen çıktı değerleri her defasında değişir.
Özyineleme Kavramı Birçok dilde olduğu gibi bir alt programı C/C++’ da da yalnızca başka bir altprogram/ program değil kendiside çağırabilir. Böyle bir çağırmaya özyineleme adı verilir ve bu altprogramın özyineli olduğu söylenir. Özyineleme, yinelemeye (döngü deyimleri kullanarak yapılan işlem tekrarları) bir seçenek olarak düşünülebilir. Genellikle özyineli bir çözüm, bilgisayar zamanı ve bellek kullanımı açısından yinelemeye göre daha az etkindir. Fakat bazı durumlarda özyineleme, bir probleme doğal ve basit bir çözüm sağlar. Bu nedenle özyinelemeli fonksiyon ve yordamlar diğer dilerde olduğu gibi C’ de de önemli ve yararlı araçlardır.
Örnek ; Özyinelemeli bir fonksiyon kullanarak girilen bir pozitif değerin faktöriyelini hesaplayan bir C/C++ programı yazalım. Faktöriyelin matematiksel ifadesi aşağıdaki şekilde yazılabilir;
#include <stdio.h> #include <conio.h> long int fakt(int); int x; void main(void) { clrscr(); printf("sayiyi girin: "); scanf("%d",&x); printf("%d ! = %ld \n",x,fakt(x)); getch(); } long int fakt(int a) { long int g; if (a>1) g=a*fakt(a-1); /* n!=n*(n-1)! */ else g=1; return g;
Algoritmalar ve Programlama I Sunu Tamamlandı Doç. Dr. Cemil Öz Algoritmalar ve Programlama I SAÜ Bilgisayar Mühendisliği Dr. Cemil Öz