|
Fonksiyonlar C++’ın ve hatta C dilinin dahi vazgeçilmez hazır kod bloklarıdır. Bir kere kodlamak yeterlidir. Bunu bütün program boyunca ve hatta başka programlarda da kullanabilirsiniz. Bu hem işinizi çok kolaylaştıracak hem de size zaman kazandıracaktır. Çünkü aynı işlemleri yapacağınız kod yığınlarını defalarca aynı şekilde yazmak uzun ve zahmetli bir iştir. Bu hem sizi yapacağınız işten zevk almaktan alıkoyar hem de vaktinizi boşa harcamış olursunuz. Ayrıca bellek alanından büyük ölçüde tasarruf etmiş olursunuz, ki en önemli olanı da bu olsa gerek… Derse girmeden önce bir hatırlatmada bulunmak istiyorum. Eğer C++’ın temelini edinmemişseniz, yani değişken tiplerini, sorgulama çeşitlerini ve döngüleri öğrenmemişseniz fonksiyonlara direkt olarak girmenizi tavsiye etmiyorum. Çünkü fonksiyonlar bu işleri tekdüze indirmek için programcıya sunulmuş büyük bir avantajdır. Zaten C++’ın temelini almamışsanız fonksiyonları öğrenmenin de bir anlamı olmayacaktır. İlk olarak argüman ve dönüş değeri olmayan basit fonksiyonlardan giriş yapmak istiyorum. Bunlar yalnızca bir kod bloğunu basitçe istenilen yerde kullanmak için yazılmış fonksiyonlardır. Fonksiyonlar şu şekildedir genel olarak. Dönüşdeğeri FonksiyonAdı(Tip Argüman1, Tip Argüman2, …) { ………. KodBloğu ………. } Fakat biz öncelikle argüman almamış ve geri dönüş değeri olmayan (void) fonksiyonlardan başlayacağız… Bir fonksiyonun dönüş değeri değişkenlere verilen herhangi bir değer gibi olabilir. Bu sonuçta ilerde de göreceğiniz üzere fonksiyonu değişkenlik özelliği gösteren bir yapıyla karşımıza çıkaracaktır. Eğer bir fonksiyonun geri dönüş değeri olsun istemiyorsanız o zaman dönüş değerini “void” olarak girmelisiniz. Void i sanırım yeni duymuş olacaksınız eğer ilk defa fonksiyonları görüyorsanız. Void kelime anlamı itibariyle C/C++ dillerinde boş, içerdiği bir değer olmayan anlamlarına gelir. Unutmamalısınız ki bu kelimeler ufak olarak kullanılmalıdır. Aksi halde derleyiciniz hata verecektir. Ayrıca eğer bir fonksiyon argüman değerleri almayacak ise parantez içersinde “(void)” olarak yazılabilir veya direkt olarak “()” içi boş parantezler kullanabilirsiniz, ikisi de aynı anlamlara gelir. Neyse artık ilk programımıza geçebiliriz sanırım. Ayrıca unutmadan da geçmemek gerekir ki “main()” de bir fonksiyondur. Diğer fonksiyonlardan tek farkı derleyici bütün fonksiyonlar içersinde otomatik olarak ilk onu çağıracaktır. Bu yüzden ana fonksiyondur. #include <iostream> using namespace std; void basitfonksiyon() { cout << “Bu benim ilk basit fonksiyonum” << endl; } void main() { basitfonksiyon(); //Fonksiyonumuzu çağırdık system(“pause”); } Bu programın çıktısı elbette ki tahmin ettiğiniz gibidir. Çıktı şu şekilde olacaktır. Bu benim ilk basit fonksiyonum İşte artık ilk fonksiyonumuzu yazdıktan sonra bu işi biraz daha zorlaştırabiliriz. Bu sefer fonksiyonumuza iki argüman ekleyelim. Sonra bu değerleri ekranda çıktı olarak göstermesini isteyelim… #include <iostream> using namespace std; void basitfonksiyon(int sayi1, int sayi2) { cout << “Sayi1 = ” << sayi1 << endl; cout << “Sayi2 = “ << sayi2 << endl; } void main() { basitfonksiyon(412, 56); //Fonksiyonumuzu çağırdık system(“pause”); } Sonucu tahmin edebiliyorsunuzdur herhalde. Çıktı şu şekilde olacaktır. Sayi1 = 412 Sayi2 = 56 Bu fonksiyonu biraz daha değiştirip adımızı soyadımızı yazmasını isteyelim. #include <iostream> using namespace std; void basitfonksiyon(char *ad, char *soyad) { cout << “Adiniz : ” << ad << endl; cout << “Soyadiniz : “ << soyad << endl; } void main() { basitfonksiyon(“Evren”, “Acigul”); //Türkçe karakter desteklemediği için böyle yazmak zorunda kalıyoruz system(“pause”); } Çıktı şu şekilde olacaktır. Adiniz : Evren Soyadiniz : Acigul Evet artık fonksiyona argüman aktarabilmeyi öğrenmiş isek, fonksiyonun nasıl değer döndürdüğünü görmek isteyebiliriz. Bunun için matematiksel işlemleri örnek olarak gösterebiliriz. Ama şunu unutmayın ki fonksiyonların temelini kavradıktan sonra gerisi sizin hayal gücünüz kadarıyladır… Şimdi başka bir fonksiyon yazalım. Bu fonksiyon dört sayıyı toplasın ve değeri bize döndürsün. Sonra bu değeri çıktı olarak main() fonksiyonu içersinde yazdıralım. #include <iostream> using namespace std; int topla(int sayi1, int sayi2, int sayi3, int sayi4) { return sayi1 + sayi2 + sayi3 + sayi4; } void main() { cout << “Sayilarin toplami : “ << topla(53,67,12,45) << endl; system("pause"); } Sonuç elbette tahmin ettiğiniz gibi olacaktır. Sayilarin toplami : 177 Elbette aklınıza hemen gelmiştir. Acaba topla(53,67,12,45) gibi bir ifade yazmak yerine, argüman değerlerinin olduğu kısma değişkenler girebilir miyim diye… Evet o şekilde düşünmüşseniz doğru düşünmüşsünüz demektir. Basit bir örnek vermek gerekirse. Bunu anlatmak için sadece iki argümanlı bir fonksiyon yazmak yeterli olacaktır. Unutmayın ki argüman sayısı ve tipi sizin dilediğiniz kadar ve dilediğiniz şekildedir. Dolayısıyla bu sizin hayal gücünüze ve fonksiyonun amaçlanan işlevine bağlıdır. #include <iostream> using namespace std; int topla(int sayi1, int sayi2) { return sayi1 + sayi2; } void main() { int birincisayi; int ikincisayi; cout << “Lutfen birinci sayiyi giriniz : “; cin >> birincisayi; cout << “Lutfen ikinci sayiyi giriniz : “; cin >> ikincisayi; cout << “Sayilarin toplami : “ << topla(birincisayi, ikincisayi) << endl; system("pause"); } Birinci sayı için 64 girdik diyelim. İkincisi için de 36 girdiğimizi kabul edersek çıktı elbette ki tahmin ettiğiniz gibi 100 olacaktır… Daha ileri seviyelerde göreceğiniz üzere değişkenleri fonksiyon argümanlarına referans olarak ya da işaretçi argümanlara adres olarak aktarabilirsiniz. Bunu anlamak için ise işaretçiler(pointer) hakkında bilgi sahibi olmanız gerekiyor. Ama bu dersimizin konusu bu olmadığı için bu kadar bilgi vermek yeterli görünüyor. İlerde inşallah yeni bir derste değineceğiz… Sizlere şimdi fonksiyon prototiplerinden söz etmek istiyorum. Nedir fonksiyon prototipleri? Diyelim ki bir fonksiyonumuz var ve bu fonksiyonumuz ondan daha önce gelen bir fonksiyon içersinde çağırılması gerekiyor. Ama derleyici okuma sırasına göre onu daha sonradan okuduğu için daha önceden prototip gösterilmesi gerekiyor. Yani deyimi yerindeyse biz derleyiciye diyoruz ki, ileriki satırlarda karşına bu fonksiyon gelecek, o bu satırdan sonra çağırılırsa hata verme ve fonksiyonu çağır diyoruz. Önceki örneği biraz değiştirerek bunu açmaya çalışalım… #include <iostream> using namespace std; void main() { int birincisayi; int ikincisayi; cout << “Lutfen birinci sayiyi giriniz : “; cin >> birincisayi; cout << “Lutfen ikinci sayiyi giriniz : “; cin >> ikincisayi; cout << “Sayilarin toplami : “ << topla(birincisayi, ikincisayi) << endl; system("pause"); } int topla(int sayi1, int sayi2) { return sayi1 + sayi2; } Normalde bu şekilde programımızı derlediğimizde “Undeclared Identifier” hatası alacağız. Çünkü bir fonksiyon prototipi sunmamış durumdayız. O halde main() fonksiyonunun evveline bir topla fonksiyonu prototipi yerleştiriyoruz. #include <iostream> using namespace std; int topla(int, int); //İşte prototipimiz bu şekildedir… void main() { int birincisayi; int ikincisayi; cout << “Lutfen birinci sayiyi giriniz : “; cin >> birincisayi; cout << “Lutfen ikinci sayiyi giriniz : “; cin >> ikincisayi; cout << “Sayilarin toplami : “ << topla(birincisayi, ikincisayi) << endl; system("pause"); } int topla(int sayi1, int sayi2) { return sayi1 + sayi2; } Fonksiyon prototipimizi yazarken parantez aralığında bulunan argüman tiplerine dikkat edin. Argüman adlarını yazmıyoruz. Aslında istesek yazabilirdik. Ama derleyici için tip belirtilmesi yeterli oluyor. Yani istesek “int topla(int sayi1, int sayi2);” şeklinde yazsak bu yine aynı anlamda bir prototip olacaktı. Eğer siz okunabilirliği artırmak istiyorsanız elbette argüman adlarını da yazabilirsiniz... Şimdi bu kadar bilgiyle artık kendimizi biraz daha derin matematiksel işlemlere verebiliriz. Matematiği sevmiyorsanız eğer, oyun programlamaya pek yanaşmayın derim :) Çünkü yapacağınız işlemler tamamı ile matematiğe ve mantığa bağlı olacaktır. Ki zaten pointer ve referanslarıda ilerde göreceğiniz üzere matematik üzerine değerlendireceksiniz. Eğer daha derine inmek gerekirse tüm bu sistemlerin 0 ve 1 lerden oluştuğunu artık anlamış olmanız gerekmektedir… Neyse konumuza devam edelim. Sırada faktöriyel hesabı yapan bir fonksiyonumuz var. Burada bunu yaparken hem değişik veri tiplerinde fonksiyon örneği yapacağız hem de bir fonksiyon içerisinde bir döngünün kullanımını göreceğiz… #include <iostream> using namespace std; int faktoriyel(int sayi) { int temp = 0; if(!(sayi>10)){ //Bu şekilde sayımız 10 dan büyük olamayacaktır for(long i = 1; i <= sayi; i++) { if(i==1)temp=i; else temp=i*temp; } } return temp; } void main() { int sayi; cout << "Lutfen faktoriyelini istediginiz sayiyi giriniz"; cin >> sayi; cout << sayi << "! = " << faktoriyel(sayi); system("pause"); } sayi değişkenine 5 girdiğimizi varsayarsak çıktı 120 olacaktır. 10 dan daha büyük bir değer girilmesini önlüyoruz. Çünkü eğer 10 dan büyük bir sayı girersek bu sefer bellek alanında taşma yaşarız ve hatalı bir sonuç elde ederiz. Ya da program hata verip çöker. Fonksiyonları anlamışsak bize bu kadarı şimdilik yeterli olacaktır. Eğer bu konuda daha fazla tecrübe edinirseniz kendi bellek yönetim sınıflarınızı yazar ve bu tarz sorunlardan uzak fonksiyonlar yazabilirsiniz. Sınıflar ve yapılar konusu ileri ki bir dersimizdir. O yüzden bu konuya burada değinmek istemiyorum… Bu arada merak etmiş olabilirsiniz neden long kullanmadığımızı. Faktöriyel sayıların sonuçlarının long için ayrılmış bellek alanını dahi aşabileceğine emin olabilirsiniz. O yüzden int veri tipi ile bu konuyu anlatmak yeterlidir... Şimdiki konumuz ise varsayılan argüman değerleridir. Diyelim ki bir fonksiyon yazdınız. Ama bazı argümanlara da değer girilmemesini istemiyorsunuz. Bu durumda o argümanlara varsayılan değerler atayabilirsiniz. Eğer o argümanlara değer girilmezse derleyici varsayılan değerleri ele alacaktır. Hemen örneğimize geçelim. Yine “topla()” adlı fonksiyonumuzu ele alalım. #include <iostream> using namespace std; int topla(int sayi1, int sayi2 = 8) { return sayi1 + sayi2; } void main() { cout << "Sayilarin toplami : " << topla(10) << endl; system("pause"); } Sonuç nedir dersiniz? Elbette 18 dir. Peki neden 15 değil de 18? Çünkü “topla()” fonksiyonunu çağırırken biz ilk argüman için yani sayi1 için 10 değerini girmiş oluyoruz. Eğer topla fonksiyonunu aşağıdaki gibi çağırmış olsaydık sonuç daha farklı olurdu elbette. #include <iostream> using namespace std; int topla(int sayi1, int sayi2 = 8) { return sayi1 + sayi2; } void main() { cout << "Sayilarin toplami : " << topla(10, 4) << endl; system("pause"); } Sonuç tabi ki 14 olacaktır. Ama diyelim ki hiçbir değer girilmeyecek. Bu durumda ne yapacağız. Elbette sayi1 e de bir varsayılan değer verebiliriz. Bu durumda fonksiyon boş argümanlı şekilde çağırıldığında derleyici varsayılan değerleri ele alıp sonucu döndürecektir. #include <iostream> using namespace std; int topla(int sayi1 = 5, int sayi2 = 8) { return sayi1 + sayi2; } void main() { cout << "Sayilarin toplami : " << topla() << endl; system("pause"); } Burada ki sonuçta tahmin edeceğiniz üzere 13 olacaktır. Bunu da bu şekilde anladıysak artık satır içi/yerel(inline) fonksiyonlara artık geçebiliriz. Normal bir fonksiyon bellek alanından kazandırabilmektedir. Fakat bu olay programınızın çalışma hızının çok az da olsa düşmesine sebep olmaktadır. Bunun aksine “inline” fonksiyonlar direkt olarak kod bloğu arasındaki kodları programda çağırıldıkları yere taşırlar. Eğer örnek vermek gerekirse. #include <iostream> using namespace std; inline int topla(int sayi1, int sayi2) { return sayi1 + sayi2; } void main() { int s1, s2; s1 = 4; s2 = 6; cout << "Sayilarin toplami : " << topla(s1, s2) << endl; system("pause"); } Sonuç bildiğiniz üzere 10 olacaktır. Peki fark nerede? #include <iostream> using namespace std; void main() { int s1, s2; s1 = 4; s2 = 6; cout << "Sayilarin toplami : " << s1 + s2 << endl; system("pause"); } İşte üstteki örnek ile alttaki örnek yapı olarak aynıdır. “inline” komutu girilince derleyici fonksiyonun kod bloğunda bulunan kodları direkt olarak fonksiyonun çağırıldığı yerlere yerleştirir. Bunu istediğiniz yerde kullanabilirsiniz. Elbette ki hayal gücünüze kalmış. C dilinde programlama yapmış olanlar “#define” makrolarını bilirler. İşte inline da C++ a özel bir makro fonksiyondur. Bu bilgileri kullanmak sizin hayal gücünüze kalmıştır. İlerde Sanal(virtual) ve Arkadaş(friend) fonksiyonlarıda ele alacağız. Fakat onların nesne yönelimli programlayla yakından ilişkisi bulunduğundan bu derste onlardan söz etmeyeceğiz. Dersimiz bu kadar. Anlayamadığınız, takıldığınız konu ve noktaları forumda belirtebilirsiniz. Herkese başarılar dilerim… Gönderen üye: Evren ACIGÜL (Bellerophon)
|