C++ bilindigi gibi programlama dünyasinda en çok ilgi gören C
dilinden türemistir. C++'i klasik C dilinden farkli yapan yani; Nesne Yönelimli
Programlamayi da ( Object Oriented Programming) C'nin sözdizimi kurallariyla
birlikte desteklemesidir. Normalde C ile sadece yapisal programlama yaparken
C++ dili ile hem yapisal hem de nesne yönelimli programlar yazabilirisiniz. C++
diline baslarken önce dilin C'den gelen ve temel olan özelliklerini ögrenmek
gerekir. Örnegin, degisken tanimlama, atama ve diger basit aritmektik islemler,
kontrol yapilari ve döngüler gibi.
Teknolojinin ulastigi son noktadaki programlama dillerinden olan
C ve C++, bir çok yeni ve güçlü özellikleri içerir. Derslerimiz devam ettikçe
bunlarin teker teker içine girecegiz. C dilinin özelliklerinin %80 i C++'da da
mevcuttur (bu karsilastirma sahsi görüsümdür). Zaten C++, C'nin üst gurubudur.
Bunu söyle siralayabiliriz. C, C++ ve C# dir.
C dilinin avantajlari, az komut kümesinden olusmasi ve bu
komutlarin diger yüksek seviyeli dillere nazaran daha hizli çalismasidir.
Ayrica C deki kütüphaneler sayesinde fonksiyon tanimlamaniza gerek kalmadan
islemlerinizi yapmak mümkün olacaktir. Bu konuda çok detaya inmeden,
programlamaya geçmek istiyorum. Çünkü, programlamaya basladigimizda her
örnekten sonra o an kullandigimiz programin içinde geçen fonksiyon, hata,
degisken, belirleyiciler, kisitlamalar, notasyonlar v.s gibi bilgilerden ara
ara bahsedecegim. Yalniz çok önemli olan bir konuya burada deginmek istiyorum.
C nin avantajlarini programlamayla birlikte görmek güzel ama C nin
dezavantajlarini programlamadan önce bilmeliyiz ki bunlardan sakinalim.
Öncelikle Tanimlayicilardan bahsetmek istiyorum. Her derleyici ve assmbley için
degiskenleri, sabitleri, etiketleri ve fonksiyon adlarini tanimlama kurallari
vardir. Bu notasyonlara, tanimlayici denir. C++ da tüm tanimlayicilar a, . . .
, z - A, . . . , Z harfleri ile ya da alt çizgi "_" ile baslar.
Bundan sonra rakam, harf, ya da alt çizgi kullanilabilir. ANCI C uyumlu derleyiciler
31 karaktere kadar tanimlayici kabul ederler fakat tanimlayicinin ilk sekiz
karakterini kullanmayi kendimize aliskanlik etmeliyiz. Dikkat etmemiz gereken
özelliklerden biri de kullandigimiz ifadelerdeki büyük küçük harflerdir. C ve
C++ büyük ve küçük harf duyarliligina sahiptir. Kullandigimiz ifadeleri
birbirinden farkli ve ayni ifade olarak kullaniyorsak programimiz hata
verecektir. Bunu bir örnekle anlatayim:
Program
program
PROGRAM
Bu sekilde tanimlarsak hepsi birbirinden farkli ifadeler olarak C++ da okunacaktir. Biz Sunu aliskanlik edinmeliyiz; tanimlayicilarimizin bas harfi büyük olacak. Büyük ve küçük harf kombinasyonlarinin kullanilmasi ile önceden yapilan tanimlamalar bazen isi zorlastirabilir. Eger bu degiskenlerden birini kullanmak isterseniz, bu zamana kadar nasil tanimladiginizi bilmeniz gerekir. Örnegin printf()`in PRINTF() olarak çagrilmasi durumunda " bilinmeyen tanimlayici " (Unknown identifier) hata mesaji vererek sizi uyarir. Buna benzer olarak %f ve %F kullanimi hata verdirecektir. Programlamayi yaparken bunlara dikkat etmemiz gerekecek. Çünkü bir degiskeni veya tanimlayiciyi basta nasil kullandiysaniz üç, dört sayfa kod yazdiktan sonrada ayni sekliyle kullanmak zorundasinizdir. Iste burada en büyük handikap yasanacaktir. Çünkü C/C++ derleyicileri her zaman hatanin nerde oldugunu göstermez. Bunu programci kendisi satir satir takip ederek bulacaktir. Bundan dolayi bu söylediklerime bastan dikkat etmemiz gerekiyor.
Ilk programimiz! // ilk1.cpp // Ekrana "Bu benim ilk programim" yazdiriyoruz #include <iostream.h> int main() { cout << "Bu benim ilk programim"; return 0; } |
Simdi Yazdigimiz programi inceleyelim:
"//"
isaretini açiklama satirlarinda kullaniyoruz. C++ derleyicisi bu notasyonla
baslayan satiri okumaz. Bununla birlikte daha uzun cümlelerimiz olursa bunlari
da " /* */ " notasyonunun içinde yazicagiz. Bu özellik de C den bize
kalma. Demistik zaten C `nin tüm özelliklerini C++ içerir. Fakat biz genelde
" // " yi kullanacagiz.
#include : Bu bizim C++
da bulunan kütüphane dosyamizi çagirmaya yariyor. Ben size söyle tarif edeyim.
iostream.h kütüphanesindeki hazir olan " cout " fonksiyonunu
çagiriyor. Yani buda bizim fazla kod yazmamiza engel oluyor. .h ile biten
dosyalar kütüphane dosyalaridir. Bunu suna da benzetebiliriz. Farz edelim ki
elimizde bir alet çantasi var içinden tornavidayi çagirdigimizda vida
sikacagizdir. Bu da ona benziyor. C++ da ki hazir kütüphanelerde bir çok hazir
fonksiyonlar vardir. Ilerde Bu hazir fonksiyonlar isimizi görmemeye baslayinca
kendi kütüphanemizi yapmaya baslayacagiz. Tabi bu seviyeye geldigimizde olayi
hemen hemen kavramis olacagiz, tabi neden olmasin öyle degil mi?
Daha sonraki satir her
C++ programinda mutlaka bulunmasi gereken bir satirdir. Her C++ programinda main()
fonksiyonu olmak zorundadir; bu fonksiyonumuzun önünde ise o fonksiyonun
dönderdigi degiskenin veri tipi olmalidir. Tabi ki C++ fonksiyonlar ve onlarin
dönderdikleri degerler konusunu da ileride isleyecegiz.
Bir sonraki satirda
ise; C++ fonksiyonlar ve kod bloklari " { } " parantezleri arasinda
bulunmalidir. main de bir fonksiyon ise onun içindeki kodlar dogal olarak { }
parantezleri arasindadir.
Program derlenip
çalistirildiginda ise ( Turbo C++ 3.1 kullaniyorsaniz ctrl+f9 kisa yoluyla
programi çalistirabilirsiniz (Run) ) karsimiza "Bu benim ilk
programim" yazisi çikacaktir. Iste bu yaziyi ekrana veren komut da
iostream.h kütüphanesindeki cout fonksiyonudur.
Önemli bir nokta ise
C++ dilinde her satir ifadenin sonuna " ; " koymak zorundayiz. Bundan
farkli olarak #include satirlarinin ve bir kaç farkli satirin arkasina " ;
" gelmez. Bunlari ileride görecegiz.
Return 0 :
programimizin (ayni zamanda main fonksiyonumuzun) çikis noktasidir. Eger return
ile 0 degeri dönderirsek programimizin güvenle çiktigini isletim sistemine
bildirmis oluruz. Bu sayede güvenle programimizin çalistigini görecegiz.
Simdi size bir örnek
daha verecegim bununla da ayni çiktiyi elde edecegiz. Arasindaki farklari
eminim basit olarak sizlerde göreceksinizdir.
// ilk2.cpp // Ekrana "Bu benim ilk programim" yazdiriyoruz #include <stdio.h> main() { printf("Selam bu benim ilk programim.\n"); return 0; } |
Evet simdi burada çok
fark varmis gibi gözüküyor aslinda ama öyle degil. Sadece kütüphanemiz stdio.h
oldu ve ekrana yazdir fonksiyonumuzda printf oldu. Bu özellik C den kalma.
Bunlar diger program ile ayni islevi görüyor. Buradaki fark " \n "
notasyonu. Bu notasyon bir sonraki satira geçmek için kullanilir.
Simdi bize yine çok
lazim olacak bir özellik de degisken tanimlamak ve atama yapmaktir. Bunu bir
örnek üzerinde anlatmak istiyorum. Örnegimiz;
// degisken.cpp // Burda degisken tanimlamayi görecegiz. // Ayni zamanda verilen bir sayiyi kendisi ile carpma 2.2=4 gibi #include <iostream.h> #include <stdio.h> // kütüphane dosyamiz main() { int i; // Degisken tanimlama cout << "Bir sayi giriniz: "; cin >> i; i=i*i; cout << "sonuc: " << i ; return 0; } |
|
Burada bundan önce
yaptigimiz programlardan farkli olarak int i kullandik, yani degisken tanimladik.
Degisken Nasil
Tanimlanir?
Degiskenleri
tanimlamak için asagidaki sema kullanilir.
[Veri Tipi] [Degisken
Adi];
Örnegin
int sayi;
Simdi degisken.cpp
örnegindeki int i; kismini anlamissinizdir. Burada degiskenlere deginmek
istiyorum. Biz yukarda Içinde sayi tutan bir degiskeni tanimladik. Benzer
olarak asagidaki tanimlamalar da vardir.
char c;
int i;
float f;
double d;
unsigned int ui;
Burada [Veri Tipi]
[Degisken Adi]; bu kaliba göre tanimlama yaptigimiz için önce Veri Tiplerini
inceleyelim.
1) Int tip.
Integer = Tamsayi
Tamsayilari içerir.
Bellekte 2 Byte tutar. DOS'ta ve Win3.1'de 16 bit uzunlugunda ama Windows9x,
WinNT, Win200 ve WinXP 32 bit uzunlugundadir.
Deger araliklari Short
ve long için degisir.
Örnek: 5, -20, 1 gibi.
2) Sort tip.
Tam sayilari içerir.
16 bit uzunlugundadir.
signed: -32768 ile
+32767 arasinda deger alir, unsigned: 0 ile 65535 arasinda deger alir.
3) Long tip.
Tam sayilar içerir. 32
bit uzunlugundadir.
signed: -2147483648
ile +2177483647 arasinda deger alir, unsigned: 0 ile 65535 arasinda deger alir.
4) Gerçel Tipler
(Float, Double, Long double
Gerçel sayilari
içerirler.
float : Bellekte 4
Byte yer tutar. 3.4E-38 ile 3.4E+38 araliginda deger alir. Hassasiyet 7-8
basamaktir.
double : Bellekte 8
Byte ter tutar. 1.7E-308 ile 1.7E308 araliginda deger alir. Hassasiyet 15-16
basamaktir.
long double :
doublenin tipinin daha genisidir.1.2E-4932 ile 1.2E-4932 araliginda deger alir.
Hassasiyet 19-20 basamak.
5) Char Tip
Char : Karakter
Alfanumerik
karakterleri içerir. Ve ya 8 bit uzunlugunda tamsayi.
signed: -128 ile 127
arasinda deger alir, unsigned: 0 ile 255 arasinda deger alir.
Örnegin: '
0,1,2,3,4,5,6,7,... ' , ' *,-,+,... ' , 'a,b,c,....,A,B,C,D,,,,, '
6) Bool tip.
true(dogru) = 1 veya
false(yanlis) = 0 degerini alir. Eski derleyiciler bu türü desteklemeyebilir.
Yeni ANSI C++ standardinda eklenmistir. Bu soyut matematik gördüyseniz. "p
V q" ya benzer :) ( matematikçiyiz, konusturalim azicik). Deger araligi
ise ya 1 dir (dogru) yada 0 dir (yanlis).
7) Enum tip.
enum siralanmis
degerleri tutar. Short int ile ayni degeri tasir.
Basta Fazla Detaya
inip sizi bunaltmak istemiyorum. Çünkü C++ dili baslarda karmasik gelen bir
dildir. Bu da zaten kendisini yüksek seviyeli bir dil yapiyor :). Ben size Bu
dilin temel özelliklerini anlatarak basit programlar yapmayi gösterecegim.
Bu temel bilgileri
aldiktan sonra programlamaya geçebiliriz. Derleyici Olarak ben Turbo C++ 3.1 i
tavsiye ederim. Su an bununla baslar iseniz isiniz daha kolay olacaktir
(bence). Ilerde Borland a geçecegiz.
Degisken tanimlama
konusunda bir konuya daha deginmek istiyorum. Degiskenlere deger atama ve ayni
anda bir çok degisken tanimlamamiz C++ da mümkündür.
char c = 'c';
int i = 5;
Daha sonradan deger
atama:
char c;
int i;
c = 'c ';
i = 5;
Bir de ayni anda bir
çok degisken tanimlayalim.
Örnegin:
int x , y , z;
x = y = z = 5;
x,y,z' nin degeri 5 oldu
Bir sonraki derste ise
degiskenlerle birlikte bir de Operatörleri ele alacagiz.
Bunu bir örnek
üzerinde anlatmak istiyorum. Örnegin; x + y ''de x ve y operand + ise
operatördür. Bu bir aritmetiksel operatördür. Matematikte islemler operatörler
ve operandlar ile anlatilir.
Operatörleri öncelikle
türlerine göre ayiralim:
1) Aritmetiksel
operatörler + , - , * , / , % , ++ , --
2) Karsilastirma
operatörleri < , > , <=, >= , ==, !=
3) Esitleme
operatörleri = , += , -=, *= , /= , %= , <=, >>=, &=, != , ^=
4) Mantiksal
Operatörler ! , || , &&
5) Bit bazinda islem
yapan operatörler & , ! , ^ , ~ ,
Matematiksel ifadeleri
günlük hayattaki biçimde bilgisayarda yazamadigimiz için belli kurallara
uymamiz gerekir. Bu kisim önemli oldugu için biraz genis yer verecegim.
Kullandigimiz matematiksel islemler ve anlamlari söyledir:
|
Bu operatörle verilen
iki veya daha fazla operand toplanabilir. Yazilis sekli Asagidaki gibidir.
degisken1 + degisken2
Eger bu iki degiskeni
Sonuç gibi baska bir degiskene atarsak esitleme operatörüyle asagidaki gibi
yapariz.
Sonuç = degisken1 +
degisken2
Buna bir örnek
verelim.
// toplama.cpp //Vize ve final notlarinindan geçme notunu hesaplama #include <iostream.h> #include <math.h> main() { int vize, final, ort; vize = 10; final = 80; ort = vize * 0.4 + final * 0.6; cout<< "Geçme notunuz: " << ort; } |
Burada çarpma
operatörünü de kullandik sanirim, artik digerlerinin de ne oldugunu kavramis
oldunuz. Bir örnekte isi ucuza getirdim :). Fakat bir artma ve bir azalmaya
örnek verelim. Bu bana çok lazim olmustu.
Burada dikkat etmemiz
gereken olay " ++
" operatörünü degiskenin önüne yazmaniz gerektigidir. Bu
sayede degisken bir arttirilarak isleme konur. Arkasina konursa degisken
islenir, sonra bir arttirilir. " --
" operatöründe
ise ayni sekilde de bir azaltma yapilir.
// carpim.cpp // x i bir arttirip y yi bir azaltip çarptik. #include <iostream.h> main() { int x = 5; int y = 10; cout << "x = " <<x << endl; cout << "y = " << y << endl; cout <<"++x * --y = " << ++x * --y ; } |
Iste bir fark daha
yakaladik bunu da hemen örnek üzerinde anlatalim. Sanirim buraya kadar
geldigimiz yerlerde int
i , çarpma islemini, bir arttirip azaltmayi
gördük, ama diyeceksiniz ki " endl
" ne oluyor?
Hemen açiklayayim; Satir sonunu belirterek yeni satira geçmemizi saglar, bir
nevi " \n
" Escape operatörü gibi bir isleve sahiptir.
|
Bunlarin teker teker
ne oldugunu söylemeye gerek yok. Ifadeler gayet basittir. Burada dikkat etmemiz
gereken önemli bir sey var: " >=
, <=
, ==
, !=
" notasyonlarini
kullanirken iki notasyon arasinda bosluk birakmamaliyiz. Buna dikkat edelim!
Bunlarida liste
halinda verelim.
|
if komutu anlasilmasi ve
yazilimi en basit olanidir. if komutu, bir grup komutun kosullu olarak
yürütülmesi amaciyla kullanilir. Buna bir örnek verecek olursak; düsünün ki bir
sinav yapiliyor ve 50 ve üzeri alanlar geçecek. Bunun için if i
kullanirsak not 50 ye esit veya büyükse (büyük esit) geçer not olacak.
//not.cpp // 50 ve 50 den yukarsi geçiyor. #include <iostream.h> main() { int not; cout << "Notu yaziniz:"; cin >> not; if ( not >= 50 ) cout << "Geçtiniz!"; } |
Sanirim bu örnekte ne
dedigimi anlamis olacaksiniz.
if ( not >= 50 ) cout << "Geçtiniz!"; if (ifade) { Komut; Komut; ... } |
Burda görüldügü gibi if
(ifade) ve sonraki komutlarda { }
blogunun içine
yazilir. Simdi if`e bir de su açidan yaklasalim. if in kelime anlami
"eger" dir. Mantik sudur: eger belirtilen parametre dogruysa, if
komutu, if ten sonra gelen bloktaki fonksiyonlari gerçeklestirir. Dogru
degilse, if den sonraki blogu yok sayar. Burada bir detaya daha inmek
istiyorum. Ne demistik, mantik islemlerinde olay ya dogrudur (1) ya da
yanlistir (0). Simdi yukaridaki if in genel kullanim sekline tekrar bakalim.
Bunu, eger parametre dogru ise kullanabiliriz. Bir de bunun tersini düsünelim.
Bit bazinda islemlerde sanirim ( !
) bunu görmüstük. Her
bir biti ters çevirir.
if (!ifade) { komut (yanlis (0)); Komut (yanlis (0)); .... } |
Derdimi anlamis oldugunuzu
ümit ediyorum :). Ama bence buranin üstünde biraz daha duralim. Çünkü bunu
anlarsak digerlerinde zorlanmayiz. Son yaptigimizda ifadeyi tersine çevirdik.
//pozitif.cpp // Bunada açiklama yaptirmayin:) ( yapamadimda) #include <iostream.h> main() { int x; cout << "Bir sayi girin:" ; cin>> x; if ( x > 0 ) cout << "Pozitif" ; } |
Aynisinin negatif ini
de siz yapin. Simdi bir de iç içe if örnegine bakalim:
//gecti.cpp // Buna açiklama yapmiycam! #include <iostream.h> main() { int not; cout << "Notunuzu giriniz:"; cin >> not; if ( not> 50) cout << "Geçtiniz!" ; if (not < 50) cout << "Kaldiniz!" ; if ( not==50) cout << "zar zor geçtin :)"; } |
Anlamis oldugunuzu
umut ederek if komutunu burada bitiriyorum.
if-else komutu iki islemden
hangisinin uygulanacagina karar verir. Else kismi seçimlidir,
gerekmiyorsa kullanilmayabilir. Yazilim kurali ile söyledir;
if ( ifade)
komut1;
else
komut2;
daha genel sekliyle
if ( ifade )
{
komut1;
komut2;
...
}
else
{
komut1;
komut2;
...
}
Veya lojik olarak
baktigimizda sanirim daha iyi anlayacaksiniz
if (ifade)
blok_dogru (1);
else
blok_yanlis (0);
Sanirim artik açiklama
yapmama gerek kalmayacak. Simdi örneklerle bunu pekistirmeye çalisalim.
//tekcift.cpp //sayi tekmi çiftmi onu görücegiz #include <iostream.h> main() { int sayi; cout<< "Bir sayi giriniz:"; cin >> sayi; if (sayi %2==1 ) cout <<"tek"; else cout << "çift" ; } |
Bir örnek daha
verelim:
//ifelse.cpp #include <iostream.h> main() { int not; cout<< "Notu giriniz:"; cin >> not; if (not >= 50) cout << "Geçti!"; else cout << "Kaldi!"; } |
if kismindan anlatmaya
baslayacagim. Eger notumuz 50 ye esit veya 50 den büyük ise geçiyoruz aksi
halde kaliyoruz.
Bir de bir if-else in
altinda bir tane daha if-else kullanalim.
//sinav.cpp // alt alta if-else #include <iostream.h> main() { int not; cout<< "Not`u giriniz:"; cin >> not; if (not >= 50) cout << "Geçtiniz!"; else { cout <<"Bütten alinan not:"; cin >>not; if( not>=60 ) cout << "Geçtiniz!"; else cout <<"Kaldiniz!"; } } |
Burada da sunu
inceledik: diyelim ki sinava girdik ve notumuzu ögrendik, notu giriyoruz 50 nin
altindaysa kaliyoruz. ve bütünleme sinavina giriyoruz. Bütte de geçer not en az
60. Sanirim bu basit örneklerle olayi iyice kavramisizdir. if-else i de burada
bitiriyoruz.
Bu komut, yalnizca C++
a özgüdür. Kendine özgü bir yazilimi ve mantiksal kullanimi vardir. if-else
komutunun kisaltilmisidir. Fakat, tüm if-else komutlari yerine kullanilmaz.
Yalnizca karsilastirma sonrasi, tek komut kullanilan uygulamalar için
geçerlidir. Bu söylediklerimizi örnek üstünde gösterelim:
//tekcift.cpp //tekcift.cpp yi bu sefer ?: ile yapiyoruz #include <iostream.h> main() { int sayi; cout<< "Bir sayi giriniz:"; cin >> sayi; cout << (sayi %2==1 ? "tek" : "çift") ; } |
Kullanis biçimi: cout
<< (sayi %2==1 ? "tek" : "çift") ;
çok basit ama dikkat
edelim. Her zaman kullanmiyoruz.
Switch Case deyimi
islev bakimindan if deyimine çok benzemektedir. Çok sayida if islem bloklari
kullandigimizda programin okunurlugu azalacak ve programi izlemek
zorlasacaktir. Programimizin bir degerini bir çok degerle karsilastirmak
gerektiginde switch komutunu kullanacagiz. Switch seçenegi ile degiskenin
durumuna göre bir çok durum içersinden bir tanesi gerçeklestirilir. Istersek de
if deyimi ile switch case'' yi birlikte kullanabiliriz. Switch in yaptigi is
kisaca, ifadenin degerini sirayla sabitlerle karsilastirarak ve her satiri
islemektir.
switch( Kontrol Degiskeni ) { case Sabit1 : komut1; case Sabit2 : komut2; . . . default : Komutson; } |
//switch.cpp // switch-case yi ögreniyoruz. #include <iostream.h> main() { int i; cout<< " 1 ile 4 arasi sir sayi giriniz:"; cin>>i; switch(i) { case 1 :cout<<"1 Girdiniz"; break; case 2 :cout<<"2 Girdiniz"; break; case 3 :cout<<"3 Girdiniz"; break; case 4 :cout<<"4 Girdiniz"; break; default:cout<<"1 ile 4 ten farkli"; } } |
Burada gördügümüz gibi
i degiskenine bagli olarak program isliyor. Case''lerinin aldigi degere göre
kendinden sonra gelen komutlari isliyorlar. Burada daha önce görmedigimiz break
komutunu gördük. Buna ilerde daha detayli olarak deginecegim. Fakat biraz
bahsetmek istiyorum. Programimizda degiskene 1 degerini verdigimizi farz
edelim. Case 1 adli satiri geçip ondan sonraki komut dizisini isleme soktuk. Bu
islemin tamamlanmasi için break komutu kullaniliyor. Yazilimda break komutu
goto gibi islev görür ve derleyiciye switch komutundan çikmasi için talimat
verir. Sorunu ortadan kaldirmak için her durum için break deyimi eklemeliyiz
(tavsiye). Ne demistik; bir çok karsilastirma oldugunda switch''e ihtiyaç
duyuyoruz. Karsilastirmalarin hiç biri olmadigi anda da ortaya default tan
sonraki satirin islenmesi kaliyor. Sanirim bu örnekte basit olarak anlamis
olacagiz.
Daha karmasik bir
örnek verecek olursak:
//ucgen.cpp // Program girecegimiz ölçülere göre üçgenin Alan, Yükseklik ve Tabanini bulur // switch-case örnegimiz. #include <iostream.h> int main() { char secenek; float alan, yukseklik, taban; cout << "Program girecegimiz ölçülere göre üçgen''in Alan, Yükseklik ve Tabanini bulur!\n" << endl << " A ---> Alan : Bulmak için yükseklik ve tabani girecegiz:" << endl << " h ---> Yükseklik : Bulmak için alan ve tabani girecegiz:" << endl << " t ---> Taban : Bulmak için alan ve yüksekligi girecegiz:" << endl << endl << endl; cout<< "Seçeneginiz? ---> A, h, t :"; cin>> secenek; switch(secenek) { case ''a'': case ''A'': { cout<< endl <<endl <<"Yükseklik: "; cin>> yukseklik; cout<<endl << "Taban: "; cin >> taban; alan = 0.5 * taban * yukseklik; cout<<endl << endl << "Alani: " << alan << endl; break; } case ''h'': case ''H'': { cout<< endl << endl <<"Alani: "; cin>> alan; cout<<endl << "Tanabi: "; cin >> taban; yukseklik = 2.0 * alan / taban; cout << endl << endl << "Yükselik: " << yukseklik << endl; break; } case ''t'': case ''T'': { cout << endl <<endl <<"Alani: "; cin >> alan; cout << endl << "Yüksekligi: "; cin >> yukseklik; taban = 2.0 * yukseklik / alan; cout << endl << endl <<"Tabani: " << taban << endl; break; } } return 0; } |
Gayet basit bir örnek
degiskenleri tanimladik. Caseleri koyduk ve caselerden sonra gelecek komut
satirlarini yerlestirdik. Bu program göründügü gibi zor degildir.
Içlerinde anlatimi ve
anlasilmasi en kolay olan döngüdür. While döngüsü, döngü sayisinin belli
olmadigi zamanlarda kullanilir.
while ( kosul )
Komut;
While döngüsü, içinde
bulunan ifade dogru oldugu sürece altindaki komut veya komut blogu yürütülür.
Eger yanlis ise kontrol bir sonraki komut veya komut bloguna geçer.
while ( ifade )
{
komut;
komut;
komut;
.
.
.
}
Burada bir seye dikkat
etmenizi istiyorum. Çoklu komutlar kullandigimizda " { }
"parantezleri
gereklidir.
// while1.cpp // while döngüsünü kullandik // girdigimiz sayidan 100 e kadar olan sayilari topladik #include <iostream.h> main() { int x, y; y= 0; cout<< " Bir Sayi Giriniz ( Sayi 100 den küçük olucak ) : "; cin>>x; while (x< 101) { y =y+x; x =x+1; } cout<< "Toplam= "<< y; } |
Burada önce x ve y yi
tanimladik. y=0 degerini verdik. Sonra klavyeden girilen degerin x oldugunu
yazdik. while (x< 101)
iste burada ifademiz x< 101. Simdi bu
kosul saglanincaya kadar döngümüz devam edecek. While'' den sonraki bloga
geçtigimizde ise. y` ye x i ekliyoruz ve x in degerini her seferinde 1
arttiriyoruz. Sanirim bu basit örnekte döngünün basit yapisini ve mantigini
anlamis oldunuz.
Döngünün verilen ifade
veya kosula göre saglanmasi döngülerin en önemli konusudur. Eger bir döngüden
çikilmazsa o döngü sonsuza gider. Buna da "sonsuz döngü" denir.
Döngüler konusunda en çok rastlayacagimiz hata da budur.Simdi buna bir örnek
verelim. Fakat, simdiden uyariyorum, sonsuz döngü yapildiginda bilgisayariniz
kilitlenebilir. Onun için buna simdiden hazir olun. Zaten bir sefer
denedigimizde ne demek istedigimi anlayacaksinizdir.
//sonsuz.cpp //while döngüsü ile sonsuz bir döngü yaptik #include <iostream.h> main() { int x=1; while(x) cout<< "x= "<< x++<< endl; } |
Burada neden sonsuz
bir döngü oldu? Evet iste x ifadesini kosula baglamadik. Sayet while(x<10)
demis olsaydik.
1,2,3,4,5,6,7,8,9 a kadar x sayisi siralanacakti.
//klavye.cpp //while döngüsü ile klavyeden girilen sayi #include <iostream.h> main() { int x, y = 0; while (y< 20) { cin>>x; y = y+x; } cout<< "Toplam= "<< y ; } |
Bu programda da
klavyeden girilen sayilarin toplami 20'' den büyük olunca program Toplam olarak
söylüyor. Sanirim basit While yapisini anladiniz. Simdi birazda karmasik
programciklar yapalim:).
1. Örnek: Girilen alti
not''un ortalamasini aliyor.
//ortalama.cpp // while döngüsü ile girilen notlarin ortalamasini aldik. #include <iostream.h> int main() { int toplam, sayac, not, ortalama; toplam = 0; sayac = 1; while ( sayac <= 6 ) { cout << "Notu giriniz: "; cin >>not; toplam = toplam + not; sayac = sayac + 1; } ortalama = toplam / 6; cout << "Sinif ortalamasi = " << ortalama << endl; return 0; } |
Bu örnegimizde yine
toplam, sayac, not, ortalama gibi degiskenleri tanimladik. ( toplam
=0 ; ve sayac = 1; )
de degiskenlere ilk degerlerini atadik. While döngüsünün
içinde sayac degiskenimizi alti defa islemesini söyledik. Sonra alttaki toplam
ve sayac bölümlerinde ise toplam a not'' u ekliyoruz, her seferinde de sayac
degerini bir arttiriyoruz ve sayac degeri 6'' ya gelince while döngümüz
duruyor. Program sonra toplami alip altiya böler bu sayede ortalamayi alir,
sonrada çiktisini gerçeklestirir.
2. Örnek:
//faktoriyel.cpp // while ile faktoriyel hesaplama #include <iostream.h> int main() { int sayi; long int faktoriyel=1; cout << "Bir sayi giriniz: "; cin >> sayi; cout << sayi << " `in Faktöriyeli: "; while (sayi > 1) faktoriyel *= sayi--; cout << faktoriyel << endl; return 0; } |
Burda while
(sayi>1) seklinde kosulumuzu belirttik. Bir altinda ise faktoriyel
*= sayi--;
evet burda da daha önce gördügümüz gibi esitleme operatörü olan
( *= ) i kullandik. Yani faktoriyel''e faktoriyel*sayi-- nin degeri atanir.
Matematigini düsünürseniz; 7 sayisinin faktöriyeli 7 *= 7-- gibi. yani 7 ye
devamli 7-- oda 6 demektir. 6 ile carpimi eklenir, bu 6-- ile devam eder. En
basit anlatimi bu:) Sonrada tüm while döngüsü bittikten sonrada faktoriyel'' in
sonucu çikti olarak ekrana gelir. Bu örnekte negatif sayilarin faktöriyelini de
1''e esit tutuyor. Dikkat ediniz. Negatif sayilarin faktöriyeli alinmaz sartini
koymadik. Sayet siz koymak isterseniz bir if else blogu yerlestirmelisiniz
if(sayi>=0) faktoriyel al yoksa faktoriyel alma gibi.
3. Örnek:
// maas.cpp // while if-else ile bir maas vergi uygulamasi #include <iostream.h> int main( ) { unsigned long maas, net, vergi = 0.0; // maas net vergi bunlari tanimladik cout<< "Lütfen maasinizi giriniz: "; // maasi giriyoruz cin>> maas; // maasi programa aliyoruz while( maas >= 0.0 ) // maasin koslunu yaziyorus döngüye { if( maas <= 250000000 ) // maas 250 milyondan az ise vergi = 0.0; else // vergi yok:) if( maas < 500000000 ) // maas 500 den az ise vergi = maas * 0.10; // vergi %10 else // 500 den fazla ise vergi = maas * 0.20; // vergi %20 net = maas - vergi; // net maasimiz vergi düsünce çikar cout<< "Ödenmesi Gereken vergi " << vergi << endl; // vergi ekranda cout<< "Net maasiniz: " << net << endl; // geriye kalan maasimiz cout<< "Lütfen maasinizi giriniz: "; // bir dahaki ayki yeni maasimiz cin>> maas; // maasi program aliyor } return 1; } |
Bu örnekte sanirim
fazla açiklama yok. Sizden istedigim, üç kisinin maasini girdikten sonra
onlarin alacagi toplam maas ve ödemeleri gereken toplam vergiyi bulmaniz. Bunu
yaparsaniz buraya kadar olanlardan bir seyler anlamisizdir.
For döngüsünün
çalismasi, döngünün kontrol degiskenine baslangiç degerinin atanmasi ile
baslar. Asagida verecegimiz ilk deger atama cümlesinden kastimizda budur. Yani
bu kisimda baslangiç tanimlari yapilir. For döngüsünün baslangiç adimidir. Bu
kisimda yapilan bir degisken tanimindaki degiskenin ömrü, for döngüsünün sonunda
biter. Sonra döngü kosul kismina gelinir ve bu test edilir. Sayet degeri !0,
dogru (1) oldugunda döngü içindeki komutlar uygulanir. Arttirma ise for döngüsü
isleminin sonunda meydana gelir. for içindeki tüm deyimler meydana geldikten
sonra uygulanir.
Genel yapisi:
for ( ilk deger atamalar, kosul, arttirma)
cümle
Bunu daha da
genellersek, digerlerinde de oldugu gibi cümleler birden fazla oldugunda komut
blogu arasina alinacaktir.
for ( ilk deger atamalar, kosul, arttirma)
{
cümle1
cümle2
cümle3
...
}
Bu söylediklerimizi
bir örnek üzerinde izah edelim.
//for.cpp // for döngüsüyle bir örnek. #include <iostream.h> int main () { for (int n=10; n> 0; n--) { cout << n << " -> "; } cout<< "Bitti!"; return 0; } |
Ben sadece for (int
n=10; n>0; n--)
bu kismi anlatacagim, diger kisimlar apaçik gözüküyor zaten.
For diyip () imizi açtik. Sonra içine ilk basamagimiz olan degisken
tanimlamamizi yaptik. Int n=10; Bu bizim yukarida bahsettigimiz ilk deger atamalar
kismi. Daha sonra kosulumuzu yazdik. n>0; bunu test ettik ve !0 yani dogru
(1) çikti. Sonrada n-- yi yazdik. Genel tanimda yazdigimiz arttirma kismi.
Aslinda buna yenileme komutlari desek daha dogru olur. Biz bu örnekte örnegin
azaltma yaptik. Neyse umarim bu for örnegini anlamissinizdir.
C++ da yapacagimiz
çogu örnekte for u kullanacagiz. C++ ''nin en güçlü yanlarindan biriside for
döngüsüdür. For döngüsünün basinda yani ilk deger atama kisminda birden çok
degisken tanimlayip deger atiyorsak bunlari virgül ( ,
) ile bir birinden
ayirmaliyiz. Ilk deger atamadan kosul bölümüne geçtigimizde ve kosul bölümünden
arttirma ya geçerken noktali virgül ( ;
) kullanmaliyiz. Tabi
kullandigimiz bu üç kisim seçimlidir istersek bos birakabiliriz. Fakat, noktali
virgüller ( ;
) konulmasi zorunludur.
1.Örnegimiz:
//factoriyel_for.cpp //for döngüsüyle faktöriyel hesap. #include <iostream.h> int main() { int fac, sayi; cout<<"Sayiyi giriniz: "; cin>>sayi; fac=1; for (int j=1; j<=sayi; j++) { fac=fac*j; } cout<<"Sonuc: \a"<< fac; return 0; } |
Bu örnegimiz oldukça
basit. Bildigimiz matematiksel faktöriyel islemini C++ kodlari olarak yazdik.
(\a yi kullandim bip! demesi için:) ).
2.Örnegimiz:
//carpim_for.cpp // iç içe for döngüsüyle çarpim tablosu #include <iostream.h> main() { cout<<"Çarpim Tablosu! \n"<<endl; int x,y; for (x=1; x<=10; x++) { for (y =1; y<=10; y++) cout<<" "<<x*y; cout<<"\n"; } } |
Görüldügü gibi ilk for
döngüsünde, birinci bilesen olan x i önce 1 e esitledik sonra birer arttirarak
10'' a kadar götürdük. Sonraki for da da aynisini y için yaptik ve bu iki
bileseni çarparak ekrana yazdirdik. Son derece basit bir örnek.
3.Örnegimiz:
//asal_for.cpp // for , if ve while ile asal sayi bulma #include <iostream.h> int main() { int sayi; cout << "Bir sayi girinizr: "; cin >> sayi; for (int sayac=1; sayac< sayi; sayac++) { int asal, test; test = sayac; asal = 1; while (test--> 2) if ((sayac % test) == 0) asal = 0; if (asal == 1) cout<< sayac << " bir asal sayidir!\n"; } return 0; } |
Bu örnegimizde ikinci
örnegimize benziyor. Içinde for, while ve if de var. While ve if'' in içindeki
matematiksel ifadeleri biliyorsak örnek gayet basit gelicektir. Burada birakmak
istiyorum. Bir sonraki ders görüsmek üzere.
Break komutunu, swtich
komutundan çikmak için önceki derslerimizde görmüstük. Komutun kendine özgü bir
kullanimi daha vardir. Break komutu bir döngünün içinde çalistirilirsa o an o
döngü biter. Bir goto gibi islem gördügünü de söyleyebiliriz. Break kullaninca
program döngüyü bitirir ve döngünün sonundaki satirdan çalismaya devam eder.
Bir örnek verelim.
//break.cpp //break komutunu kullandik. #include <iostream.h> main() { for (int x = 1; x <= 10; x++) { if (x == 7) { break; } cout<< x << " "; } } |
Iste örnegimizde
gördügünüz gibi. X 7''ye esit olunca break; döngüyü bitiriyor ve döngüden
sonraki satiri çalistirmaya basliyor.
Hayati hata
durumlarini ele almak için exit() fonksiyonundan yararlanilir. Bu hatalar
main() fonksiyonunu return ile normal olarak sonlandirilmadan önce olusabilir.
Exit() fonksiyonu, durum degerini bir tam sayi parametre olarak döndürür.
Exit() ile özel bir
degerin gönderilmesi bazi islemler yapmasi için kullanilabilir. Örnegin program
komut satirinda kullaniliyorsa ve durum degeri bazi hatalari gösteriyorsa,
isletim sistemi bunlari mesaj olarak yazabilir. Exit() fonksiyonu programi
sonlandirmanin yaninda, tüm bekleyen yazma islemlerini tamamlar ve açik tüm
dosyalari kapatir.
Exit() fonksiyonunu
kullanirken kullanmamiz gerek kütüphaneler ise process.h ve stdlib.h tir.
Bundan sonraki
bölümlerdeki kullanacagimiz derleyici Borland Turbo C++ 4.5 tir. Fazla
zorlanmayacaginizi umut ediyorum. Kolay anladiginiz yerlere lütfen dikkat
ediniz. Hata yapma olasiliginiz daha da çok artmaktadir. Yapacaginiz hatalar
programin çökmesine, belki de sistemin zarar görmesine sebep olabilir. Lütfen
vermis oldugum uyarilara ve tavsiyelere uymaya çalisin. Sizin de tavsiyeniz
olursa bana bildiriniz:). Haydi kolay gelsin...
Fonksiyonlarin
programlama hayatina girmesi ile daha büyük boyutta sistemlerin tasarimi mümkün
hale gelmistir. Fonksiyonlar ile alakali derslerimizde, fonksiyonlarin
tanimlanmasi ve kullanimi hakkinda bilgi edineceksiniz. Fonksiyonlar konusu
size her ne kadar ilk bakista "Fonksiyon" adi altinda bir konu gibi
gelse de, aslinda bir alt programdir. Hatta programimizin içine, kodlamamizin
daha kolay ve gelistirilebilir hale gelmesini saglayan programciklar da
diyebiliriz.
Daha önce baska bir
programlama dili gördüyseniz (yüksek seviyeli diller), bu konuda fazla
zorlanmayacaksinizdir. Diger yüksek seviyeli dillerdeki fonksiyon kullanimina
çok benzemektedir. Hiç bilmediginizi farz ederek konuya giris yapalim.
Fonksiyon Nedir?
Örnegin, y=F(x)
fonksiyonu; Bu matematiksel fonksiyon parametre olarak aldinan deger üzerinde
bir islem gerçeklestirip, bir sonuç degerini döndürür. Mesela F(x)=x^3+5
seklinde bir fonksiyonumuz olsun, x=2 için F(x)=13 olur. Burada x fonksiyonun
parametresi, 13 ise fonksiyonun geri döndürdügü degerdir. Simdi de bu
matematiksel ifadeyi kodlarimizla yorumlayalim.
Int x;
x=F(2,5)
//buradan da " int f(2,5)
" gibi görebiliriz...
Dikkat edersek ikinci
satirda, daha önce islemedigimiz bir kod var. Int x
, F(2,5) degerine
esitlenmistir. Simdi bir fonksiyonun nasil yazildiginin kalibini çikartabiliriz.
<Döndürdügü deger> <Fonksiyonun adi> ( <parametre listesi> ) { <ifadeler> } |
Buradaki parantezlere
ve küme isaretlerine dikkat ediniz. Simdi yukarda yazdigimiz kalibi biraz
açalim.
<Döndürdügü
deger> : Fonksiyon her hangi bir tipte deger döndürebilir. Bu bilesen
fonksiyonun döndürecegi degerin tipini ifade eder. (örnegin, int, dounle, float
v.s v.s )
<Fonksiyonun
adi> :
Yapmak istedigimiz islemin adidir. Örnegin bir asal sayi fonksiyonu yazacagiz.
Burada yazacagimiz fonksiyonun adini belirtiyoruz. Benim size tavsiyem AsalSayi
veya asal_sayi seklinde kullanmanizdir. Okunabilirlik açisindan size avantaj
saglayacaktir.
<parametre
listesi> : Fonksiyonun kullanacaga parametrelerin tipleri ile siralanir.
Örnegin, FonksiyonAdi(int x, double y)
gibi.
<ifadeler> : Fonksiyonun
kullanacagi tanimlamalar ve kodlardan olusan kisimdir. Nasil biz main() {
kodlar }
seklinde kullaniyorsak. Bunu da ona benzetebiliriz. Ama main()
i bunlarla karistirmayiniz.
Simdi bu fonksiyon
kalibina uygun bir kod yazalim. Örnegin, Faktoriyel bulma islemini ele alalim.
Biz bir sayinin Faktörüyelini nasil bulurduk?
n!=n(n-1)(n-2)...1 Yani, 1 den n e kadar
olan sayilarin çarpimidir.
long Faktoriyel(int n) { return n*Faktoriyel(n-1); } |
Evet, burada
fonksiyonumuzu tanimladik. Sanirim yukaridaki blokla karsilastirinca, ne kadar
kolay oldugunu sizde görmüssünüzdür. Simdi bu Faktoriyel fonksiyonumuzu nasil
bir programda kullanacagiz? Hemen devamini yazayim.
long Faktoriyel(int n) { return n*Faktoriyel(n-1); } void main() { cout<<"5! (Bes Faktoriyel)= "<<Faktoriyel(5); } |
Iste gördügünüz gibi
ne kadar basit degil mi? J Fonksiyonumuzu tanimladik. Sonra programimizda n`e 5
degerini verdik. Faktoriyel fonksiyonu hesaplayip bize söyledi.
Biraz da yaygin
yapilan hatalardan ve dikkat etmemiz gereken noktalardan bahsedelim. Kodlama
yaparken fonksiyon adini belirttigim sekilde yazarsaniz 30-40 sayfalik kodlarda
hata bulmaniz ve de fonksiyonlarin yerini belirlemeniz açisindan büyük kolaylik
olucaktir. Yukarida verdigimiz x=F(2,5) fonksiyonununu göz önünde tutalim.
Görüldügü gibi F(2,5) degeri x e atanmistir. Hiç bir zaman Fonksiyonun aldigi
deger sola yazilmaz. Ayrica bir Fonksiyon çagrisi, baska bir fonksiyonun
çagrisi olabilir. Örnegin, x=F(a,F(a,5) gibi. Burada F Fonksiyonun iki
parametresi vardir a ve F(a,5) dir. Bu durumda öncelikle parametreler
hesaplananacagi için F(a,5) in degeri ile a nin degeri F te parametreler olarak
kullanilir.
Diziler, "indisleri
olan degiskenler" olarak adlandirilirlar. Diger bir deyisle, birden
fazla tek düze veri tipi içeren degiskenlerdir. Diziler birbirine bitisik
bellek gözleri kullanilarak olusturulurlar. Bunu biraz daha açarsak: farz
edelim ki elimizde üç tane kutu var, birinde yesil kalemler, birinde kirmizi
kalemler ve birinde de mavi kalemler olsun. Bu kutucuklari 1,2,3 diye
adlandirdigimizi düsünelim. Biz diziler ile numarasini bildigimiz kutucugun
içindeki malzemeyi alabilecegiz. Daha dogrusu numarasini vermis oldugumuz
kutunun içindeki bilgiyi bilgisayar okuyacaktir.
Not: For döngüsü dizi
elemanlarina ulasmak için en çok kullanilan yöntemdir.
Dizilerin indislerden
olustugunu söylemistik. Diger yüksek seviyeli dillerle karsilastirildiginda
arasindaki fark ilk elemanin indisi daima sifir (0)
olmasidir.
for(int i=0; i<boyut; i++)
Burada dikkat etmek istedigimiz
"int i=0
" kismidir. Görüldügü gibi indisin ilk aldigi degeri
sifir (0)`dan baslatiyoruz. Bu kismi unutmayiniz. Genellikle yapilan en büyük
hatalardan biridir.
Bir dizi tanimlayicisi
-adi-, dizinin ilk elemaninin adresini tanimlayan adrestir. Bunu söyle izah
edelim; elimizde bir dizi var ve ilk elemani karakter ise biz "char
DiziAdi[boyut]
" seklinde tanimlariz. Tam sayi ise "int
DiziAdi[boyut]
" seklinde olur.
Dikkat edilmesi
gereken diger bir konu da: dizi adi hiçbir zaman (=) isaretinin solunda bulunmaz.
Bu yukarida söylediklerimi anlamamis olabilirsiniz. Onun için alt kismi okuyup
bir daha tekrar etmenizi tavsiye ederim.
Int a[10];
Seklinde bir diziyi
tanimlayabiliriz. Bunu daha genel bir kaliba dökersek.
<tip> <dizi
adi> [<boyut>]; halini alir. Birde boyutlarinin arttirilmis halini
verelim.
<tip> <dizi
adi> [<boyut1>][<boyut2>][<boyut3>]....[<boyutn>]; n boyutlu dizi:).
<tip>: Yukarida söylemis
oldugumuz "int DiziAdi[boyut]
" olayidir.
<dizi adi>: Kurallara uygun
herhangi bir isim olabilir. Genellikle dizilerinizin amacina uygun isimler
kullaniniz.
[<boyut>]: Dizinin kaç eleman
içerdigini gösterir. 5 elemanli ise [5] seklinde yazariz.
Basta " int
a[10];
" almistik. Simdi bunu degisik bir formda yazalim
const int boyut=10;
Int a[boyut];
Önce boyut adinda bir
sabiti tanimladik ve deger atadik sonrada bunu dizi içine çagirdik.
Bu yöntemleri madde
madde verelim,
1. Duragan ve global
(erisilen) dizilerde yaratildiklari anda içerik otomatik olarak belirlenebilir.
Programin taniminda erisilen tüm degiskenler, otomatik olarak sifir yapilir.
2. Duyuru sirasinda
sabit degerler belirtilerek belirlenebilir.
3. Programin çalismasi
sirasinda indisler kullanilarak her elemana tek tek veri kopyalanabilir.
1. maddenin örnegi
#include <iostream.h> const int boyut=5; int GlobalDizi[boyut]; main() { //"satatic" yerel degiskende tanimlanmasina ragmen tüm program boyunca //geçerlidir. Ancak sadece tanimlandigi fonksiyon tarafindan erisilebilir. static int DuraganDizi[boyut]; for(int i=0; i<boyut;i++) cout<<GlobalDizi[i]; return 0; } |
Programin çiktisinada
göreceginiz gibi, dizi aratilirken indislere ait eleman bloklari temizlenmis ve
sifir degerlerini almistir.
Burada bir konuya daha
dikkat çekmek istiyorum. Çok yaptigimiz hatalardan biri olarak da, dizi
duyurusunu yaparken belirttigimiz degerden fazla sayida deger girmemizdir.
int
DiziAdi[5]={1,8,9,5,4,6};
Görmüs oldugunuz gibi bes tane dedik ama alti tane
yazdik. !!! hata !!!. Bu tür hatalar için elimizde kullanabilecegimiz bir kalip
var.
char DiskOkunmuyor[ ] = "Disk okunmuyor";
char DosyaYok[ ]= "Dosya Yok";
Bunu yaptigimizda
derleyici, tüm degerleri içerebilecek en büyük diziyi olusturur.
C++ da sözcükler için
farkli bir tip yoktur. Sözcükler ile ilgili islemler diziler yardimi ile
kolaylikla yapilabilir. Dikkat edilmesi gereken bir kural vardir. Sözcüklerin
(strings) son elemanlari "\0" degerini alir (null terminator). Burdan
da anlayacagimiz gibi son karakter bos dizgiyi belirtiyorsa stringtir. Suna da
dikkat edilmelidir ki string sabitlerinin sonuna "\0" koymamiza gerek
yoktur. Derleyici bunu otomatik olarak yapacaktir.
Char sozcuk[7]="Deneme";
Char sozcuk[7]=''D'', ''e'', ''n'', ''e'', ''m'', ''e'', ''\0''};
Bu dizilerin
içerikleri tamamen aynidir. Hazir söz gelmisken suna da deginelim. ''\n'',
''\t'', ''\0'' v.s, bunlar birer karakter olarak okunur. Ben önceleri iki diye
okurdum:)
#include <stdlib.h> #include <iostream> #include <string> using namespace std; int main() { string Cevap = ""; cout << "Hazirmisin?"; cin >> Cevap; if( ( Cevap == "evet" ) || ( Cevap == "Evet" )) { cout << "Ee Tamam... ne gec ti eline?:) " << endl; } else { cout << "Zorlamaya devam et!" << endl; } cout << "Hazirmisin? " << endl; cin >> Cevap; if( ( Cevap[0] == ''e'' ) || ( Cevap[0] == ''E'' ) ) { cout << "Ee Tamam... ne geçti eline?:)" <<endl; } else { cout << "Zorlamaya devam et!" << endl; } system("pause"); return 0; } |
Bu, sanirim bu
konudaki en zor örnegimiz. Simdi örnek üzerinde biraz konuyu konusmaya devam
edelim. Zaten diger if, else bloklarindan ve cout, cin gibi komutlardan
bahsetmeyecegim. string Cevap = "";
bir sabitimizle
isleme basladik. if( ( Cevap[0] == ''e'' ) || ( Cevap[0] == ''E'' ) )
burasi sanirim
tanidik geldi:) Evet simdi burda Cevap[1] i çagirmis olsaydik ''v'' veya ''V''
degerlerini alicaktik. Tabi burada index degerinin yani dizideki ilk degerin 0
ile basladigini bir daha gördük. Simdi bu örnekle alakali olarak da Diziler ve
Fonksiyonlar konusuna geçelim....
Iste buraya biraz
dikkat, kafaniz gerçekten karisabilir. Daha dogrusu hangisi hangisiydi diye
ugrasir durursunuz:)
Bu fonksiyon bir
karakter dizisinin uzunlugunu verir ve "string.h" kitapliginda
tanimlidir. Strlen() fonksiyonu, sözcükler (strings) bölümünde bahsettigimiz
string ifadeleri okumak için kullanilir. Fakat sondaki "nul
terminator" diger sekliyle ''\0'' degerini okumaz. Örnegimizde de oldugu
gibi "Deneme" ve ''d'' ''e'' ''n'' ''e'' ''m'' ''e'' sözcükler
kisminda ki biz buna 7 karakter demistik, "null" ile birliktedir ama
strlen() bunu bize 6 diye okuyacaktir.
int boy = strlen(h);
for (int i = 0; i<=boy; i++)
y[i] = h[i] ;
Bu fonksiyonda sözcük
kopyalamaya yarar ve "string.h" kitapligindadir.
#include <iostream.h>
#include <string.h>
#define OTUZ 30
void main(void)
{
char Dosya1[OTUZ]="C:\\belgelerim\\deneme.txt",
Dosya2[OTUZ];
strcpy(Dosya2, Dosya1);
cout<<Dosya2<<endl;
cout<<"\n ikinci dosyayi gir: ";
cin>>Dosya1;
strcpy(Dosya2, Dosya1);
cout<<"\n"<<Dosya2<<"\n";
}
strcat() fonksiyonu
iki karakter katarini bir birine ekler.
Iki sözcügün (iki
karakter katarinin) ayni olup olmadigini kontrol etmek için kullanilir. Bu
fonksiyon büyük/küçük harf duyarli degildir.
Bazen sayilari
karakter dizisi olarak okumamiz gerekebilir. Ancak esas, bu sayilarin sayi
degerlerine gereksinmemiz vardir. Atoi fonksiyon, bir karakter dizisini alir ve
onu sayiya çevirir.
Örnegin;
"123456" dizisini alir 123456 sayisina döndürür.
Bunu bir örnekle
anlatayim: "C++ dersleri" gibi bir sözcügümüz var, strstr()
fonksiyonu ile bu sözcük içinde "d" harfinin varligini
sorgulayabiliriz.
Isaretçiler (Pointers)
ve bundan önce görmüs oldugumuz diziler (Arrays) ilerde yapacagimiz
uygulamalarda kullanimina kesin ihtiyaç duyacagimiz basliklardir. Bunlar bize
dinamik bellek kullanimini saglarlar. Dinamik bellek kullanimindan bahsedecek
olursak, bellegimizin kutucuklardan olustugunu hayal edin. 100 kutucuklu bir
bellegimiz var. Bu kutucuklarin her birinin bir adresi vardir ve biz de bu
adresler yolu ile kutucuklara erisiriz. Iste isaretçiler bu erisimi sagliyor.
Bu konuya çalisirken, anlamanin gayet kolay oldugunu göreceksiniz. Fakat ben
sizi uyarayim, en kolay konular en çok hata yapilanlardir. Isaretçilerde
yapilan hatalar programin hatta sistemin çökmesine sebep olabilir, ayni zamanda
yapilan hatalari kolay kolay bulamayabilirsiniz. Büyük projelerde bu sizi
bayagi sikintiya sokacaktir. Onun için isaretçiler konusunda, kullanim teknigi
hakkinda size sik sik tavsiyelerde bulunacagim.
Isaretçilerin
Tanimlanmasi ve Deger Atanmasi
Bir isaretçi tipi,
hangi tipe isaret ettigini belirten ve birer adres degeri içeren verilere
sahiptir. Bir isaretçi degisken bildirimi, açik olarak hangi tip veriyi
kullanacagini bildirerek baslar. Derleyicimizde *
isareti ile isaretçi
degiskeni tanimladigimizi anlar.
<tip>
*<isaretçi adi>; Seklinde yazilir. Örnegin, int *IsaretciAdi;
Simdi de ayni satirda
birden fazla isaretçi tanimlayalim.
Int *is1, *is2, *is3;
Seklinde
tanimlayabiliriz. Benim size tavsiye ettigim budur. Fakat farkli bir yol olarak
da (Int *) is1, is2, is3;
seklinde de yazilabiliriz. Burda dikkat
etmemiz gereken olay ise, int tipinde isaretçileri tanimlarken herhangi bir
degiskende tanimlarsak (int *) seklinde tek satirda yapmamiz hatalidir.
(Int *) is1, is2, is3, x=4; //hata
int *is1, *is2, *is3, x=4; //dogru
Sanirim ne demek
istedigimi anladiniz:).
Daha önce görmüs
oldugumuz "&
" adres operatörünü hatirlayalim, kendisisinden
sonra gelen ifadenin adresini gösterir.
Int x;
Int *is1=&x;
x i tanimladik, sonra
is1 isaretimize x in adresini atadik. Kisaca is1 in gösterdigi adresteki deger
diye biliriz:)
#include <iostream.h> #include <string.h> int main(void) { char *is1="deneme"; int index; for(index=(strlen(is1)-1); index>=0; index--) cout<<is1[index]<<endl; cout<<"\n"<<is1; return 0; } Programin çiktisi --------- e m e n e d deneme --------- |
Isaretçilere daha önce
görmüs oldugumuz artirma (++), azalatma (--), çikarma (-), toplama (+)
islemlerini uygulayabilirsiniz. Bunlarin yaninda iliskisel operatörleri de (
<=, =, !=, >= ) kullanmaniz mümkündür. Iliskisel operatörlerin sadece
ayni tip isaretçiler üzerinde uygulanacagini unutmayiniz.
Bir dizinin boyutu
degisken olabilir, daha dorusu bir program içinde degiskenler ve isaretçiler
kullanilarak diziler dinamik bellek yerlesimi ile yapilabilir. C++ da dinamik
belles islemleri new ve delete komutlari ile gerçeklestirilir.
Genel tanimimiz:
new <tür> [<[uzunluk]>]
new int
new char
new double [10]
new float[n]
new char[strlen(s) + 1]
new komutu ile yer
tahsis etme islemi yapmaktayiz. new int
->1 int''lik yer
tahsis edilmistir. Simdide tahsis ettigimiz yerin serbest birakilisini ele
alalim. Bu sirada da delete komutu devreye giriyor. Daha dogrusu delete
operatöürü new operatörüyle tahsis edilmis olan bloklari serbest birakmak için
kullanilir.
Genel tanimimiz:
Delete[ ] <isaretçiadi>;
Eger yer ayirma islemi
tek parça olarak yapilmissa (köseli parantez kullanilmadan yapilmissa) silme
islemi de köseli parantez kullanilmadan yapilmalidir. Bir de suna dikkat edelim
Delete x+1; //hatalidir
Delete (x+1); //dogrudur
kullanilacaktir. Simdi
bu söylediklerimizi asagidaki örnek üstünde uygulayalim.
//dinamik.cpp //dinamik bellek kavrami #include <iostream.h> struct tarih { //struck u daha görmedigimiz int ay; //icin su an buraya egilmeyin. int gun; int yil; }; void main() { int i, *is1, *is2; // i bir sabit ve *is1, *is2 isaretcilerimiz is1 = &i; *is1 = 77; is2 = new int; *is2 = 178; cout << "Degerler "<<i<<" "<<*is1<<" "<<*is2<<"\n"; is1 = new int; is2 = is1; *is1 = 95454; cout << "Degerler "<<i<<" "<<*is1<<" "<<*is2<<"\n"; delete is1; float *float_is1, *float_is2 = new float; float_is1 = new float; *float_is2 = 3.14159; *float_is1 = 2.4 * (*float_is2); delete float_is2; delete float_is1; tarih *tarih_is; tarih_is = new tarih; tarih_is->ay = 10; tarih_is->gun = 18; tarih_is->yil = 1938; cout<<tarih_is->ay<<"/"<<tarih_is->gun<<"/"<<tarih_is->yil<<"\n"; delete tarih_is; char *c_is; c_is = new char[37]; delete [] c_is; c_is = new char[sizeof(tarih) + 133]; delete [] c_is; } |
Isaretçiler ve diziler
bölümünde görmüs oldugumuz örnektede oldugu gibi. Biz fonksiyonun adresine onun
adi ile ulasiriz.
Kareal(x);
gibi. Simdi bir
fonksiyonu isaret eden bir isaretçiyi ele alalim.
Int KareAl( );
fonksiyonumuz olsun.
Int (*KareAl)( );
Bu da Fonksiyonu isaret eden bir isaretçimiz oldu.
Biz genellikle isaret
edilen fonksiyonlari menülerde ve siralamalarda kullaniriz. Asagida bir
siralama örnegi verilmistir.
//is_ve_fonk.cpp //isaretçiler ve fonksiyonlar #include <stdlib.h> #include <iostream> using namespace std; void YatayYaz(char*); void DikeyYaz(char*); void ismiYaz(char*, void (*Yaz)(char*)); int main() { char isim[] = "Deneme"; ismiYaz(isim,DikeyYaz); ismiYaz(isim,YatayYaz); system("pause"); return 0; } void YatayYaz(char *isim) { if(!isim) return; cout << isim; } void DikeyYaz(char *isim) { if(!isim) return; int i = 0; while(isim[i] != NULL) { cout << isim[i++]; cout << endl; } } void ismiYaz(char *isim, void (*Yaz)(char*)) { Yaz(isim); cout << endl; } |