C/C++ da Fonksiyonlar
(1360 kelime) (1231 okuma)
Merhaba arkadaşlar.Başka bir başlangıç düzeyinde dökümanda tekrar
birlikteyiz.Bu dökümanda c/c++ dillerinde fonksiyonlardan bahsedeceğiz.
Önce basitçe fonksiyonların matematikte ki haline bakacağız daha sonra
c/c++ dillerinde nasıl yazıldıklarını ve nasıl parametre aldıklarını
inceleyeceğiz. Ardından sırasıyla nasıl fonksiyon üstüste yüklemesi
yapıldığını,bir fonksiyon ile bir değişkenin değerini nasıl kalıcı
şekilde değiştireceğimizi ve son olarak varsayılan
parametreleri(default parameters) göreceğiz.Uzatmadan başlayalım.
Matematikte Fonksiyonlar
Öncelikle fonksiyonların matematikteki hepimizin bildiği halini bir
görelim :
y = f(x)
Burada bir f(x) fonksiyonu var.Bu fonksiyonun ne yaptığını burada
göremiyoruz.Ama bu fonksiyona bir x parametresi yolladığımızı
anlıyoruz. Ayrıca bu fonksiyon hesaplandıktan sonra sonuçta oluşan
değer y olacak.
f(x) fonksiyonunun da şu olduğunu düşünelim :
f(x) = 2x2+3x+5
Artık f(x) fonksiyonunun ne yaptığını biliyoruz.Herhangi bir x
değeri için f(x) fonksiyonunu hesaplayabiliriz.Örneğin :
f(3) = 2*32+3*3+5
f(3) = 32
Yani y artık 32 oldu.Fonksiyonlar temel olarak böyle.Ayrıca
fonksiyonlara birden fazla parametre de yollayabilirsiniz.
y = f(x,y) gibi.
C/C++ da Fonksiyonlar
Peki c/c++ da nasıl oluyor bu iş?Aslında pek bi fark yok.Fonksiyonun
ismine karar veriyorsunuz,alacağı parametreleri ya da parametre
almamasını belirliyorsunuz.Sonra yapacağı işi belirliyorsunuz ve
programınız da kullanıyorsunuz. Zaten c/c++ herhangi bir program
yazdıysanız.çoktan bir fonksiyon kullandınız demektir :) Hangi
fonksiyon mu??Tabi ki main() :)
Şimdi main'e yakından bakalım.
void
main()
{
}
En basit haliyle yazabileceğimiz main bu.Aynı f(x) gibi düşünün.f(x)
fonksiyonunun aksine main burada herhangi bir parametre
almıyor.Matematikte bu pek işe yarar birşey değil yani parametre
almayan bir fonksiyon ama program yazarken parametreye ihtiyaç duymayan
fonksiyonlarınız olabilir.
main() in başında yazan void nedir?
void in anlamı hiç birşey demek.Boşluk,yokluk anlamlarına da
geliyor.Yani main() fonksiyonu tamamlanırken geri birşey
döndürmüyor.Halbuki f(x) fonksiyonu geriye yaptığı işlemin değerini
döndürüyordu.Bir de main() in geriye birşey döndüren haline bakalım.
int
main()
{
return 0;
}
Gördüğünüz gibi main'in geri döndüreceği tipi yazdık ve return
anahtar kelimesini(keyword) kullanarak istediğimiz değeri geri
gönderdik.Bu durumda 0 değeri işletim sistemine gidiyor çünkü main()
fonksiyonu programımızın ana fonksiyonu.
Şimdi dökümanın başında yazdığımız f(x) fonksiyonunu c/c++ da
yazalım.
int f(int x)
{
return (2*x*x+3*x+5);
}
Görüldüğü üzere f(x) fonksiyonu geriye tam sayı döndürecek
fonksiyonun ismi f ve tamsayı bir x parametresi alıyor.Fonksiyon ismini
yukarıdaki ile aynı olsun diye f yaptım ama buraya istediğiniz ismi
yazabilirsiniz(draw,render,patlican vs.. :D).Aynı şekilde parametre
olarak kullandığımız x değişkeni de herhangi bir isim alabilir. Tabi
fonksiyon içindeki formülde de bu isim kullanılmalı.Şimdi bu fonksiyonu
yaptığımız bir programda nasıl kullanırız onu görelim.
#include <stdio.h>
#include
<conio.h>
int f(int x)
{
return (2*x*x+3*x+5);
}
void
main()
{
int iParam = 0;
int iResult = 0;
printf("f(x)
fonksiyonu icin x parametresi alim canim : ");
scanf("%d",&iParam);
iResult =
f(iParam);
printf("%d",iResult);
getch();
}
Gördüğünüz gibi f fonksiyonunu main fonksiyonundan önce
yazdık.Böylece f fonksiyonunu main fonksiyonu içinde
kullanabiliyoruz.Bunu yapmanın bir başka yolu da main fonksiyonundan
önce fonksiyonun sadece tanımını yapmak ama gövdesini yani neler
yaptığını başka biyerde yazmak.Bunu da yazalım.
#include <stdio.h>
#include
<conio.h>
int f(int x);
void
main()
{
int iParam = 0;
int iResult = 0;
printf("f(x)
fonksiyonu icin x parametresi alim canim : ");
scanf("%d",&iParam);
iResult =
f(iParam);
printf("%d",iResult);
getch();
}
int f(int x)
{
return (2*x*x+3*x+5);
}
Bu nerede işimize yarar?Projemiz büyüdükçe birden fazla
kaynak(source) dosyamız olacak.Ve tabiki başlık(header)
dosyalarımız.Fonksiyonların başlığını başlık dosyasına gövdesini ise
istediğimiz bir kaynak dosyasına koyabiliriz.Daha sonra bu fonksiyonu
kullanmak istediğimizde tanımının bulunduğu başlık dosyasını eklememiz
yeterli olacaktır. Buna örnek görmek için dökümanla gelen kaynak
dosyasını inceleyebilirsiniz.
İki Parametre
Fonksiyonlara birkaç parametre birden yollayabileceğimizden
bahsetmiştik bunu yapmak için parantezlerin içine fonksiyonun alacağı
parametreleri sırası ile tiplerini belirterek yazıyoruz.Örneğin :
int
carp(int a,int
b)
{
return a*b;
}
Bu fonksiyon gönderilen iki tam sayı değeri çarpıyor ve sonucu geri
döndürüyor.İsterseniz farkli tipte parametreleri de fonksiyona
yollayabilirsiniz. Peki diyelim ki biz tamsayı değilde iki tane kesirli
sayı çarpmak istedik ancak yine carp isimli bir fonksiyon kullanmak
istiyoruz.Bunu nasıl yapıcaz?C de mümkün değil ancak farkli bir
fonksiyon yazip carp_kesirli gibi bunun parametrelerini ve döndüreceği
değeri float tipinde yapabiliriz.Örnek :
//Tam sayi carpan
fonksiyon
int
carp(int a,int
b)
{
return a*b;
}
//Kesirli sayi
carpan fonksiyon
float
carp_kesirli(float a,float
b)
{
return a*b;
}
Fonksiyon Üst Üste Yükleme(Function Overloading)
Bunun c++ da çok daha kullanışlı bir yolu var.Function
Overloading.Türkçeye direk çevirmeye kalkarsak fonksiyon aşırı
yüklemesi diyebiliriz.Ama ayıp etmiş oluruz :) Çünkü aşırı yükleme
falan yapmıyoruz.Fonksiyon üst üste yükleme diyelim daha iyi.Bir
fonksiyonu yüklediğimiz zaman fonksiyonun ismi aynı kalıyor ama ona
gönderdiğimiz parametre leri değiştirebiliyoruz.Yukarıda ki fonksiyonu
birde yükleme ile yapalım :
//Tam sayi carpan
fonksiyon
int
carp(int a,int
b)
{
return a*b;
}
//Kesirli sayi
carpan fonksiyon
float
carp(float a,float
b)
{
return a*b;
}
Görüldüğü üzere fonksiyon isimleri aynı ama farklı veri tipleri
üzerinde çalışıyorlar.Burada unutulmaması gereken bir fonksiyonu
yüklerken farklı olması gereken parametreler. Fonksiyonların sadece
dönüş tiplerini değiştirip yükleyemezsiniz.
//Tam sayi carpan
fonksiyon
int
carp(int a,int
b)
{
return a*b;
}
//Kesirli sayi
carpan fonksiyon
float
carp(int a,int
b)
{
return a*b;
}
Bu yazdığım hata verecektir.
Fonksiyon ile bir değişkenin değerini değiştirme
Eninde sonunda bunu yapmanız gerekecektir.Mesela bir değişkeniniz
var,atıyorum "speed" olsun.Bunu "stop" diye bir fonksiyona gönderip
sıfır olmasını istiyorsunuz. speed değişkeni main fonksiyonunda
tanımlı.Siz bunu parametre olarak fonksiyona yollayacaksınız.Şöyle bir
deneme yapalım :
#include <stdio.h>
#include
<conio.h>
int
stop(int deger)
{
deger = 0;
}
void
main()
{
int speed = 100;
printf("speed
degiskeninin su anki degeri %d",speed);
stop(speed);
printf("speed
degiskeninin su anki degeri %d",speed);
getch();
}
Bu programı yazıp çalıştırırsak alacağımız sonuç bizi şaşırtabilir
çünkü speed değişkeni ekrana iki defa 100 olarak yazılır.Halbuki biz bu
değişkeni stop fonksiyonuna yolladık ve fonksiyon içinde sıfıra
eşitledik.Ama neden bu değişiklik main fonksiyonuna yansımadı??Burada
bilinmesi gereken önemli birşey var.Ne zaman bir değişkeni bir
fonksiyona yollarsanız bu değişkenin o fonksiyon için bir kopyası
oluşur ve siz fonksiyon içinde bu kopyayı kullanırsınız.Yani aslında
"speed" değişkenini diil onunla aynı değere sahip olan kopyası "deger"
değişkenini değiştiriyoruz.Buna pass by value yani değerle göndermekte
deniyor.Gerçekten main fonksiyonu içindeki speed değişkenin değiştirmek
için yapabileceğimiz iki şey var.Bunlar işaretçi(pointer) veya
referans(reference) kullanmakBunların ikiside aynı işi yapıyor aslında
ama referanslar c++ da var.Temel mantıkları fonksiyona değişkenin
değerini yollamaktansa değişkenin bellekteki adresini yollamak böylece
o değişkeni kalıcı olarak değiştirilebiliyoruz.Şimdi yukarıdaki
programı bir de bunları kullanarak yapalım :
#include <stdio.h>
#include
<conio.h>
void
stop(int deger)
{
deger = 0;
}
void
stop_pointer(int *deger)
{
*deger =
0;
}
void stop_reference(int
°er)
{
deger = 0;
}
void
main()
{
int speed = 100;
printf("speed
degiskeninin su anki degeri %d",speed);
stop(speed);
printf("speed
degiskeninin su anki degeri %d",speed);
stop_pointer(&speed);
//veya
//stop_reference(speed);
getch();
}
Burada dikkat edilmesi gereken pointer kullanırken fonksiyona
değişkenin adresini yolladığımızı belirtmek (& ile).Ve fonksiyon
içinde değişkene ulaşmak için "*deger" kullanmak.Eğer deger i
kullanırsak işaretçinin gösterdiği adresi değiştiririz.Bunu istemiyoruz
:)Referans ile yollamada tek yapmamız gereken fonksiyon tanımında
parametre isminden önce & eklemek.
Varsayılan Parametreler (Default Parameters)
Son olarak bahsetmek istediğim konu varsayılan parametreler.Şimdiye
kadar gördüğümüz tüm fonksiyonlarda fonksiyonun parametrelerini
fonksiyonu kullanırken yazmak zorundaydık.Ama buna mecbur değiliz.Bazen
öyle durumlar oluyor ki bir fonksiyonun ilk parametresini siz girmek
istiyorsunuz ama diğer parametrelerin otomatik olarak doldurulmasını
istiyorsunuz.Ama gerektiğinde yine bu parametrelere değer
verebiliyorsunuz :) Karışık oldu biraz ondan örnek yazalım birtane:
#include <stdio.h>
#include
<conio.h>
float
findHeight(int t,float
g = 9.8f)
{
return 1.0f/2.0f*g*t*t);
}
void
main()
{
int time = 0;
printf("cismin
yere düsme süresini girin : ");
scanf("%d",&time);
printf("cisim %f
metreden dustu",findHeight(time));
getch();
}
Görüldüğü gibi fonksiyona sadece bir tek parametre
yolladık.İsteseydik ikinci parametreyide gönderebilirdik.Ama
göndermediğimiz zaman g değeri 9.8f olacaktır. Varsayılan
parametrelerde dikkat edilmesi gereken şey çok sayıda parametre varsa
ve bunlar default ise aradan herhangi bir parametreye değer veremeyecek
olmanız. Örneğin şöyle bir fonksiyon olsun :
void func(int t,int a = 9,int b =
1,int c = 2,int
d = 20);
Bu fonksiyonu programda kullanırken eğer c parametresine değer
vermek istiyorsak ondan önceki a ve b parametrelerine de değer vermek
zorundayız.Aradan karpuz gibi şeçmeye kalkarsak c/c++ hangi
parametreden bahsettiğimizi anlamaz.Örnek:
func(time,3,2,0);
Böyle çağırılmış fonksiyon t yi time'a,a'yı üçe,b'yi ikiye,c'yi
sıfıra ve d'yi yirmiye(varsayılan) eşitler.Hepsi bu.
Kapanış
Evet dökümanımızın sonuna geldik :).Fonksiyonlar gerçekten basit ve
her zaman kullanacağınız şeyler o yüzden öğrenmekte fayda var :)
Dökümanla birlikte gelen kaynak dosyalarında burda yazdığım
fonksiyonlarla yapılmış bir program bulabilirsiniz. Başka değinmek
istediğim bir konu:Fonksiyonlara gönderdiğiniz değişken eğer büyük bir
veri yapısı ise, buu pointer ya da referans olarak göndermeniz aksi
halde fonksiyon bu yapının bir kopyasını yaratmakla uğraşacaktık ve bu
zaman kaybına yok açar.
Dökümandaki yazım hatalarını ve diğer hataları farkedersek lütfen
paylaşalım Herkese İyi Çalışmalar.
Not : Bu döküman hazırlanırken bol miktarda kola,panço
tüketilmiştir.Ayrıca In Flames,NightWish,Ensiferum ve Hammerfall ile
ortam renklendirilmiştir :)
[
Bu dökümana ilişkin örnek dosyaları indirmek için tıklayın (16Kb) ]
Black_Knight :: Barış S. Uşaklı :: 2005 :: www.oyunyapimi.org
|