Uploaded by epikurosster

Programlamaya Giriş - Ders Notları (C)

advertisement
Programlamaya Giri³ Ders Notlar
H. Turgut Uyar
“ubat 2004
ii
Önsöz
(C) 2001-2004, H. Turgut Uyar <[email protected]>
Bu notlar, stanbul Teknik Üniversitesi'nde verilen Introduction to Scientic and Engineering
Computation dersi için Bilgisayar Mühendisli§i Bölümü ö§retim görevlisi H. Turgut Uyar
tarafndan hazrlanm³tr. Yazarnn açkça belirtilmesi ko³uluyla e§itim amaçl kullanlabilir
ve da§tlabilir. Di§er her türlü kullanm için yazarndan izin alnmaldr.
Sürüm: 0.99.5
Son düzenleme tarihi: 5 “ubat 2004
Web sayfas:
http://www.ce.itu.edu.tr/Members/uyar/c
Bu dersin amac, ö§renciye yalnzca programlamay ya da C dilini ö§retmek de§il, ayn zamanda temel saysal yöntemleri ve sralama algoritmalar gibi skça kullanlan programlama
tekniklerini de göstermektir. Bu amaçla uygulamalarda daha çok saysal yöntemler üzerine
örnekler seçilmeye çal³lm³tr. Bu örneklerin ço§u Prof. Dr. Nadir Yücel'in Saysal Analiz
Algoritmalar kitabndan uyarlanm³tr.
Notlarn hazrlanmasnda yeni standartlara uyumu kolayla³trmas açsndan C++ dilinin getirdi§i baz yeniliklerden yararlanlm³tr. Metin içinde yeri geldikçe, C++ dilinde geçerli olup
C dilinin izin vermedi§i özellikler belirtilmi³tir.
Programlarn ekran çktlarnda kullancnn yazd§ de§erler italik olarak i³aretlenmi³tir.
Örnek programlar ve ders için hazrlanan sunumlar (ngilizce) yukarda belirtilen web sayfasnda bulunabilir.
iii
iv
çindekiler
1 Giri³
1
1.1
Veriler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
1.1.1
Taban Tipler
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
1.1.2
Kaytlar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
1.1.3
Diziler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
1.2
Algoritmalar
1.2.1
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
Algoritmalarn Kar³la³trlmas . . . . . . . . . . . . . . . . . . . . . . .
11
1.3
Blok Yapl Programlama
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
1.4
Soyutlama . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
1.5
Giri³ / Çk³ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
1.6
Program Geli³tirme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
1.6.1
Programlarn De§erlendirilmesi . . . . . . . . . . . . . . . . . . . . . . .
23
1.6.2
Programlarn Çal³trlmas
. . . . . . . . . . . . . . . . . . . . . . . . .
24
1.6.3
Kitaplklar
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
1.6.4
Standartlar
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
1.6.5
Derleme A³amalar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
2 C Diline Giri³
29
2.1
simler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
2.2
De§erler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33
2.3
De§i³kenler
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
34
2.4
Veri Tipleri
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
2.5
De§i³mezler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
2.6
Aritmetik Deyimler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
2.7
Tip Dönü³ümleri
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
2.8
Artrma / Azaltma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
2.9
Matematik Kitapl§
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
2.10 Giri³ / Çk³ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
v
vi
ÇINDEKILER
3 Ak³ Denetimi
3.1
3.2
45
Ko³ul Deyimleri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
47
3.1.1
Kar³la³trma ³lemleri . . . . . . . . . . . . . . . . . . . . . . . . . . . .
47
3.1.2
Mantksal ³lemler
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
48
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
Seçim
3.2.1
Ko³ullu ³leç
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
3.3
Çoklu Seçim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
3.4
Ko³ul Denetiminde Yineleme
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
59
3.5
Döngü Denetimi
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
62
3.6
Sayaç Denetiminde Yineleme
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
4 Türetilmi³ Veri Tipleri
63
73
4.1
Numaralandrma
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
76
4.2
Yaplar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
79
5 Diziler
85
5.1
Tek Boyutlu Diziler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
87
5.2
Katarlar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
91
5.3
Katar Kitapl§ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
92
5.4
Çok Boyutlu Diziler
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
94
5.5
Ba³vurular
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
98
6 Fonksiyonlar
103
6.1
Fonksiyon Bildirimi ve Tanm . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
6.2
Parametre Aktarm
6.3
Yerel De§i³kenler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
6.4
Genel De§i³kenler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
6.5
Ba³vuru Aktarm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
6.6
Giri³ Parametreleri Üzerinden De§er Döndürme . . . . . . . . . . . . . . . . . . 116
6.7
Dizilerin Fonksiyonlara Aktarlmas . . . . . . . . . . . . . . . . . . . . . . . . . 117
6.8
E³ simli Fonksiyonlar
6.9
Varsaylan Parametreler
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
vii
ÇINDEKILER
7 ³aretçiler
127
7.1
³aretçi Tipinden De§i³kenler
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
7.2
Bellek Yönetimi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
7.3
³aretçi - Dizi li³kisi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
7.4
³aretçi Tipinden Parametreler
7.5
Statik De§i³kenler
7.6
Adres Aktarm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
. . . . . . . . . . . . . . . . . . . . . . . . . . . 133
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
8 Giri³-Çk³
141
8.1
Çk³ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
8.2
Giri³ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
8.3
Ana Fonksiyona Parametre Aktarma . . . . . . . . . . . . . . . . . . . . . . . . 146
8.4
Dosyalar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
8.4.1
Dosya Açma - Kapama . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
8.4.2
Dosyada Okuma-Yazma
. . . . . . . . . . . . . . . . . . . . . . . . . . . 148
8.5
Standart Giri³ / Çk³ Birimleri . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
8.6
Hata letileri
8.7
Katarlar ile Giri³-Çk³ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
8.8
kili Dosyalar
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
9 Öni³lemci
153
9.1
Makrolar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
9.2
Projeler
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
10 Ba§lantl Listeler
163
10.1 Yaplara ³aretçiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
11 Rekürsiyon
171
A Simgelerin Kodlanmas
177
B Unix'de Program Geli³tirme
179
B.1
Yardmc Belgeler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
B.2
Derleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
B.3
Editörler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
B.4
Hata Ayklayclar
B.5
Ba³arm nceleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
ÇINDEKILER
viii
Bölüm 1
Giri³
Bir problemi çözmek üzere bir bilgisayar program yazarken iki temel soruna çözüm getirmek
gerekir:
Problemin nasl temsil edilece§i.
Bilgisayarlar temelde saylar üzerinde i³lem yapmak üzere tasarlanm³ makinalardr;
dolaysyla tandklar varlk yelpazesi fazla geni³ de§ildir. Örne§in Türkiye'deki karayollaryla ilgili bir program yazlacaksa ³ehirlerin ve aralarndaki yollarn bir ³ekilde temsil
edilmesi gerekir çünkü bilgisayarn ³ehir, yol gibi kavramlar yoktur. Bir ³ehri temsil
etmek için ³ehrin ad, enlemi ve boylam kullanlabilir. Bir yolun temsili içinse farkl
seçenekler dü³ünülebilir:
•
Yolun düz oldu§unu varsayarak bir do§ruyla göstermek (“ekil 1.1a). Bu durumda
yalnzca ba³langç ve biti³ ³ehirlerini (yani enlem, boylam ve isimlerini) bilmek
yeterli olacaktr. Bu yöntem i³lemleri çok basitle³tirmekle birlikte gerçek durumdan
büyük ölçüde sapmaya neden olur.
•
Yolu ucuca eklenmi³ do§ru parçalaryla göstermek (“ekil 1.1b). “ekilde stanbulAnkara yolu iki, stanbul-zmir yolu dört, Ankara-zmir yolu üç do§ru parçasndan
olu³maktadr. Ancak bu yöntem daha zordur ve yolu ne kadar ayrntl temsil etmek
isterseniz o kadar fazla do§ru parças kullanmanz gerekir.
Problemi olu³turan varlklarn nasl temsil edileceklerinin belirlenmesi, problem için bir
model olu³turulmas anlamna gelir. Problemin çözümünde ilk ve en önemli adm do§ru
ve yeterli ayrntda bir model olu³turmaktr. Yukardaki örnekten de görülebilece§i gibi,
çözece§iniz problemi nasl modelledi§iniz son derece önemlidir, çünkü çözdü§ünüz ³ey
problemin kendisi de§il, sizin o problemi temsil etmek üzere tasarlad§nz modeldir.
Modeliniz problemden uzaksa siz ne kadar iyi bir çözüm uygularsanz uygulayn elde
edece§iniz sonuç anlamsz olur.
Di§er yandan, modelin ne kadar ayrntl olmas gerekti§i, çözmek istedi§iniz problemin
gereksinimleriyle belirlenir. Gerekenden daha ayrntl bir model hazrlarsanz belki daha
iyi bir sonuç elde edersiniz ama o daha iyi sonuca ula³mak için harcamanz gerekecek ek
çaba ya da çözümüzün gerçekleme maliyeti aradaki farka de§meyebilir. Yine yukardaki
1
2
örnekle sürdürürsek, stanbul-Ankara karayolunun 274. kilometresi gibi bilgilerden söz
edecekseniz yolu do§ru parçalaryla modellemeniz gerekecektir çünkü gerçek ya³amda
bu nokta büyük olaslkla o iki ³ehri birle³tiren çizginin üzerinde bir yere dü³meyecektir.
Ancak yollarn yalnzca uzunluklaryla ilgileniyorsanz do§rularla modellemeniz yeterlidir; bu durumda da do§ru parçalaryla modellemek yolun uzunlu§unun bulunmasnda
zorluk çkaracaktr.
Istanbul
Istanbul
Ankara
Izmir
Ankara
Izmir
(a)
(b)
“ekil 1.1: Karayollarnn gösterilmesi.
Çözümün nasl ifade edilece§i.
Bir problem için dü³ündü§ünüz çözümü ba³ka birine (insan ya da bilgisayar) anlatabilmeniz gerekir. Adm adm hangi i³lemlerin yaplaca§nn açklanmas ³eklinde anlatlan
bir çözüme algoritma ad verilir. Algoritmalara günlük ya³amdan skça verilen bir örnek
yemek tarieridir. A³a§da, bezelyeli Jamaika pilav yapmak için nternet'ten alnm³ bir
tarif algoritma biçiminde yazlm³tr:
1. 1 1/2 kutu bezelyeyi 4-5 ncan suya koy.
2. 1/4 kutu hindistan cevizi sütü, 1 tutam kekik ve a§z tadna göre tuz ve biber ekle.
3. Bezelyeler yumu³ayncaya kadar ha³la.
4. Bir so§ann dibini ez ve 2 ncan pirinç, 1/4 kutu hindistan cevizi sütü ve 2 tutam
kekik ile birlikte suya ekle.
5. Pirincin üstünden 2 cm kadar su kalacak ³ekilde fazla suyu al.
6. 5 dakika kaynat.
7. Pirinç yumu³ayncaya kadar pi³irmeye devam et.
Algoritmann bir bilgisayar tarafndan yürütülebilmesi için iki önemli özellik sa§lanmaldr:
•
Her admda ne yaplaca§ açk olarak belli olmal, hiçbir ³ekilde yorum gerektirmemelidir. Yukardaki örnek bu bakmdan bir algoritma saylamaz çünkü pek çok
admda ne yaplaca§ yoruma braklm³tr. Sözgelimi, 4-5 bardak, a§z tadna
göre, bezelyeler yumu³ayncaya kadar gibi deyimler yeterince kesin de§ildir.
•
Sonlu sayda admda ya çözüm bulunmal ya da bulunamad§ bildirilmelidir.
3
Giri³
1.1
Veriler
Modelinizde kulland§nz büyüklükler programnzn verilerini olu³turur. Her büyüklük programda bir de§i³ken ile temsil edilir. De§i³ken aslnda o büyüklü§e verilmi³ simgesel bir isimden
ba³ka bir ³ey de§ildir. De§i³kenler, programn i³leyi³i srasnda de§erler alrlar. De§i³kenlerin
bellekte tutulduklar gözönüne alnrsa, de§i³ken bir bellek gözünün ad, de§er ise bu gözün
içeri§idir.
Örne§in, bir ³ehri modellemek için üç büyüklük öngörmü³tük: isim, enlem ve boylam. Her büyüklü§e bir de§i³ken kar³ dü³ürmemiz gerekti§inden isim bilgisini
ve boylam bilgisini
boylam
isim, enlem bilgisini enlem
de§i³kenleriyle temsil etti§imizi varsayalm. Bu durumda temsil
etti§imiz ³ehre göre bu de§i³kenlere uygun de§erler vermemiz gerekir. Sözgelimi, stanbul ³ehrini temsil etmek için
isim
de§i³kenine stanbul,
1
29 de§erleri verilmelidir (“ekil 1.2).
isim
enlem
de§i³kenine 41,
enlem
"Istanbul"
boylam
de§i³kenine
boylam
41
29
“ekil 1.2: “ehri temsil eden de§i³kenler ve örnek de§erler.
Bir de§i³kene bir de§er verilmesi i³lemine atama denir ve sola bakan bir ok i³aretiyle gösterilir:
enlem ← 41.
2
Atama i³aretinin sol tarafna bir de§i³ken ad, sa§ tarafna bir deyim yazlr.
Deyim, bir de§er üreten bir hesaplama olarak tanmlanabilir. Bir deyim, tek bir de§er ya da bir
de§i³ken olabilece§i gibi, bunlarn i³lemler ile çe³itli ³ekillerde ba§lanmalarndan da olu³abilir:
• 41:
yalnzca bir de§er
• boylam:
yalnzca bir de§i³ken
• 4 * boylam:
bir de§er ile bir de§i³kenin çarpma i³lemiyle ba§lanmas
• enlem + boylam:
iki de§i³kenin toplama i³lemiyle ba§lanmas
41 ← enlem atamasnn bir anlam
i ← i + 1 atamas, i de§i³keninin de§erinin o anki de§erine göre bir
Atama i³lemi bir matematiksel e³itlik de§ildir. Örne§in
yoktur. Benzer ³ekilde,
artrlmas demektir; yani de§eri bu i³lemden önce 5 ise, i³lemden sonra 6 olur. Oysa, bu bir
e³itlik olsayd yanl³ olurdu (0 = 1).
Örnek. Takas
Programlarda skça gerekebilen i³lemlerden biri, iki de§i³kenin de§erlerini kar³lkl de§i³tir-
say1 de§i³keninin de§eri 32 ve say2 de§i³keninin de§eri 154 ise bu i³lemsay1 de§i³keninin 154, say2 de§i³keninin de 32 de§erini almas istenir (“ekil 1.3).
mektir. Sözgelimi,
den sonra
Takas i³lemini yapmak üzere ³u atamalarn kullanld§n dü³ünelim:
1
Burada kuzey enlemlerinin ve do§u boylamlarnn pozitif saylarla gösterildi§i varsaylm³tr. Güney enlem-
leri ve bat boylamlar negatif saylarla gösterilirse örne§in New York ³ehrinden söz edildi§inde
New York,
2
boylam
de§i³keni -74,
enlem
de§i³keni 40 de§erini almaldr.
Bu i³lem için programlama dilleri genelde = ya da := i³aretini kullanrlar.
isim
de§i³keni
4
Veriler
sayi1
sayi2
32
154
(a) Önce
sayi1
sayi2
154
32
(b) Sonra
“ekil 1.3: Takas i³lemi.
say1 ← say2
say2 ← say1
Birinci atama i³leminden (“ekil 1.4a) sonra
say1
de§i³keni 154 de§erini alr,
ninde ise bir de§i³iklik olmaz. kinci atama i³lemi (“ekil 1.4b) ise
de§i³keninin o anki de§erini atad§ndan
say2
say2
say2
de§i³ke-
de§i³kenine
say1
de§i³kenine yine 154 de§eri atanr ve sonuçta
her iki de§i³ken de 154 de§erini alm³ olur (“ekil 1.4c).
sayi1
sayi2
32
154
(a)
sayi1
sayi2
154
154
(b)
sayi1
sayi2
154
154
(c)
“ekil 1.4: Takas i³lemi çözümü (hatal).
ki atama i³leminin yetersiz oldu§u görülmektedir. Yaplmas gereken, de§i³kenlerin de§erlerini
yitirmemek için, bir de§i³kenin de§erini ba³ka bir de§i³kende yedeklemektir:
ara ← say1
say1 ← say2
say2 ← ara
5
Giri³
ara de§i³keni 32 de§erini alr. kinci atamada (“ekil 1.5b)
say2 de§i³kenine 32 de§eri
atanr (“ekil 1.5d). Bu atamalardan sonra ara de§i³keninin de§erinin ne oldu§unun bir önemi
Birinci atama (“ekil 1.5a) sonucunda
say1
de§i³kenine 154, üçüncü atama (“ekil 1.5c) sonucunda da
yoktur.
sayi1
sayi2
32
154
ara
xxx
(a)
sayi1
sayi2
32
154
ara
32
(b)
sayi1
sayi2
154
154
ara
32
(c)
sayi1
154
sayi2
ara
32
32
(d)
“ekil 1.5: Takas i³lemi çözümü (do§ru).
De§i³kenlerin, temsil ettikleri varl§a göre, bir tip leri vardr. Baz programlama yakla³mlarnda
programcnn de§i³kenin hangi veri tipinden oldu§unu belirtmesi ³art ko³ulurken, bazlarnda
de§i³kenin tipi, içinde kullanld§ ba§lamdan kestirilmeye çal³lr.
1.1.1
Taban Tipler
En sk kullanlan de§i³ken tipi saylardr. Örnekteki
enlem ve boylam de§i³kenleri duruma göre
birer tamsay ya da kesirli say olarak seçilebilir. Ço§u programda gerekecek temel veri tipleri
³unlardr:
tamsay
Bir insann do§um yl, soyadndaki harf says, boyunun santimetre cinsinden
uzunlu§u, bir i³lemin kaç kere yapld§n sayan sayaç gibi bilgiler.
kesirli say Bir insann boyunun metre cinsinden uzunlu§u, iki snavdan alnan notlarn ortalamas, bir saynn karekökü gibi bilgiler.
6
Veriler
mantksal
Bir ö§rencinin bir dersten ba³arl olup olmad§, bir insann onsekiz ya³ndan
büyük olup olmad§, kullancnn bast§ tu³un bir rakam tu³u olup olmad§ gibi
bilgiler. Bu tipten de§i³kenler
Do§ru
ya da
Yanl³
3
de§erini alabilirler.
Birinin adnn ba³ har, programn çal³mas srasnda Devam
simge
musunuz (E/H)?
etmek istiyor
sorusuna kar³lk hangi tu³a bast§, bir tarih bilgisinde gün, ay
ve yl arasna hangi i³aretin konaca§ (nokta, tire, bölü, vs.) gibi bilgiler. Simgeler
ço§unlukla tek trnak i³aretleri içinde yazlrlar: 'E', ' ?', '4' gibi. Burada ayrm
yaplmas gereken önemli bir nokta, rakamlar ile rakamlar gösteren i³aretleri birbirine kar³trmamaktr. Örne§in 5 rakam ile '5' simgesi farkl büyüklüklerdir (bkz.
Ek A).
katar
Bir insann ad, do§du§u ³ehir, bir kitabn ISBN numaras gibi bilgiler katarlarla
temsil edilmeye uygundur. Katarlar ço§unlukla çift trnak içinde yazlrlar: Dennis Ritchie, 0-13-110362-8 gibi. Bir büyüklük bütünüyle rakamlardan olu³sa bile
baz durumlarda say yerine katarla göstermek daha uygun olabilir. Bir de§i³kenin
ancak üzerinde aritmetik bir i³lem yaplacaksa say tipinden olmas anlaml olur.
Örne§in, stanbul Teknik Üniversitesi'nde ö§renci numaralar dokuz haneli tamsaylardr ancak bunlar tamsay olarak temsil etmenin bir anlam yoktur çünkü
ö§renci numaralar üzerinde aritmetik i³lem yapmak gerekmeyecektir (iki ö§rencinin numaralarn toplamak ya da çarpmak gibi).
1.1.2
Kaytlar
Birden fazla büyüklü§ü ortak bir tip altnda toplarlar. Burada gruplanan büyüklükler ayn tipten ya da farkl tiplerden olabilir. Örne§in bir ³ehri temsil etmek üzere kullanlan üç büyüklük
(³ehrin ismi, enlemi ve boylam) birle³tirilerek ³ehirleri gösterecek bir
kent
veri tipi olu³turu-
labilir. Bu veri tipinin biri bir katar (³ehir ismi), di§er ikisi de birer kesirli say olan (enlem
ba³kent de§i³keni tanmlanismi, ba³kent kentinin enlemi
ve boylam) üç alan olacaktr (“ekil 1.6a). Bu tipten diyelim bir
d§nda, de§i³kenin alanlarna eri³mek için ba³kent kentinin
gibi deyi³ler kullanlmaldr. Bu amaçla ço§unlukla noktal gösterilimden yararlanlr; örne§in
ba³kent de§i³keninin isim alanna Ankara de§erini atamak için ba³kent.isim ← Ankara
yazlr (“ekil 1.6b).
Kaytlar alan olarak ba³ka kaytlar da içerebilirler. Örne§in, bir yolu temsil için yolun kodu
(katar), uzunlu§u (tamsay) ve ba³langç ve biti³ kentleri bilgileri kullanlabilir (“ekil 1.7).
Eri³im, tek düzeyli kaytlara benzer ³ekilde yaplr (tem.son_kent.isim
tem.kod ← E-6
1.1.3
← Ankara
ve
gibi).
Diziler
Ayn tipten varlklardan olu³an bir grubu tek bir çat altna toplamak için kullanlrlar. Bir
dizinin bütünü tek bir de§i³ken olarak de§erlendirilir. Örne§in 50 ö§rencili bir snfta bir
snavdan alnan notlar i³lenece§inde, her bir ö§rencinin notunu göstermek üzere
· · ·, not50
3
gibi ayr ayr 50 tamsay de§i³ken tanmlanaca§na,
Bu de§erler örneklerde
D
ve
Y
³eklinde ksaltlacaktr.
notlar
not1, not2,
adnda 50 elemanl
7
Giri³
baskent
kent
kent
isim
isim
enlem
enlem
boylam
boylam
(a)
"Ankara"
(b)
“ekil 1.6: Kayt tipinden de§i³ken örne§i.
tem
yol
kod
uzunluk
son_kent
ilk_kent
isim
isim
enlem
enlem
boylam
boylam
“ekil 1.7: çiçe kaytlar tipinden de§i³ken örne§i.
8
Veriler
bir tamsay dizisi tanmlanabilir. Ayr ayr de§i³kenler bellekte da§nk bir yap olu³tururken
dizinin elemanlar bellekte birbirini izleyen gözlere yerle³tirilir (“ekil 1.8).
not4
not13
not1
not22
notlar
1
2
3
50
“ekil 1.8: Dizi tipinden de§i³ken örne§i.
Elemanlar üzerinde i³lem yapmak için dizinin kaçnc elemanndan söz etti§inizi söylemeniz
gerekir. Sözgelimi, 22. ö§rencinin ald§ not 95 ise yaplacak atama
4
gösterilir .
notlar22 ← 95
³eklinde
Katarlar ço§u programlama dilinde simge dizileri olarak görülürler; yani bir katar her bir
eleman bir simge olan bir dizidir. Sözgelimi, birinin ad ve soyad
adsoyad
isimli bir de§i³-
kende tutulacaksa, bu de§i³ken simge dizisi tipinden olacaktr (“ekil 1.9). Örnekte
adsoyad7
büyüklü§ünün de§eri 'D',
adsoyad1
büyüklü§ünün de§eri ' ' (bo³luk) simgesidir.
adsoyad
’D’ ’e’ ’n’ ’n’ ’i’ ’s’ ’ ’ ’R’ ’i’ ...
1
2
3
4
5
6
7
8
9
10
“ekil 1.9: Katar tipinden de§i³ken örne§i.
Dizilerle kaytlar birlikte de kullanlabilir. Sözgelimi, bir saynn asal çarpanlarn temsil etmek
üzere bir dizi kullanabiliriz (6776
= 23 ∗ 71 ∗ 112 ).
Dizinin her bir eleman bir asal çarpan
gösterir, her bir asal çarpan da bir taban ve bir üs de§erinden olu³tu§u için bir kaytla temsil
edilir (“ekil 1.10). Elemanlara eri³im daha önce belirtilen kurallarda görüldü§ü gibi olacaktr:
ç arpanlar2 .taban ← 7
carpanlar
taban
2
taban
7
taban
11
...
üs
3
üs
1
üs
2
...
1
2
3
“ekil 1.10: Kayt dizisi tipinden de§i³ken örne§i.
4
Bu i³lem için programlama dillerinde kö³eli ayraçlar kullanlr:
notlar[22]
gibi.
9
Giri³
Örneklerden de görülebilece§i gibi, bir dizinin bütünüyle temsil edilmesi için dizinin eleman
de§erlerinin yansra kaç eleman oldu§u bilgisinin de bir ³ekilde tutulmas gerekir.
1.2
Algoritmalar
Algoritmalar göstermek için skça kullanlan yöntemlerden biri ak³ çizenekleridir. Ak³ çizeneklerinde ³u simgeler kullanlr:
•
Kutu: Bir i³lemi gösterir. Kutunun içine i³lemi anlatan bir komut yazlr.
•
Ok: Ak³ yönünü belirtir. Algoritmann bir sonraki admnn hangisi oldu§unu gösterir.
•
E³kenar dörtgen: Karar noktalarn gösterir. çine yazlan sorunun yantnn do§ru ya da
yanl³ olmasna göre farkl bir yöne gidilmesini sa§lar.
•
Paralelkenar: Giri³/çk³ i³lemlerini gösterir.
Algoritmann tamam belirtilmi³se ak³ çizene§i kö³eleri yuvarlatlm³ kutular içinde bulunan ba³la komutuyla ba³lar ve dur komutuyla biter. Algoritmann tamam de§il, yalnzca
ilgilenilen bir parças belirtilmek isteniyorsa çizenek bo³ bir yuvarlak ile ba³lar ve bo³ bir yuvarlak ile sona erer. Ak³ çizene§inin büyümesi ve topluca görülmesinin zorla³mas durumunda
ak³ çizene§i parçalarnn ba³ndaki ve sonundaki yuvarlaklarn içine etiketler yazarak hangi
parçann hangi parçaya nereden ba§land§ belirtilebilir.
Algoritmalarn örnek de§erler üzerinde i³leyi³lerini daha kolay izleyebilmek amacyla tablolar
kullanlabilir. Tablonun her bir satr algoritmann bir admna kar³ dü³er ve o admda çe³itli de§i³kenlerin ya da deyimlerin aldklar de§erlerin görülmesini sa§lar; yani de§i³kenler ve
deyimler tablonun sütunlarn olu³turur.
Örnek. En Büyük Eleman Bulma
Bir dizinin en büyük elemann bulma algoritmasn, 50 ö§rencili bir snfta bir snavdan alnan
en yüksek notun bulunmas örne§i üzerinde inceleyelim. Bu i³i yapacak bir algoritma ³öyle
yazlabilir:
1. Dizideki ilk notu en yüksek not olarak seç ve sray ikinci ö§renciye geçir.
2. Srada ö§renci varsa 3. adma, yoksa 5. adma git.
3. Sradaki ö§rencinin notu ³u ana kadarki en yüksek nottan büyükse bu yeni notu en
yüksek not olarak seç.
4. Sray bir sonraki ö§renciye geçir ve 2. adma dön.
5. En yüksek notu bildir.
10
Algoritmalar
Daha çok gündelik dil kullanlarak yazlm³ bu algoritmay biçimsel olarak ifade edebilmek için
ö§rencilerin notlarn 50 elemanl bir tamsay dizisi (bu de§i³kene
notlar adn verelim), o ana
kadar bulunmu³ en yüksek notu bir tamsay (max de§i³keni diyelim) ile ve sradaki ö§rencinin
kaçnc ö§renci oldu§unu tutmak için bir sayaç (i de§i³keni) tanmlarsak:
1.
max ← notlar1 , i←2
2.
i ≤ 50
3.
notlari > max
4.
i ← i + 1
ise 3. adma, de§ilse 5. adma git.
ise
max ← notlari
ve 2. adma dön.
5. en yüksek not:
max
Yukarda verilen algoritma örne§inin ak³ çizene§i “ekil 1.11'de görüldü§ü gibidir. 50 eleman
yerine 6 elemanl bir dizide en büyük elemann bulunmas algoritmasnn i³leyi³i Tablo 1.1'de
verilmi³tir (notlarn srasyla 43, 74, 65, 58, 82, 37 olduklar varsaylm³tr, sürme ko³ulu
i ≤ 6
³eklinde de§i³melidir).
basla
max ← notlar1
i←2
i ≤ 50
Y
D
notlari > max
Y
bas: max
D
dur
max ← notlari
i←i+1
“ekil 1.11: En büyük eleman bulma algoritmasnn ak³ çizene§i.
Örnek. Say Tahmin Etme
Arkada³nzn önceden aranzda kar³la³trd§nz iki snr arasnda bir tamsay tuttu§unu ve
sizin bu sayy bulmaya çal³t§nz varsayn. Siz bir say söyledi§inizde arkada³nz, tuttu§u
11
Giri³
max
43
74
i
2
3
4
5
6
7
82
D
D
D
D
D
Y
i ≤ 6
(2 < 6)
(3 < 6)
(4 < 6)
(5 < 6)
(6 = 6)
(7 > 6)
notlari > max
D (74 > 43)
Y (65 < 74)
Y (58 < 74)
D (82 > 74)
Y (37 < 82)
Tablo 1.1: En büyük eleman bulma algoritmasnn örnek de§erlerle i³leyi³i.
say sizin söyledi§inizden büyükse büyük, küçükse küçük diyecek, do§ru sayy söyledi§inizde oyun sona erecektir. Bu oyunu oynarken nasl bir algoritma kullanrsnz?
Kararla³trd§nz snr de§erlerinden küçük olann
taban,
büyük olann
tavan
isimli birer
de§i³ken ile gösterelim. Ayrca, biri arkada³nzn tuttu§u sayy temsil edecek (tutulan isimli),
di§eriyse sizin söyledi§iniz sayy temsil edecek (söylenen isimli) iki tamsay de§i³ken daha
kullanalm.
Algoritma 1.
Alt snrdan ba³la, bulana kadar birer artrarak ilerle.
1.
söylenen ← taban
2.
söylenen = tutulan
3.
söylenen ← söylenen + 1
Algoritma 2.
ise buldun, dur
ve 2. adma dön
Deneme aral§nn ortasndaki sayy söyle. Büyük derse deneme aral§n ³u
anki aral§n üst ksmna, küçük derse alt ksmna daralt. Bu algoritmay gerçeklemek
için o anki deneme aral§nn alt ve üst snrlarn gösterecek iki yeni de§i³kene (alt ve
üst
diyelim) gerek duyulur.
1.
alt ← taban, üst ← tavan
2.
söylenen ← (alt + üst) / 2
3.
söylenen = tutulan
ise buldun, dur
4.
söylenen > tutulan
ise
üst ← söylenen - 1,
de§ilse
alt ← söylenen + 1
ve
2. adma dön.
Bu algoritmann ak³ çizene§i “ekil 1.12'de verilmi³tir. Alt snrn 1, üst snrn 63 oldu§unu ve arkada³nzn 19 saysn tuttu§unu varsayarsak, her turda de§i³kenlerin aldklar
de§erler Tablo 1.2'de görüldü§ü gibi olacaktr.
1.2.1
Algoritmalarn Kar³la³trlmas
Yukardaki örneklerde görüldü§ü gibi, ço§u zaman bir problemi çözmenin birden fazla yolu
vardr. Ayn problemi çözen iki algoritmadan hangisinin daha iyi oldu§una karar vermek üzere
algoritmalar iki özelliklerine göre kar³la³trlrlar:
12
Algoritmalar
basla
alt ← taban
üst ← tavan
söylenen ← (alt + üst) / 2
söylenen = tutulan
D
bas: söylenen
Y
Y
söylenen > tutulan
alt ← söylenen + 1
D
dur
üst ← söylenen - 1
“ekil 1.12: Say tahmin etme algoritmasnn ak³ çizene§i.
alt
1
17
19
üst
63
31
23
19
söylenen
32
16
24
20
18
19
söylenen = tutulan
Y (32 > 19)
Y (16 < 19)
Y (24 > 19)
Y (20 > 19)
Y (18 < 19)
D (19 = 19)
Tablo 1.2: Say tahmin etme algoritmasnn örnek de§erlerle i³leyi³i.
13
Giri³
1. Hzlar: Hangi algoritma çözümü daha çabuk buluyor? Bu sorunun yant da iki durum
için incelenir:
(a) en kötü durumda
(b) ortalama durumda
Say bulma için verilen yukardaki iki algoritmay bu bakmdan kar³la³trrsak, birinci algoritmann örnek de§erlerle sayy en kötü durumda 63, ortalama durumda 32 denemede
bulaca§ görülür. Oysa ikinci algoritma sayy en kötü durumda 6, ortalama durumda
5.09 denemede bulur.
2. Harcadklar yer: Hangi algoritma bellekte daha fazla yer kullanyor?
Say bulma algoritmalarnda gördü§ümüz gibi, ikinci algoritma birinci algoritmann kullandklarna ek olarak iki de§i³ken daha gerektirmektedir.
Günümüzde bilgisayarlarn kapasiteleri eskiye oranla çok yükselmi³ oldu§u için harcanlan
yer ölçütünün önemi göreli olarak azalm³tr. Yine de projenin boyutuna ve çal³lan ortamn
yeteneklerine göre algoritma geli³tirirken hzn yansra harcanacak yerin de gözönüne alnmas
gerekebilir.
Algoritmalarn hzlarnn ve harcadklar yerlerin incelenmesi algoritma analizi dalnn konusudur. Bu dalda geli³tirilmi³ bulunan karma³klk kuram, benzer problemlerin çözümü için
önerilen algoritmalarn kar³la³trlmasnda ba³vurulan en önemli araçtr.
1.3
Blok Yapl Programlama
Blok yapl programlamann temelinde blok kavram yatar. Blok, birbiriyle ili³kili komutlarn
olu³turdu§u gruptur. Her algoritma birbirlerine çe³itli ³ekillerde ba§lanm³ bloklardan olu³ur.
Bloklar ba§lamann üç yolu vardr:
Sra
Bloklarn yukardan a³a§ya do§ru yazldklar srayla yürütülürler (“ekil 1.13a). Sra
yaps, komutlarn yazl³ sralarnn önemli oldu§unu vurgular. Bölüm 1.1'de görülen
takas örne§i için verilen do§ru çözümde yaplan üç atama i³leminin sralar de§i³tirilirse
varlacak sonuçlar yanl³ olabilir.
Seçim
Bir ko³ulun do§ru olup olmamasna göre farkl bir blo§un yürütülmesidir. Yani ko³ul
do§ruysa bir blok, yanl³sa ba³ka bir blok yürütülür (“ekil 1.13b). ki bloktan herhangi
biri bo³ olabilir, yani ko³ul do§ruysa ³u blo§u yürüt, yanl³sa hiçbir ³ey yapma ³eklinde
bir yap kurulabilir.
Yineleme
Belirli bir ko³ul sa§land§ sürece (ya da sa§lanana kadar) bir blok yinelenebilir.
Ak³ çizene§inden (“ekil 1.13c) görülebilece§i gibi, bu yapdan çklabilmesi için blo§un
ko³ulu de§i³tiren bir komut içermesi gerekir, aksi durumda ko³ul ba³langçta do§ruysa
hep do§ru olaca§ndan yapdan çklamayacaktr. Yine ak³ çizene§inden görülebilecek
bir di§er özellik de, ko³ul ba³langçta yanl³sa blo§un hiç yürütülmeyece§idir. Baz uygulamalarda blok ko³uldan önce de yer alabilir (“ekil 1.12 böyle bir örnektir); böyle
durumlarda ko³ul ba³tan yanl³ olsa bile blok en az bir kere yürütülür.
14
Soyutlama
D
blok1
blok2
Y
kosul
kosul
blok1
blok2
Y
D
blok
(a)
(b)
(c)
“ekil 1.13: Temel yaplarn ak³ çizenekleri.
Bu yaplarn ortak bir özelli§i, hepsinin bir giri³ ve bir çk³larnn olmasdr. Böylelikle bir
blo§un çk³ öbür blo§un giri³ine ba§lanabilir; ba³ka bir deyi³le, bloklar ardarda eklenebilir.
Ayrca, bir blo§un içinde ba³ka bir blok yer alabilir. “ekil 1.12'de
³uluyla belirlenen seçim yaps,
söylenen = tutulan
söylenen > tutulan
ko-
ko³uluyla belirlenen yineleme yapsnn
bir alt bile³eni durumundadr.
Bir programn okunmasn ve anla³lmasn en çok zorla³tran etkenlerden biri programda yer
alan dallanma komutlardr. “imdiye kadar yazd§mz baz algoritmalarda geçen n. adma
git tipi komutlar için -programlama dillerinde genellikle
goto
olarak adlandrlan- bir komut
bulunmas gerekti§i dü³ünülebilir (özellikle yineleme yaplar için). Ancak blok yapl programlamada yineleme için özel yaplar vardr ve
1.4
goto
5
komutunun kullanlmamas özendirilir.
Soyutlama
Programlamann temel düzeneklerinden biri soyutlama kavramdr. Soyutlama, programn yapaca§ i³in daha küçük ve birbirinden olabildi§ince ba§msz alt-i³lere bölünmesidir. Alt-i³ler
de, benzer ³ekilde, yapacaklarn alt-alt-i³lere bölebilirler (“ekil 1.14). Bu tip tasarma yukardan a³a§ya tasarm ad verilir.
6
Her i³ bir yordam (C dilindeki adyla fonksiyon ) tarafndan gerçeklenir. Ana-yordamn görevi,
alt-i³leri gerçekleyen yordamlar ba³latmak ve bunlar arasnda e³güdümü sa§lamaktr. Bir üstyordam, kulland§ alt-yordamlarn nasl çal³tklaryla de§il, yalnzca sonuçlaryla ilgilenir.
Soyutlamann kazandrdklar ³öyle özetlenebilir:
•
Bir i³i gerçekleyen yordam yazlrken, kulland§ alt-yordamlarn ayrntlaryla u§ra³lmaz; alt-yordamn do§ru çal³t§ varsaylarak yordamn kendi i³ine yo§unla³labilir. Böy-
5
Bu konuyla ilgili olarak, Edsger W. Dijkstra'nn Go To Statement Considered Harmful ba³lkl klasik
makalesini
6
http://www.acm.org/classics/oct95/
adresinde bulabilirsiniz.
Bu konuyla ilgili olarak, Niklaus Wirth'ün Program Development by Stepwise Renement ba³lkl klasik
makalesini
http://www.acm.org/classics/dec95/
adresinde bulabilirsiniz.
15
Giri³
ana-is
alt-is-1
alt-is-2
alt-is-1a
alt-is-3
alt-is-3a
alt-is-3b
“ekil 1.14: Ana i³in alt i³lere bölünmesi.
lelikle büyük ve çözülmesi zor olan bir sorunla u§ra³mak yerine, her biri küçük ve çözülebilir sorunlarla u§ra³lr ve bunlar daha sonra biraraya getirilir.
•
Programn bakm kolayla³r. Alt-yordamlarn çal³malar birbirlerinden ba§msz oldu§undan bir alt-yordamda bir de§i³iklik yapld§nda bunu kullanan üst-yordam (üstyordamla olan etkile³im de§i³medi§i sürece) de§i³iklikten etkilenmez.
Yordamlar olabildi§ince genel amaçl yazlmaldr. Sözgelimi bir yordamn i³i BL105E dersini
alan ö§rencilerin ylsonu snav notlarnn en büyü§ünü bulmak ³eklinde tanmlanabilir. Oysa
i³i herhangi bir dizinin en büyü§ünü bulmak olarak tanmlanan bir yordam geli³tirmek ve
bu yordam kullanrken hangi dizinin en büyü§ünün bulunmasnn istendi§i belirtmek daha
etkin bir çal³ma biçimidir. Bu durumda hangi dizi üzerinde i³lem yaplaca§ bilgisi yordamn giri³ parametresi olur. Yordam, çal³mas sonucu üretti§i de§eri çk³ parametresi olarak
döndürür. Örnekteki yordam kullanlrken giri³ parametresi olarak BL105E dersini alan ö§rencilerin ylsonu snav notlar verilirse snavda alnan en yüksek not, Los Angeles Lakers
basketbol takmnn oyuncularnn ayakkab numaralar belirtilirse takmn en büyük ayakl
oyuncusunun ayakkab numaras çk³ parametresi olur.
Örnek. En Büyük Ortak Bölen Bulma
ki saynn en büyük ortak bölenini bulma i³i ³u ³ekilde alt i³lere bölünebilir:
1. Birinci sayy asal çarpanlarna ayr.
2. kinci sayy asal çarpanlarna ayr.
3. Saylarn ortak çarpanlarn belirleyerek en büyük ortak bölenin asal çarpanlarn bul.
4. Bir önceki admda belirledi§in asal çarpanlardan en büyük ortak böleni hesapla.
Saylarn 9702 ve 945 olduklar varsaylrsa:
16
Soyutlama
1 * 32 * 72 * 111
1. 9702 = 2 * 3 * 3 * 7 * 7 * 11 = 2
3 * 51 * 71
2. 945 = 3 * 3 * 3 * 5 * 7 = 3
2 * 71
3. ortak çarpanlar: 3
4. en büyük ortak bölen: 63
1. ve 2. admlar için herhangi bir sayy asal çarpanlarna ayran bir yordam yazlabilir ve
asal çarpanlarna ayrlacak say bu yordama parametre olarak yollanabilir. Benzer ³ekilde,
3. admdaki ortak çarpanlarn bulunmas i³i de bir alt-yordama verilebilir. 4. admda ortak
çarpanlardan en büyük ortak bölenin hesaplanmas i³lemleri için alt-yordam kullanmann fazla
bir anlam yoktur, ana yordama brakmak daha yerinde olur. Böylece “ekil 1.15'deki yap ortaya çkar. Örnek saylar üzerinde yordamlarn hangi giri³ ve çk³ parametreleriyle çal³tklar
“ekil 1.16'da verilmi³tir.
1. sayi
en büyük
ortak bölen
hesapla
2. sayi
1. sayinin
çarpanlari
2. sayinin
çarpanlari
1. sayinin
çarpanlari
asal
çarpanlara
ayir
ortak
çarpanlar
2. sayinin
çarpanlari
ortak
çarpanlari
bul
“ekil 1.15: En büyük ortak bölen hesaplama algoritmasnn yukardan a³a§ya tasarm.
Asal çarpanlara ayrma algoritmasnda görülen bir sonraki asal sayy bulma i³i de asal
çarpanlarna ayrma i³inin bir alt-i³i olarak dü³ünülerek bir ba³ka yordama braklabilir. Bu
yordam kendisine parametre olarak gönderilen saydan bir sonraki asal sayy bularak sonucu
geri yollayacaktr. Benzer ³ekilde bu yordam da bir saynn asal olup olmad§n snamak üzere
ba³ka bir yordamdan yararlanmak isteyebilir. Bu örnek için verilen yordamlar gerçekleyecek
algoritmalar bölümün sonundaki uygulamada verilmi³tir.
Örnek. Euclides Algoritmas
Yukarda verilen algoritmann en önemli sorunu, özellikle büyük saylar asal çarpanlarna
ayrmann zorlu§udur. Bilinen en eski algoritma örneklerinden biri olan Euclides algoritmas,
iki saynn en büyük ortak böleninin çarpanlara ayrmadan hzl biçimde hesaplanmasn sa§lar.
En büyük ortak böleni bulunacak saylardan büyük olanna
a,
küçük olanna
b
dersek:
17
Giri³
9702
en büyük
ortak bölen
hesapla
945
2 × 32 × 72 × 11
33 × 5 × 7
32 × 7
2 × 32 × 72 × 11
33 × 5 × 7
asal
çarpanlara
ayir
ortak
çarpanlari
bul
“ekil 1.16: Örnek saylar üzerinde en büyük ortak bölen hesaplama algoritmasnn i³leyi³i.
a = q 1 b + r1
³eklinde yazlabilir. Burada
ile
b
r1 = 0
ise iki saynn en büyük ortak böleni
saylarnn en büyük ortak böleni
b
ile
r1
b'dir.
De§ilse
a
saylarnn en büyük ortak bölenine e³ittir.
Dolaysyla, bölümden kalan 0 olana kadar a³a§daki e³itlikler yazlabilir:
b = q 2 r1 + r2
r1 = q 3 r 2 + r 3
...
rn−2 = qn rn−1 + rn
rn−1 = qn+1 rn + rn+1 (rn+1 = 0)
Bu durumda
a
ile
b'nin
en büyük ortak böleni
rn 'dir.
Yine
a = 9702, b = 945
örne§ini alrsak:
9702 = 10 ∗ 945 + 252
945 = 3 ∗ 252 + 189
252 = 1 ∗ 189 + 63
189 = 3 ∗ 63 + 0
a, küçük olann b
r de§i³keninde tutarsak (kalan i³lemi %
Her denklem için en büyük ortak böleni alnacak saylardan büyük olann
de§i³keninde, bu ikisinin bölümünden kalan de§eri de
i³aretiyle gösterilsin), bu algoritma bir yineleme yapsyla gerçeklenebilir. Bir bölme i³leminde
18
Soyutlama
her zaman kalan, bölenden küçük olaca§ için her yinelemede
de
r'nin
de§erini alarak ilerlenir ve
b
a
de§i³keni
0 oldu§unda en büyük ortak bölen
a
b'nin, b
de§i³keni
de§i³keninde elde
edilmi³ olur. Bu algoritmann ak³ çizene§i “ekil 1.17'de, örnek de§erlerle i³leyi³i Tablo 1.3'de
verilmi³tir.
7
D
sayi1 > sayi2
Y
a ← sayi1
b ← sayi2
a ← sayi2
b ← sayi1
b>0
Y
D
bas: a
r←a%b
a←b
b←r
“ekil 1.17: Euclides algoritmasnn ak³ çizene§i.
a
9702
945
252
189
b
945
252
189
63
r
252
189
63
0
Tablo 1.3: Euclides algoritmasnn örnek de§erlerle i³leyi³i.
Uygulama: Algoritmalar
Örnek. Asal Çarpanlarn Bulunmas
Herhangi bir saynn asal çarpanlarna ayrlmas için kullanlabilecek bir algoritma “ekil 1.18'de
verilmi³tir. Bu algoritmada
7
x asal çarpanlarna ayrlacak sayy, c çarpan olup olmad§ o anda
Orijinal haliyle algoritmada bölmeden kalan i³lemi yerine çkartma i³lemi kullanlyordu. Bölmeden kalan
i³lemi algoritmann önemli ölçüde hzlanmasn sa§layan bir de§i³iklik olarak sonradan getirilmi³ bir yöntemdir.
19
Giri³
snanmakta olan asal sayy,
u da sradaki çarpann kuvvetini gösterir. 945 says örnek olarak
alnrsa algoritmann i³leyi³i Tablo 1.4'de verilmi³tir.
c←2
x>1
Y
D
x%c=0
Y
D
c bir carpandir
u←0
x%c=0
Y
D
u←u+1
x←x/c
c ← sonraki asal sayi
“ekil 1.18: Bir sayy asal çarpanlarna ayrma algoritmas.
Örnek. Ortak Çarpanlarn Bulunmas
ki saynn çarpanlarndan en büyük ortak bölenin çarpanlarn bulma i³ini yapacak yordamn
algoritmas geli³tirilirken, asal çarpanlara ayrma yordamnn çal³ma ³ekli nedeniyle çarpanlarn küçükten büyü§e do§ru sral olduklar varsaylabilir. Bu varsayma gören çal³an algoritma
“ekil 1.19'da verilmi³tir. Bu algoritmada carpanlar1 birinci saynn asal çarpanlar dizisini,
carpanlar2 ikinci saynn asal say çarpanlar dizisini, c1 birinci saynn sradaki asal çarpann, c2 de ikinci saynn sradaki asal çarpann gösterir. Her iki dizinin elemanlarna eri³mek
için de srasyla i1 ve i2 sayaç de§i³kenleri kullanlm³tr. Örnek dizilerle algoritmann i³leyi³i
Tablo 1.5'de verilmi³tir.
20
Soyutlama
x
945
315
105
35
7
1
2
3
x > 1
D (945 > 1)
D (945 > 1)
5
D (35 > 1)
7
D
(7 > 1)
11
Y
(1 = 1)
c
Y
D
D
D
D
Y
D
D
Y
D
D
Y
x % c = 0
(945 mod 2 =
(945 mod 3 =
(945 mod 3 =
(315 mod 3 =
(105 mod 3 =
(35 mod 3 =
(35 mod 5 =
(35 mod 5 =
(7 mod 5 =
(7 mod 7 =
(7 mod 7 =
(1 mod 7 =
1)
0)
0)
0)
0)
2)
0)
0)
2)
0)
0)
1)
carpan
u
3
0
1
2
3
5
0
1
7
0
1
Tablo 1.4: Asal çarpanlarna ayrma algoritmasnn i³leyi³i.
c1
c2
taban
1
2
3
3
2 < 3
2
3
2
7
1
11
3= 3
1
7 > 5
1
7
7= 7
5
us
carpan
2 < 3
3
2
1 < 2
7
1
-
Tablo 1.5: Ortak çarpanlar bulma algoritmasnn i³leyi³i.
21
Giri³
c1 ← carpanlar11, c2 ← carpanlar21
i1 ← 1, i2 ← 1
c1 ve c2
bos değil
Y
1
D
c1.taban < c2.taban
D
i1 ← i1 + 1
c1 ← carpanlar1i1
Y
c1.taban > c2.taban
D
i2 ← i2 + 1
c2 ← carpanlar2i2
Y
D
c1.us < c2.us
c1 bir carpandir
Y
c2 bir carpandir
i1 ← i1 + 1, i2 ← i2 + 1
c1 ← carpanlar1i1, c2 ← carpanlar2i2
“ekil 1.19: Ortak çarpanlar bulma algoritmas.
22
Giri³ / Çk³
1.5
Giri³ / Çk³
Bir programlama dilinin kullanlabilir olmas için dilde blok yapl programlamann kavramlarn desteklemenin d³nda baz gereklilikler de yerine getirilmelidir:
Giri³
Bir program her seferinde ayn veri de§erleri üzerinde çal³maz, i³leyece§i verileri çal³ma srasnda bir ³ekilde ö§renmesi gerekir. Bunun en sk kar³la³lan yöntemi verileri
program kullanan ki³iye sormak olmakla birlikte verileri bir dosyadan okumak ya da
ortamdan ö§renmek (sözgelimi odann scakl§n ölçen bir duyargadan almak) gibi seçenekler de bulunabilir. Programlama dillerinin girdi komutlar giri³ birimlerinden aldklar
de§erleri de§i³kenlere aktarrlar. Aksi belirtilmedikçe standart giri³ birimi kullancnn
tu³takmdr.
Çk³
Program, verilerin i³lenmesi sonucu elde etti§i sonuçlar bir ³ekilde de§erlendirmelidir.
En sk görülen yöntem sonucun kullancnn ekranna yazlmasdr ama giri³te oldu§u
gibi sonuçlarn bir dosyaya yazlmas ya da ortama gönderilmesi (oda scakl§n denetleyen klimaya bir sinyal yollanmas gibi) sözkonusu olabilir. Programlama dillerinin çkt
komutlar, de§i³ken de§erlerini istenen çk³ birimine yönlendirirler. Aksi belirtilmedikçe
standart çk³ birimi kullancnn ekrandr.
Programn çal³mas srasnda kar³la³lan hata durumlarnn bildirilmesi de çktnn bir
parçasdr. Ancak, hatalarn daha kolay farkedilmelerini sa§lamak amacyla, bu iletilerin
normal çkt iletilerinden ayrlabilmeleri istenir. Bu nedenle, hata iletileri hata birimine
yönlendirilir. Aksi belirtilmedikçe bu birim -standart çk³ta oldu§u gibi- kullancnn
ekrandr.
Bu notlarda i³lenecek örnek programlarda çal³ma hep ayn ³ekilde olacaktr: verilerin girilmesi, i³lenmesi, sonuçlarn gösterilmesi. Bu tip programlara konsol program, komut satr
program ya da metin kipi program gibi adlar verilir. Grak arayüzle çal³an programlar ise
olaya dayanan bir mantkla çal³rlar. Program çal³maya ba³lad§nda kullancyla ileti³imi
için gerekli arayüzü kurar (pencere çizer, menü olu³turur, dü§me koyar, v.b.) ve sonra kullancnn bir edimde bulunmasn bekler. Kullancnn edimine göre ilgili yordamlar çal³trr.
1.6
Program Geli³tirme
Bir programn geli³tirilmesi çe³itli a³amalardan olu³ur:
Tasarm
Bu a³amada yazlacak program ka§t üzerinde tasarlanr. Yani programn algorit-
masna, hangi programlama dilinin kullanlaca§na, kullancyla nasl bilgi al³veri³inde
bulunulaca§na, ksacas neyin nasl yaplaca§na karar verilir. Dikkatli bir tasarm, programn hem geli³tirilmesinde hem de bakmnda büyük kolaylklar sa§lar.
Kodlama
Bu a³amada program tasarm srasnda verilen kararlara göre bir programlama di-
8 Kaynak kodunu bilgisayar
liyle yazlr. Bunun sonucunda yazlmn kaynak kodu olu³ur.
ortamnda olu³turmak için editör ad verilen yazlmlar kullanlr.
8
Metinde bunda sonra geçen
kod
sözcü§ü aksi belirtilmedikçe kaynak koduna kar³ dü³ecektir.
23
Giri³
Snama
Bu a³amada program çal³trlarak çe³itli senaryolar için do§ru sonuçlar üretip üret-
medi§ine, beklendi§i gibi davranp davranmad§na baklr. Bu i³lemin etkinli§i gözönüne
alnan senaryolarn gerçekte olu³abilecek durumlarn ne kadarn örttü§üyle ba§lantldr.
Hata Ayklama
Bu a³amada snama a³amasnda bulunan hatalarn nedenleri belirlenerek
gerekli düzeltmeler yaplr. Programlarn ilk yazldklar ³ekliyle do§ru olmalar neredeyse
olanakszdr. Hatta üstüne çok çal³lm³, pek çok hatas bulunup düzeltilmi³ programlarda bile bütün hatalarn bulunup düzeltilmi³ olmas son derece dü³ük bir olaslktr.
Ayrca programlara yeni yetenekler eklendikçe yeni hatalar olu³aca§ndan a³a§ yukar
hiçbir program hiçbir zaman tam olarak hatasz olmayacaktr. Hata ayklama i³lemine
yardmc olmak üzere hata ayklayc ad verilen yazlmlar kullanlr.
Programlarda iki tür hata sözkonusu olabilir:
1. Yazm hatalar: Programcnn yazd§ baz komutlar kulland§ programlama dilinin kurallarna uymuyordur.
2. Mantk hatalar: Programcnn yazd§ kod dilin kurallar açsndan do§rudur ama çal³trlmasnda sorun çkar. Sözgelimi bir tamsayy ba³ka bir tamsay de§i³kene bölmek
geçerli bir i³lemdir ama bölen say 0 olursa bu i³lem gerçekle³tirilemez. Bu tür hatalara
çal³ma-zaman hatas da denir.
1.6.1
Programlarn De§erlendirilmesi
Bu a³amalar sonucunda ortaya çkan bir programn iyi bir program olup olmad§nn, ya da
ne kadar iyi bir program oldu§unun de§erlendirilmesinde ³u ölçütlere ba³vurulur:
Etkinlik
Bu konu algoritmalarn kar³la³trlmalarnda kullanlan ölçütlerle ayndr. Program
ne kadar hzl çal³yor? Düzgün kullanlabilmesi için ne kadar sistem kayna§ gerekiyor
(hangi i³lemci, ne kadar bellek, ne kadar disk, v.b.?).
Sa§lamlk
Program, kullancnn yapaca§ kullanm hatalarna kar³ dayankl m? Sözgelimi,
kendisine bir yl bilgisi soruldu§unda kullanc yanl³lkla (ya da kötü niyetle) bir isim
yazarsa ne oluyor?
Ta³nabilirlik
Program, üzerinde fazla de§i³iklik yaplmas gerekmeden, ba³ka bir donanm
ve ba³ka bir i³letim sistemi üzerinde çal³acak hale getirilebiliyor mu?
Anla³labilirlik
Ba³ka biri program okudu§unda anlayabilecek mi? Hatta üstünden bir süre
geçtikten sonra kendiniz bakt§nzda anlayabilecek misiniz?
Bakm kolayl§
Programda hata oldu§unda hatann kayna§nn belirlenmesi ve düzeltilmesi
kolay m?
Geli³tirilebilirlik
Program yeni yeteneklerin eklenmesiyle geli³tirilmeye açk m? Bu tip ek-
lemelerin yaplmas kolay m?
Program Geli³tirme
24
Geli³tirme a³amalarnda daha az sorunla kar³la³mak ve daha kaliteli yazlmlar üretmek için
çe³itli yöntemler geli³tirilmi³tir. Bu yöntemlerin temel fark, problemin nasl modellenece§ine
ili³kin yakla³mlardr. Blok yapl yakla³m, nesneye dayal yakla³m, fonksiyonel yakla³m gibi
yöntemler çe³itli alanlarda yaygn olarak kullanlmaktadr. Seçti§iniz programlama dili hangi
programlama yakla³mn kullanaca§nz da belirler. Sözgelimi C dili blok yapl, Java dili
nesneye dayal, Haskell diliyse fonksiyonel dillerdir. C++ dili hem blok yapl hem de nesneye
dayal özellikler gösteren karma bir dildir.
1.6.2
Programlarn Çal³trlmas
Bilgisayarlarn çal³tracaklar programlarn belli bir biçimi olmas zorunludur. Bu biçim, bilgisayardan bilgisayara ve i³letim sisteminden i³letim sistemine göre farkllklar gösterir. Sözgelimi, bir ki³isel bilgisayar üzerinde Windows i³letim sisteminde çal³an bir program, Sun marka
bir i³istasyonunda Solaris i³letim sisteminde çal³maz. Hatta, yine ayn ki³isel bilgisayar üzerinde Linux i³letim sisteminde de çal³maz. Programlarn bu çal³trlabilir biçimine makina
kodu ad verilir. Makina kodu, insanlarn anlamas ve üzerinde çal³mas son derece zor bir
biçim oldu§undan programclar programlar do§rudan bu kod ile yazmazlar. nsann anlamas
daha kolay (insan diline daha yakn) yüksek düzeyli bir dil ile kaynak kodunu olu³turup
yardmc yazlmlar aracl§yla makina koduna çevirir ve çal³trrlar.
Kaynak kodunun makina koduna çevrilmesi ve çal³trlmas i³lemi üç farkl yakla³mla gerçekle³tirilebilir:
Yorumlama
Programn komutlar bir yorumlayc tarafndan teker teker okunur, makina
koduna çevrilir ve çal³trlr. Yani yorumlayc, önce birinci komutu okur, makina koduna
çevirir ve çal³trr. Sonra ikinci komutu alr ve ayn i³lemleri yapar. Programn her
çal³masnda çevirme i³lemi yeniden yaplr. Herhangi bir komutun çevrilmesinde ya
da çal³trlmasnda bir hatayla kar³la³t§nda bunu kullancya bildirir ve çal³may
durdurur. Basic, Perl, Tcl gibi diller genellikle yorumlayclar aracl§yla kullanlrlar.
Derleme
Program bir derleyici tarafndan bir bütün halinde okunur ve makina koduna çev-
rilerek bir çal³trlabilir dosya olu³turulur. Bu dosya daha sonra istendi§i zaman çal³trlr, yani çevirme ile çal³trma i³lemleri birbirinden ayrlr. Böylelikle çevirme i³lemi
yalnzca bir kere yaplr. Herhangi bir komutta hata varsa çevirme i³lemi tamamlanmaz,
yani çal³trlabilir kodun olu³mas için hiçbir yazm hatas olmamas gerekir; ancak program daha sonra çal³trlrken çal³ma-zaman hatalaryla kar³la³labilir. Fortran, Pascal,
C gibi diller genelde derleyicilerle kullanlrlar.
Karma
Hem derleme hem de yorumlama tekni§i kullanlr. Bu tip çal³mada kaynak kodu
sanal bir bilgisayarn makina koduna (bytecode) çevrilir ve daha sonra bu sanal bilgisayar gerçekleyen bir program yardmyla yorumlanarak çal³trlr. Örne§in Java dilinde
yazlm³ bir kaynak kodu önce Java derleyicisinden geçirilerek Java sanal makinasnn
(Java Virtual Machine - JVM) makina koduna dönü³türülür; sonra da bu sanal makinay gerçekleyen bir Java çal³ma ortam (Java Runtime Environment - JRE) yardmyla
çal³trlr.
Yorumlama yönteminde kodun okunmas ve çevrilmesi programn çal³mas srasnda yapld§ndan hz dü³üktür. Ayrca yorumlayc yalnzca kar³la³t§ ilk hatay rapor edebilir. Bu
25
Giri³
hata düzeltildi§inde sonraki çal³mada da program ancak bir sonraki hataya kadar ilerleyebilir. Oysa derleyici kaynak kodundaki bütün hatalar bulabilir. Buna kar³lk hata ayklama
i³lemi yorumlayclarla daha kolaydr. Ayrca derleyicilerle gelen baz snrlamalarn kalkmas
nedeniyle daha esnek bir çal³ma ortam sa§lanr. Son yllarda iki yöntemin üstün yanlarn
birle³tiren karma diller (Java ve Python gibi) öne çkmaya ba³lam³lardr.
1.6.3
Kitaplklar
Bir programcya gerekebilecek her ³eyi programlama dilinin içine almak o dili i³leyecek araçlarn hantalla³malarna neden olur. C dili bu nedenle oldukça küçük bir dil olarak tasarlanm³tr. Örne§in basit aritmetik i³lemlerin ötesindeki matematik i³lemleri dilin tanm içinde
yer almaz; sözgelimi karekök alma i³lemi için bir C komutu yoktur. Bununla birlikte, pek çok
programcnn bu tip i³lemlere gereksinim duyacaklar da açktr. Böyle bir durumda programc, isterse karekök alma i³lemini yapacak kodu kendisi yazabilir. Ancak programcnn bu
tip i³lemler için kendi kodlarn yazmasnn önemli sakncalar vardr:
1. Her programcnn ayn i³leri yapan kodlar yazmas büyük zaman kaybna yol açar.
2. Programcnn yazaca§ kod hatal olabilir, yani yanl³ sonuç üretebilir. Ya da do§ru sonuç
üretse bile, yeterince etkin olmayabilir, yani i³lemi yapmak için gere§inden fazla zaman
ya da sistem kayna§ harcayabilir.
Hem dilin tanmn küçük tutmak hem de bu sakncalar giderebilmek için, ço§u programcya gerekebilecek i³lemler (yordamlar) kitaplk ad verilen ar³ivlerde toplanm³tr. Bir saynn
karekökünü almak isteyen bir programc matematik kitapl§ndaki
sqrt
yordamn kullanabi-
lir. Kitapl§n kullanlmas yukarda sözü geçen sakncalar giderir, yani programcya zaman
kazandrd§ gibi, do§ru ve etkin çal³t§ snanm³ oldu§undan dikkatini programn di§er ksmlarna yo§unla³trma frsat verir.
1.6.4
Standartlar
C dilinin geli³tirilmesinde gözetilen ana hedeerden biri ta³nabilirlikti. Bunun için de§i³ik
ortamlardaki araçlar arasnda bir standart olmas gerekti§i açktr. C dilinde yaplan standartla³ma çal³malar sonucunda olu³an ANSI C standard, hem C dilinin kurallarn belirler,
hem de bir C geli³tirme ortamnda bulunmas zorunlu olan standart kitaplklar ve bu kitaplklarda yer alacak yordamlar tanmlar. Uluslararas Standartlar Organizasyonu'nun (ISO)
C++ dili için hazrlad§ ISO-C++ standard da son yllarda yazlm³ bütün C/C++ geli³tirme ortamlar için en temel kaynaklardan birini olu³turmaktadr.
Di§er önemli bir standart olan POSIX standard ise programlama dili ile i³letim sistemi arasndaki ba§lantlar belirler. Örne§in dosya silmek, dosya ad de§i³tirmek, sistemdeki ba³ka
bir programla haberle³mek gibi i³lemler için gereken yordamlar bu standartta yer alrlar.
Yine de skça gereksinim duyulan bütün i³lemler için bütün kitaplklarda bir standart henüz
sa§lanamam³tr. Örne§in grak bir arayüze sahip uygulamalardaki grak i³lemlerini yapacak
kitaplklar standartla³trlmam³ oldu§undan çe³itli rma ve kurumlar bu i³lemleri yapan farkl
26
Program Geli³tirme
kitaplklar geli³tirmi³lerdir. Dolaysyla bu kitaplklar kullanlarak yazlan programlar tam anlamyla ta³nabilir olmamakta, yalnzca bu kitapl§n destekledi§i ortamlara ta³nabilmektedir. Son zamanlarda farkl i³letim sistemlerinde çal³abilen grak kitaplklar yaygnla³t§ için
do§ru araçlar seçildi§inde bu sorunun da üstesinden gelinebilmektedir.
1.6.5
Derleme A³amalar
Kaynak koddan üretilecek olan çal³trlabilir makina kodunda hem programcnn kendi yazd§
yordamlarn, hem de yararland§ kitaplk yordamlarnn makina koduna çevrilmi³ hallerinin
bulunmas gerekir. Bu nedenle, kaynak kodunun makina koduna çevrilmesi iki a³amada gerçekle³ir (“ekil 1.20):
derleme
kaynak kodu
baglama
ara kod
çalistirilabilir kod
kitapliklar
“ekil 1.20: Tek kaynak kodlu projelerin derleme a³amalar.
Derleme
lk a³amada kaynak kodu derlenerek bir ara koda dönü³türülür. Bu kod, kullancnn
yazd§ yordamlarn makina kodu kar³lklarn içeren bir dosyadr. Ancak, programcnn
kullanm³ oldu§u kitaplk yordamlarn içermedi§inden henüz çal³trlabilir durumda
de§ildir.
Ba§lama
kinci a³amada ara kod ile programcnn kulland§ kitaplk yordamlar arasnda
ba§lantlar kurulur ve çal³trlabilir dosya üretilir. Sözgelimi, programc karekök alma
için matematik kitapl§ndaki bir yordam kullandysa, ba§layc ara kodda karekök yordamnn kullanld§ yerlerde gerekli düzenlemeleri yapar.
Sorular
1. Bölüm 1.1'de verilen takas i³lemi için yazlan üç atama komutunun sralarn de§i³tirerek
ne sonuçlar elde edildi§ini belirleyin. Problemin kaç do§ru çözümü vardr?
2. Bölüm 1.2.1'de yaplan algoritma hz kar³la³trmalarnda verilen en kötü ve ortalama
n - 1 ³eklinde verildi§i genel
durum de§erlerini kendiniz çkarn. Alt snrn 1, üst snrn 2
durumda en kötü ve ortalama de§erleri
n
cinsinden hesaplayn.
3. ki saynn en büyük ortak bölenini hesaplamak için verilen iki algoritmay, basitlik ve
etkinlik açlarndan kar³la³trn. kiden fazla saynn en büyük ortak bölenlerini hesaplamak için bir algoritma geli³tirin.
27
Giri³
a
say2 de§erleri atanarak yineleme yapsna girildi§ini
say1 > say2 ya da say1 < say2 olmas durumlarnda al-
4. Euclides algoritmasnda iki saydan büyük olannn hangisi oldu§una baklmakszn
de§i³kenine
say1, b
de§i³kenine
varsayalm. Ba³langçta
goritma do§ru sonuç üretir mi?
5. Çarpanlara ayrarak en küçük ortak kat hesaplamak için gereken en küçük ortak katn
çarpanlarn bulma yordamnn ak³ çizene§ini çizin ve örnek de§erler üzerinde nasl
i³leyece§ini gösteren tabloyu olu³turun.
Program Geli³tirme
28
Bölüm 2
C Diline Giri³
Bu bölümde de§i³kenler, atama, deyimler, giri³-çk³ gibi konularn C dilinde nasl gerçeklendikleri üzerinde durulacaktr.
Örnek 1. Daire Çevresi ve Alan
Yarçapn kullancdan ald§ bir dairenin çevresini ve alann hesaplayarak ekrana yazan bir
program yazlmas isteniyor. Programn örnek bir çal³masnn ekran çkts “ekil 2.1'de verilmi³tir.
Yarçap yaznz: 4.01
Çevresi: 25.1828
Alan: 50.4915
“ekil 2.1: Örnek 1 ekran çkts.
Örnek üzerinde bir C programnn baz temel özelliklerini görelim:
Açklamalar
Anla³labilirli§i artrmak için kodun içinde gerekli yerlere açklamalar yazmakta
büyük yarar vardr. Özellikle kolayca anla³lmayacak programlama tekniklerinin kullanld§ kod parçalarnn açklanmas gerekir. Açklamalar derleyici tarafndan gözard
edilir, yani programn i³leyi³lerine hiçbir etkileri yoktur. Kodun içine açklama iki ³ekilde yazlabilir:
•
Birinci yöntemde, açklamann ba³na bölü-yldz, sonuna yldz-bölü simgeleri konur. Bu ³ekildeki açklamalar birden fazla satr sürebilir. Örnekteki birinci açklama birinci satrdaki lk
alann
hesaplar.
C programm
sözcükleriyle ba³lar ve üçüncü satrdaki
sözcükleriyle biter. Bu tip açklamalar içiçe yazlamaz, yani
bir açklamann içinde ikinci bir açklama olamaz. çiçe açklamalar ³u ³ekilde bir
yap olu³turur:
...a... /* ...b... /* ...c... */ ...d... */ ...e...
29
30
Örnek 1 Bir dairenin çevresini ve alann hesaplayan program.
/* lk C programm.
*
*
*
* Yarçap verilen bir dairenin çevresini ve alann hesaplar. */
#include <iostream>
#include <stdlib.h>
// cout,cin,endl için
// EXIT_SUCCESS için
using namespace std;
#define PI 3.14
int main(void)
{
float radius;
float circum, area;
}
cout << "Yarçap yaznz: ";
cin >> radius;
circum = 2 * PI * radius;
area = PI * radius * radius;
cout << "Çevresi: " << circum << endl;
cout << "Alan: " << area << endl;
return EXIT_SUCCESS;
31
C Diline Giri³
Bu yapda birinci
/*
/*
ile açklama ba³lar. Açklamann içinde görülen ikinci
zard edilir ve gelen ilk
*/
açklamay sona erdirir; yani açklamay
b
ve
c
gö-
bölgeleri
olu³turur. Bundan sonra gelen bölüm (d bölgesi) normal C kodu gibi de§erlendirilece§inden hataya yol açar.
•
1 Ksa
kinci yöntemde, açklama çift bölü ile ba³lar ve satrn sonuna kadar sürer.
açklamalar için bu yöntem daha kullan³ldr. Örnekteki ikinci açklama be³inci
satrdaki cout,cin,endl
satrdaki EXIT_SUCCESS
Komutlar
için sözcüklerinden olu³ur. Üçüncü açklama da altnc
için sözcüklerini kapsar.
C dilinde komutlar noktal virgül ile sona erer. Pe³pe³e birden fazla bo³luk derleyici
tarafndan tek bo³luk olarak de§erlendirilir; dolaysyla bir komutun bir satr içinde
ba³layp sona ermesi zorunlulu§u yoktur. Yani
cout < < Alan: < < area < < endl;
komutu
cout < < Alan: < < area < < endl;
biçiminde ya da
cout < < Alan: < < area
< < endl;
biçiminde yazlabilirdi.
C dilinde komutlarn noktal virgül ile sona ermesi ve fazla bo³luklar ile satr geçi³lerinin Gelenek
öneminin olmamas nedeniyle komutlar satrlara istendi§i ³ekilde yerle³tirilebilir.Ancak
bu konuda bir düzene uyulmazsa kodun okunmas ve anla³lmas son derece zorla³r.
Okunabilirli§i artrmak amacyla alt-bloklar bir miktar içeriden ba³latlrlar (girintileme ). Böylece ayn düzeydeki (ayn blo§a ait) komutlar ayn hizadan ba³larlar. Örnekte
fonksiyon blo§undaki bütün komutlar satr ba³ndan dört harf içeriden ba³lamaktadr.
Özellikle içiçe yaplarn kullanld§ durumlarda (seçimin içindeki yinelemenin içindeki
seçimin içindeki seçim gibi) bloklar hiyerar³ik bir ³ekilde girintilemek büyük önem ta³r.
Atama
Atama i³lemi e³it i³aretiyle yaplr. Örnekteki
circum = 2 * PI * radius;
komutu bir atama komutudur,
nine atar.
1
2
2
2 * PI * radius
deyiminin sonucunu
circum
de§i³ke-
Bu açklama yöntemi C++ ile getirilmi³ bir yeniliktir, C dilinde geçerli de§ildir.
Tek atama komutuyla birden çok de§i³kene ayn de§er atanabilir. Örne§in
a = b = c = 24;
komutu
a, b ve c de§i³kenlerinin üçüne de 24 de§erini atar. Bu i³lem sa§dan sola do§ru gerçekle³tirilen pe³pe³e
atamalar ³eklinde dü³ünülebilir:
c = 24; b = c; a = b;
32
simler
Fonksiyonlar
Blok yapl programlamadaki yordamlar C dilinde fonksiyonlar ile gerçekle³ti-
rilir. Ana i³i yapan fonksiyonun ad
main
olarak verilmelidir. Programn yürütülmesine
ana i³ten ba³lanaca§ için her programn bir ve yalnz bir
main
fonksiyonu bulunmas
zorunludur.
C dilinde bir fonksiyonun içerdi§i komutlar bir blok olarak de§erlendirilir. Bloklar açsüslü-ayraç ile ba³lar ve kapa-süslü-ayraç ile sona erer. Bu notlardaki ço§u örnekte
main
fonksiyonu ³u ³ablona uyacaktr:
int main(void)
{
...
return EXIT_SUCCESS;
}
Ba³lk dosyalar
Kitaplklarda tanmlanm³ olan fonksiyonlar, birimler ya da büyüklükler
kullanld§ zaman derleyiciye bunlarla ilgili bilgileri nerede bulabilece§ini söylemek gerekir. Bu bilgilerin yer ald§ ba³lk dosyalar program ba³nda
belirtilir. Örne§in
cout
birimi
iostream
#include
komutuyla
ba³lk dosyasnda bulundu§undan örnek prog-
ramda
#include <iostream>
komutu yer almaktadr.
stdlib.h
3 Benzer ³ekilde,
EXIT_SUCCESS sözcü§ünün kullanlabilmesi için
dosyas içerilmelidir.
Bir kitaplktan yararlanaca§nz zaman gerekli bilgilerin hangi ba³lk dosyalarnda yer ald§n bilmeniz gerekir. Temel fonksiyonlar standartlarda belirlenmi³ oldu§undan (bkz.
Bölüm 1.6.4) bunlarn ba³lk dosyalarn ço§u C/C++ kitabnda bulabilirsiniz. Standartlara girmemi³ fonksiyonlar içinse kulland§nz derleyici ve kitaplklarn yardmc
belgelerine ba³vurmalsnz.
2.1
4
simler
Programlardaki de§i³ken, fonksiyon gibi varlklara verilen isimlerin baz kurallara uymalar
gerekir:
•
simler, ngilizce büyük ve küçük harer, rakamlar ve altçizgi i³aretinden olu³abilir. Bu
kurala göre
weight-1
•
3
pi, weight, weight1
ve
weight_1
geçerli isimlerdir, ancak
ve
geçerli isimler de§ildir.
smin ilk simgesi bir rakam olamaz. Bu kurala göre
2weight
geçerli bir isim de§ildir.
.h uzants verilir. C++ standardnda ise baz ba³lk dosyalarnn uzaniostream ba³lk dosyas C++ ile tanmlanm³ yeni ba³lk dosyalarna bir ör-
C standardnda ba³lk dosyalarna
ts bulunmayabilir. Örnekteki
nektir.
4
π , a§rlk
Unix i³letim sistemlerinde yardmc belgeler ile ilgili bilgi için bkz. Ek B.1.
33
C Diline Giri³
•
smin en az ilk 31 simgesi anlamldr. Ba³ka bir deyi³le, ilk 31 simgesi ayn olmayan iki ismin farkl olaca§ kesindir ama aynlarsa derleyici bu iki ismin farkl olmad-
population_increase_between_years_2000_and_2001 ile
population_increase_between_years_2001_and_2002 isimli iki de§i³ken tanmlanrsa
§na karar verebilir. Örne§in
ilk 31'er simgeleri ayn oldu§undan baz derleyiciler bu ikisinin ayn de§i³ken olduklarna
karar verebilir.
•
simlerde büyük-küçük harf ayrm vardr. Yani
weight1, Weight1, WEIGHT1 ve wEiGHT1
isimlerinin hepsi geçerli olmakla birlikte hepsi birbirinden farkldr.
•
C dilinin sözcükleri isim olarak seçilemez. Yani örne§in
int, main, void, return
geçerli
isimler de§ildir. Kitaplklardan alnan fonksiyon ya da di§er varlklarn isimleri sakl
isimler arasnda de§ildir. Sözgelimi, istenirse
bu durumda çkt için kullanlan
cout
cout isimli bir de§i³ken kullanlabilir ancak
kitaplk biriminden artk yararlanlamaz.
Büyük projelerde isim çak³malar sorun yaratmaya ba³lar. Bu durumu düzeltmek amacyla isim uzaylarndan yararlanlr. Bu kitaptaki örnekler küçük boyutta olduklar için
bu sorunlar gözard edilecek ve standart isim uzaynn kullanld§n belirtmek üzere
programn ba³nda
using namespace std;
bildirimi yaplacaktr. Bu bildirim
cin, cout
endl de§erlerine kolay
std:: eklemek gerekir:
ve
kullanlmazsa bu de§erlere eri³im için ba³larna
eri³imi sa§lar;
std::cin > > radius;
std::cout < < Area: < < ... < < std::endl;
simlerin seçiminde ço§u programcnn uydu§u baz gelenekler vardr:
•
Gelenek
De§i³ken ve fonksiyon isimleri küçük harerle ba³lar. Ba³ka bir deyi³le, büyük harer
ya da altçizgi i³aretiyle ba³lamaz.
•
De§i³ken ve fonksiyonlara gösterdikleri bilgiye ya da yaptklar i³e uygun dü³en, anlaml
bir isim verilir. Sözgelimi bir insann a§rl§ bilgisini tutacak bir de§i³kene
anlamsz ya da
•
height
x4szb
gibi
gibi yanltc isimler verilmez.
Anlaml isimler verilmek istendi§inde bazen birden fazla sözcü§e gereksinim duyulabilir. Bu durumda ya ismi olu³turan iki sözcük bir altçizgi i³aretiyle birle³tirilir (örne§in
birth_month)
2.2
ya da ikinci sözcük büyük hare ba³lar (örne§in
birthMonth).
De§erler
Tamsaylarn do§al gösterilimleri onlu düzendedir, ancak istenirse sekizli ya da onaltl düzende
de gösterilebilirler. Örnekte 2 says onlu gösterilimde yazlm³ bir tamsaydr. 0 rakamyla
ba³layan saylarn sekizli, 0x ile ba³layanlarn onaltl düzende olduklar varsaylr. Buna göre,
59 says sekizli düzende 073, onaltl düzende 0x3b olarak yazlr.
34
De§i³kenler
Kesirli saylarn do§al gösterilimi noktal gösterilimdir, ancak istenirse bilimsel gösterilim
us ) de kullanlabilir. Örnekte 3.14 says noktal gösterilimde yazlm³ bir ke-
(mantis * 10
sirli saydr. Saynn yazl³nda E simgesi geçiyorsa bu simgenin öncesi mantis, sonras üs
olarak de§erlendirilir. Buna göre, 3.14 says bilimsel gösterilimde 314E-2 (314 * 10
−2 ) olarak
yazlabilir.
Simgeler tek, katarlar çift trnak i³aretleri arasnda yazlrlar. Örnekte Alan: de§eri bir
katardr; yalnzca A harnden söz edilmek isteniyorsa 'A' ³eklinde yazlr. Katar içinde yazlan
her bo³lu§un önemi vardr, yani sözgelimi pe³pe³e be³ bo³luk brakld§nda bu bir bo³luk
olarak de§il, be³ bo³luk olarak de§erlendirilir. Örne§in Alan
: katarnda Alan sözcü§ü
ile iki nokta üstüste i³areti arasnda be³ bo³luk bulunacaktr.
2.3
De§i³kenler
C dilinde, bir de§i³kene bir de§er vermeden ya da de§erini bir hesapta kullanmadan önce
de§i³kenin tanmlanmas gerekir. Tanmlama i³lemi, bellekte gerekti§i kadar yerin bu de§i³ken
için ayrlmasn sa§lar; böylece sistem, bellekte ayrlan bu yeri bu de§i³ken için kullanr ve
ba³ka i³lerde kullanmaz.
Tanmlama, de§i³kenin tipinin ve adnn belirtilmesinden olu³ur. Örnekte
float radius;
tanm derleyiciye
radius adnda bir de§i³ken oldu§unu ve bir kesirli say tutaca§n belirtmeye
yarar.
Ayn tipten olan de§i³kenler ayn tanmn içinde yer alabilirler. Örnekteki
float circum, area;
tanm, her ikisi de birer kesirli say olan,
circum
ve
area
adnda iki de§i³ken kullanaca§mz
anlamna gelir. Örnekteki tanmlar istenirse
float radius;
float circum;
float area;
³eklinde ayrlarak ya da
float radius, circum, area;
³eklinde birle³tirilerek de yazlabilirdi.
Tanm srasnda istenirse de§i³kene ba³langç de§eri de verilebilir:
float radius, circum = 0.0, area = 0.0;
35
C Diline Giri³
Bu durumda tanm srasnda
radius
Gelenek
circum
ve
area
de§i³kenlerinin her ikisine de 0.0 de§eri verilir,
de§i³kenine bir ba³langç de§eri verilmez.
De§i³kenlere ba³langç de§eri atanmas yararl bir al³kanlktr. Ba³langç de§eri atanmazsa
de§i³ken rasgele bir de§er alabilir ve programcnn dikkatsiz davranmas durumunda bu rasgele
de§er yanl³lkla hesaplarda kullanlabilir ve istenmeyen sonuçlara yol açabilir.
Genelde bir blok içindeki de§i³ken tanmlar ile komutlar birbirlerinden ayrlr, yani kullan- Gelenek
5 Tanmlarn sona erdi§i
lacak bütün de§i³kenlerin tanmlar bittikten sonra komutlar ba³lar.
ve komutlarn ba³lad§ yerin kolayca görülmesini sa§lamak amacyla tanmlar ile komutlar
arasnda bir satr bo³luk braklr.
2.4
Veri Tipleri
C dilinde tanmlanan taban veri tipleri ³unlardr (bkz. Bölüm 1.1.1):
int sakl sözcü§üyle belirtilir. Bu veri tipi short ve long belirteçleriyle geli³tirilerek ksa tamsay (short int) ve uzun tamsay (long int) tipleri olu³turulabilir.
tamsay
Aksi belirtilmedikçe tamsay tiplerinin i³aretli olduklar varsaylr, yani hem pozitif
hem de negatif de§erler alabilirler. De§i³ken yalnzca pozitif saylardan (0 da olabi-
unsigned sözcü§ü kullanlabiint, short int, long int, unsigned int,
unsigned long int.
lir) de§er alacaksa i³aretsiz olarak tanmlamak için
lir. Ksacas, 6 adet tamsay tipi vardr:
unsigned short int
kesirli say
float
ve
sakl sözcü§üyle belirtilir. Say daha yüksek duyarllkla gösterilmek iste-
nirse çifte duyarllkl (double) ya da uzun çifte duyarllkl (long
double)
tipleri
kullanlabilir.
simge
char
sakl sözcü§üyle belirtilir. Simgeler kullanlan kodlamadaki sralarna göre
de§erler alrlar (bkz. Ek A). Örne§in 'A' har ASCII kodlamasnda 65. srada
oldu§undan 'A' simgesinin say de§eri 65'tir.
mantksal
bool
sakl sözcü§üyle belirtilir. Bu tipten de§i³kenler
alabilirler.
6
true
ya da
false
de§erini
Bir de§i³kenin tanmlanaca§ veri tipi, o de§i³kenin alabilece§i de§er aral§n belirledi§inden
son derece önemlidir. Bu nedenle bir de§i³kenin veri tipine karar verirken o veri tipinin izin
verdi§i de§er aral§na dikkat etmek gerekir. Sözgelimi
short int
veri tipi yalnzca -32768
ile +32767 arasndaki saylarn gösterilebilmesine olanak veriyorsa ve sizin tanmlayaca§nz
de§i³kenin 45000 de§erini almas sözkonusu olabilecekse de§i³keninizi bu tipten tanmlamamalsnz. Bir veri tipinin boyu
sizeof
i³lemi yardmyla belirlenebilir. Her de§i³ken bellekte
bu boy kadar yer kaplar (sekizli cinsinden).
Ksa tamsay veri tipinin boyunun 2 sekizli yani 16 bit oldu§unu varsayalm. Bu boy hem
i³aretli hem de i³aretsiz ksa tamsaylar için geçerlidir. Bu durumda i³aretsiz ksa tamsay
cinsinden tanmlanan bir de§i³kenin alabilece§i en küçük de§er 0, en büyük de§er ise
216 − 1
yani 65535 olacaktr.
5
6
C++ dilinde komutlar ba³ladktan sonra da de§i³ken tanmlanabilir. C dilinde buna izin verilmez.
C dilinde mantksal verileri temsil edecek özel bir veri tipi yoktur, bu tip C++ dilinde getirilmi³tir; yani
bool, true
ve
false
sözcükleri geçerli C sözcükleri de§ildir.
36
De§i³mezler
2.5
De§i³mezler
Programda kullanlan baz bilgiler de programn farkl çal³malar arasnda de§er de§i³tirmezler. Örnekteki
PI
says ve dairenin çevresinin hesaplanmasnda kullanlan 2 says bu tipten
büyüklüklerdir. De§i³mezlerin bazlarna isim vermek birtakm kolaylklar sa§lar:
•
Anla³lrl§ artrr. Programn içinde 3.14 yazmak yerine
PI
yazmak program okuyan
birinin bu saynn neye kar³ dü³tü§ünü daha kolay anlamasn sa§lar.
•
De§i³tirmek kolay olur. Diyelim programn geli³tirilmesinin ileri a³amalarnda 3.14 de§erinin yetersiz kald§na ve 3.14159 de§erinin daha uygun oldu§una karar verirsek kod
içinde tek bir noktada de§i³tirmek yeterli olur. Öbür türlü, kodun içindeki bütün 3.14
saylarnn yerine 3.14159 yazmamz gerekir. Daha da kötüsü, kodun içindeki ba³ka büyüklükleri gösteren 3.14 de§erlerinin de geçmesi olasl§dr. Bu durumda bütün 3.14
de§erlerini tek tek inceleyerek de§i³tirilip de§i³tirilmeyece§ine karar vermek gerekir.
De§i³mezler iki ³ekilde tanmlanabilirler:
1.
#define
bildirimiyle tanmlama. Bu yöntem bir de§ere bir isim vermekte kullanlr.
PI ismini vermektir. Bu bildirimin sonucu, programcnn
PI geçen her yere kendisinin 3.14 de§erini yazm³ olmasyla ayndr. Bu ³ekilde
Örnekte yaplan 3.14 saysna
kod içinde
tantlan de§i³mezlere gelenek olarak tamam büyük harerden olu³an isimler verilir.
Bu bildirim yönteminde de§i³mezlerin tipleri ayrca belirtilmez. Tamsay de§i³mezler
int
tipine s§myorlarsa
eklenirse
long, u
ya da
U
long int
eklenirse
varsaylrlar. De§erlerinin sonuna
unsigned
l
ya da
L
hareri
belirteci seçilmi³ olur.
#define MAXSHORT 0x7FFF
#define MAXUSHORT 65535U
f ya da F eklenmemi³se double
long double tipinden olurlar.
Kesirli de§i³mezlerin de§erlerinin sonuna
duklar varsaylr.
l
ya da
L
eklenirse
tipinden ol-
#define EULER 2.81782F
#define PERCENT 1E-2
2. De§i³ken tanmna benzer ³ekilde ancak veri tipinin önüne
const
niteleyicisi koyarak
tanmlama. Böylece de§eri de§i³tirilemeyen bir de§i³ken tanmlanm³ olur. Bu ³ekilde
tanmlanan de§i³mezlere büyük harerden olu³an isimler verilmez. Örnekteki
PI
de§i³-
mezinin bu yöntemle tanm ³öyle olurdu:
const float pi = 3.14;
Her iki tanmda da de§i³mez olarak bildirilmi³ bir büyüklü§e de§er atanmaya çal³rsa derleyici
7
hata verir.
7
C dili
const
ile tanmlanm³ de§i³mezlerin de§erlerinin de§i³tirilebilmesine izin verir. Bu tipten bir de§i³-
kene atama yaplmak istendi§inde derleyici hata de§il, yalnzca bir uyar üretecektir.
37
C Diline Giri³
2.6
Aritmetik Deyimler
Aritmetik deyimlerde kullanlabilecek i³lemler ³unlardr:
+
•
Toplama:
•
Çkartma:
•
Çarpma:
•
Bölme:
/
i³leciyle gerçeklenir.
•
Kalan:
%
i³leciyle gerçeklenir. Yalnzca iki tamsay arasnda yaplabilir, kesirli saylarda
*
i³leciyle gerçeklenir.
-
i³leciyle gerçeklenir.
i³leciyle gerçeklenir.
tanml de§ildir.
Bunlarn yansra matematik kitapl§nda yer alan fonksiyonlar da aritmetik deyimlerde yer
alabilirler (bkz. Bölüm 2.9).
Komutlarn okunurlu§unu artrmak amacyla C programclarnn uyduklar geleneklerden biri Gelenek
de, e³it i³aretinin öncesinde ve sonrasnda birer bo³luk brakmaktr. Benzer ³ekilde, deyimlerde
yer alan i³leçlerin (örnekte
+
simgesi) önce ve sonralarnda da birer bo³luk braklr.
C'de deyimlerin hesaplanmasnda izlenen öncelik sras, matematikten al³k olunan sradr.
Yüksek öncelikliden alçak öncelikliye do§ru öncelik gruplar ³öyledir:
1. Ayraç içindeki deyimler
2. Say i³areti belirten
+
ve
-
i³lemleri, artrma, azaltma
3. Çarpma, bölme, kalan
4. Toplama, çkarma
E³it öncelik gruplar kendi içlerinde soldan sa§a do§ru de§erlendirilirler.
Örnek.
a+b+c+d+e
5
aritmetik deyimi C'de
(a + b + c + d + e) / 5
³eklinde yazlmaldr. Ayraçlar kullanlmazsa ortaya çkan
a + b + c + d + e / 5
38
Tip Dönü³ümleri
C deyimi
a+b+c+d+
e
5
aritmetik deyimine kar³ dü³er.
Örnek.
p * r % q + w / x - y
deyimi ³u srayla hesaplanr:
t1:
t2:
t3:
t4:
t5:
2.7
p * r
t1 % q
w / x
t2 + t3
t4 - y
Tip Dönü³ümleri
³leme giren saylarn her ikisi de tamsay ise sonuç da tamsay olur. Saylardan herhangi birinin
kesirli say olmas durumunda sonuç da kesirli say olacaktr. Bu durum bölme i³leminde dikkat
edilmesi gere§ini do§urur. Bölme i³lemine giren her iki say da tamsay ise sonuç da tamsay
olacaktr, yani sonucun varsa kesir ksm atlacaktr. Örne§in
14 / 4
deyiminin sonucu 3.5
de§il 3 olacaktr. ³leme giren her iki say da tamsay ise ve sonucun kesir ksmnn yitirilmemesi
isteniyorsa saylardan en az birinin kesirli say olmasn sa§lamak gerekir. Yukardaki örnek
için çözüm ³u yazl³larla sa§lanabilir:
14.0 / 4
14 / 4.0
14.0 / 4.0
Bir bölme i³lemine giren iki de§i³kenin ikisinin de tamsay tipinden olmas durumunda sonuç
yine tamsay olacaktr. Örne§in
int num1 = 14, num2 = 4;
float quotient;
quotient = num1 / num2;
i³lemleri sonucui
mak için
num1
ve
quotient de§i³keni 3.0 de§erini alr. ³lemin do§ru olarak yaplmasn sa§lanum2 de§i³kenlerinden en az birinin kesirli say tipine çevrilmesi gerekir. Bu
i³leme tip zorlama ad verilir ve bir deyimin ba³na ayraç içinde deyimin sonucunun almas istenen tipin adnn yazlmasyla yaplr. Yukardaki örne§in do§ru çal³mas için ³u komutlardan
herhangi biri kullanlabilir:
39
C Diline Giri³
quotient = (float) num1 / num2;
quotient = num1 / (float) num2;
quotient = (float) num1 / (float) num2;
Birinci komutta yalnzca
num1
de§i³keni, ikinci komutta yalnzca
num2
de§i³keni, üçüncü ko-
mutta ise her ikisi birden kesirli sayya çevrilmektedir. Buna kar³lk
quotient = (float) (num1 / num2);
komutu ise önce bölmeyi sonra tip zorlamasn yapaca§ndan
quotient
de§i³kenine yine 3.0
de§erini atar.
Genel olarak, bir i³leme giren saylar farkl tiptense, bunlarn ortak bir tipe çevrilmeleri gerekir.
Dar tipten geni³ tipe geçi³ i³lemleri derleyici tarafndan otomatik olarak yaplr. Örne§in,
bir toplama i³leminin i³lenenlerinden biri tamsay di§eri kesirli say ise tamsay olan kesirli
sayya çevrilir ve toplama yaplr. A³a§daki örnekte toplama i³leminin ikinci i³leneni kesirli
say oldu§undan toplamadan önce
num1
de§i³keni kesirli sayya çevrilecektir:
int num1 = 14;
float sum;
sum = num1 + 7.32;
Geni³ tipten dar tipe geçi³ler ise bilgi yitirilmesine neden olabilirler. Örne§in kesirli say tipinden bir de§i³kenin tamsay tipinden bir de§i³kene atanmas srasnda saynn kesir ksm
yitirilebilir:
int num1;
float num2 = 65.717;
num1 = num2;
Derleyiciler bu gibi durumlarda genelde hata de§il yalnzca uyar üretirler.
2.8
Artrma / Azaltma
Bir atamann sa§ tarafndaki deyim, atamann sol tarafndaki de§i³keni içeriyorsa, yani
de§i³ken = de§i³ken ◦ deyim;
(◦ herhangi bir i³lem simgesi olabilir) ³eklindeyse bu komut
de§i³ken ◦= deyim;
40
Matematik Kitapl§
³eklinde ksaltlabilir. Örne§in:
a += 5;
a /= 2;
a *= c + d;
// a = a + 5;
// a = a / 2;
// a = a * (c + d);
Buna göre, bir de§i³kenin de§erini artrmak ya da azaltmak için a³a§daki komutlar kullanlabilir:
a = a + 1; a += 1;
a = a - 1; a -= 1;
Ancak artrma ve azaltma i³lemleri programlarda skça gereksinim duyulan i³lemlerden olduk-
++ i³leci, önüne ya da arkasna yazld§
-- i³leciyse önüne ya da arkasna yazld§ i³lecin de§erini 1 azaltr.
larndan C'de bunlar için özel i³leçler tanmlanm³tr.
de§i³kenin de§erini 1 artrr;
Her iki i³leç de yalnzca tamsay veri tipleri ile çal³rlar ve basit kullanmda i³lecin de§i³kenin
önüne mi arkasna m yazld§nn bir önemi yoktur:
8
a++;
a--;
++a;
--a;
2.9
Matematik Kitapl§
ANSI standard, bir C derleme ortamnn matematik kitapl§nda bulunmas zorunlu olan
fonksiyonlar belirler. Bu fonksiyonlarn kullanlabilmesi için programlarn ba³nda
math.h
ba³lk dosyasnn alnmas gerekir.
Matematik kitapl§nn en sk kullanlan fonksiyonlar Tablo 2.1'de verilmi³tir. Bütün bu fonksiyonlardaki
x
ve
y
giri³ parametreleri
double
tipindendir ve çk³ parametresi de
double
tipinden olacaktr.
8
Artrma ve azaltma i³lemleri ba³ka i³lemlerle birlikte kullanlabilir. Sözgelimi bir artrma i³lemiyle bir
atama i³lemi ayn komut içerisinde yaplabilir. Böyle durumlarda artrma/azaltma i³lecinin de§i³ken adnn
önüne ya da arkasna yazlmas önem kazanr. Önüne yazld§nda önce artrma, sonra atama yaplacaktr.
Arkasna yazld§ndaysa önce atama, sonra artrma yaplr. Yani
y = ++x;
komutu
x++;
y = x;
koduna kar³ dü³erken
y = x++;
komutu
41
C Diline Giri³
Ad
³levi
sin(x) cos(x) tan(x)
asin(x) acos(x) atan(x)
sinh(x) cosh(x) tanh(x)
exp(x)
log(x) log10(x)
pow(x,y)
sqrt(x)
floor(x) ceil(x)
fabs(x)
trigonometrik fonksiyonlar
ters trigonometrik fonksiyonlar
hiperbolik trigonometrik fonksiyonlar
ex
e ve 10
xy
√
x
tabannda logaritma fonksiyonlar
alt ve üst snr fonksiyonlar:
bxc dxe
|x|
Tablo 2.1: Matematik kitapl§ fonksiyonlar.
Trigonometrik fonksiyonlarda giri³ parametresi derece de§il radyan cinsinden verilmelidir; örne§in sin(30) deyimi 0.5 de§il -0.988032 de§erini üretir. 30 derecenin sinüsünü
sin(30*3.141529/180) ya da sin(3.141529/6) deyimini yazmak gerekir.
almak için
Alt ve üst snr fonksiyonlarnn çal³masnda giri³ parametresinin pozitif ya da negatif olmasna dikkat edilmelidir. Alt snr fonksiyonu her zaman o saydan daha küçük olan ilk tamsayy,
üst snr fonksiyonu ise o saydan daha büyük olan ilk tamsayy verir.
• floor(3.1) → 3, floor(-3.1) → -4
• ceil(3.1) → 4, ceil(-3.1) → -3
Tamsaylar için de tamsay giri³ parametresi alan ve tamsay çk³ parametresi üreten
abs
isimli bir mutlak de§er fonksiyonu vardr.
2.10
Giri³ / Çk³
C dilinde kullancyla ileti³imi sa§layan i³lemler giri³/çk³ birimleri üzerinden yaplr (bkz.
Bölüm 1.5). Girdiler
9
gönderilir.
cin biriminden alnrken, çktlar cout, hatalar da cerr biriminebirimine
Örnekteki
cin > > radius;
y = x;
x++;
koduna kar³ dü³er.
9
C dilinde
cin, cout ve cerr birimleri yoktur, bunlarn yerine standart girdi/çkt kitapl§ndaki fonksiyon-
larn kullanlmas gerekir (bkz. Ek 8).
42
Giri³ / Çk³
komutu sonucunda
radius
de§i³keni kullancnn tu³takmndan yazd§ saynn de§erini alr.
Birden fazla de§i³ken birlikte okunmak isteniyorsa bunlar birbiri ardna > > i³aretleriyle belirtilebilir. Sözgelimi, iki tane say de§eri okunacak ve kullancnn yazd§ birinci saynn de§eri
num1,
ikinci saynn de§eriyse
num2
de§i³kenine aktarlacaksa:
cout < < Saylar yaznz: ;
cin > > num1 > > num2;
gibi bir program parças kullanlabilir. Bu örnekte kullancnn saylar yazarken aralarnda bir
bo³luk brakmas gerekir.
Çk³ birimlerine katarlar ya da deyimler gönderilebilir. Katarlar olduklar gibi yazlrken deyimlerin de§erleri görüntülenir. Örnekteki
cout < < Alan: < < area < < endl;
komutu ekrana önce
Alan: katarn, daha sonra area de§i³keninin de§erini yazar ve yeni
circum ve area de§i³kenleri tanmlanmadan ve atama komutlar
satra geçer. Programda
kullanlmadan çkt i³lemleri
cout < < Çevresi: < < 2 * PI * radius < < endl;
cout < < Alan: < < PI * radius * radius < < endl;
komutlaryla da yaplabilirdi.
Uygulama: Geli³tirme Ortam
Bu uygulamada basit giri³/çk³ i³lemlerine ve matematik kitapl§nn kullanmna örnek verilmesi istenmektedir. Grak bir editör (kate) tantlacak ve C derleyicisinin nasl kullanlaca§
10
ö§retilecektir. Basit hatalarda derleyicinin hangi mesajlar üretti§i gözlenecektir.
Örnek 2. Formül Hesab
y = e−πx
formülünde
x
de§erini kullancdan alarak
y
de§erini hesaplayan ve ekrana yazdran
bir program yazlmas isteniyor.
•
Örnekte verilen program yazn, derleyin ve çal³trn.
y'nin
x
için 0.002 de§erini verdi§inizde
ald§ de§eri gözleyin.
• PI de§i³mezinin tanmn 3.14 yerine 3.14159 olarak verin ve ayn x de§erinde y'nin ald§
de§eri gözleyin.
•
10
De§i³ken tanmlarnn yapld§
Unix i³letim sistemlerinde derleme a³amalar ile ilgili bilgi için bkz. Ek B.2.
43
C Diline Giri³
Örnek 2 y = e−πx
formülünü hesaplayan program.
#include <iostream>
#include <stdlib.h>
#include <math.h>
// cout,cin.endl
// EXIT_SUCCESS
// exp
using namespace std;
#define PI 3.14
int main(void)
{
float x, y;
cout << "x: ";
cin >> x;
y = exp(-PI * x);
cout << "y: " << y << endl;
return EXIT_SUCCESS;
}
float x, y;
satrndaki 'x' harni 'X' ile de§i³tirin ve derleme sonucunda olu³an hatay gözleyin.
•
Örnekteki
cin > > x;
satrnn ardna
PI = 3.14159;
komutunu ekleyin ve derleme sonucunda olu³an hatay gözleyin.
•
Bir önceki admda yapt§nz de§i³ikli§i silmeden, örnekte
#define
PI de§i³mezinin tanmland§
satrn silin ve
float x, y;
satrnn ardna
const float PI = 3.14;
de§i³mez tanmn ekleyin. Derleme sonucunda olu³an hatay gözleyin.
•
Ba³taki
#include <math.h>
satrn silin ve derleme sonucunda olu³an hatay gözleyin.
44
Giri³ / Çk³
Sorular
1. Çal³t§nz geli³tirme ortamnda
int
tabanl veri tiplerinin de§er aralklarn belirleyin
ve bu aralklar d³nda bir de§er atand§nda nasl bir sonuç elde edildi§ini gözleyin.
2. A³a§daki deyimlerin sonuçlarn bulun:
8 + 17 % 3 * 5
45 / (4 + 7) - 5.0 / 2
3. A³a§daki aritmetik deyimleri gerçekleyen C deyimlerini yazn:
k←
− cd efh−g
x(y + z)
1
2ab
4. A³a§daki C deyimlerinin gerçekledi§i aritmetik deyimleri yazn:
a + 3 * b - (c + d) / 2 * y;
Bölüm 3
Ak³ Denetimi
Bu bölümde blok yapl programlamada gereken seçim ve yineleme yaplarnn C dilinde nasl
gerçeklendikleri üzerinde durulacaktr.
Örnek 3. kinci Derece Denklem Kökleri
2
kinci dereceden (ax
+ bx + c = 0
³eklinde) bir denklemin köklerinin yerlerini belirleyen bir
program yazlmas isteniyor. Diskriminantn
x1,2 =
b2 − 4ac
−b ±
³eklinde tanmland§n ve köklerin
√
b2 − 4ac
2a
formülüne göre hesaplanaca§n gözönünde bulundurarak, program denklemin katsaylarn
kullancdan aldktan sonra a³a§daki i³lemleri gerçekle³tirecektir:
•
Denklemin gerçel kökü yoksa (diskriminant negatifse) bu durum kullancya bildirilir.
•
Denklemin kökleri çak³ksa (diskriminant sfrsa) bu durumu kök de§eriyle birlikte kullancya bildirilir.
•
Denklemin iki farkl gerçel kökü varsa (diskriminant pozitifse) bunlar hesaplanarak ekrana çkartlr.
Programn örnek bir çal³masnn ekran çkts “ekil 3.1'de verilmi³tir
a, b ve c katsaylarn yaznz: -2 1 9.2
-1.90928 ve 2.40928 noktalarnda iki gerçel kökü var.
“ekil 3.1: Örnek 3 ekran çkts.
45
46
Örnek 3 kinci dereceden bir denklemin köklerini bulan program.
#include <iostream>
#include <stdlib.h>
#include <math.h>
// cout,cin,endl
// EXIT_SUCCESS
// sqrt
using namespace std;
int main(void)
{
float a, b, c;
float disc;
float x1, x2;
}
cout << "a, b ve c katsaylarn yaznz: ";
cin >> a >> b >> c;
disc = b * b - 4 * a * c;
if (disc < 0)
cout << "Gerçel kök yok." << endl;
else {
if (disc == 0) {
x1 = -b / (2 * a);
cout << x1 << " noktasnda çak³an iki kök var. " << endl;
} else {
x1 = (-b + sqrt(disc)) / (2 * a);
x2 = (-b - sqrt(disc)) / (2 * a);
cout << x1 << " ve " << x2
<< " noktalarnda iki gerçel kök var." << endl;
}
}
return EXIT_SUCCESS;
47
Ak³ Denetimi
3.1
Ko³ul Deyimleri
Blok yapl programlamadaki seçim ve yineleme yaplarnda bir ko³ula göre bir karar verilmesinin sa§lanmas gerekti§i görülmü³tü (bkz. Bölüm 1.3). Ko³ullar, ko³ul deyimleriyle gösterilirler. C dilinde bir ko³ul deyimi, iki saysal büyüklü§ün (aritmetik deyimin) kar³la³trlmas
ile olu³turulur ve mantksal bir de§er (do§ru ya da yanl³) üretir. Di§er bütün veri tipleri
gibi mantksal de§erler de saylarla temsil edilirler; yanl³ de§eri 0, do§ru de§eriyse 1 saysyla
gösterilir.
3.1.1
Kar³la³trma ³lemleri
ki say de§eri arasnda ³u kar³la³trma i³lemleri yaplabilir:
•
E³itlik:
== i³leciyle gerçeklenir. ³lecin solundaki de§erle sa§ndaki de§er aynysa do§ru,
farklysa yanl³ sonucunu üretir.
•
Farkllk: != i³leciyle gerçeklenir. E³itlik kar³la³trmasnn tersidir. ³lecin solundaki de§erle sa§ndaki de§er farklysa do§ru, aynysa yanl³ sonucunu üretir.
•
Küçüklük:
<
i³leciyle gerçeklenir. ³lecin solundaki de§er sa§ndaki de§erden küçükse
do§ru, küçük de§ilse yanl³ sonucunu üretir.
•
Büyüklük:
>
i³leciyle gerçeklenir. ³lecin solundaki de§er sa§ndaki de§erden büyükse
do§ru, büyük de§ilse yanl³ sonucunu üretir.
•
Küçüklük veya e³itlik:
<= i³leciyle gerçeklenir. Büyüklük kar³la³trmasnn tersidir. ³le-
cin solundaki de§er sa§ndaki de§erden küçük veya e³itse do§ru, büyükse yanl³ sonucunu
üretir.
•
Büyüklük veya e³itlik:
>= i³leciyle gerçeklenir. Küçüklük kar³la³trmasnn tersidir. ³le-
cin solundaki de§er sa§ndaki de§erden büyük veya e³itse do§ru, küçükse yanl³ sonucunu
üretir.
Örnekler
•
Yl 4'e kalansz bölünebiliyor mu?
(year % 4) == 0
•
Ya³ 18'den büyük ya da e³it mi?
age >= 18
Kar³la³trma i³lemleri tam ya da kesirli saylarn kar³la³trlmasnda kullanlabilece§i gibi,
harerin abecedeki sralarna göre kar³la³trlmasnda da kullanlabilir. Sözgelimi
'm' < 'u'
48
Ko³ul Deyimleri
ko³ul deyimi do§ru de§erini üretir. Ancak bu i³lem yalnzca ngilizce harer arasnda do§ru
sonuç üretecektir. Ayrca, büyük-küçük harf kar³la³trmalarnda da abece srasndan farkl
sonuçlar çkabilir. Örne§in ³u ko³ul deyimi do§ru de§erini üretir:
'Z' < 'a'
Bu nedenlerle, simgelerin kar³la³trlmas yalnzca ngilizce harer için ve ikisi de büyük ya da
ikisi de küçük harerin kar³la³trlmasnda kullanlmaldr.
1 Ayrca, kar³la³trma i³leçleriyle
katarlar abece srasna göre kar³la³trlamaz, yani a³a§daki komut geçerli de§ildir (do§ru ya
da yanl³ sonucunu üretmez, derleyicinin hata vermesine neden olur):
dennis < ken
Kesirli saylarn e³itlik açsndan kar³la³trlmasnda da dikkatli olunmas gerekir. Kesirli saylar bilgisayarlarda tam olarak temsil edilemeyebileceklerinden bunlar arasnda e³itlik kar³la³trmas yapmak hatal sonuçlar do§urabilir. Genellikle farklarnn mutlak de§erinin yeterince
küçük bir say olup olmad§na bakmak daha emin bir yöntemdir. Örne§in
f1 == f2
yerine a³a§daki gibi bir ko³ul yazlabilir:
fabs(f1 - f2) < 1E-6
3.1.2
Mantksal ³lemler
Baz durumlarda tek bir kar³la³trma i³lemi bütün ko³ul deyimini olu³turmak için yeterli olmaz. Örne§in bir insann ya³nn 18 ile 65 arasnda olup olmad§n snamak istiyorsanz, bunu
tek bir kar³la³trma i³lemiyle yapamazsnz (18
<= x < 65
gibi bir deyim yazlamaz). Böyle
durumlarda, kar³la³trma i³lemleri mantksal i³lemlerle ba§lanarak karma³k ko³ul deyimleri
üretilebilir. Üç tane mantksal i³lem vardr:
•
DE‡L i³lemi: ! i³leciyle gerçeklenir. Önüne yazld§ ko³ul deyimini de§iller, yani do§ruysa yanl³, yanl³sa do§ru de§erini üretir (bkz. Tablo 3.1).
ko³ul
!(ko³ul)
do§ru
yanl³
yanl³
do§ru
Tablo 3.1: De§il i³lemi do§ruluk tablosu.
Örnek
Ya³ 18'den küçük de§il:
!(age < 18)
49
Ak³ Denetimi
ko³ul1
ko³ul2
(ko³ul1) && (ko³ul2)
do§ru
do§ru
do§ru
do§ru
yanl³
yanl³
yanl³
do§ru
yanl³
yanl³
yanl³
yanl³
Tablo 3.2: VE i³leminin do§ruluk tablosu.
•
VE i³lemi:
&&
i³leciyle gerçeklenir. Ba§lad§ ko³ullarn hepsi do§ruysa do§ru, en az biri
yanl³sa yanl³ de§erini üretir (bkz. Tablo 3.2).
Örnek
Ya³ 18'den büyük veya e³it ve 65'den küçük:
(age >= 18) && (age < 65)
•
VEYA i³lemi:
||
i³leciyle gerçeklenir. Ba§lad§ ko³ullarn hepsi yanl³sa yanl³, en az
biri do§ruysa do§ru de§erini üretir (bkz. Tablo 3.3).
ko³ul1
ko³ul2
(ko³ul1) || (ko³ul2)
do§ru
do§ru
do§ru
do§ru
yanl³
do§ru
yanl³
do§ru
do§ru
yanl³
yanl³
yanl³
Tablo 3.3: VEYA i³leminin do§ruluk tablosu.
Örnek
Ya³ 18'den küçük veya 65'den büyük veya e³it:
(age < 18) || (age >= 65)
Örnek
Bir yln artk yl olup olmad§n belirleyen ko³ul deyimi. Sonu 00 ile biten (100'e
kalansz bölünen) yllar d³ndaki yllar 4 saysna kalansz bölünüyorlarsa artk yl olurlar. Sonu 00 ile bitenler ise 400 saysna kalansz bölünüyorlarsa artk yldrlar. Bunlarn
d³nda kalan yllar artk yl de§ildir. Sözgelimi, 1996, 2000, 2004 ve 2400 yllar artk
yldr ama 1997, 2001, 1900 ve 2100 yllar artk yl de§ildir.
((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)
Ayraçlar kullanlmad§nda mantksal i³leçlerin öncelikleri yüksek öncelikliden ba³layarak DE‡L, VE, VEYA srasyladr. Buna göre yukardaki örnek
(year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)
ya da
1
Aslnda burada kar³la³trlan bu iki simgenen ASCII kodlamasndaki sralardr.
50
Seçim
(year % 400 == 0) || (year % 4 == 0) && (year % 100 != 0)
biçiminde de yazlabilirdi.
3.2
2
Seçim
C dilinde seçim yaplar,
alyorsa
if
if/else
bloklaryla gerçeklenir. Verilen ko³ul deyimi do§ru de§erini
ile ba³layan blok (blok1), yanl³ de§erini alyorsa
else
ile ba³layan blok (blok2)
yürütülür:
if (ko³ul ) {
blok1 ;
} else {
blok2 ;
}
Örnekte içiçe iki seçim yaps vardr. çteki seçim yaps ³u ³ekildedir:
if (disc == 0) {
x1 = -b / (2 * a);
cout < < x1 < < noktasnda çak³an iki kök var. < < endl;
} else {
x1 = (-b + sqrt(disc)) / (2 * a);
x2 = (-b - sqrt(disc)) / (2 * a);
cout < < x1 < < ve < < x2
< < noktalarnda iki gerçel kök var. < < endl;
}
Burada
disc de§i³keninin de§eri 0 ise çak³k köklerle ilgili i³lemler yaplr (iki komuttan olu³an
bir blok); de§ilse farkl iki gerçel kök bulunmas durumundaki i³lemler yaplr (üç komuttan
olu³an bir blok).
Seçim yaplarnda bir
else
blo§u bulunmas zorunlu de§ildir, yani yap
if (ko³ul ) {
blok ;
}
2
Birden fazla ko³uldan olu³an mantksal deyimler de§erlendirilirken sonuç belli oldu§u zaman deyimin geriye
kalan hesaplanmaz. Örne§in
(year % 4 == 0) && (year % 100 != 0)
(year % 4 == 0) ko³ulu yanl³ de§erini verirse deyimin
(year % 100 != 0) ko³ulu snanmaz. Benzer ³ekilde
deyiminde
§ndan
geri kalanna baklmaya gerek kalmayaca-
(year % 4 == 0) || (year % 100 != 0)
deyiminde
(year % 4 == 0)
ko³ulu do§ru de§erini verirse yine ikinci ko³ul snanmaz.
51
Ak³ Denetimi
³eklinde olabilir. Bu durumda ko³ul do§ruysa blok yürütülür, de§ilse hiçbir ³ey yaplmaz.
Bir blok tek bir komuttan olu³uyorsa blo§un süslü ayraçlar ile snrlanmas zorunlu de§ildir.
Örnekteki d³ seçim yapsnda dikkat edilirse ko³ulun do§ru olmas durumunda yürütülecek
blokta süslü ayraçlar kullanlmam³tr:
if (disc < 0)
cout < < Gerçel kök yok. < < endl;
else {
...
...
...
}
Burada istenseydi birinci blok da süslü ayraçlarla belirtilebilirdi:
if (disc < 0) {
cout < < Gerçel kök yok. < < endl;
} else {
...
...
...
}
Gelenek olarak tek komutlu bloklarda süslü ayraçlar kullanlmaz, yani örnek programda kul- Gelenek
lanlan yazl³ ³ekline uyulur. Ancak bu durumda süslü ayraç kullanlmayan blo§un tek komut
içermesine çok dikkat etmek gerekir. Di§er bir gelenek de, ko³ulun do§ru ya da yanl³ olmasna göre yürütülecek bloklardan biri di§erine göre çok ksaysa, ksa olan blok üste gelecek
(ko³ulun do§ru olmas durumunda yürütülecek) ³ekilde düzenlenmesidir. Örnekte bu gelene§e
uyulmam³ olsayd d³ seçim yaps ³u ³ekilde yazlabilirdi:
if (disc >= 0) {
...
...
...
} else
cout < < Gerçel kök yok. < < endl;
Seçim ve ileride görülecek yineleme yaplar bir bütün olarak tek bir komut olarak de§erlendirilirler. Dolaysyla bir blokta yer alan tek yap ba³ka bir seçim ya da yineleme blo§uysa süslü
ayraçlarn kullanlmas zorunlu de§ildir. Yani ³u blok
if (ko³ul1 ) {
if (ko³ul2 )
blok ;
}
52
Seçim
³u ³ekilde de yazlabilir:
if (ko³ul1 )
if (ko³ul2 )
blok ;
Süslü ayraçlar kullanlmad§nda içiçe
if / else
yaplarnda belirsizlikler olu³abilir. Girinti-
lenmeden yazlm³ ³u örne§e bakalm:
if (ko³ul1 )
if (ko³ul2 )
blok1 ;
else
blok2 ;
Burada
blok2
hangi ko³ul sa§lanmazsa yürütülecektir? C dilinin bu konudaki kural
kendinden önce gelen son
ko³ul2
if
ko³uluna ba§land§dr, yani örnekte
blok2 , ko³ul1
else'in
do§ru ve
yanl³sa yürütülür. Do§ru bir girintilemeyle yazlrsa
if (ko³ul1 )
if (ko³ul2 )
blok1 ;
else
blok2 ;
Yine de kar³kl§a neden olmamas için böyle durumlarda süslü ayraçlar kullanmak daha
do§rudur.
DKKAT
Herhangi bir aritmetik deyim ko³ul de§eri olarak de§erlendirilebilir; deyimin sonucu 0 ise yanl³, 0'dan farkl ise do§ru oldu§u varsaylr. Buna göre, sözgelimi 8 - 2 deyimi do§ru, 8 - 2 * 4
deyimiyse yanl³ bir ko³ul olarak de§erlendirilir. Bu davran³ özellikle e³itlik kar³la³trmalarnda hataya yol açabilir. En sk yaplan C hatalarndan biri bir e³itlik kar³la³trmasnda
yerine
=
==
i³areti kullanlmasdr.
age = 12;
...
...
if (age = 18)
blok1 ;
else
blok2 ;
Yukardaki programda ko³ulun snanmas srasnda e³itlik i³lemi de§il atama i³lemi belirtildi§inden
age
de§i³kenine 18 atanr, deyimin de§eri 18 olarak bulunur ve 0'dan farkl oldu§u
için do§ru saylarak
de§i³mez ve
blok2
blok1
yürütülür. Oysa
yürütülürdü.
==
simgesi kullanlsayd
age
de§i³keninin de§eri
53
Ak³ Denetimi
3.2.1
Ko³ullu ³leç
Ko³ullu i³leç, bir ko³ulun gerçekle³ip gerçekle³memesine göre iki deyimden birini seçer.
deyim1 ? deyim2 : deyim3
Burada öncelikle
deyim1
de§erlendirilir. Sonuç do§ruysa
deyim2 ,
yanl³sa
deyim3
seçilir.
Basit bir örnekle, iki saydan küçü§ünü seçmek için ³öyle bir kod kullanlabilir:
if (x < y)
z = x;
else
z = y;
Ayn i³lem ko³ullu i³leç kullanlarak ³öyle de yazlabilirdi:
z = x < y ? x : y;
Adndan da anla³labilece§i gibi, ko³ullu i³leç bir i³leçtir, yani birtakm büyüklükler üzerinde
bir i³lem yapar ve belli bir tipten bir sonuç üretir. Bir seçim yaps de§ildir, yani programn
ak³nn nasl devam edece§i üzerinde bir etki yaratmaz; ak³ bir sonraki komutla devam eder.
Örnek 4. ³lem Seçimi
³lemi ve i³lenenleri kullancnn belirtti§i hesaplamay yaparak sonucu ekrana yazan bir program yazlmas isteniyor. Programn örnek bir çal³masnn ekran çkts “ekil 3.2'de verilmi³tir.
³lemi yaznz: 18 / 5
18/5 i³leminin sonucu: 3
“ekil 3.2: Örnek 4 ekran çkts.
3.3
Çoklu Seçim
Bir deyimin çok sayda de§er içinden hangisini alm³ oldu§unu snamak istiyorsak yazaca§mz
if
kodu uzun ve çirkin bir görünüm alr. Örne§imizde yaplacak i³lemin hangisi oldu§unu
anlamak için yazlacak
if
if (op == '+') {
...
} else {
kodu ³u tip bir ³ey olurdu:
54
Çoklu Seçim
Örnek 4 Kullancnn belirtti§i i³lemi yapan program.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
int main(void)
{
int num1, num2, result;
char op;
}
cout << "³lemi yaznz: ";
cin >> num1 >> op >> num2;
switch (op) {
case '+': result = num1 + num2;
break;
case '-': result = num1 - num2;
break;
case '*': result = num1 * num2;
break;
case '/': result = num1 / num2;
break;
case '%': result = num1 % num2;
break;
default: cout << "Böyle bir i³lem yok." << endl;
return EXIT_FAILURE;
}
cout << num1 << op << num2 << " i³leminin sonucu: " << result << endl;
return EXIT_SUCCESS;
55
Ak³ Denetimi
if (op == '-') {
...
} else {
if (op == '*') {
...
Seçim bloklarnn tek bir komut olarak de§erlendirilmesi çoklu kar³la³trmalarda da daha
kolay bir yazm olana§ sa§lar. Buna göre, yukardaki çoklu kar³la³trma yaps ³u ³ekilde de
yazlabilir:
if (op == '+')
...
else if (op == '-')
...
else if (op == '*')
...
switch
komutu bu tip kar³la³trmalar için daha okunakl bir yap sunar:
switch (deyim ) {
case de§er_1 : blok_1 ;
break;
case de§er_2 : blok_2 ;
break;
...
case de§er_n : blok_n ;
break;
default:
blok ;
break;
}
Bu komutun ak³ çizene§i “ekil 3.3'de görüldü§ü gibidir. Deyim, önce birinci de§erle kar³la³trlr ve e³itse buna ili³kin blok yürütülür ve
break
komutuyla
switch
yapsnn d³na
çklr. Birinci de§ere e³it de§ilse ikinci de§erle kar³la³trlr. Kar³la³trmalarn hiçbiri do§ru
de§ilse
default blo§u yürütülür ve switch sona erer. Her switch yapsnda bir default blo§u
bulunmas zorunlu de§ildir.
Burada dikkat edilmesi gereken bir nokta, deyimin di§er bir deyimle de§il, bir de§erle kar³la³trld§dr. Yani, kar³la³trlacak de§erlerin yazld§ deyimlerde de§i³kenler yer alamaz.
Örne§in a³a§daki yazmda deyim yazl³ geçerlidir ancak de§erin yazl³ geçerli de§ildir:
switch (5 * x) {
...
case y: ...
...
}
56
Çoklu Seçim
case 1
D
blok 1
break
blok 2
break
blok n
break
Y
case 2
D
Y
case n
D
Y
default blok
“ekil 3.3:
switch
komutunun ak³ çizene§i.
57
Ak³ Denetimi
Kar³la³trlan deyim ve de§erler yalnzca tamsay ve simge tipinden olabilir (örnekte simge
tipinden de§erlerle kar³la³trma yaplm³tr). Örne§in a³a§daki yazmlar geçerli de§ildir:
switch (name) {
...
case Dennis: ...
...
}
switch (x) {
...
case 8.2: ...
...
}
Yine dikkat edilmesi gereken bir nokta, kar³la³trmann yalnzca e³itlik üzerinden yapld§dr. Bu yazmda, deyimin de§erden küçük ya da büyük olup olmad§ ya da di§er herhangi
bir mantksal deyimin do§rulu§u belirtilemez. Ayrca, yazmdan görülebilece§i gibi,
switch
yaplarnda bloklar süslü ayraçlar içine alnmaz.
C programlarnda skça yaplan hatalardan biri bloklardaki
Örne§in birinci blo§un sonuna konmas gereken
break
break komutlarnn unutulmasdr.
switch komutu
komutu unutulursa
“ekil 3.4'de görüldü§ü gibi çal³r. Birinci kar³la³trma i³lemi ba³arsz olursa bir sorun çkmaz
ama ba³arl olursa
blok 1
yürütüldükten sonra
blok 2
de yürütülür ve
sonlanr. Yani, ba³arl olan ilk kar³la³trmadan ba³lanarak
gelen bütün bloklar yürütülür.
Örnek programdaki hiçbir
3
break
break
ile
switch
komutu görülene kadar
break komutu konmam³ olsa i³lemin toplama oldu§u durumda önce
toplama, sonra çkartma, çarpma, bölme ve son olarak da kalan i³lemi yaplr (yani yalnzca
kalan i³lemi geçerli olur), ayrca da
Böyle bir i³lem yok.
denilerek herhangi bir sonuç
görüntülenmeden programdan çklr. ³lem çkartma oldu§unda toplama ksm atlanr, gerisi
deminki gibi devam eder.
Uygulama: Seçim Yaplar
Bu uygulamada Windows ortamnda bir tümle³ik geli³tirme ortam (Visual C++ ya da DevC++) tantlacaktr. Hata ayklaycda adm adm ilerleme ve de§i³ken de§erlerinin gözlenmesi
gösterilecektir.
Örnek 5. Birim Dönü³ümü
Bu örnekte ngiliz uzunluk ve scaklk ölçü birimlerinin metrik birimlere dönü³ümünü yapan
bir program yazlacaktr. inch biriminden verilen bir uzunlu§u santimetre birimine çevirmek
için
3
Bu davran³, baz durumlarda yararl yönde de kullanlabilir (bkz. Örnek 10).
58
Çoklu Seçim
case 1
D
blok 1
Y
case 2
D
blok 2
break
blok n
break
Y
case n
D
Y
default blok
“ekil 3.4:
switch
komutunda
break
kullanlmazsa olu³an ak³ çizene§i.
59
Ak³ Denetimi
1 inch = 2.54 cm
e³itli§i ve Fahrenheit biriminde verilen bir sckl§ Celcius birimine çevirmek için de
5
C = (F − 32)
9
formülü kullanlacaktr.
•
Verilen örnek program yazn, çal³trn, birkaç de§er için deneyin
•
case 1 blo§unun sonundaki break komutunu silin ve program çal³trarak her iki dönü³üme de birer örnek deneyin
•
cm->inch ve c->f dönü³ümlerini yapmak üzere kodunuzu geli³tirin
• 1f t = 12inch e³itli§ini kullanarak ft cinsinden verilmi³ bir uzunlu§u mt cinsine çevirecek
eklemeyi yapn
•
mt->ft dönü³ümünü yapacak eklemeyi yapn
Örnek 6. Euclides Algoritmas
ki saynn en büyük ortak bölenini Euclides algoritmasn kullanarak bulan bir program yazlmas isteniyor. Bu algoritmaya ili³kin ak³ çizene§i “ekil 1.17'de, programn örnek bir çal³masnn ekran çkts “ekil 3.5'de verilmi³tir.
Saylar yaznz: 9702 945
9702 ve 945 saylarnn en büyük ortak böleni: 63
“ekil 3.5: Örnek 6 ekran çkts.
3.4
Ko³ul Denetiminde Yineleme
C dilinde temel yineleme yaplar
while (ko³ul ) {
blok ;
}
while
sözcü§üyle kurulur:
60
Ko³ul Denetiminde Yineleme
Örnek 5 ngiliz-metrik birim dönü³ümü yapan program.
#include <iostream>
#include <stdlib.h>
// cout,cin,endl
// EXIT_SUCCESS,EXIT_FAILURE
using namespace std;
int main(void)
{
int choice;
float inch, cm, f, c;
cout << "1. inch-cm" << endl;
cout << "2. f-c" << endl;
cout << "3. Çk³" << endl;
cout << "Seçiminiz: ";
cin >> choice;
}
switch (choice) {
case 1:
cout << "inch cinsinden uzunluk: ";
cin >> inch;
cm = 2.54 * inch;
cout << cm << " cm" << endl;
break;
case 2:
cout << "f cinsinden scaklk: ";
cin >> f;
c = (f - 32) * 5.0 / 9.0;
cout << c << " C" << endl;
break;
case 3:
return EXIT_SUCCESS;
default:
cout << "Böyle bir i³lem yok." << endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
61
Ak³ Denetimi
Örnek 6 ki saynn en büyük ortak bölenini bulan program.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
int main(void)
{
int num1, num2;
int a, b, r = 1;
cout << "Saylar yaznz: ";
cin >> num1 >> num2;
a = num1 > num2 ? num1 : num2;
b = num1 > num2 ? num2 : num1;
}
while (b > 0) {
r = a % b;
a = b;
b = r;
}
cout << num1 << " ve " << num2
<< " saylarnn en büyük ortak böleni: " << a << endl;
return EXIT_SUCCESS;
62
Döngü Denetimi
Örnekteki
while
blo§u
b
de§i³keninin de§eri 0'dan büyük oldu§u sürece yinelenecek, 0 oldu-
§unda sona erecektir. Bu örnekte algoritmann do§as gere§i bu de§i³ken eninde sonunda 0
de§erini alacaktr; ancak yineleme yaplar kurarken döngünün her durumda mutlaka sonlanmasnn sa§lanmasna özellikle dikkat edilmelidir.
Benzer bir di§er yineleme yaps ise
do-while
sözcükleriyle kurulabilir:
do {
blok ;
} while (ko³ul );
Bu yapnn
while
yapsndan en önemli fark, ko³ulun do§ru olup olmamasna baklmakszn
blo§un en az bir kere yürütülmesidir. Örnekteki yineleme bölümü ³u ³ekilde de yazlabilirdi:
do {
r = a % b;
a = b;
b = r;
} while (b > 0);
Ba³langçta
num1 ve num2 de§i³kenlerinden birinin 0 olmas durumunda b de§i³keni 0 de§erini
alrd. lk örnekte ko³ul sa§lanmayaca§ için en büyük ortak bölen 1 olarak bildirilirdi; ikinci
Gelenek
örnekte ise sfra bölme yapmaya kalklaca§ndan bir çal³ma zaman hatas olu³urdu. Her ne
kadar
while ile kurulan yaplar ve do-while ile kurulan yaplar birbirlerinin e³i olacak ³ekilde
while kullanlmas önerilir.
düzenlenebilseler de, yineleme yaps kurmak için genelde
3.5
Döngü Denetimi
Yineleme yaplarnda kullanlan di§er bir yöntemse, döngüyü bir sonsuz döngü olarak kurup
döngüden çkma durumu olu³tu§unda
break
komutunu kullanmaktr:
4
while (true) {
...
if (<çkma ko³ulu sa§lanyor >)
break;
...
// çkma ko³ulu sa§lanmad§ zaman yaplacaklar
}
Çoklu seçim (switch) yapsnda oldu§u gibi burada da
break komutu içinde bulunulan yapdan
çk³ sa§lar. Ancak örnekte görüldü§ü gibi içinden çklan yap if de§il while yapsdr. Yani,
break komutu switch, while, do-while ve birazdan görece§imiz for yaplarndan çkartr,
if yapsndan çkartmaz.
çiçe döngüler kullanld§nda, beklenebilece§i gibi,
break komutu yalnzca en içteki döngüden
çkartr ve bir üstteki döngünün sradaki komutundan devam edilmesini sa§lar:
4
Bu tür bir yap Örnek 10'da görülebilir.
63
Ak³ Denetimi
while (true) {
...
while (true) {
...
if (<çkma ko³ulu sa§lanyor >)
break;
...
}
... // üstteki break komutu sonucunda buraya gelinir
}
Döngülerde ak³ denetimine yönelik di§er bir komut ise
continue komutudur. Bu komut dön-
günün geri kalan ksmnn atlanarak döngü ba³na gidilmesini sa§lar:
i = 0;
while (i < 50) {
i++;
...
if (<ko³ul> ) {
...
continue;
}
...
}
if ile belirtilen ko³ul sa§lanyorsa birtakm i³lemlerin gerçekle³tirilmesinden sonra
ba³na dönülür. Yani if blo§undan sonra gelen komutlar atlanarak i de§i³keninin
Bu örnekte
döngünün
bir sonraki de§erinden i³lemler sürdürülür.
Örnek 7. Yinelemeli Yaz-Tura At³
Kullancnn verdi§i say kadar yaz-tura atarak yaz ve turalarn kaçar kere geldi§ini sayan ve
sonuçlar ekrana çkartan bir program yazlmas isteniyor. Bu programa ili³kin ak³ çizene§i
“ekil 3.6'da, programn örnek bir çal³masnn ekran çkts “ekil 3.7'de verilmi³tir.
3.6
Sayaç Denetiminde Yineleme
Örnekte yaz-tura simülasyonunun kullancnn belirtece§i sayda yinelenmesi isteniyor. Bir
blo§un belli sayda yinelenmesi istendi§inde kullanlabilecek en uygun yap
for
yapsdr. Bir
sayacn denetiminde yineleme yapmak için ³unlarn belirtilmesi gerekir:
•
Sayacn ba³langç de§eri: Örnekte bu de§er 1'dir.
•
Kaça kadar saylaca§: Örnekte bu de§er kullancdan alnan saynn tutuldu§u
de§i³keniyle belirlenir.
count
64
Sayaç Denetiminde Yineleme
basla
oku: count
i←1
heads ← 0
tails ← 0
i ≤ count
Y
D
Tura
at
bas: heads
bas: tails
Yazi
dur
bas: "Tura"
bas: "Yazi"
heads ← heads + 1
tails ← tails + 1
i←i+1
“ekil 3.6: Yinelemeli yaz-tura at³nn simülasyonu.
Kaç kere atlacak? 7
Yaz
Tura
Tura
Yaz
Yaz
Yaz
Yaz
Tura says: 2, Yüzdesi: %28.5714
Yaz says: 5, Yüzdesi: %71.4286
“ekil 3.7: Örnek 7 ekran çkts.
65
Ak³ Denetimi
Örnek 7 Yinelemeli yaz-tura at³ simülasyonu yapan program.
#include <iostream>
#include <stdlib.h>
#include <time.h>
// cin,cout,endl
// EXIT_SUCCESS,srand,rand,RAND_MAX
// time
using namespace std;
int main(void)
{
int count, i;
float number;
int heads = 0, tails = 0;
}
cout << "Kaç kere atlacak? ";
cin >> count;
srand(time(NULL));
for (i = 1; i <= count; i++) {
number = (float) rand() / RAND_MAX;
if (number < 0.5) {
cout << "Tura" << endl;
heads++;
} else {
cout << "Yaz" << endl;
tails++;
}
}
cout << " Tura says: " << heads
<< ", Yüzdesi: %" << 100.0 * heads / count << endl;
cout << " Yaz says: " << tails
<< ", Yüzdesi: %" << 100.0 * tails / count << endl;
return EXIT_SUCCESS;
66
Sayaç Denetiminde Yineleme
•
for
Kaçar kaçar saylaca§: Örnekte sayacn birer birer artrlaca§ belirtilmi³tir.
yaps bu üç belirtimin ayn anda yaplmasna olanak sa§lar. Ay içinde önce ba³langç
de§eri atamas, ikinci olarak hangi ko³ul sa§land§ sürece devam edilece§i ve son olarak da
sayacn nasl artrlaca§ belirtilir.
for (i = 1; i <= count; i++)
komutu ³öyle okunabilir:
i de§i³kenine 1 de§erini ver ve bu de§i³kenin de§eri count de§i³keninin de§erinden
i de§i³keninin de§erini
küçük veya e³it oldu§u sürece blo§u her yürütü³ünden sonra
1 artr.
for
döngüleri
while
döngüleri ³eklinde de yazlabilirler:
for (ba³langç_atamas ; sürme_ko³ulu ; artrma_komutu ) {
blok ;
}
döngüsü
ba³langç_atamas ;
while (sürme_ko³ulu ) {
blok ;
artrma_komutu ;
}
döngüsüne e³de§erlidir. Yine de sayaç denetiminde yinelemeler için
yinelemeler için
while
for,
ko³ul denetiminde
kullanmak anla³lrlk açsndan daha do§rudur.
Bu yapyla ilgili olarak baz noktalara dikkat etmek gerekir:
•
Döngü, belirtilen ko³ul sa§lanmad§ zaman sonlanr ve programn yürütülmesi döngünün arkasndan gelen komutla sürdürülür. Örnekte
i de§i³keninin de§eri count de§i³ke-
ninin de§erinden büyük oldu§u zaman döngü sona erer.
•
Artrma i³lemi döngü gövdesi yürütüldükten sonra yaplr. Örnekte döngünün gövdesi
de§i³keninin 1, 2, ...,
•
count
i
de§erleri için yinelenir, 1 de§eri atlanmaz.
Verilen ba³langç de§eri döngü ko³ulunu sa§lamyorsa döngünün gövdesi hiç yürütülmez.
Örne§in
for (i = 1; i == 10; i++)
67
Ak³ Denetimi
döngüsünde ba³langç de§eri sürme ko³ulunu sa§lamad§ndan (1 == 10 do§ru olmad§ndan) döngüye hiç girilmez.
•
Artm miktar için artrma i³leci kullanlmas zorunlu de§ildir, herhangi bir C deyimi
kullanlabilir.
for (i = 1; i < count; i = i + 3)
döngüsü 1, 4, 7, 10, 13, ... ³eklinde sayarken
for (i = 1; i < count; i = i * 2)
döngüsü 1, 2, 4, 8, 16, ... ³eklinde sayar.
Rasgele Saylar
Yaz-tura at³n temsil etmek için en kolay yol 0 ile 1 arasnda bir rasgele say üretmek ve bu
saynn 0.5'den küçük olmas durumunu bir sonuca (diyelim tura), e³it ya da büyük olmasn
da di§er sonuca (bu durumda yaz) atamaktr.
rand fonksiyonu 0 ile RAND_MAX arasnda bir rasgele tamsay üretir.
RAND_MAX standart kitaplkta tanmlanm³ bir de§erdir ve sistemden sisteme farkllk gösterebilir. rand fonksiyonundan gelen say RAND_MAX de§erine bölünürse 0 ile 1 arasnda bir rasgele
C standart kitapl§ndaki
kesirli say elde edilir. Rasgele saylarn kullanmnda daha çok 1 ile bir üst snr arasnda de§er
alacak bir rasgele tamsayya gereksinim duyulur. Bu üst snr
max
ile gösterilirse
1 + rand() % max
deyimi istenen türden bir say üretir (Neden?).
Rasgele saylar, bir seri olarak üretilirler; yani her rasgele say seride bir önceki rasgele saydan üretilir. Bu serinin ba³layabilmesi için ilk sayy üretmekte kullanlacak bir ba³langç
de§eri (tohum ) verilmesi gerekir.
srand
fonksiyonu bu tohumun belirtilmesini sa§lar. Ayn
tohumla ba³lanrsa ayn seri üretilir. Her serinin programn çal³masndaki bir senaryoya kar³lk dü³tü§ü dü³ünülürse istendi§i zaman ayn senaryoyu üretebilmek programn hatalarnn
ayklanmas açsndan yararldr.
Her defasnda farkl bir tohumla ba³lamak için tohumun da her defasnda farkl verilmesi
gerekir. Standart kitaplktaki
time
fonksiyonu, 1 Ocak 1970 tarihinden o ana kadar geçen
saniyelerin saysn verdi§inden her ça§rl³nda farkl bir tohum üretebilir. Bu fonksiyona
NULL
giri³ parametresini göndermek yeterlidir.
Uygulama: Döngüler
Bu uygulamada Unix bir hata ayklayc (ddd) tantlacaktr. Hata ayklaycda adm adm
ilerleme ve de§i³ken de§erlerinin gözlenmesi gösterilecektir.
68
Sayaç Denetiminde Yineleme
Örnek 8. Seri Toplam
Bu uygulamada görülecek programlarda,
ex
fonksiyonunun hesaplanmas için a³a§daki seri
toplamndan yararlanlacaktr:
f (x) =
∞
X
xi
i=0
i!
=1+x+
x2 x3 x4
+
+
+ ···
2!
3!
4!
Birinci programda (Örnek 8) içiçe iki döngü vardr. çerideki döngü o anda i³lenmekte olan
terimde gerekecek faktöryel de§erinin hesaplanmasn sa§lar. D³ döngüyse her yineleni³inde
serinin o anki terimi hesaplayarak toplama ekler. Hesaplanan terim kullancnn belirtti§i
hatadan küçük oldu§unda de§erin istenen duyarllkta hesapland§na karar verilerek sonuç
ekrana çkartlr.
Örnek 8 ex
deyimini genel terimden giderek hesaplayan program.
#include <iostream>
#include <stdlib.h>
#include <math.h>
// cin,cout,endl
// EXIT_SUCCESS
// pow
using namespace std;
int main(void)
{
float x, error, term, result = 1.0;
int i = 1, f;
float fact;
cout << "x: ";
cin >> x;
cout << "Hata: ";
cin >> error;
term = error + 1;
while (term > error) {
fact = 1.0;
for (f = 2; f <= i; f++)
fact = fact * f;
term = pow(x, i) / fact;
result = result + term;
i++;
}
cout << "Sonuç: " << result << endl;
}
return EXIT_SUCCESS;
69
Ak³ Denetimi
kinci programdaysa (Örnek 9) ayn i³lemin nasl daha etkin (daha az hesap yüküyle) yaplabilece§i görülecektir. Serinin genel teriminin
ai =
elemann kendisinden önceki elemana bölümü
kendisinden önceki terimin
x
ile çarplp
i'ye
ai
ai−1
xi
i! oldu§u gözönüne alnd§nda dizide bir
= xi olarak hesaplanabilir. Yani her terim,
bölünmesiyle bulunabilir. Böylece her admda
üs alma ve faktöryel hesaplama i³lemlerine gerek kalmaz ve seri toplam çok daha hzl elde
edilir.
Örnek 9 ex
deyimini bir önceki terimden giderek hesaplayan program.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
int main(void)
{
float x, error, term, result = 1.0;
int i = 1;
cout << "x: ";
cin >> x;
cout << "Hata: ";
cin >> error;
term = 1;
while (term > error) {
term = term * x / i;
result = result + term;
i++;
}
cout << "Hata: " << result << endl;
return EXIT_SUCCESS;
}
•
Her iki program da yazarak çal³trn.
•
Ta³ma durumunun gözlenmesi
Sorular
1.
(x % 3 == 2) && (x > 4) || !(x % 3 == 2) && (x < 6)
(a) do§ru yapacak bir
x
de§eri verin.
(b) yanl³ yapacak bir x de§eri verin.
mantksal deyimini
70
Sayaç Denetiminde Yineleme
(c)
x
i³aretsiz bir tamsay ise,
x'in
hangi de§erleri için bu deyim do§ru de§erini alr?
2. A³a§da verilen program parças için
x
de§i³keninin ba³langç de§erinin 115 oldu§u var-
saymyla de§i³kenlerin alacaklar de§erleri izlemek üzere bir çizelge olu³turun. Ak³ çizene§ini çizin.
i = -1;
while (x >= 1) {
i++;
y[i] = x % 8;
x = x / 8;
}
for (j = i; j >= 0; j--)
cout < < y[j];
3.
x ve m saylar aralarnda asalsa x saysnn m saysna göre evri§i r says, xr = 1 mod m
e³itli§ini sa§layan saydr (r < m). Örne§in, x = 5 ve m = 7 ise r = 3 olur. Buna göre,
kullancdan ald§ x ve m saylarna göre r de§erini hesaplayan ve ekrana çkartan bir
program yazn. x = 8, m = 11 de§erleri için programnzdaki de§i³kenlerin alacaklar
de§erleri bir çizelge halinde gösterin.
4. Kusursuz bir say, kendisinden küçük bütün çarpanlarnn toplamna e³it olan saydr.
Örne§in,
28 = 1 + 2 + 4 + 7 + 14.
Buna göre, ilk 10000 say içindeki kusursuz saylar
ekrana döken bir program yazn.
5. nsan bedeninin alann hesaplamakta kullanlabilecek iki formül a³a§da verilmi³tir.
DuBois formülü:
Boyde formülü:
bsa = h0.725 ∗ w0.425 ∗ 71.84 ∗ 10−4
bsa = h0.3 ∗ w(0.7285−0.0188 log w) ∗ 3.207 ∗ 10−4
h de§i³keni cm cinsinden boyu ve bsa de§i³keni de m2 cinsinden beden
gösterirken, w de§i³keni kütleyi DuBois formülünde kg, Boyde formülündeyse
Her iki formülde de
alann
g cinsinden gösterir. DuBois formülü yeti³kinlerde iyi sonuç verirken, çocuklarda (bu
formülle elde edilen alan de§eri 0.6'dan küçükse) çok hatal olabilmektedir. Buna göre,
boy ve kütlesini kullancdan ald§ bir insann (yeti³kin ya da çocuk) beden alann
yukarda anlatlan ölçütlere göre hesaplayarak ekrana çkaran bir program yazn.
6. A³a§da verilen Pascal üçgeni için
i.
satr
j.
sütundaki de§er (binom katsays) yanda
verilen formülle hesaplanr:
0
1
2
3
0
1
1
1
1
2
1
2
1
3
1
3
3
1
4
1
4
6
4
4
(
binomi,j =
1
binomi−1,j−1 + binomi−1,j
j =0∨j =i
aksi durumda
1
Buna göre, üçgenin ilk 30 satrn hesaplayp ekrana çkartacak bir program yazn.
7. A³a§daki seri toplam hesaplanmak isteniyor:
71
Ak³ Denetimi
n
X
i=0
(a) Bu serinin
i.
(−1)i
xi
x0 x1 x2 x3 x4
x5
=
−
+
−
+
−
+ ...
(2i)!
0!
2!
4!
6!
8!
10!
eleman
ai
ise,
ai+1 /ai
oran nedir?
(b) Bu bilgiyi kullanarak, serinin toplamn hesaplayan bir program yazn (x ve
n
de-
§erleri kullancdan alnacaktr).
8. Rasgele say üretirken kalan i³lecini (%) kullanarak sayy belli bir aral§a indirgemek saylarn üretilme olaslklarn bozar m? Sözgelimi,
RAND_MAX'n de§erinin 32767 oldu§unu
varsayarak 1 ile 6 arasnda üretece§iniz rasgele sayda bu alt saynn gelme olaslklar
e³it midir? De§ilse, daha iyi bir yöntem önerebilir misiniz?
Sayaç Denetiminde Yineleme
72
Bölüm 4
Türetilmi³ Veri Tipleri
Bu bölümde programcnn var olan veri tiplerinden kendi veri tiplerini (sözgelimi kaytlar, bkz.
Bölüm 1.1.2) nasl türetebilece§i üzerinde durulacaktr.
C dilinin programcya kendi veri tiplerini tanmlayabilmesi için sundu§u temel olanak, var
olan veri tiplerine yeni isimler verilebilmesidir. Bunun için
typedef veri_tipi yeni_isim ;
komutu kullanlr. Bunun sonucunda
veri_tipi
isimli tipe
yeni_isim
adnda bir isim daha
verilmi³ olur.
Örne§in bir ö§rencinin snav notlar i³lenmek isteniyor olsun. Notlarn 0 ile 100 arasnda birer
tamsay olaca§ varsaymyla, ö§renci notu tipinden bilgileri temsil etmek üzere bir veri tipi
tanmlanabilir:
typedef int score_t;
Böylece
int veri tipine score_t diye yeni bir isim verilmi³ olur. Daha sonra bu tipten de§i³ken
tanmlamak için
score_t midterm1, midterm2, final;
gibi bir komut yazlabilir. stenirse asl veri tipi isminin kullanlmasnda da bir saknca yoktur,
yani
int midterm1, midterm2, final;
tanm da geçerlili§ini korur ve bu iki tanm birbirine e³de§erlidir.
Bir veri tipine yeni bir isim vermenin yararlar ³öyle açklanabilir:
•
Anla³lrlk artar: Programn kodunu okuyan ki³i bu veri tipinin temsil etti§i bilgiyle
ilgili daha iyi bir kir edinebilir.
73
74
•
De§i³tirmek kolay olur: Programn geli³tirilmesinin ileri a³amalarnda ya da sonraki sürümlerde ö§renci notlarnn kesirli olabilece§i durumu ortaya çkarsa yalnzca veri tipine
isim verme komutunun
typedef float score_t;
biçiminde de§i³tirilmesi yeterli olur. Veri tipi tanm olmasa bütün kodun taranarak ö§renci notuna kar³lk gelen
int
veri tiplerini bulup de§i³tirmek gerekir. Bu da baz
int
sözcüklerinin de§i³mesi, bazlarnn de§i³memesi anlamna gelir ve programn boyutlarna göre büyük zorluklar çkarabilir.
Örnek 10. Barbut
1
Barbut oyununun kurallar ³öyledir:
•
Oyuncu bir çift zar atar.
•
Att§ zarlarn toplam 7 ya da 11 ise oyuncu kazanr.
Att§ zarlarn toplam 2, 3 ya da 12 ise oyuncu kaybeder.
Di§er durumlarda att§ zarlarn toplam oyuncunun says olur.
Oyuncu ayn toplam veren zarlar bir daha atana kadar ya da att§ zarlarn toplam 7
olana kadar zar atmaya devam eder.
Ayn toplam bir daha atarsa oyuncu kazanr.
Att§ zarlarn toplam 7 olursa oyuncu kaybeder.
switch yapsbreak kullanlmamasdr. Böylelikle durumlar gruplanarak
Verilen örnek, bu oyunu simüle eden bir programdr. Bu örne§in ilginç bir yönü
nn baz durumlarnda kastl olarak
her bir grup için yaplacak i³lemlerin bir kere belirtilmesi sa§lanm³tr. Programn örnek bir
çal³masnn ekran çkts “ekil 4.1'de verilmi³tir.
Zarlar: 1 + 4 =
Say: 5
Zarlar: 5 + 1 =
Zarlar: 5 + 5 =
Zarlar: 6 + 5 =
Zarlar: 4 + 1 =
Oyuncu kazanr.
5
6
10
11
5
“ekil 4.1: Örnek 10 ekran çkts.
1
Bu örnek, H.M. Deitel ve P.J. Deitel'in yazdklar C: How to Program kitabndan uyarlanm³tr.
75
Türetilmi³ Veri Tipleri
Örnek 10 Barbut oyununu simüle eden program.
#include <iostream>
#include <stdlib.h>
#include <time.h>
// cin,cout,endl
// EXIT_SUCCESS,srand,rand
// time
using namespace std;
enum status_e { GAME_CONTINUES, PLAYER_WINS, PLAYER_LOSES };
typedef enum status_e status_t;
int main(void)
{
int die1, die2, sum, point;
status_t game_status = GAME_CONTINUES;
srand(time(NULL));
die1 = 1 + rand() % 6;
die2 = 1 + rand() % 6;
sum = die1 + die2;
cout << "Zarlar: " << die1 << " + " << die2 << " = " << sum << endl;
switch (sum) {
case 7:
case 11: game_status = PLAYER_WINS; break;
case 2:
case 3:
case 12: game_status = PLAYER_LOSES; break;
default: game_status = GAME_CONTINUES;
point = sum;
cout << "Say: " << point << endl;
break;
}
while (game_status == GAME_CONTINUES) {
die1 = 1 + rand() % 6;
die2 = 1 + rand() % 6;
sum = die1 + die2;
cout << "Zarlar: " << die1 << " + " << die2 << " = " << sum << endl;
if (sum == point)
game_status = PLAYER_WINS;
else {
if (sum == 7)
game_status = PLAYER_LOSES;
}
}
if (game_status == PLAYER_WINS)
cout << "Oyuncu kazanr." << endl;
else
cout << "Oyuncu kaybeder." << endl;
76
Numaralandrma
4.1
Numaralandrma
Örnekte oyunun içinde bulunabilece§i çe³itli durumlara birer say de§eri atanarak oyunun o an
hangi durumda oldu§u izlenebilir. Örne§in kodumuzda oyunun durumunu gösteren
game_status
de§i³keninin de§erinin 0 olmas oyunun sürüyor olmasna, 1 olmas oyuncunun kazanmasna
ve 2 olmas da oyuncunun kaybetmesine kar³lk dü³ürülebilir. Burada 0, 1 ve 2 de§erlerinin
özel bir anlamlar yoktur, herhangi üç farkl de§er de ayn i³levi görür.
Okunulurlu§u artrmak amacyla bu saylara birer isim vermek yararl olur. Öyleyse
#define GAME_CONTINUES 0
#define PLAYER_WINS 1
#define PLAYER_LOSES 2
³eklinde de§i³mez tanmlar yaplarak kodun içinde saylar yerine isimler yazlabilir.
Bu tip, birbiriyle ilintili birden fazla de§i³mezi birlikte tanmlamak için numaralandrma yöntemi kullanlabilir.
enum { GAME_CONTINUES, PLAYER_WINS, PLAYER_LOSES };
komutu yukarda yazlm³ olan üç
#define komutuyla ayn etkiyi yaratr. Aksi belirtilmedikçe,
süslü ayraçlar içinde yazlan de§i³mezlerden ilkine 0, sonrakine 1, sonrakine 2 vs. ³eklinde
de§er verilir. Programc isterse ba³ka de§erler belirtebilir ancak bizim örne§imizde -demin de
söylendi§i gibi- de§erlerin, farkl olduklar sürece, ne olduklarnn bir önemi yoktur:
enum { GAME_CONTINUES = 58, PLAYER_WINS = 17, PLAYER_LOSES = 154 };
Herhangi bir de§i³meze de§er verilirse onu izleyen de§i³mezlerin de§erleri birer artarak devam
eder:
enum { JANUARY = 1, FEBRUARY, MARCH, APRIL, MAY, JUNE,
JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER };
Numaralandrma ile olu³turulmu³ bir de§i³mezler kümesine de topluca bir isim verilerek yeni
bir veri tipi olu³turulabilir:
enum künye { de§i³mez_tanmlar };
Bu komutun sonucunda
enum künye
isimli yeni bir veri tipi olu³ur ve bu tipten de§i³kenler
tanmlanabilir. Örnekte önce bu ³ekilde
da bu tipe
typedef
enum status_e isimli bir tip olu³turulmu³, daha sonra
komutuyla yeni bir isim verilmi³tir. Bu tipten de§i³ken tanmlarken her
iki yeni isim de kullanlabilir, yani örnekteki
status_t game_status = GAME_CONTINUES;
77
Türetilmi³ Veri Tipleri
komutu
enum status_e game_status = GAME_CONTINUES;
komutuyla e³de§erlidir.
2
Düzenli bir çal³ma için numaralandrma tipinden tanmlanan de§i³kenlerin yalnzca o numaralandrmayla belirlenen de§i³mezler kümesinden de§er almas gerekir. Sözgelimi örne§imizde
tanmlanan
game_status
de§i³keni
GAME_CONTINUES, PLAYER_WINS
ve
PLAYER_LOSES
d³nda
herhangi bir de§er alamamaldr. Ancak C dili böyle bir kstlama getirmez, yani
game_status = 25;
gibi anlamsz olacak bir atama C dilinin kurallarna göre yasak de§ildir.
Örnek 11. Paralel Direnç E³de§eri
Dirençlerin paralel e³de§eri a³a§daki formülle hesaplanabilir:
1
R1
+
1
R2
1
+ ··· +
1
Rn
Buna göre, kullancdan ald§ dirençlerin paralel e³de§erini hesaplayarak sonucu ekrana çkartan bir program yazlmas isteniyor. Kullancnn kaç tane direnç de§eri girece§i ba³tan belli
olmad§ için bu döngü
for
yapsyla de§il
while
yapsyla kurulmaya daha uygundur. Son-
suz döngüden çkabilmek için kullancnn bir ³ekilde bunu belirtmesine olanak verilmelidir.
Bu programda uygulanan yöntem, özel bir de§eri (örne§in 0) bitirme i³areti olarak seçmektir.
Kullanc bu de§eri girerek ba³ka direnç de§eri yazmayaca§n belirtebilir. Sonlandrma de§erinin uygun seçilmesi gerekir; geçerli direnç de§erleri sonlandrma de§eri olmaya uygun de§ildir.
Programn örnek bir çal³masnn ekran çkts “ekil 4.2'de verilmi³tir.
Bu programn çal³masnda dikkat çekici bir nokta, kullancnn yazd§ direnç de§erlerinin uygun ³ekilde toplama eklenmelerinin ardndan unutulmalardr. Yani ileride kullancnn girmi³
oldu§u de§erlerle bir i³lem yaplmak istense bunlar bir ³ekilde ula³labilir olmayacaklardr. Bu
programn amac açsndan bu durum bir saknca do§urmaz ancak ba³ka problemlerde farkl
yaplar kullanmak gerekebilir.
2
C dilinde mantksal bir veri tipi ve
true, false
de§erleri bulunmad§ daha önce söylenmi³ti. Ancak,
do§ru ve yanl³ büyüklükleri programlarda skça gereksinim duyulan de§erler olduklarndan C programlarnda
genellikle bunlar genellikle programn ba³nda de§i³mez olarak tanmlanrlar.
#define TRUE 1
#define FALSE 0
Daha sk kullanlan bir yöntemse bunlar bir numaralandrma içinde tanmlayarak olu³acak veri tipine yeni bir
isim vermektir.
enum bool_e { FALSE, TRUE };
typedef enum bool_e bool_t;
Böylelikle C++ dilinde oldu§u gibi mantksal bir veri tipi tanmlanm³ olur ve bu tipten de§i³kenler kullanlabilir.
78
Numaralandrma
Örnek 11 Paralel direnç e³de§eri hesaplayan program.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
struct rational_s {
int nom;
int denom;
};
typedef struct rational_s rational_t;
int main(void)
{
int res_value;
rational_t equiv = { 0, 1 };
int a, b, r;
int i = 0;
while (true) {
i++;
cout << "R" << i << " (bittiyse 0): ";
cin >> res_value;
if (res_value == 0)
break;
equiv.nom = equiv.nom * res_value + equiv.denom;
equiv.denom = equiv.denom * res_value;
// kesiri basitle³tir
a = equiv.nom;
b = equiv.denom;
while (b > 0) {
r = a % b;
a = b;
b = r;
}
equiv.nom = equiv.nom / a;
equiv.denom = equiv.denom / a;
}
}
if (equiv.nom != 0)
cout << "E³de§er direnç: " << equiv.denom
<< " / " << equiv.nom
<< " = " << (float) equiv.denom / equiv.nom << endl;
else
cout << "Hatal i³lem." << endl;
return EXIT_SUCCESS;
79
Türetilmi³ Veri Tipleri
R1 (bittiyse 0): 5
R2 (bittiyse 0): 8
R3 (bittiyse 0): 11
R4 (bittiyse 0): 4
R5 (bittiyse 0): 0
E³de§er direnç: 440/293 = 1.50171
“ekil 4.2: Örnek 11 ekran çkts.
4.2
Yaplar
Kayt tiplerinin özelliklerinden Bölüm 1.1.2'de söz edilmi³ti. C dilinde kaytlara yap ad verilir
ve ³öyle tanmlanrlar:
struct künye {
alan_tanmlar ;
};
Yap tanmnn sonucunda
struct künye
isimli yeni bir veri tipi olu³ur ve bu tipten de§i³ken-
ler tanmlanabilir. Alan tanmlar de§i³ken tanmlarna benzer ³ekilde yaplr ancak de§i³ken
tanm de§ildirler. De§i³ken tanmlarnn bellekte ilgili de§i³ken için yer ayrlmasna neden oldu§u görülmü³tü, oysa tip tanm bellekte yer ayrlmasna neden olmaz. Yer ayrlmas ancak
bu yap tipinden bir de§i³ken tanmland§nda gerçekle³ir.
Örnekte rasyonel saylar göstermek üzere iki alan olan bir yap kullanlm³tr: saynn pay
ksmn gösteren
nom
ve payda ksmn gösteren
denom.
Rasyonel saylarn tanm gere§i her
iki alan da tamsay tipindendir. Tip tanm sonucunda artk
struct rational_s
adnda bir veri tipi olu³mu³tur. Kullanm kolayl§ açsndan bu veri tipine
3
yeni bir isim verilmi³tir.
Yap tipinden de§i³ken tanmlanrken istenirse künyeli isim, istenirse
typedef komutuyla
typedef
ile verilen yeni
isim kullanlabilir ve de§i³kenin alanlarna süslü ayraçlar içinde ba³langç de§erleri verilebilir.
A³a§daki iki komut ayn i³i yaparlar, yani
yapsnda olan iki de§i³ken tanmlarlar ve
res ve equiv isimlerinde, her biri birer rasyonel say
equiv de§i³keninin nom alanna 0, denom alanna 1
ba³langç de§erini verirler (“ekil 4.3):
3
Tipin tanmlanmas ve yeni isim verilmesi i³lemleri istenirse tek komutta birle³tirilebilir:
typedef struct rational_s {
int nom, denom;
} rational_t;
Birle³tirilmi³ tanmlamada istenirse tipin künyesi de belirtilmeyebilir, yani yukardaki örnekte
rational_s
sözcü§ü yazlmasa da olurdu. Yine de ço§unlukla önerilen yöntem, belirtilmeleri zorunlu olmasa da künyeleri
yazmaktr. Bu yazl³ numaralandrmalar için de geçerlidir.
80
Yaplar
rational_t res, equiv = { 0, 1 };
struct rational_s res, equiv = { 0, 1 };
res
equiv
nom
nom
0
denom
denom
1
“ekil 4.3: Yap tipinden de§i³ken tanmlama.
Bu de§i³kenlerin her biri, yapda belirtilen alanlar barndrr. Alanlar üzerinde i³lem yapmak
için, daha önce görüldü§ü gibi, noktal gösterilim kullanlr, yani de§i³kenin adndan sonra
nokta i³aretiyle alann ad belirtilir. Bu durumda, e³de§er direnç de§erini tutan de§i³kenin
payda ksmyla bir i³lem yaplacaksa
equiv.denom
yazlr.
Yaplarn alanlar skalar tiplerden tanmlanabilece§i gibi, ba³ka yap tiplerinden ya da tipli
numaralandrma tipinden de tanmlanabilir:
enum month_e { JANUARY = 1, FEBRUARY, ..., DECEMBER };
typedef enum month_e month_t;
struct date_s {
int day;
month_t month;
int year;
};
typedef struct date_s date_t;
struct academic_year_s {
date_t begin, end;
};
typedef struct academic_year_s academic_year_t;
tanmlar “ekil 4.4'de görülen yapy olu³turur. Alanlara eri³im yine noktal gösterilimle sa§lanr:
academic_year_t year_2001_2002;
year_2001_2002.end.day = 31;
year_2001_2002.end.month = MAY;
year_2001_2002.end.year = 2002;
Ayn yap tipinden de§i³kenler arasnda atama i³lemi yaplabilir. Atama sonucunda kaynak
de§i³kenin bütün alan de§erleri var³ de§i³kenin ayn isimli alanlarna atanr. Bu gösterilim
bütün alt alanlarn tek tek atanmas zorunlulu§unu giderir, yani
81
Türetilmi³ Veri Tipleri
year_2001_2002
academic_year_t
begin
end
day
day
month
month
year
year
“ekil 4.4: Yap içinde yap kullanma.
equiv.nom = res.nom;
equiv.denom = res.denom;
³eklinde atama yapmak yerine yalnzca
equiv = res;
yazlabilir.
Uygulama: Yaplar
Örnek 12. Noktann Daireye Göre Konumu
Koordinatlarn kullancdan ald§ bir noktann, merkez noktasnn koordinatlar ile yarçapn
yine kullancdan ald§ bir dairenin içinde mi, d³nda m, üzerinde mi oldu§unu belirleyerek
sonucu ekrana çkaracak bir program yazlmas isteniyor. Noktann koordinatlar
merkezinin koordinatlar
p
xc
(x − xc )2 + (y − yc )2 < r
ve
yc ,
dairenin yarçap
r
ise nokta dairenin d³nda
p
ise nokta dairenin üzerindedir.
(x − xc )2 + (y − yc )2 = r
daire
ise nokta dairenin içinde
p
(x − xc )2 + (y − yc )2 > r
x ve y ,
ile gösterilirse:
•
Program yazarak çal³trn.
•
Merkez noktasnn koordinatlarn (2.1,5.664), yarçapn 3.2, aranan noktann koordinatlarn (5.3,5.664) olarak verin. Bu nokta dairenin neresindedir? Program ne çkt veriyor?
Hatalysa neden hataldr ve nasl düzeltilebilir?
82
Yaplar
Örnek 12 Noktann daireye göre konumunu bulan program.
#include <iostream>
#include <stdlib.h>
// cout,cin,endl
// EXIT_SUCCESS
using namespace std;
typedef struct point_s {
float x, y;
} point_t;
typedef struct circle_s {
point_t center;
float radius;
} circle_t;
int main(void)
{
circle_t circle1;
point_t point1;
float p, deltaX, deltaY;
}
cout << "Daire merkezinin koordinatlarn yazn (x y): ";
cin >> circle1.center.x >> circle1.center.y;
cout << "Dairenin yarçapn yazn: ";
cin >> circle1.radius;
cout << "Noktann koordinatlarn yazn (x y): ";
cin >> point1.x >> point1.y;
deltaX = point1.x - circle1.center.x;
deltaY = point1.y - circle1.center.y;
p = deltaX * deltaX + deltaY * deltaY;
if (p < circle1.radius * circle1.radius)
cout << "Nokta dairenin içinde." << endl;
else {
if (p > circle1.radius * circle1.radius)
cout << "Nokta dairenin d³nda." << endl;
else
cout << "Nokta dairenen üzerinde." << endl;
}
return EXIT_SUCCESS;
83
Türetilmi³ Veri Tipleri
•
Bir noktann konumunun belirtilmesinden sonra programdan çkmadan kullancnn ayn
daireye göre ba³ka noktalarn da konumlarn sorabilmesi için programda gerekli de§i³iklikleri yapn.
•
Merkez koordinatlar ve yarçaplar kullancdan alnan iki dairenin kesi³ip kesi³mediklerini belirleyen bir program yazn.
Sorular
1. Örnek 11'da
equiv
de§i³kenine farkl bir ba³langç de§eri verilebilir miydi? Örne§in
de§i³ken tanmlama komutu
rational_t res, equiv = { 0, 0 };
³eklinde olsayd program do§ru çal³r myd?
2. Ayn örnekte kullanc ilk direnç de§eri olarak 0 verirse programn davran³ nasl olur?
Gerekiyorsa programda dazeltmeler yapn.
3. Örnek 10'da uygulamas yaplan barbut oyunu adil bir oyun mudur? Yani oyuncunun
kazanma olasl§ ile kaybetme olasl§ ayn mdr?
Yaplar
84
Bölüm 5
Diziler
Bu bölümde programlamada skça gereken dizi tiplerinin (bkz. Bölüm 1.1.3) C dilinde nasl
kullanlaca§ üzerinde durulacaktr.
Örnek 13. statistik Hesaplar
Kullancdan ald§ snav notlarnn ortalamasn, varyansn, standart sapmasn ve mutlak
sapmasn hesaplayan bir program yazlmas isteniyor. Programn örnek bir çal³mas “ekil 5.1'de verilmi³tir.
Ö§renci says
sapma
ad
n, i.
ö§rencinin notu
si ,
ortalama
m,
varyans
v,
standart sapma
sd,
mutlak
ile gösterilirse:
Pn
i=1 si
m =
n
Pn
sd =
− m)2
n−1
i=1 (si
v =
√
v
Pn
ad =
i=1 |si
− m|
n
Bu problemde dört döngü i³lemi görülebilir:
1. Kullancnn girdi§i notlar okumak için bir döngü.
2. Ortalama için gereken, notlarn toplamn hesaplamakta kullanlan döngü (birinci e³itlikteki
P
i³aretine kar³ dü³er).
3. Varyans ve standart sapma için gereken, her bir notun ortalamayla farklarnn karelerinin
toplamn hesaplamakta kullanlan döngü (ikinci e³itlikteki
P
i³aretine kar³ dü³er).
4. Mutlak sapma için gereken, her bir notun ortalamayla farklarnn mutlak de§erlerinin
toplamn hesaplamakta kullanlan döngü (dördüncü e³itlikteki
85
P
i³aretine kar³ dü³er).
86
Örnek 13 Çe³itli istatistik hesaplar yapan program.
#include <iostream>
#include <stdlib.h>
#include <math.h>
// cin,cout,endl
// EXIT_SUCCESS
// fabs,sqrt
using namespace std;
#define MAXSTUDENTS 100
int main(void)
{
int score[MAXSTUDENTS];
int no_students = 0;
float mean, variance, std_dev, abs_dev;
float total = 0.0, sqr_total = 0.0, abs_total = 0.0;
int i = 0;
}
cout << "Kaç ö§renci var? ";
cin >> no_students;
for (i = 0; i < no_students; i++) {
cout << i + 1 << ". ö§rencinin notu: ";
cin >> score[i];
total = total + score[i];
}
mean = total / no_students;
for (i = 0; i < no_students; i++) {
sqr_total = sqr_total + (score[i] - mean) * (score[i] - mean);
abs_total = abs_total + fabs(score[i] - mean);
}
variance = sqr_total / (no_students - 1);
std_dev = sqrt(variance);
abs_dev = abs_total / no_students;
cout << "Ortalama: " << mean << endl;
cout << "Varyans: " << variance << endl;
cout << "Standart sapma: " << std_dev << endl;
cout << "Mutlak sapma: " << abs_dev << endl;
return EXIT_SUCCESS;
87
Diziler
Kaç ö§renci var? 5
1. ö§rencinin notu: 65
2. ö§rencinin notu: 82
3. ö§rencinin notu: 45
4. ö§rencinin notu: 93
5. ö§rencinin notu: 71
Ortalama: 71.2
Varyans: 329.2
Standart sapma: 18.1439
Mutlak sapma: 13.04
“ekil 5.1: Örnek 13 ekran çkts
Burada birinci ve ikinci döngüler tek bir döngüde birle³tirilebilir, kullanc notlar girdikçe bunlar toplama eklenebilir. Ancak üçüncü ve dördüncü döngüler bu döngüye eklenemez, çünkü o
döngülerde her bir notun ortalamayla farkna gereksinim vardr ve bu ortalama ancak birinci
döngü sona erdi§inde elde edilmektedir. Döngü sayac ayn snr de§erleri arasnda de§i³ti§inden ve her yinelemede ayn ö§renci notu üzerinde i³lem yapld§ndan üçüncü ve dördüncü
döngüler de kendi aralarnda tek bir döngüde birle³tirilebilirler.
Örnek 11'da kullancnn girdi§i direnç de§erleri toplama eklendikten hemen sonra yitiriliyorlard. Oysa bu örnekte ö§renci notlarnn birinci döngünün çk³nda unutulmamas gerekir,
çünkü ikinci döngüde de bunlar gerekecektir. Yani bu notlarn bir yerde tutulmas gerekir.
Ayn tipten çok sayda eleman bulunan de§i³kenler için en uygun yapnn diziler oldu§u Bölüm 1.1.3'de görülmü³tü. Örne§imizde de ö§renci notlar bir dizi olarak temsil edilmektedir.
5.1
Tek Boyutlu Diziler
Dizi tanmnn yazm
veri_tipi dizi_ad [dizi_boyu ];
³eklindedir. Burada
dizi_ad dizi tipinden tanmlanan de§i³kenin adn, dizi_boyu bu dizide
veri_tipi ise her bir elemann hangi tipten oldu§unu belirtir.
kaç eleman bulundu§unu,
Örnekte
int score[MAXSTUDENTS];
komutu, her biri tamsay tipinden
MAXSTUDENTS elemanl, score adnda bir dizi tanmlar. Bu
MAXSTUDENTS * sizeof(int) sekizli yer ayrlr.
dizi için bellekte birbirini izleyecek ³ekilde
Di§er de§i³kenlerde oldu§u gibi, dizilere de tanm srasnda ba³langç de§eri verilebilir. Örne§in:
88
Tek Boyutlu Diziler
int score[4] = { 85, 73, 91, 66 };
tanm 4 elemanl bir dizi tanmlar ve elemanlara srasyla 85, 73, 91 ve 66 de§erlerini atar. Özel
bir durum olarak, bütün diziye 0 ba³langç de§eri verilmek isteniyorsa ³u komut kullanlabilir:
int score[50] = { 0 };
Derleyicinin dizi için bellekte ne kadar yer ayrlaca§n bilmesi gerekir, yani derleme a³amasnda dizinin kaç elemannn olaca§ belli olmaldr. Bunun için iki yöntem kullanlabilir:
açk belirtim
Dizinin kaç eleman oldu§unun tanm srasnda açk olarak belirtildi§i, yuka-
rda da örnekleri görülen yöntemdir. Boy olarak de§i³mez bir de§er vermek zorunludur.
Örnekte snftaki ö§renci says
no_students
no_students
de§i³keniyle gösterilmektedir, yani dizinin
eleman olmas gerekli ve yeterlidir. Ancak
no_students
de§i³keninin de-
§erinin ne olaca§ programn çal³mas srasnda belirlendi§inden derleyici bu de§eri dizi
boyu olarak kullanamaz, yani
int score[no_students];
³eklinde bir dizi tanm yaplamaz. Ba³ka bir deyi³le, dizi boyu için yazlacak deyimde
yalnzca saylar ve de§i³mezler yer alabilir, de§i³kenler yer alamaz. Bu durumda, dizinin kaç eleman olaca§ ba³tan bilinmiyorsa gerekebilecek en büyük eleman says boy
olarak belirtilmelidir. Örnekteki
MAXSTUDENTS
de§i³mezi bu i³levi görmektedir. Burada
belirtilen say, bir yandan gereksiz bellek kullanmna yol açabilir, di§er yandan da programn bir kstlamas haline gelir. Örnek programn yapt§ i³in açklamasn ³u ³ekilde
düzeltmek gerekir:
Bu program, en fazla 100 ö§rencili bir snfta, ö§renci notlarnn ortalamasn,
varyansn ve standart ile mutlak sapmalarn hesaplar.
örtülü belirtim
Diziye ba³langç de§eri verilirse eleman saysn belirtmek zorunlulu§u yok-
tur, yani
int score[] = { 85, 73, 91, 66 };
tanm da dört elemanl bir tamsay dizisi tanmlar ve söylenen ba³langç de§erlerini atar.
Bu durumda derleyici ba³langç de§eri olarak verilen dizideki eleman saysn sayarak
boyu kendisi belirler. Dizideki eleman says ileride artmayacaksa bu yazm kullanmann
bir sakncas yoktur, ancak artmas olasl§ varsa yine gerekebilecek en büyük eleman
saysnn dizi tanmnda açk olarak belirtilmesi gerekir çünkü aksi durumda sonradan
gelen elemanlar için yer ayrlmam³ olur.
Dizinin bir eleman üzerinde i³lem yapmak için o elemann kaçnc eleman oldu§unu belirtmek gerekir. Bu belirtim de dizi adnn yannda elemann sra numarasnn kö³eli ayraçlar
içine yazlmasyla yaplr, yani
score[i], score dizisinin i. eleman anlamna gelir. Bu yazm
89
Diziler
dizi tanmndaki yazmla ayn olmakla birlikte anlam olarak tamamyla farkldr: tanmda kö³eli ayraçlar içine yazlan say dizinin tutabilece§i eleman saysn gösterirken burada kaçnc
eleman üzerinde i³lem yapld§n gösterir.
C dilinde dizilerin ilk elemannn sra numaras her zaman 0'dr; yani ilk elemann sra numaras
0, ikinci elemann sra numaras 1 olacak ³ekilde ilerler (“ekil 5.2a). Bu durumda n elemanl
bir dizinin son elemannn sra numaras n - 1 olur. Bu özellik nedeniyle
n
elemanl bir dizi
üzerinde i³lem yapacak tipik bir C döngüsü
for (i = 0; i < n; i++)
³eklinde ba³lar. lk elemann sra numaras 0 oldu§undan
for
blo§una ilk giri³te dizinin ilk
eleman ile i³lem yaplr. Son i³lem de n - 1 sra numaral elemanla yaplr, döngü sayac
n de§erini ald§nda döngüden çklr. Burada dizinin tanmda belirtilen boyuyla gerçekten
kullanlan eleman says arasndaki ayrma dikkat edilmelidir. Örnekte tanmda belirtilen boy
MAXSTUDENTS olsa da döngü 0. elemandan MAXSTUDENTS - 1. elemana kadar gitmez çünkü son
no_students - 1 olacaktr:
geçerli elemann sra numaras
for (i = 0; i < no_students; i++)
score
0
1
2
MAXSTUDENTS-1
(a)
score
0
1
2
MAXSTUDENTS
(b)
“ekil 5.2: Dizi elemanlarnn sra numaralar.
Derleyici dizilerin elemanlarna eri³imde dizi snrlarnn denetimini yapmaz; yani n elemanl
bir dizinin n. ya da daha sonraki elemanlarna eri³ilmeye kalklrsa hata vermez. Dizi snrlarndan ta³mamak programcnn sorumlulu§undadr. Dizi snrndan ta³acak bir sra numaras
verilirse bellekte ilk elemandan ba³lanarak istenen sayda eleman kadar ilerlenip orada ne bulunursa o de§erle i³lem yaplmaya çal³lr (“ekil 5.2b). Böyle bir eri³im çal³ma annda iki tür
soruna yol açabilir:
1. Gelinen bellek gözü, ba³ka bir de§i³ken için ayrlm³ bir bölgeye dü³ebilir. Bu durumda,
ba³ka bir de§i³kenin de§eri istenmeden de§i³tirilmi³ olur ve programn çal³mas üzerinde
beklenmedik etkiler yaratabilir.
2. Eri³ilmek istenen bellek bölgesi kullancnn izni olan bölgeler d³nda bir yere dü³ebilir.
Bu durumda bir bellek hatas olu³ur.
90
Tek Boyutlu Diziler
Örnek 14. Tümce Tersine Çevirme
Kullancnn yazd§ tümceyi tersine çevirerek ekrana çkartan bir program yazlmas isteniyor.
Programn örnek bir çal³mas “ekil 5.3'de verilmi³tir.
Tümce: Deneme bir ...
Tersi: ... rib emeneD
“ekil 5.3: Örnek 14 ekran çkts.
Örnek 14 Tümceyi tersine çeviren program.
#include
#include
#include
#include
<iostream>
<stdlib.h>
<stdio.h>
<string.h>
//
//
//
//
cin,cout,endl
EXIT_SUCCESS
gets
strlen
using namespace std;
#define MAXLENGTH 80
int main(void)
{
char sentence[MAXLENGTH];
int len, i;
char tmp;
}
cout << "Tümce: ";
gets(sentence);
len = strlen(sentence);
for (i = 0; i < len / 2; i++) {
tmp = sentence[i];
sentence[i] = sentence[len - 1 - i];
sentence[len - 1 - i] = tmp;
}
cout << "Tersi: " << sentence << endl;
return EXIT_SUCCESS;
Örnek program, ba³tan ve sondan ayn srada olan simgelerin yerlerinin takas edilmesi algoritmasn kullanr. Yani ilk simgeyle son simge, ikinci simgeyle sondan bir önceki simge v.b.
takas edilir. Bu algoritmann do§ru çal³mas için takasn katarn ortasna kadar sürmesi ve
katar ortasn geçmemesi gerekir. (Neden?)
91
Diziler
5.2
Katarlar
C dilinde katarlar birer simge dizisi olarak de§erlendirilir ve sonlarna konan '\0' simgesiyle
sonlandrlrlar. Bu nedenle katar için bellekte ayrlmas gereken yer, katarn içerdi§i simge
saysnn bir fazlasdr. Örnekteki
char sentence[MAXLENGTH];
tanm, her biri simge tipinden, 80 elemanl,
sentence adnda bir katar olu³turur. Bu eleman-
lardan biri '\0' simgesi için kullanlaca§ndan kullancnn yazaca§ tümce en fazla 79 simge
uzunlu§unda olabilir.
Katar tipinden bir de§i³kenin tanmlanmas srasnda çift trnaklar içinde ba³langç de§eri
belirtilebilir. Tanmlanan boyun katar için gereken yeri ayrmasna dikkat edilmelidir. stenirse
boyut belirtilmeyebilir; bu durumda derleyici gerekli yeri kendisi ayrr. A³a§daki iki tanm
ayn i³i görürler (“ekil 5.4a):
char sentence[15] = Deneme bir ...;
char sentence[] = Deneme bir ...;
sentence
’D’ ’e’ ’n’ ’e’ ’m’ ’e’ ’ ’ ’b’ ’i’ ’r’ ’ ’ ’.’ ’.’ ’.’ ’\0’
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
(a)
sentence
’D’ ’e’ ’n’ ....... ’.’ ’.’ ’.’ ’\0’
0
1
2
11
12
13
14
........
15
79
80
(b)
“ekil 5.4: Katarlara ba³langç de§eri atanmas.
Tam gerekti§i kadar yer ayrmak riskli bir davran³tr. Programn içinde katarn uzamas sözkonusu olabilecekse gerekebilecek maksimum alan gözönüne alnmal ve tanm srasnda bu
boy belirtilmelidir.
char sentence[MAXLENGTH] = Deneme bir ...;
komutu
MAXLENGTH
simgelik yer ayrr ancak yalnzca ilk 15 simgeyi doldurur (“ekil 5.4b).
Katarlarn elemanlarna dizilerde oldu§u gibi teker teker eri³ilebilir. Dizilerde oldu§u gibi, ilk
elemann, yani katarn ilk simgesinin sra numaras 0 olacaktr. Son elemann sra numaras da
ayrlan yerin bir eksi§idir. Yukardaki örnekte
' ',
sentence[13]
eleman '.',
sentence[14]
sentence[0] eleman 'D', sentence[6] eleman
eleman '\0' de§erlerini alrlar.
92
Katar Kitapl§
cout birimi yardmyla çktya gönderilmelerinde herhangi bir
cin ile girdi a³amasnda sorun çkabilir. Kullancnn yazd§ katarda bo³luk
simgesi varsa, cin birimi birden fazla de§i³kenin girildi§ini dü³ünerek yalnzca ilk bo³lu§a
kadar olan bölümü de§i³kene aktaracaktr. Örnekte bu amaçla katarn girdi i³lemi gets kitaplk
Katar tipinden de§i³kenlerin
sorun olmazken,
fonksiyonuyla gerçekle³tirilmi³tir.
1 Bu komutun yerine
cin > > sentence;
komutu kullanlm³ olsayd programn çal³mas “ekil 5.5'de görüldü§ü gibi olurdu.
Tümce: Deneme bir ...
Tersi: emeneD
“ekil 5.5: Örnek 14 hatal ekran çkts.
5.3
Katar Kitapl§
Katarlar birer dizi olduklarndan katarlar arasnda atama yapmak ya da katarlar kar³la³trmak için katar kitapl§ndaki fonksiyonlarn kullanlmas gerekir. Örnek programda, katarn
uzunlu§unu belirlemek üzere bu kitaplktaki
strlen
fonksiyonundan yararlanlm³tr.
Katar tipinden iki de§i³kenin birbirine atanmas ya da kar³la³trlmas i³lemleri standart i³leçler kullanlrsa beklenmedik sonuçlar do§urabilir. Ba³ka bir deyi³le, atama için
str1 = str2;
ya da kar³la³trma için
if (str1 == str2)
gibi yaplar kullanlmaz.
2
Katarlar üzerinde skça kullanlan temel i³lemler için bir katar kitapl§ tanmlanm³tr. Bu
fonksiyonlarn kullanlabilmesi için programlarn ba³nda
string.h ba³lk dosyasnn alnmas
gerekir.
Katar kitapl§nn en sk kullanlan fonksiyonlar Tablo 5.1'de verilmi³tir.
Katar uzunlu§u fonksiyonu sondaki
'\0'
simgesini gözönüne almaz.
• strlen(computer) → 8
1
Güvenlik nedenleriyle
gets
kitaplk fonksiyonunun kullanlmas tehlikelidir. Bu komutun yerine
fonksiyonunun kullanlmas önerilir (bkz. Bölüm 8).
2
Daha ayrntl açklama için bkz. Bölüm .7.3.
fgets
93
Diziler
Ad
³levi
strlen(s)
strcopy(dest,src) strncpy(dest,src,n)
strcmp(s1,s2) strncmp(s1,s2,n)
strcat(dest,src) strncat(dest,src,n)
katar uzunlu§u
katar kopyalama
katar kar³la³trma
katar biti³tirme
Tablo 5.1: Katar kitapl§ fonksiyonlar.
Katar kopyalama fonksiyonlar ikinci giri³ parametresi olan katar, birinci giri³ parametresi
olan katarn üstüne yazarlar. Biti³tirme fonksiyonlarysa ikinci giri³ parametresi olan katar,
birinci giri³ parametresi olan katarn ardna eklerler. Her iki fonksiyon grubu da sonuç katarnn
sonuna konmas gereken '\0' simgesini kendileri koyarlar.
Katar i³lemi yapan fonksiyonlarn bazlarnda uzunluk denetimi yaplr, bazlarnda yaplmaz.
Sözgelimi
strcpy
fonksiyonu
src
dest
katarnn de§erini
fonksiyonu da ayn i³levi görür, ancak en fazla
katarnn üstüne yazarken,
strncpy
n simgeyi kopyalar. Güvenlik açsndan uzunluk
3
denetimi yapan fonksiyonlarn kullanlmas önerilir.
Katar kar³la³trma fonksiyonlar giri³ parametresi olan katarlar arasnda ngilizce dilinin kurallarna göre sözlük sras kar³la³trmas yaparlar. ki katar e³itse 0, birinci katar ikinciden
önce geliyorsa -1, sonra geliyorsa 1 de§erini döndürürler.
• strcmp(abc, ad) →
-1
• strcmp(abcd, abc) →
1
• strncmp(abcd, abcde, 4) →
0
Kopyalama ve biti³tirme fonksiyonlarnda dikkat edilmesi gereken bir nokta, hedef katarn
yeterli uzunlukta olmasnn sa§lanmasdr. Örne§in, a³a§daki program parças hataya yol
açabilir:
char author1[] = Brian, author2[] = Dennis;
...
strcpy(author1, author2);
author1 katarna 6 simgelik, author2 katarnaysa 7 simgelik yer ayracaktr. Daha
author1 katarnn üstüne author2 katar yazlmaya kalkld§nda author1 katarnda
Derleyici
sonra
yeterli yer olmad§ için bu de§i³kenin snrlarndan ta³lr. Benzer ³ekilde, biti³tirme i³lemlerinde de hedef katar için iki asl katarn toplam uzunluklarn tutmaya yetecek kadar yer
ayrlm³ olmaldr.
3
Uzunluk denetimi yapmayan katar fonksiyonlar tampon ta³rma ad verilen saldrlara yol açan kaynaklar
arasnda en büyük yeri tutar.
94
Çok Boyutlu Diziler
Uygulama: Tek Boyutlu Diziler
Örnek 15. Polinom Hesab
p(x) = an xn + an−1 xn−1 + · · · + a1 x + a0
³eklinde yazlan
n.
dereceden bir polinomda verilen bir
n(n+1)
adet çarpma ve
2
n
x
de§eri için
p(x)'in
hesaplanmas
adet toplama i³lemi gerektirir. çiçe çarpma ve toplama yöntemiyle
bu say azaltlabilir.
Polinomu ³u ³ekilde yeniden yazalm:
p(x) = (((an x + an−1 )x + an−2 )x + · · · + a1 )x + a0
b de§eri, ba³langçta b = an ve i. admda b = bx+an−i olacak ³ekilde hesaplanarek
a0 katsaysnn da toplanmasyla elde edilecek b de§eri hesaplanmak istenen p(x) de§eri
Yaplmas gereken i³lem says da n çarpma ve n toplamaya iner.
O halde bir
gidilirse
olur.
•
Çkts verilen program kullanarak
p(x) = 13x7 − 9x6 + 12x4 − 4x3 + 3x + 5
polinomunun
p(4), p(2.5)
ve
p(19)
de§erlerini hesaplatn.
Örnek 16. Matris Çarpm
Bu bölümde üzerinde çal³lacak program, boyutlar ve elemanlar kullancdan alnan iki matrisi çarparak sonucu ekrana çkartr. Programn örnek bir çal³masnn ekran çkts “ekil 5.6'da
verilmi³tir.
5.4
Çok Boyutlu Diziler
Çok boyutlu bir dizi tanmlanmasnda her boyut ayr bir kö³eli ayraç çifti içinde belirtilir.
Örnekteki
int left[MAXSIZE][MAXSIZE];
komutu, 30 satrl ve 30 sütunlu bir matris tanmlar. Bu matrisin, her biri birer tamsay olan,
30*30=900 eleman olacaktr, yani bellekte 900 tamsay tutacak kadar yer ayrlmasna neden
olur. Daha çok boyutu olan bir dizi tanmlanmak istenseydi boyutlar yanyana sürdürülebilirdi:
int m[30][20][7][12];
95
Diziler
Örnek 15 Polinom de§eri hesaplayan fonksiyon.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
#define MAXDEGREE 50
int main(void)
{
float a[MAXDEGREE];
float x, b;
int n, i;
char response = 'E';
cout << "Polinomun derecesi: ";
cin >> n;
cout << "Katsaylar: " << endl;
for (i = n; i >= 0; i--) {
cout << "a" << i << ": ";
cin >> a[i];
}
while (true) {
cout << "x: ";
cin >> x;
b = a[n];
for (i = n - 1; i >= 0; i--)
b = b * x + a[i];
cout << "p(x): " << b << endl;
cout << "Devam etmek istiyor musunuz (E/H)? ";
cin >> response;
if ((response == 'H') || (response == 'h'))
break;
}
}
return EXIT_SUCCESS;
96
Çok Boyutlu Diziler
Sol matrisin satr says: 5
Sol matrisin sütun says: 3
Sa§ matrisin sütun says: 4
Sol matris:
[1,1]: 2
[1,2]: 7
[1,3]: -1
[2,1]: 3
[2,2]: 5
[2,3]: 2
[3,1]: 0
[3,2]: 4
[3,3]: 1
[4,1]: 9
[4,2]: 0
[4,3]: -3
[5,1]: 4
[5,2]: 7
[5,3]: 2
Sa§ matris:
[1,1]: 0
[1,2]: 5
[1,3]: 2
[1,4]: -4
[2,1]: 1
[2,2]: 7
[2,3]: 3
[2,4]: 2
[3,1]: 5
[3,2]: 2
[3,3]: 0
[3,4]: -1
Çarpm sonucu:
2 57 25 7
15 54 21 -4
9 30 12 7
-15 39 18 -33
17 73 29 -4
“ekil 5.6: Örnek 16 ekran çkts.
97
Diziler
Örnek 16 ki matrisi çarpan program.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
#define MAXSIZE 30
int main(void)
{
int left[MAXSIZE][MAXSIZE], right[MAXSIZE][MAXSIZE];
int product[MAXSIZE][MAXSIZE] = { 0 };
int rl, cl, cr;
int &rr = cl;
int i, j, k;
cout << "Sol matrisin satr says: "; cin >> rl;
cout << "Sol matrisin sütun says: "; cin >> cl;
cout << "Sa§ matrisin sütun says: "; cin >> cr;
cout << "Sol matris: " << endl;
for (i = 0; i < rl; i++) {
for (j = 0; j < cl; j++) {
cout << " [" << i + 1 << "," << j + 1<< "]: ";
cin >> left[i][j];
}
}
cout << "Sa§ matris: " << endl;
for (j = 0; j < rr; j++) {
for (k = 0; k < cr; k++) {
cout << " [" << j + 1 << "," << k + 1 << "]: ";
cin >> right[j][k];
}
}
for (i = 0; i < rl; i++) {
for (j = 0; j < cr; j++) {
for (k = 0; k < cl; k++)
product[i][j] = product[i][j] + left[i][k] * right[k][j];
}
}
cout << "Çarpm sonucu:" << endl;
for (i = 0; i < rl; i++) {
for (k = 0; k < cr; k++)
cout << "\t" << product[i][k];
cout << endl;
}
98
Ba³vurular
Bu i³lem sonucunda da bellekte 30*20*7*12=50400 tamsay tutacak kadar yer ayrlr.
Tek boyutlu dizilerde oldu§u gibi, çok boyutlu dizilerde de ba³langç de§eri verilebilir. Bunun
için her bir boyutun kendi içinde süslü ayraçlar içine alnmas gerekir:
int m[2][3] = { { 1, 2, 1 }, { 3, 5, 1 } };
"
tanm
m=
1 2 1
3 5 1
#
matrisini olu³turur. Tek boyutlu dizilerdekine benzer ³ekilde
{ 0 }
ba³langç de§eri bütün elemanlara 0 ba³langç de§erini atar. Çok boyutlu dizilerde ilki d³nda
bütün boyutlarn belirtilmesi zorunludur. Sözgelimi bir isim dizisi olu³turulmak isteniyorsa
char names[][] = { Dennis, Brian, Ken };
tanmlamas derleyicinin hata vermesine neden olur. Birinci boyut d³ndakiler belirtilerek
yazlrsa
char names[][10] = { Dennis, Brian, Ken };
her bir eleman en fazla 10 simge uzunlu§unda olabilen 3 elemanl bir katar dizisi tanmlanm³
olur. Yani derleyici isim dizisinin eleman saysn sayar ancak belirtilen ba³langç katarlarnn
uzunluklarn hesaplamaya çal³maz. Yine de belirtilen uzunluktan daha uzun bir ba³langç
katar yazlrsa (diyelim 15 uzunluklu) derleyici bir hata üretebilir.
5.5
Ba³vurular
4 Örnekte sol matrisin satr
Ba³vurular, ayn de§i³kene ikinci bir isim verilmesini sa§larlar.
says ile sa§ matrisin sütun saylarnn ayn olmas zorunlulu§u nedeniyle bu bilgiyi tek bir
cl de§i³keni tanmlanm³tr. Ancak döngülerde
rr de§i³keninin de tanmlanmasnn yararl olaca§ dü³ünülerek
de§i³kenle temsil etmek yeterli görülmü³ ve
anla³lrl§ artrmak amacyla
rr
de§i³keninin
cl
de§i³kenine ba³vurmas sa§lanm³tr. Bu iki de§i³ken bellekte ayn gözde
bulunurlar ve dolaysyla birinde yaplan de§i³iklik do§rudan do§ruya di§erini etkiler.
Örnekte
rr de§i³keni ba³vuru olmak yerine ikinci bir de§i³ken olarak da tanmlanabilirdi. Bu
cl de§i³keni kullancdan okunduktan sonra rr = cl ³eklinde bir atamayla i³lem sür-
durumda
dürülebilirdi. Bu yakla³mda, iki de§i³ken birbirinden ayrlm³ olaca§ için birindeki de§i³iklik
di§erini etkilemezdi, ancak programda boyut de§i³kenleri üzerinde bir de§i³iklik olmad§ için
bir sorun çkmazd. Tek fark, gereksiz yere ikinci bir de§i³ken tanmlanm³ olmas olurdu.
4
Ba³vurular, C++ ile gelmi³ bir yeniliktir, C dilinde yoktur.
99
Diziler
Uygulama: Matrisler
Örnek 17. Gauss Eliminasyon Yöntemi
ax = b ³eklinde yazlan n bilinmeyenli bir lineer denklem takmnda a katsay matrisini,
b de§i³mezler vektörünü ve x çözüm vektörünü gösterir. Bu denklem takmnn çözümü iki
a³amaldr:
1.
a matrisi baz dönü³ümlerle bir üçgen matris haline getirilir. Bunun için önce sistemin
i1
i = 2, 3, . . . , n. denklemlerinden x1 yok edilir (birinci denklem aa11
ile çarplp i. denklemden çkarlr). Benzer ³ekilde, i = 3, 4, . . . , n. denklemlerden x2 yok edilerek devam edilir.
Birinci denklemin birinci eleman olan a11 'e pivot ad verilir ve x1 yok edilip ikinci denkleme geçildi§inde a22 eleman pivot olur. Yöntemin çal³abilmesi için bütün pivotlarn
sfrdan farkl olmas gerekti§i açktr.
2.
xn
n. denklemden do§rudan hesaplanr. Bu de§er n − 1. denklemde yerine koxn−1 bulunur ve böylece geriye do§ru yerine koyma i³lemleriyle bütün bilinmeyen
de§eri
nursa
de§erler hesaplanabilir.
Denklem takm ³u ³ekilde verilmi³ olsun:
x1 + x2 = 3.5
x1 − x2 + 5x3 = 11
2x1 − x2 + x3 = 3.3
a
matrisi ve
b
vektörünün de§erlerini adm adm izlersek:

ba³langçta:



1 1 0
3.5




a =  1 −1 5  b =  11 
2 −1 1
3.3

x1 'in
yok edilmesinden sonra:


x2 'nin
yok edilmesinden sonra:
Son denklemden
7.5


1 1 0
3.5




a =  0 −2 5  b =  7.5 
0 −3 1
−3.7



1 1
0
3.5




5  b =  7.5 
a =  0 −2
0 0 −6.5
−14.95
x3 = 2.3 elde edilir. Bu de§er ikinci denklemde yerine konursa:−2x2 + 5x3 =
x2 = 2 ve bu de§er birinci denklemde yerine konursa x1 + x2 = 3.5 denkle-
denkleminden
minden
x1 = 1.5
bulunur.
Gauss eliminasyon yöntemini kullanarak
Örnek 17'da verilmi³tir.
n
bilinmeyenli bir denklem takmn çözen program
100
Ba³vurular
Örnek 17 Gauss eliminasyon yöntemiyle denklem takm çözen program.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
#define MAXEQUATIONS 5
int main(void)
{
float a[MAXEQUATIONS][MAXEQUATIONS], b[MAXEQUATIONS];
float x[MAXEQUATIONS];
float pivot, f;
int n;
int i, j, k;
cout << "Denklem says: ";
cin >> n;
for (i = 0; i < n; i++) {
cout << "Denklem " << i + 1 << ": ";
for (j = 0; j < n; j++) {
cin >> a[i][j];
}
cin >> b[i];
}
for (j = 0; j < n - 1; j++) {
pivot = a[j][j];
for (i = j + 1; i < n; i++) {
f = a[i][j] / pivot;
for (k = j + 1; k < n; k++)
a[i][k] = a[i][k] - f * a[j][k];
b[i] = b[i] - f * b[j];
}
}
x[n-1] = b[n-1] / a[n-1][n-1];
for (i = n - 2; i >= 0; i--) {
f = b[i];
for (k = i + 1; k < n; k++)
f = f - a[i][k] * x[k];
x[i] = f / a[i][i];
}
for (i = 0; i < n; i++)
cout << "x" << i + 1 << ": " << x[i] << endl;
}
return EXIT_SUCCESS;
101
Diziler
Sorular
1. Kullancnn girdi§i bir tümcedeki sözcük saysn sayan bir program yazn. Sözcüklerin önünde ve arkasnda bo³luk oldu§u varsaylacaktr. Ancak sözcük arasnda istendi§i
sayda bo³luk olabilece§i gibi tümcenin ba³nda ve sonunda da istendi§i kadar bo³luk olabilir. Örnek olarak kullanc
the
world
is not
enough
tüm-
cesini girerse programn çkts 5 olacaktr.
2. Eratosthenes kalburu yöntemini kullanarak ilk 10000 say içindeki asal saylar ekrana
çkartan bir fonksiyon yazn.
3. Kullancdan alnan bir sayy yaz olarak ekrana çkartan bir program yazn. Örne§in
kullanc 21355 saysn girerse program ekrana Yirmibirbinüçyüzellibe³ yazacaktr.
4. Kullancnn verdi§i sayy Roma rakamlarna çevirerek ekrana çkartan bir program
yazn. Örne§in kullanc 523 saysn girerse ekrana DXXIII katar çkarlmaldr.
5. Verilen bir tarihin haftann hangi gününe geldi§ini bulan bir program yazn. Örne§in
kullanc 24-09-2002 tarihini girerse ekrana Sal katar çkarlmaldr.
6. Kullancdan alnan iki tarih arasnda geçen gün saysn hesaplayan bir program yazn.
7. Kullancdan ald§ bir tarihin haftann hangi gününe geldi§ini bulan bir program yazn.
Ba³vurular
102
Bölüm 6
Fonksiyonlar
“u ana kadar yaplan örneklerde bütün i³lemler tek bir fonksiyonda (main fonksiyonu) gerçekle³tiriliyordu. Gereken yerlerde kitaplk fonksiyonlarndan yararlanlmakla birlikte, kendi
yazd§mz kod tek bir fonksiyonla snrlyd. Oysa blok yapl programlamada soyutlama kavramnn öneminden Bölüm 1.4'de söz edilmi³, i³leri alt-i³lere, alt-i³leri alt-alt-i³lere bölerek
yazlan programlarn hem geli³tirme hem de bakm a³amalarnda sa§layaca§ kolaylklar görülmü³tü. Bu bölümde de programcnn kendi fonksiyonlarn nasl yazaca§n inceleyece§iz.
C dilinde her i³ ya da alt-i³ bir fonksiyon tarafndan gerçeklenir. Fonksiyonlar yapacaklar i³i
belirleyen giri³ parametreleri alrlar ve i³lemin sonucuna göre bir çk³ parametresi üretirler.
Yani giri³ parametrelerinin says birden fazla olabilir ancak çk³ parametresi en fazla bir
tanedir. “imdiye kadar kullanlan kitaplk fonksiyonlarnn bazlarna parametreleri açsndan
bakarsak:
• sqrt:
Kesirli say tipinden bir giri³ parametresi alr, kesirli say tipinden bir çk³ para-
metresi üretir.
• pow:
kisi de kesirli say tipinden iki giri³ parametresi alr, kesirli say tipinden bir çk³
parametresi üretir.
• strlen:
Katar tipinden bir giri³ parametresi alr, tamsay tipinden bir çk³ parametresi
üretir.
• rand:
Giri³ parametresi almaz, tamsay tipinden bir çk³ parametresi üretir.
• srand:
³aretsiz tamsay tipinden bir giri³ parametresi alr, çk³ parametresi üretmez.
Bir fonksiyonun bir alt-i³ini yaptrmak üzere ba³ka bir fonksiyonu kullanmasna fonksiyon
ça§rs ad verilir. Örnek 7'da,
main
fonksiyonu,
for
blo§unun ilk komutunda
rand
fonksiyo-
nunu ça§rmaktadr. Fonksiyon ça§rsnda üst fonksiyona ça§ran fonksiyon, alt fonksiyona da
ça§rlan fonksiyon denir, yani örnekte
main
fonksiyonu ça§ran,
rand
fonksiyonuysa ça§rlan
fonksiyondur. Fonksiyon ça§rsnn sona ermesinden sonra ça§ran fonksiyonda ak³ bir sonraki
komutla devam eder.
Ça§ran fonksiyon ça§rlan fonksiyona giri³ parametrelerini gönderir, ça§rlan fonksiyonsa üretti§i sonucu ça§ran fonksiyona döndürür. Döndürülen de§er ça§ran fonksiyonda bir de§i³kene
103
104
atanabilece§i ya da bir deyimde kullanlabilece§i gibi, do§rudan ba³ka bir fonksiyona giri³
parametresi olarak da gönderilebilir.
1 Örnekte
time
fonksiyonunun döndürdü§ü de§er,
srand
fonksiyonuna parametre olarak gönderilmi³tir:
number = rand();
number = rand() % 6;
srand(time(NULL));
// do§rudan atama
// deyimde kullanma
// ba³ka fonksiyona gönderme
Çk³ parametrelerinin kullanmnda tip uyumuna dikkat edilmelidir. Sözgelimi,
yonu tamsay tipinden bir de§er döndürdü§üne göre
olmaldr, katar tipinden olamaz.
number
rand
fonksi-
de§i³keni de tamsay tipinden
2 Benzer ³ekilde, bir fonksiyondan gelen bir de§er kalan i³le-
mine sokulacaksa bu de§erin tamsay tipinden olmasna dikkat etmek gerekir.
Giri³ parametrelerinin aktarm için ça§ran fonksiyondaki parametreleri yollama ³ekliyle ça§rlan fonksiyonun parametreleri bekleme ³ekli uyumlu olmaldr. Bu uyumluluk ³u ³ekilde
tanmlanabilir:
1. Ça§rlan fonksiyon kaç parametre bekliyorsa ça§ran fonksiyon o sayda parametre yollamaldr.
2. Ça§rlan fonksiyon her bir sradaki giri³ parametresinin tipinin ne olmasn bekliyorsa
ça§ran fonksiyon bu tipe uyumlu bir de§er göndermelidir.
Örne§in
pow
fonksiyonu iki tane kesirli say bekliyorsa bu fonksiyona iki tane kesirli say
(ya da tamsay) de§eri yollanmaldr. Bir, üç ya da daha fazla de§er yollanmas, hiç de§er
yollanmamas, yollanan iki de§erin say d³nda bir tipten (sözgelimi katar) olmas hataya yol
açar.
Örnek 18. Asal Çarpanlara Ayrma
Kullancnn girdi§i bir saynn asal çarpanlarn ekrana döken bir program yazlmas isteniyor. Gerekli algoritmann ak³ çizene§i “ekil 1.18'de, örnek bir çal³masnn ekran çkts
“ekil 6.1'de verilmi³tir. Programda bir saynn asal olup olmad§nn snanmasna ve asal saylarn bulunmasna gerek duyulacaktr. Soyutlama ilkesine göre bu i³lemler fonksiyonlarla
gerçekle³tirilecek, ana fonksiyon, asal saylar bulan fonksiyondan srayla ald§ asal saylarn
kullancnn verdi§i sayy bölüp bölmediklerini snayacaktr. Örnekte
is_prime
fonksiyonu
kendisine gönderilen bir saynn asal olup olmad§n belirleyerek geriye asalsa do§ru, de§ilse
yanl³ mantksal de§erini yollar.
next_prime fonksiyonu ise kendisine gönderilen saydan daha
büyük olan ilk asal sayy bularak kendisini ça§ran fonksiyona döndürür.
1
2
Aslnda bu durumlarn hepsi deyimde kullanma olarak de§erlendirilebilir.
Eski C derleyicileri bu tip denetimlerde fazlasyla gev³ek davranabilmektedir. Bu durum programcnn
hata yapmasna zemin hazrlar.
105
Fonksiyonlar
Örnek 18 Bir sayy asal çarpanlarna ayran program.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
int next_prime(int prime);
int main(void)
{
int number, factor = 2;
}
cout << "Sayy yaznz: ";
cin >> number;
while (number > 1) {
while (number % factor == 0) {
cout << factor << " ";
number = number / factor;
}
factor = next_prime(factor);
}
cout << endl;
return EXIT_SUCCESS;
bool is_prime(int cand)
{
int count;
}
if (cand == 2)
return true;
if (cand % 2 == 0)
return false;
for (count = 3; count * count <= cand; count += 2) {
if (cand % count == 0)
return false;
}
return true;
int next_prime(int prime)
{
int cand = (prime == 2) ? 3 : prime + 2;
}
while (!is_prime(cand))
cand += 2;
return cand;
106
Fonksiyon Bildirimi ve Tanm
Sayy yaznz: 6468
2 2 3 7 7 11
“ekil 6.1: Örnek 18 ekran çkts.
6.1
Fonksiyon Bildirimi ve Tanm
Bir fonksiyon iki bile³enden olu³ur:
•
Fonksiyonun ba³l§, fonksiyonun adn ve giri³/çk³ parametrelerini belirtmeye yarar.
Soyutlamadaki kar³l§yla fonksiyonun NE yapt§n anlatr. Fonksiyon ba³l§nn belirtilmesi i³lemine fonksiyonun bildirimi denir ve ba³l§n sonuna bir noktal virgül konarak
yaplr. Bildirim komutunun yazm ³u ³ekildedir:
çk³_parametresi_tipi fonksiyon_ad (giri³_parametresi_listesi );
Örnekte
next_prime
fonksiyonu için yaplan
int next_prime(int prime);
bildirimine göre,
next_prime
fonksiyonu tamsay tipinden bir giri³ parametresi alr ve
yine tamsay tipinden bir çk³ parametresi döndürür.
Çk³ parametresi herhangi bir skalar ya da bile³ke tipten olabilir ancak dizi olamaz. Giri³ parametresi listesiyse birbirinden virgülle ayrlm³
veri_tipi de§i³ken_ad
çiftleri
³eklindedir. Çk³ parametresi döndürmeyen fonksiyonlarn çk³ parametresi tipi
void
sakl sözcü§üyle belirtilir. Benzer ³ekilde, giri³ parametresi almayan fonksiyonlarn giri³
listesi parametresine de
void
yazlr. Bu bilgileri gözönünde bulundurarsak, kulland§-
mz baz kitaplk fonksiyonlarnn sistemde ³öyle bildirilmi³ olmalar gerekti§i görülebilir:
double sqrt(double x);
double pow(double x, double y);
int rand(void);
void srand(unsigned int seed);
Giri³ parametresi listesindeki de§i³kenlerin yazm de§i³ken tanm yazmna benzer ancak ayn tipten de§i³kenler gruplanamaz. Sözgelimi a³a§daki bildirim hataldr:
double pow(double x, y);
Fonksiyon bildirimi, derleyiciye giri³ parametresi listesi tipinden de§i³kenler alan ve çk³
parametresi tipinden de§er üreten belirtilen isimde bir fonksiyon oldu§ununun bildirilmesini sa§lar. Böylelikle derleyici bu fonksiyon ça§rsn gördü§ü yerde parametrelerin
uyumlu olup olmadklarn denetleyebilir. Çal³ma annda fonksiyon ça§rsna gelindi§inde uygun yere gidilmesini sa§layacak ba§lantlar kurmak derleyicinin de§il ba§laycnn görevidir.
107
Fonksiyonlar
•
Fonksiyonun gövdesi, fonksiyonun yapaca§ i³leri belirten bloktan olu³ur, yani fonksiyonun i³ini NASIL yapt§n anlatr. Bir fonksiyonun bütününün, yani giri³/çk³ parametrelerinin yansra gövdesinin de belirtildi§i yere fonksiyonun tanm denir. Örnekte
is_prime fonksiyonu, main fonksiyonunun bitiminden sonra, next_prime fonksiyonu da
is_prime fonksiyonunun bitiminden sonra tanmlanm³tr.
return komutu yardmyla döndüreturn sakl sözcü§ünden sonra yazlan deyim fonksiyonun ba³l§nda belirtilen veri
tipine uygun tipten bir de§er üretmelidir. Örnekte is_prime fonksiyonu mantksal tipten
tanmlanm³tr ve fonksiyonun çe³itli noktalarnda false ya da true de§erlerini döndürmektedir. next_prime fonksiyonuysa tamsay tipinden tanmlanm³tr ve döndürdü§ü
de§eri tutan de§i³ken de (cand) tamsay tipindendir.
Ça§rlan fonksiyon üretti§i de§eri ça§ran fonksiyona
rür.
Bir fonksiyon ça§rsnn yaplabilmesi için ça§rlan fonksiyonun ya bildirimi ya da tanm ça-
next_prime fonksiyonunu,
next_prime fonksiyonu da is_prime fonksiyonunu ça§rr. Birinci ça§r, next_prime fonksiyonunun bildirimi main fonksiyonunun tanm ba³lamadan yapld§ndan ba³arl olur. kinci ça§rysa is_prime fonksiyonu next_prime fonksiyonundan önce tanmland§ndan ba³arl olur.
Ancak örne§in main fonksiyonu is_prime fonksiyonunu ça§ramaz çünkü öncesinde is_prime
§ran fonksiyondan önce yaplmaldr. Örnekte
main
fonksiyonu
fonksiyonunun ne tanm ne de bildirimi vardr.
Kendi yazd§nz fonksiyonlarda oldu§u gibi, kitaplk fonksiyonlarn da ça§rabilmeniz için bu
fonksiyonlarn bildirimlerinin daha önceden yaplm³ olmas gerekir. Bu bildirimler kulland§nz derleyiciyle gelen ba³lk dosyalarnda yer alr; bir kitaplk fonksiyonunu kulland§nzda
ba³lk dosyasn belirtmeniz zorunlulu§u da buradan do§ar.
6.2
Parametre Aktarm
Giri³ parametrelerinin aktarmnda fonksiyon ça§rsnda belirtilen parametre listesiyle fonksiyonun ba³l§nda belirtilen liste uyumlu olmaldr. Ça§rda yazlan her de§er, ça§rlan fonksiyonun ba³l§nda ayn srada yazlm³ de§i³kene atanr. Bu parametre aktarm yöntemine
de§er aktarm ad verilir. Örnekteki birinci fonksiyon ça§rsnda:
factor = next_prime(factor);
main fonksiyonundaki factor de§i³keninin de§eri next_prime fonksiyonunun giri³ parametresi
olan prime de§i³kenine atanr. Dönü³te de next_prime fonksiyonunun return komutuyla geri
yollad§ cand de§i³keninin de§eri main fonksiyonundaki factor de§i³kenine atanr. Fonksiyonun bir döngü içinde ça§rld§ gözönüne alnarak, parametre olarak ilk ça§rda 2 de§erinin
gönderilece§i ve 3 de§erinin dönece§i, ikinci ça§rda 3 de§erinin gönderilece§i ve 5 de§erinin
dönece§i, ileriki ça§rlarda 5, 7, 11, ... de§erlerinin gönderilece§i görülebilir. Benzer ³ekilde,
ikinci fonksiyon ça§rsnda
next_prime fonksiyonundaki cand
cand de§i³kenine atanr.
de§i³keninin de§eri
is_prime
fonksiyonunun giri³ parametresi olan
Tipi uygun oldu§u sürece parametre olarak herhangi bir deyim belirtilebilir. Sözgelimi a³a§daki ça§rlar geçerlidir:
108
Yerel De§i³kenler
number
main
6468
factor
2
prime
cand
cand
count
next_prime
is_prime
“ekil 6.2: Parametre aktarm örne§i - 1. adm.
is_prime(13)
is_prime(cand + 1)
Benzer ³ekilde, geri döndürülecek de§er için uyumlu tipten de§er üreten bir deyim yazlabilir:
return cand + 2;
6.3
Yerel De§i³kenler
Parametre aktarm anlatlrken main fonksiyonundaki
factor de§i³keninin de§eri next_prime
prime de§i³kenine , next_prime fonksiyonundaki cand
is_prime fonksiyonunun giri³ parametresi olan cand de§i³kenine gibi
fonksiyonunun giri³ parametresi olan
de§i³keninin de§eri
sözler kullanld. Buradan da görülebilece§i gibi, de§i³kenler içinde tanmlandklar fonksiyon
ile birlikte de§erlendirilirler ve yalnzca bu fonksiyon içinde geçerlidirler.
daki
factor
de§i³keni ile
next_prime
fonksiyonundaki
prime
main
fonksiyonun-
de§i³keni farkl de§i³kenlerdir,
bellekte farkl yerlerde bulunurlar; dolaysyla, birinde yaplan de§i³iklik di§erini etkilemez.
De§i³ken adlarnn ayn olmasnn da bir önemi yoktur:
de§i³keniyle
is_prime
fonksiyonundaki
cand
next_prime
fonksiyonundaki
cand
de§i³keni de farkl de§i³kenlerdir.
main fonksiyonunda factor de§i³kenine ba³next_prime fonksiyonunun prime adl giri³ parametre de§i³kenine aktarlr (“ekil 6.2). next_prime fonksiyonunda cand de§i³keni 3 de§erini alr ve bu
de§er asal olup olunmad§nn belirlenmesi için is_prime fonksiyonunun cand adl giri³ parametre de§i³kenine aktarlr (“ekil 6.3). is_prime fonksiyonunda count de§i³keni 3 de§erini alr
ancak döngü ko³ulu ba³tan sa§lanmad§ndan döngüden çklarak next_prime fonksiyonuna
true de§eri döndürülür (“ekil 6.4). Bu de§er !is_prime(cand) ko³ul deyiminin yanl³ sonucunu üretmesine neden oldu§undan döngüden çklr ve main fonksiyonuna cand de§i³keninin
o anki de§eri, yani 3 döndürülür. Bu de§er de main fonksiyonundaki factor de§i³kenine atanr
Örnekte ilk fonksiyon ça§rlar ³öyle gerçekle³ir.
langçta atanm³ olan 2 de§eri
(“ekil 6.5)
Fonksiyonun parametre olarak ald§ ya da fonksiyon gövdesinde tanmlanan de§i³kenlere o
fonksiyonun yerel de§i³kenleri ad verilir ve bunlarn tanm bölgesi tanmlandklar fonksiyonla
109
Fonksiyonlar
number
main
factor
6468
prime
next_prime
2
cand
2
3
cand
count
is_prime
“ekil 6.3: Parametre aktarm örne§i - 2. adm.
number
main
factor
6468
2
prime
next_prime
cand
2
3
cand
count
3
3
!is_prime(cand)
true
is_prime
“ekil 6.4: Parametre aktarm örne§i - 3. adm.
number
main
6468
prime
next_prime
is_prime
factor
2
cand
2
3
cand
count
3
3
“ekil 6.5: Parametre aktarm örne§i - 4. adm.
110
Genel De§i³kenler
snrlanr. Örnekteki bütün fonksiyonlarn iki³er (main:
ve
count, next_prime: prime
ve
cand)
number
ve
factor, is_prime: cand
yerel de§i³keni vardr. Fonksiyonun sona ermesiyle
tanmlad§ de§i³kenler de geçersiz hale gelir. Ba³ka bir deyi³le, de§i³kenlere tanm bölgeleri
d³nda eri³ilemez. Yani sözgelimi
main fonksiyonu number ve factor d³nda kalan de§i³kenleri
kullanamaz.
6.4
Genel De§i³kenler
Baz durumlarda birden fazla fonksiyonun ayn de§i³keni kullanabilmeleri istenir. Bu tip de§i³kenlere genel de§i³ken ad verilir ve tanm bölgeleri bütün fonksiyonlar olarak belirlenir.
Genel de§i³kenler bütün fonksiyonlarn tanmlarndan önce tanmlanrlar.
DKKAT
Genel de§i³kenlere örnek vermek için programda baz de§i³iklikler yaplabilir. BU DE‡“KLKLERN SONUCUNDA OLU“ACAK PROGRAM Y BR PROGRAM OLMAYACAKTIR. BU ÖRNEK YALNIZCA GENEL DE‡“KEN KULLANIMINI AÇIKLAMAK AMA-
next_prime ve is_prime fonksiyonlar aslnda cand de§i³kenini parais_prime
bu de§i³kenin de§erinin asal olup olmad§n belirlemek, next_prime
CIYLA VERLM“TR.
metre olarak aktarmak yerine ortak bir bellek gözünde payla³abilirler. Bu durumda
fonksiyonunun i³levi
fonksiyonunun i³leviyse bu de§i³kenin de§erini kendisinden büyük ilk asal sayya ilerletmek
olarak dü³ünülebilir. Benzer ³ekilde, ana fonksiyon da çarpan aday olan sayy parametre aktarmyla almak yerine ayn genel de§i³kende eri³erek ö§renebilir. De§i³iklikler sonucu olu³an
program Örnek 19'de verilmi³tir.
Bir fonksiyon bir genel de§i³kenle ayn isimde bir yerel de§i³ken tanmlarsa o fonksiyonun
çal³mas boyunca yerel de§i³ken genel de§i³keni ezer. Diyelim
is_prime
fonksiyonu
int count, cand;
³eklinde bir de§i³ken tanm yapm³ olsayd, genel olan
yerel olan
cand
de§i³keni olu³urdu ve
is_prime
cand
de§i³keninin yannda bir de
fonksiyonunun içindeyken genel olan
cand
de§i³kenine ula³lamazd.
Genel de§i³kenler parametre aktarm yerine kullanlabilecek bir yöntem olmakla birlikte programn anla³lrl§n azalttklar ve fonksiyonlar birbirlerine ba§ml kldklar için gerekmedikçe kullanlmamalar önerilir. Soyutlamann kazandrdklarndan birinin ileride bir fonksiyonda de§i³iklik yapld§ zaman bunu ça§ran fonksiyonlarn de§i³iklikten etkilenmemesi
oldu§u söylenmi³ti; oysa fonksiyonlarn de§i³ken payla³rlarsa bir fonksiyonda yaplan de§i³iklikler di§er fonksiyonlar etkileyebilir.
6.5
Ba³vuru Aktarm
De§er aktarm yöntemiyle parametre aktarlmas baz i³lemlerde yeterli olmaz. Sözgelimi,
kendisine giri³ parametresi olarak gönderilen iki tamsay de§i³kenin de§erlerini takas eden bir
fonksiyonun Örnek 20'daki gibi yazld§n dü³ünelim.
Bu program çal³trld§nda ekran çkts ³u ³ekilde olur:
111
Fonksiyonlar
Örnek 19 Genel de§i³ken kullanarak bir sayy asal çarpanlarna ayran program.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
int cand = 2;
void next_prime(void);
int main(void)
{
int number;
}
cout << "Sayy yaznz: ";
cin >> number;
while (number > 1) {
while (number % cand == 0) {
cout << cand << " ";
number = number / cand;
}
next_prime();
}
cout << endl;
return EXIT_SUCCESS;
bool is_prime(void)
{
int count;
}
if (cand == 2)
return true;
if (cand % 2 == 0)
return false;
for (count = 3; count * count <= cand; count += 2) {
if (cand % count == 0)
return false;
}
return true;
void next_prime(void)
{
cand = (cand == 2) ? 3 : cand + 2;
while (!is_prime())
cand += 2;
}
112
Ba³vuru Aktarm
Örnek 20 ki sayy takas eden fonksiyon ve kullanm (hatal).
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
void swap(int x, int y)
{
int tmp;
}
tmp = x;
x = y;
y = tmp;
int main(void)
{
int m = 32, n = 154;
}
cout << m << " " << n << endl;
swap(m, n);
cout << m << " " << n << endl;
return EXIT_SUCCESS;
113
Fonksiyonlar
x
swap
y
32
m
main
tmp
154
xxx
n
32
154
(a)
x
swap
y
154
m
main
tmp
32
xxx
n
32
154
(b)
“ekil 6.6: Takas fonksiyonunda parametre aktarm.
32 154
32 154
main fonksiyonundaki m de§i³keninin
de§eri swap fonksiyonundaki x de§i³kenine, n de§i³keninin de§eri de y de§i³kenine aktarlr (“ekil 6.6a). swap fonksiyonunda x ve y de§i³kenlerinin de§erleri takas edilir ancak ça§ran fonksiyondaki m ve n de§i³kenleri bu takastan etkilenmezler ve fonksiyon ça§rsndan dönüldü§ünde
Programn neden istendi§i gibi çal³mad§n inceleyelim:
eski de§erlerini koruyor olurlar (“ekil 6.6b).
Bu sorunun çözümü için yaplmas gereken, ça§rlan fonksiyonda girdi parametrelerini ba³vuru
tipinden tanmlamaktr (bkz. Bölüm 5.5). Böylelikle ça§rlan fonksiyonun girdi parametresi,
ça§ran fonksiyonun gönderdi§i parametreye verilmi³ ikinci bir isim haline gelir ve üstünde
yaplan de§i³iklikler ça§ran fonksiyondaki de§i³keni do§rudan etkiler: Bu parametre aktarm
yöntemine ba³vuru aktarm ad verilir. Bir parametrenin ba³vuru olarak aktarld§n göstermek üzere yaplmas gereken tek ³ey ça§rlan fonksiyondaki girdi parametre de§i³keninin
adnn ba³na
&
simgesi koymaktr. Yani örnekteki tek de§i³iklik
satrnn ³u ³ekle getirilmesi olacaktr:
void swap(int &x, int &y)
Uygulama: Fonksiyonlar
Örnek 21. Kombinasyon Hesab
Bu örnekte
Cnm =
m!
n!(m−n)! de§erinin hesaplanmas istenmektedir.
swap
fonksiyonunun ba³lk
114
Ba³vuru Aktarm
Örnek 21 Kombinasyon hesab (yava³).
#include <iostream.h>
#include <stdlib.h>
// cout,cin
// EXIT_SUCCESS
using namespace std;
int combin(int a, int b);
int fact(int x);
int main(void)
{
int n, r;
}
cout << "n ve r de§erlerini yaznz: ";
cin >> n >> r;
cout << combin(n, r) << endl;
return EXIT_SUCCESS;
int combin(int a, int b)
{
int f1, f2, f3;
}
f1 = fact(a);
f2 = fact(b);
f3 = fact(a - b);
return f1 / (f2 * f3);
int fact(int x)
{
int fx = 1;
int i;
}
for (i = 2; i <= x; i++)
fx = fx * i;
return fx;
115
Fonksiyonlar
Örnek 22 Kombinasyon hesab (hzl).
#include <iostream.h>
#include <stdlib.h>
// cout,cin
// EXIT_SUCCESS
using namespace std;
int combin(int a, int b);
int main(void)
{
int n, r;
}
cout << "n ve r de?erlerini yaz?n?z: ";
cin >> n >> r;
cout << combin(n, r) << endl;
return EXIT_SUCCESS;
int combin(int a, int b)
{
int f1 = 1, f2, f3;
int first = b, second = a - b;
int i;
if (b > a - b) {
first = a - b;
second = b;
}
}
for (i = 2; i <= first; i++)
f1 = f1 * i;
f2 = f1;
for (i = first + 1; i <= second; i++)
f2 = f2 * i;
f3 = f2;
for (i = second + 1; i <= a; i++)
f3 = f3 * i;
return f1 / (f2 * f3);
116
Giri³ Parametreleri Üzerinden De§er Döndürme
Örnek 23. En Büyük Ortak Bölen Bulma
Bölüm 1.4'de anlatlan algoritmalar kullanarak iki saynn en büyük ortak bölenini hesaplayan
bir program yazlmas isteniyor. Bunun için Örnek 18'de bir sayy asal çarpanlarna ayran
programn benzeri bir fonksiyon (factorize) olarak yazlacak ve bu fonksiyon kendisine parametre olarak gönderilen saynn asal çarpanlarn bir dizide olu³turacaktr. Fonksiyon yine
ayn örnekte yazlm³ olan
next_prime
ve
is_prime
fonksiyonlarn hiçbir de§i³iklik olma-
dan kullanacaktr. Asal çarpan dizilerinden en büyük ortak bölenin asal çarpanlarn bulmak
üzere
gcd_factors
fonksiyonu kullanlacak, bu fonksiyonun olu³turdu§u çarpanlar dizisinden
en büyük ortak böleni ana fonksiyon kendisi hesaplayacaktr.
Örnek 23 ki saynn en büyük ortak bölenini bulan program (ana fonksiyon).
int main(void)
{
int number1, number2;
factor_t factors1[MAXFACTOR], factors2[MAXFACTOR], factors3[MAXFACTOR];
int n1, n2, n3;
long int gcd = 1L;
int i;
cout << "Saylar yaznz: ";
cin >> number1 >> number2;
factorize(number1, factors1, n1);
factorize(number2, factors2, n2);
gcd_factors(factors1, n1, factors2, n2,
for (i = 0; i < n3; i++)
gcd = gcd * (long int) pow((double)
(double)
cout << "En büyük ortak bölen: " << gcd
return EXIT_SUCCESS;
}
6.6
factors3, n3);
factors3[i].base,
factors3[i].power);
<< endl;
Giri³ Parametreleri Üzerinden De§er Döndürme
Asal çarpanlara ayrma i³ini yapan
factorize
fonksiyonunun giri³ parametresinin çarpan-
larna ayrlacak say, çk³ parametresinin de çarpanlar dizisi olmas gerekti§i görülmü³tü.
Burada iki sorunla kar³la³lr:
1. C dilinde çk³ parametresi olarak geriye dizi döndürülemez.
2. Dizinin elemanlarn döndürmek yeterli de§ildir, dizide kaç tane geçerli eleman oldu§unu da döndürmek gerekir. Oysa C fonksiyonlar ça§ran fonksiyona birden fazla de§er
döndüremez.
117
Fonksiyonlar
Birden fazla de§erin döndürülmesi gerekti§i durumlarda bu de§erler giri³ parametrelerinde de§i³iklik yapma yöntemiyle ana fonksiyona aktarlabilir. Buna göre,
factorize
fonksiyonunun
i³levi ³öyle açklanabilir:
Birinci giri³ parametresi olarak gönderilen saynn çarpanlarn ikinci giri³ parametresi olan dizide olu³turur ve bu dizinin kaç eleman oldu§unu üçüncü giri³
parametresine yazar. Geriye bir de§er döndürmez.
Buna göre koddaki
factorize(number1, factors1, n1);
fonksiyon ça§rsnn i³levi:
number1 saysn asal çarpanlarna ayr, sonuçlar factors1 dizisinde olu³tur ve bu
dizideki geçerli eleman saysn n1 de§i³kenine yaz.
6.7
Dizilerin Fonksiyonlara Aktarlmas
Bir giri³ parametresinin dizi tipinden oldu§unun belirtilmesi için fonksiyon ba³l§nda de§i³ken
adnn ardna boyut belirtmeden kö³eli ayraçlar konur. Dizi de§i³kenlerinin giri³ parametresi
olarak aktarmlarnda en önemli özellik, aksi belirtilmedikçe dizi elemanlarnn de§i³tirilebilir
olmalardr. Yani dizi elemanlar de§i³tirilmek isteniyorsa dizi de§i³keninin ad oldu§u gibi
yazlr, ba³vuru aktarm kullanlmaz (de§i³ken adnn ba³na
&
i³areti konmaz).
3 Aksine, dizi
elemanlarnn de§er de§i³tirmemesi isteniyorsa önlem almak gerekir. Bu amaçla giri³ parametresi tanm
const
sakl sözcü§üyle ba³latlr.
Örnekte sonuçlarn olu³tu§u
factors1
dizisi ve
n1
de§i³keninin ana fonksiyonun yerel de-
§i³kenleri oldu§una dikkat edilmelidir. Fonksiyon ça§rsndan önce bu de§i³kenlerde herhangi
anlaml bir de§er yer almazken ça§rdan dönüldükten sonra anlaml de§erlerle doldurulmu³
olmalar beklenmektedir. Bu nedenle, yukarda belirtilen yazm kurallarna göre,
factorize
fonksiyonunun ba³l§ ³öyle olmaldr:
void factorize(int number, factor_t factors[], int &n)
biçimindedir. Bu fonksiyonun tam çkts Örnek 24'de verilmi³tir.
Ortak çarpanlar bulan fonksiyon ise iki tane asal çarpan dizisi alacak ve ortak çarpanlardan
bir asal çarpan dizisi olu³turacaktr. Dizilerin eleman saylar da parametre olarak gönderilmesi
gerekti§i için her çarpan dizisi, bir eleman dizisi ve bir eleman says ile gösterilecektir. Buna
göre
3
gcd_factors
fonksiyonunun i³levi ³u ³ekilde yazlabilir:
Bunun nedeni Bölüm 7'de açklanacaktr.
Dizilerin Fonksiyonlara Aktarlmas
Örnek 24
118
ki saynn en büyük ortak bölenini bulan program (asal çarpanlara ayrma fonk-
siyonu).
void factorize(int x, factor_t factors[], int &n)
{
int factor = 2;
}
n = 0;
while (x > 1) {
if (x % factor == 0) {
factors[n].base = factor;
factors[n].power = 0;
while (x % factor == 0) {
factors[n].power++;
x = x / factor;
}
n++;
}
factor = next_prime(factor);
}
Birinci parametrede verilen çarpanlar içeren ve ikinci parametrede verilen sayda
eleman olan çarpan dizisiyle, üçüncü parametrede verilen çarpanlar içeren ve dördüncü parametrede verilen sayda eleman olan çarpan dizilerinden ortak çarpanlar
bulur. Bu dizinin elemanlarn be³inci parametrede verilen dizide olu³turur ve bu
dizinin eleman saysn altnc parametreye yazar. Geriye bir de§er döndürmez.
Bu fonksiyonda ilk dört parametre gerçek anlamda giri³ parametresiyken son iki parametre
aslnda çkt parametresi olup kstlamalar nedeniyle giri³ parametresi olarak gönderilen de§erlerdir Yani ilk dört parametre de§i³meyecek, son iki parametre de§i³ecektir. Buna göre
gcd_factors
fonksiyonunun ba³l§ ³öyle olmaldr:
void gcd_factors(const factor_t factors1[], int n1,
const factor_t factors2[], int n2,
factor_t factors[], int &n);
Burada
const sözcüklerinin kullanlmamas programn do§ru çal³masna etki etmez, yalnzca
programcnn aslnda de§i³memesi gereken bir de§eri yanl³lkla de§i³tirmesine engel olmak
için konmu³tur. Fonksiyonun tanm Örnek 25'de verilmi³tir.
Uygulama: Dizilerin Fonksiyonlara Aktarlmas
Bu uygulamada proler kullanm gösterilecektir (gprof ).
119
Fonksiyonlar
Örnek 25
ki saynn en büyük ortak bölenini bulan program (ortak çarpanlar bulma fonk-
siyonu).
void gcd_factors(const factor_t factors1[], int n1,
const factor_t factors2[], int n2,
factor_t factors[], int &n)
{
int i1 = 0, i2 = 0;
}
n = 0;
while ((i1 < n1) && (i2 < n2)) {
// iki dizi de bitmedi
if (factors1[i1].base < factors2[i2].base)
i1++;
else if (factors1[i1].base > factors2[i2].base)
i2++;
else {
factors[n].base = factors1[i1].base;
if (factors1[i1].power < factors2[i2].power)
factors[n].power = factors1[i1].power;
else
factors[n].power = factors2[i2].power;
i1++;
i2++;
n++;
}
}
120
Dizilerin Fonksiyonlara Aktarlmas
Örnek 26. Newton-Raphson Yöntemiyle Polinom Kökü Bulunmas
f (x) fonksiyonunun kökü, f (x) = 0 ko³ulunu sa§layan x de§eridir. Bu de§ere x
f (x) fonksiyonunun x civarnda Taylor açlmnn ilk iki terimi ³öyle yazlabilir
Bir
dersek
f (x) = f (xi ) + (x − xi )f 0 (xi )
Bu de§er 0 olmas gerekti§inden denklem
f (xi ) + (x − xi )f 0 (xi ) = 0
³ekline getirilebilir ve buradan da
x = xi −
yazlabilir. Bu formülde
x
yerine
xi+1
f (xi )
f 0 (xi )
konursa, fonksiyonun kökü ard³l yerine koyma yön-
temiyle hesaplanabilir. Yani her admda o admdaki
konarak bir sonraki admda kullanlacak
Bu yöntemin
x
x
de§eri formüldeki
xi
de§erinin yerine
de§eri hesaplanr.
p(x) = an xn + an−1 xn−1 + · · · + a1 x + a0
³eklinde
n.
dereceden bir polinoma
uyguland§n varsayalm. O halde yineleme formülü
xi+1 = xi −
p(xi )
p0 (xi )
olacaktr. Bir polinomun hesaplanmasnn içiçe çarpma ve toplama yöntemiyle nasl hzlandrlaca§ Örnek 15'de görülmü³tü. O örnekteki
bde§erleri
bir dizide tutularak hesaplanrsa:
bn = an
bn−1 = bn xi + an−1
b0 = b1 xi + a0
Bu durumda,
p0 (x)
polinomu ³u ³ekilde yazlabilir (Neden?):
p0 (x) = bn xn−1 + bn−1 xn−2 + · · · + b2 x + b1
Bu da bir polinom oldu§undan, hesabnda yine içiçe çarpmlar yöntemi kullanlabilir:
cn = bn
cn−1 = cn xi + bn−1
c1 = c2 xi + b1
Bu yöntemi kullanarak katsaylarn kullancnn girdi§i bir polinomun köklerini hesaplayan
program Örnek 26'de verilmi³tir.
121
Fonksiyonlar
Örnek 26 Polinom kökü hesaplayan fonksiyon.
#include <iostream>
#include <stdlib.h>
#include <math.h>
// cin,cout,endl
// EXIT_SUCCESS
// fabs
using namespace std;
#define MAXDEGREE 50
float newton_raphson(float x, const float a[], int n);
int main(void)
{
float a[MAXDEGREE];
int n, i;
float xi, xj, error;
cout << "Polinomun derecesi: "; cin >> n;
for (i = n; i >= 0; i--) {
cout << "a" << i << ": ";
cin >> a[i];
}
}
cout << "Hata: "; cin >> error;
cout << "x0: "; cin >> xi;
while (true) {
xj = newton_raphson(xi, a, n);
if (fabs(xj - xi) < error)
break;
xi = xj;
}
cout << "Kök: " << xj << endl;
return EXIT_SUCCESS;
float newton_raphson(float x, const float a[], int n)
{
float b[MAXDEGREE], c[MAXDEGREE];
float xn;
int i;
b[n] = a[n];
c[n] = b[n];
for (i = n - 1; i > 0; i--) {
b[i] = b[i+1] * x + a[i];
c[i] = c[i+1] * x + b[i];
}
b[0] = b[1] * x + a[0];
xn = x - b[0] / c[1];
return xn;
122
E³ simli Fonksiyonlar
•
Bu program kullanarak
p(x) = 13x7 − 9x6 + 12x4 − 4x3 + 3x + 5
polinomunun kökünü
x0 = 1
de§erinden ba³layarak,
0.001
hatadan daha küçük olacak
³ekilde bulun.
6.8
E³ simli Fonksiyonlar
C++ dilinde giri³ parametre listeleri farkl oldu§u sürece birden fazla fonksiyonun isimlerinin
ayn olmas bir sorun yaratmaz.
4 Örne§in, iki giri³ parametresini takas eden fonksiyonlarda
swap_int, iki
kesirli sayy takas edecek fonksiyona swap_float, iki katar takas edecek fonksiyona swap_str
isimlerin ayn olmasna izin verilmese iki tamsayy takas edecek fonksiyona
gibi isimler vermek gerekir. Oysa giri³ parametreleri farkl tiplerden oldu§u için üç fonksiyona
da
swap
ad verilebilir:
void swap(int &x, int &y)
{
int tmp;
}
tmp = x;
x = y;
y = tmp;
void swap(float &x, float &y)
{
float tmp;
}
tmp = x;
x = y;
y = tmp;
void swap(char s1[], char s2[])
{
char tmp[MAXSIZE];
}
4
strcpy(tmp, s1);
strcpy(s1, s2);
strcpy(s2, tmp);
C dilinde ayn isimde birden fazla fonksiyon olamaz.
123
Fonksiyonlar
6.9
Varsaylan Parametreler
Fonksiyonlar tanmlanrken istenirse baz giri³ parametrelerine varsaylan de§erler verilebilir.
Varsaylan de§er giri³ parametresi listesinde ilgili de§i³kenden sonra atama komutunda oldu§u
gibi yazlr. Bu durumda, ça§ran fonksiyon o parametre için bir de§er göndermezse varsaylan
de§er kullanlr.
Örne§in bir katar içinde bir simgenin kaçnc srada oldu§unu belirten bir fonksiyon yazalm.
Normal durumda simge katarn ba³ndan ba³lanarak aranr ve simgeye ilk raslanlan konum
belirlenir. Sözgelimi Dennis Ritchie katarnda 'e' simgesinin sra numaras 1'dir. Ancak bazen
de bir noktadan ileriye do§ru arama yapmak istenebilir. Ayn örnek üzerinde ayn simge 4. konumdan ba³lanarak aranrsa sonuç 13 olacaktr. Bu durumda, yazlacak fonksiyonun ba³l§
³öyle olur:
int find_char(char s[], char c, int start);
Üçüncü parametrenin ço§u zaman kullanlmayaca§ndan programclar gerek duymadklar bir
parametreyi göndermek zorunda brakmak yerine varsaylan de§er kullanmak daha esnek bir
çözümdür:
int find_char(char s[], char c, int start = 0)
{
int index = -1, i;
}
Örnekte
for (i = start; s[i] != '\0'; i++) {
if (s[i] == c) {
index = i;
break;
}
}
return index;
start
parametresine 0 varsaylan de§eri verilir. Böylelikle bu de§i³ken, fonksiyon
ça§rlrken belirtilmezse 0 de§erini, belirtilirse verilen de§eri alr. lk iki parametrenin ça§rda
belirtilmesi zorunludur; yani fonksiyon iki ya da üç parametreyle ça§rlabilir:
find_char(Dennis Ritchie, 'e')
find_char(Dennis Ritchie, 'e', 4)
// 1
// 13
Sorular
1. Kendisine parametre olarak gönderilen bir katarda, yine kendisine parametre olarak
gönderilen bir simgenin ilk ve son pozisyonlar arasnda kaç simge oldu§unu bularak
sonucu döndüren bir fonksiyon yazn. Sözgelimi, giri³ katar
124
Varsaylan Parametreler
the world is not enough
ve giri³ simgesi
'o'
ise, fonksiyon 13 de§erini döndürmelidir (rld
is not en).
2. Bir katardaki bir simgenin yerine -o simgenin bulundu§u her noktada- ba³ka bir simge
geçirilmek isteniyor. Örne§in 2002-04-10 katarnda '-' simgesi yerine '/' simgesi konacaksa 2002/04/10 katar elde edilecektir.
(a) Bu i³lemi gerçekle³tiren bir fonksiyon yazn.
(b) Verilen örnek tarih üzerinde bu i³lemi gerçekle³tirmek üzere (a) ³kknda yazd§nz
fonksiyonu kullanan bir ana fonksiyon yazn.
3. ki tamsay dizisindeki ortak elemanlarn says bulunmak isteniyor. Örne§in birinci dizi
21 10 9 13 15, ikinci dizi 10 7 1 13 15 8 ise ortak elemanlarn says 3'tür (10, 13,
15). Örnekten de görülebilece§i gibi, dizilerin ayn sayda elemanlar bulunmas zorunlu
de§ildir. Bunun için:
(a) Bir saynn bir dizide bulunup bulunmad§n snayan bir fonksiyon yazn. Fonksiyonun giri³ parametreleri dizi, dizinin boyu ve aranan say olmaldr. Geriye say
dizide varsa 1, yoksa 0 de§eri döndürülmelidir.
(b) Yukarda yazd§nz fonksiyonu kullanarak, iki dizideki ortak elemanlarn saysn
belirleyen bir fonksiyon yazn. Fonksiyonun giri³ parametreleri her iki dizinin kendileri ve boylar olmaldr. Fonksiyon geriye ortak elemanlarn saysn döndürmelidir.
(c) Yukarda yazd§nz fonksiyonlar kullanarak, boyunu ve elemanlarn kullancdan
ald§ iki dizinin ortak eleman saysn bularak ekrana çkartan bir ana fonksiyon
(main) yazn.
4. Bir dizinin kipi, dizide en çok yinelenen elemandr. Sözgelimi
75 32 45 43 75 66 43 88 66 92 66 27
dizisinin kipi 66'dr. Buna göre, bir snavdaki ö§renci notlarnn kipi bulunmak isteniyor.
(a) Bir dizinin en büyük elemannn dizideki srasn döndüren bir fonksiyon yazn.
(b) Yukarda yazd§nz fonksiyonu kullanarak bir dizinin kipini döndüren bir fonksiyon yazn. (Yol gösterme: Elemanlar ilgili notun kaç kere geçti§ini gösteren 101
elemanl bir tamsay dizisi kullann. Örne§in
counts[55], kaç ö§rencinin 55 ald§n
göstersin.)
(c) Yukarda yazd§nz fonksiyonlar kullanarak, ö§renci saysn ve notlarn kullancdan alarak notlarn kipini bulan ve ekrana çkartan bir ana fonksiyon (main)
yazn.
5. Polar sistemde düzlemde bir nokta kutuptan olan uzakl§n belirten
θ de§erleriyle belirtilir. Ayn noktann kartezyen
x = r · cosθ ve y = r · sinθ e³itlikleri geçerlidir.
yapt§
ise
sistemdeki
r ve kutup eksenine
koordinatlar x ve y
(a) Noktann polar ve kartezyen koordinatlarn temsil etmek üzere birer kayt tanm
yazn.
125
Fonksiyonlar
(b) Yukarda yazd§nz kayt tanmlarn kullanarak, parametre olarak bir noktann polar koordinatlarn alan ve geriye kartezyen koordinatlarn döndüren bir fonksiyon
yazn.
(c) Kayt yaplar kullanmadan polar koordinatlar kartezyen koordinatlara çevirecek
bir fonksiyon yazn.
(d) (b) ve (c) ³klarnda yazd§nz fonksiyonlarn kullanmlarna birer örnek verin.
Varsaylan Parametreler
126
Bölüm 7
³aretçiler
“u ana kadar yaplan örneklerde skalar, bile³ke ya da vektörel tipten olsun, bütün de§i³kenlerin
bellekte kaplayacaklar alan ba³tan belliydi. Sözgelimi, 100 elemanl bir tamsay dizisi tanmlanrsa bu diziye bellekte 100 adet tamsayy tutacak kadar yer ayrlaca§ derleme a³amasnda
biliniyordu. Bu tip de§i³kenlere statik de§i³ken ad verilir. Statik bir de§i³kenin saklanaca§
bellek alan program çal³maya ba³lad§nda ayrlr ve programn sonuna kadar braklmaz. Bu
durumun baz sakncalar vardr:
•
Statik dizilerde görüldü§ü gibi (bkz. Bölüm 5), dizinin eleman says derleme a³amasnda
belli de§ilse gerekebilecek en büyük miktarda yer ayrlmak zorunda kalnr. Örne§in, de§i³ik snardaki ö§rencilerin notlarn tutmak üzere bir tamsay dizisi tanmlanacak
olsun. Bu durumda bir snftaki maksimum ö§renci says konusunda bir varsaym yapp
(diyelim 100) dizi bu boyutta açlmaldr. Verilen bu boyut hem programn bir snrlamas olacak, hem de ö§renci says bunun altnda kald§ zamanlarda gereksiz bellek
harcanmasna yol açacaktr.
•
Programnzda kullanmak istedi§iniz de§i³kenlerin kaplayaca§ toplam bellek alan çal³t§nz bilgisayarda bulunmayabilir. Di§er yandan, bu de§i³kenlerin hepsine birden ayn
anda gereksinim duymuyor olabilirsiniz, yani bir de§i³ken için ayrlan yerin programn
bütün i³leyi³i boyunca tutulmas gerekli olmayabilir. Sözgelimi bir dizi belli bir noktada
kullanlmaya ba³lyor ve bir noktadan sonra da kullanlmyor olabilir. Böyle bir durumda
diziye gerekli oldu§u zaman yer ayrmak, i³i bittikten sonra da ayrlan yeri geri vermek
programn toplam bellek gereksinimlerini azaltr.
³aretçiler, bellekte kaplanacak yerin derleme srasnda de§il çal³ma srasnda belirlenmesini
sa§larlar. Böylelikle gerekti§i zaman gerekti§i kadar yer almak ve gerek kalmad§ zaman
da geri vermek olanakl hale gelir. Bir ³ekilde kullanlan de§i³kenlere dinamik de§i³ken ad
verilir. Dinamik de§i³kenlerin zorlu§u, bellek alanlarnn yönetimi programcya brakld§ndan
programlarn en sk hata yaplan bölümleri olmalardr.
³aretçi, bir bellek gözüne i³aret eden bir de§i³kendir. Bunun anlam, i³aretçi de§i³keninin
o bellek gözünün adresini tutmasdr. Ba³ka bir deyi³le, i³aretçi de§i³keninin de§eri, bellek
gözünün adresidir. Dolaysyla, bir i³aretçi için iki de§erden söz edilebilir:
127
128
•
kendi de§eri: i³aret edilen bellek gözünün adresi
•
i³aret etti§i de§er: i³aret edilen bellek gözünün içeri§i
“ekil 7.1a'da i³aretçi de§i³keniyle i³aret edilen bellek gözü arasndaki ili³ki simgesel olarak
p
gösterilmi³tir. Burada
de§i³keni, içinde
422
yazan bir bellek gözüne i³aret etmektedir. “e-
kil 7.1b, ayn durumun örnek adres de§erleriyle nasl sa§land§n gösterir.
zl oldu§u bellek gözünün adresinin
8000
oldu§u varsaymyla,
ta³d§ görülür. Adres de§erlerinin (bu örnekteki
8000
p
422
de§i³keninin
de§erinin ya-
8000
de§erini
says) ne olduklar programcy ilgi-
lendirmez, bunlar i³letim sistemi belirler. Programc adres de§erlerinin ne olaca§ konusunda
bir varsaymda bulunamaz.
p
p
422
422
8000
12000
8000
(a)
(b)
“ekil 7.1: ³aretçi tipinden de§i³kenler.
³aretçinin i³aret etti§i bellek gözünün içeri§inin okunmas için
örnekte
p
deyiminin de§eri
8000, *p
deyiminin de§eriyse
422'dir.
*
i³leci kullanlr. “ekildeki
³aretçilerle i³lem yaparken,
i³aretçinin kendisiyle mi, yoksa i³aret etti§i alanla m i³lem yapld§na dikkat edilmelidir.
p++
Örne§in
komutu
neden olur. Oysa
422
p
i³aretçisinin bir sonraki (diyelim
8001) bellek gözüne i³aret etmesine
(*p)++ komutu kullanlmaldr.
de§erinin bir artrlmas isteniyorsa
³aretçilerle ilgili i³lemlerde kullanlan di§er bir i³leç de
&
i³lecidir. Adres i³leci ad verilen
bu i³leç, bir de§i³kenin adresinin ö§renilmesini sa§lar. Örnekte
oldu§undan
• &p:
• p:
&p
p
de§i³keninin adresi 12000
deyiminin de§eri 12000'dir. Örnekteki de§erleri toparlarsak:
12000
8000
• *p:
422
³aretçi de§i³kenleri için
NULL
adnda özel bir de§er tanmlanr. Bu de§erin anlam, o i³a-
retçinin geçerli bir bellek gözüne i³aret etmiyor oldu§udur. Dolaysyla, de§eri
i³aretçi de§i³keninin
*
NULL
olan bir
i³leciyle içeri§inin okunmaya çal³lmas derleyicinin farkedemeyece§i
ama çal³ma annda bellek hatasna yol açacak bir programlama hatasdr.
Örnek 27. Dinamik Diziler
Bu bölümdeki program, Örnek 13'de yazlan istatistik programnn aynsdr. Dolaysyla ekran
çkts “ekil 5.1'de verilenle ayndr. Programn i³leyi³indeki tek fark, statik diziler yerine di-
129
³aretçiler
score
NULL
“ekil 7.2: ³aretçi tipinden de§i³ken tanmlama.
namik diziler kullanlmasdr. Böylece snftaki ö§renci says kullancdan ö§renildikten sonra,
tam gerekti§i kadar eleman tutacak bir dizi tanmlanabilmi³tir.
7.1
³aretçi Tipinden De§i³kenler
³aretçiler, de§erleri birer adres (bir tür tamsay) olan de§i³kenlerdir, di§er de§i³ken tiplerinden
bir farklar yoktur. Dolaysyla, di§er de§i³kenlerde oldu§u gibi, i³aretçi tipinden bir de§i³ken
tanmland§nda bellekte bir adres tutmaya yetecek kadar yer ayrlr. ³aretçinin kendi de§eri
her zaman bir adrestir ama i³aret etti§i bellek gözünün nasl yorumlayaca§nn belirtilmesi
gerekir. Bu nedenle, i³aretçi tanm ³u ³ekilde yazlr:
veri_tipi * de§i³ken_ad ;
Bu tanmn anlam, ad verilen de§i³kenin bir i³aretçi oldu§u ve gösterdi§i bellek gözünde belirtilen tipten bir de§er bulunaca§dr. Buradaki
içeri§i anlamna gelen
*
* i³areti, i³aretçinin gösterdi§i bellek gözünün
i³leciyle kar³trlmamaldr. Örnekteki
int *score = NULL;
tanm,
score
de§i³keninin tamsay barndran bir bellek gözüne i³aretçi oldu§unu belirtir
(“ekil 7.2). ³aretçilere ba³langç de§eri olarak genellikle
7.2
NULL
atanr.
Bellek Yönetimi
Programda kullanlacak her türlü bellek bölgesinin kullanlaca§ i³ için ayrlmas gerekti§i
görülmü³tü. Yani i³aretçinin i³aret edece§i bellek alannn da ayrlmas gerekir. Ayrlacak bu
alan tek bir eleman boyunda olabilece§i gibi, birden fazla elemandan olu³an bir dizi olarak da
kullanlabilir. Dinamik dizi kullanrken i³aretçi tanmnda belirtilen veri tipi dizinin her bir
elemannn tipi olarak dü³ünülebilir.
Yer ayrma i³lemini gerçekle³tiren
new
i³leci istenen büyüklükte, birbirini izleyen gözlerden
olu³an bir bellek alann ayrarak ba³langç adresini verir. Yer alma giri³imi ba³arszlkla
sonuçlanrsa, örne§in bellekte yer kalmadysa, geriye NULL de§erini döndürür. Yazm ³u
³ekildedir:
new veri_tipi [eleman_says ]
130
Bellek Yönetimi
Örnek 27 Örnek 13'in dinamik dizilerle gerçeklenmesi.
#include <iostream>
#include <stdlib.h>
#include <math.h>
// cin,cout,endl
// EXIT_SUCCESS
// fabs,sqrt
using namespace std;
int main(void)
{
int *score = NULL;
int no_students = 0;
float mean, variance, std_dev, abs_dev;
float total = 0.0, sqr_total = 0.0, abs_total = 0.0;
int i = 0;
}
cout << "Kaç ö§renci var? ";
cin >> no_students;
score = new int[no_students];
for (i = 0; i < no_students; i++) {
cout << i + 1 << ". ö§rencinin notu: ";
cin >> score[i];
total = total + score[i];
}
mean = total / no_students;
for (i = 0; i < no_students; i++) {
sqr_total = sqr_total + (score[i] - mean) * (score[i] - mean);
abs_total = abs_total + fabs(score[i] - mean);
}
variance = sqr_total / (no_students - 1);
std_dev = sqrt(variance);
abs_dev = abs_total / no_students;
cout << "Ortalama: " << mean << endl;
cout << "Varyans: " << variance << endl;
cout << "Standart sapma: " << std_dev << endl;
cout << "Mutlak sapma: " << abs_dev << endl;
delete score;
return EXIT_SUCCESS;
131
³aretçiler
score
no_students*sizeof(int)
6500
6500
“ekil 7.3: Yer ayrlmasndan sonraki durum.
Örnekte ö§renci notlarn tutacak dizi için
score = new int[no_students];
komutuyla yer alnm³tr. Bu komut sonucunda bellekte
lk bir alan ayrlr ve bu alann ba³langç adresi
score
no_students * sizeof(int)
kadar-
i³aretçisine atanr (“ekil 7.3).
Tek bir elemanlk bölge ayrlacaksa eleman saysnn belirtilmesine gerek yoktur. Örne§in,
“ekil 7.1'de çizilen durum ³u komutlarla yaratlabilir:
int *p = NULL;
p = new int;
*p = 422;
// 8000 oldu§u varsaylyor
Ayrlan yerin geri verilmesi
delete i³leciyle gerçeklenir. Bu i³leç, bir i³aretçi için alnan bütün
bölgeyi geri verir; bölgenin bir ksmn geri vermek gibi bir seçenek yoktur. Bu nedenle, i³lece
yalnzca i³aretçinin adn vermek yeterlidir, geri verilecek eleman says yeniden belirtilmez.
Yukarda yazlan her iki (birden fazla eleman ya da bir eleman) yer ayrma i³leminin de geri
vermesi benzer ³ekildedir:
delete score;
delete p;
³aretçi tipinden de§i³kenler için her zaman yer ayrlmas zorunlulu§u yoktur. Zorunlu olan DKKAT
nokta, i³aretçilerin her zaman geçerli bellek gözlerine i³aret etmeleridir. Bu bellek gözleri
örneklerde oldu§u gibi dinamik olarak ayrlm³ olabilecekleri gibi, ba³ka bir i³aretçi de§i³keni
tarafndan ayrlm³ ve hatta statik olarak tanmlanm³ bile olabilirler. Örne§in “ekil 7.1'de
çizilen durum ³u komutlarla da yaratlabilirdi:
int x = 422;
int *p = &x;
Bu durumda 422 de§erini tutan bellek gözüne programn ba³nda statik olarak yer ayrlr;
i³aretçisi ise bu bellek gözünün adresini ta³r. Önemli olan
x
ile
*p
p
de§i³kenlerinin ayn bellek
gözünde bulunduklarnn ve birinin de§i³mesiyle öbürünün de de§i³ece§inin gözönünde bulundurulmasdr. Örnekte
p
de§i³keni için yer ayrlmad§ndan burann
de sözkonusu de§ildir; böyle bir deneme hataya neden olacaktr.
delete
ile geri verilmesi
132
³aretçi - Dizi li³kisi
Bellek yönetimi için
new ve delete i³leçleri C++ dilinde getirilmi³ yeniliklerdir. C dilinde ayn
malloc ve free fonksiyonlarn kullanmak gerekir. Buna göre örnekteki
i³lemleri yapmak için
programn ilgili satrlar ³u ³ekilde de§i³tirilebilir
score = (int *) malloc(no_students * sizeof(int));
...
free(score);
malloc
fonksiyonu
new
i³leciyle ayn ³ekilde yer ayrr. Aralarndaki yazm farklar ³u ³ekilde
açklanabilir:
1.
new
i³lecinde eleman tipi ve says belirtilir,
malloc
fonksiyonunda ise ayrlacak alann
boyunu sekizli cinsinden vermek gerekir.
2.
malloc
fonksiyonu geriye
void *
tipinden bir de§er döndürür (ham i³aretçi). Bu de§er
de§i³kene atanrken uygun ³ekilde tip dönü³ümü yaplmas gerekir.
3.
malloc ve free birer fonksiyon olduklarndan parametrelerinin ayraçlar içinde yazlmas
gerekir. Ayn nedenle, kullanlabilmeleri için bir ba³lk dosyasnn (stdlib.h) alnmas
gerekir.
7.3
³aretçi - Dizi li³kisi
Statik diziler ile dinamik diziler arasndaki tek fark olu³turulmalarndadr, elemanlara eri³im
her ikisinde de ayndr. Yani ³u iki tanm arasnda, bellekte olu³an durum açsndan bir fark
yoktur:
int p[10];
...
for (i = 0; i < 10; i++)
...p[i]...
...
int *p;
p = new int[10];
...
for (i = 0; i < 10; i++)
...p[i]...
...
delete p;
Statik dizilerle dinamik dizilerin ayn ³ekilde kullanlabilmeleri iki özelli§e dayanr:
1. Statik bir dizinin ad, dizinin ilk elemanna bir i³aretçidir.
2. ³aretçinin de§eri bir sayyla toplanrsa, i³aretçinin gösterdi§i adresten i³aret edilen tipten o say kadar ilerlenerek gelinen bellek gözünün adresi elde edilir. Benzer ³ekilde,
çkartma i³leminde bu miktar kadar geriye gidilir.
Bu özellikler nedeniyle, i³aretçinin tipi ne olursa olsun, a³a§daki deyimler e³de§erlidir:
p[0]
p[1]
p[n]
*p
*(p + 1)
*(p + n)
133
³aretçiler
Katarlar da birer dizi olduklarndan katarlar arasndaki atama ve kar³la³trma gibi i³lemlerin neden beklendi§i gibi çal³mayacaklarna tekrar dönelim. “ekil 7.4'deki yapda
str2
de§i³kenleri kar³la³trlrsa (str1
== str2),
str1
ile
kar³la³trma sonucu yanl³ de§eri üretilir
(32006=9450).
str1
3200
"Dennis Ritchie"
3200
str2
9450
"Dennis Ritchie"
9450
“ekil 7.4: Katarlarn kar³la³trlmas.
Benzer ³ekilde, ayn örnekte
str1 = str2
atamas
str1
i³aretçisinin
str2
i³aretçisiyle ayn
de§eri almas sonucunu do§urur (“ekil 7.5). Bu durum ayn katarn iki farkl kopyasnn olu³masn sa§lamad§ gibi
str1
katarnn önceki i³aret etti§i bellek bölgesinin (Dennis Ritchie
de§erinin bulundu§u bölge) de yitirilmesine yol açar.
Örnek 28. Morse Kodlamas
Kullancdan ald§ bir sözcü§ü Morse abecesinde kodlayan bir program yazlmas isteniyor.
Programn örnek bir çal³masnn ekran çkts “ekil 7.6'da verilmi³tir.
7.4
³aretçi Tipinden Parametreler
Dizilerin fonksiyonlara parametre olarak aktarlmalarnda statik ya da dinamik gösterilimler
arasnda bir fark yoktur. Sözgelimi, Örnek 24'de yazlan asal çarpanlarna ayrma fonksiyonunun bildirimi için ³u ikisi e³de§erlidir:
void factorize(int number, factor_t factors[], int &n);
void factorize(int number, factor_t *factors, int &n);
str1
9450
"Dennis Ritchie"
3200
str2
9450
"Ken Thompson"
9450
(b)
“ekil 7.5: Katarlarn atanmas.
134
³aretçi Tipinden Parametreler
Örnek 28 Morse kodlamas yapan program.
#include
#include
#include
#include
<iostream>
<stdlib.h>
<stdio.h>
<string.h>
//
//
//
//
cin,cout,endl
EXIT_SUCCESS
gets
strcat
using namespace std;
#define MAXLENGTH 80
char *encode(const char *s);
int main(void)
{
char word[MAXLENGTH];
char *morse = NULL;
}
cout << "Sözcü§ü yaznz: ";
cin >> word;
morse = encode(word);
cout << "Morse kar³l§: " << morse << endl;
delete morse;
return EXIT_SUCCESS;
char *encode(const char *s)
{
static char encoding[][5] =
{ ".-", "-...", "-.-.", "-..",
"....", "..",
".---", "-.-",
"---", ".--.", "--.-", ".-.",
"...-", ".--", "-..-", "-.--",
char *morse = new char[MAXLENGTH];
int i;
}
".",
"..-.", "--.",
".-..", "--", "-.",
"...", "-",
"..-",
"--.." };
morse[0] = '\0';
for (i = 0; s[i] != '\0'; i++) {
strcat(morse, encoding[s[i] - 'a']);
strcat(morse, " ");
}
return morse;
135
³aretçiler
Sözcü§ü yaznz: istanbul
Morse kar³l§: .. ... - .- -. -... ..- .-..
“ekil 7.6: Örnek 28 ekran çkts.
Fonksiyonun ba³lk satrnda bu iki gösterilimden herhangi biri kullanlabilir, fonksiyonun
gövdesinde bir de§i³iklik yapmak gerekmez.
³aretçiler, dizilerin çkt parametresi olarak döndürülememesi kstlamasn da çözerler. Statik
bir dizi bir bütün halinde (bütün elemanlarnn kopyas olu³turularak) çkt parametresi olarak
döndürülemez ancak dizinin ba³na bir i³aretçi döndürülebilir. Örnekte bu özellik kullanlarak
encode
fonksiyonu
char *encode(const char *s);
³eklinde bildirilmi³tir. Bunun anlam, bu fonksiyonun de§i³tirilmeyecek bir katar ald§ ve üretti§i katar geri döndürdü§üdür. Fonksiyonun gövdesinde tanmlanan
m³ sözcü§ü tutar ve fonksiyon sonunda
morse de§i³keni, kodlan-
ile geri döndürülür.
encode fonksiyonunun, geri
verme i³iniyse main fonksiyonunun yapmasdr. Geri verme i³lemi yine encode fonksiyonunca
yaplamaz çünkü katarn i³i henüz sona ermemi³tir. Benzer ³ekilde morse de§i³keni encode
fonksiyonunda statik olarak da (char morse[MAXLENGTH] ³eklinde) tanmlanamaz çünkü böyle
Burada önemli olan bir nokta,
morse
return
katar için yer ayrma i³ini
tanmland§nda bu bir yerel de§i³ken olaca§ndan fonksiyonun sona ermesiyle onun için ayrlm³ olan bellek geri verilir ve sonuç ana fonksiyona aktarlamaz.
7.5
Statik De§i³kenler
Örnekte
encode
fonksiyonunda tanmlanan
encoding
dizisi bu fonksiyonun bir yerel de§i³ke-
nidir, yani fonksiyonun her yaratl³nda bu dizi yeniden yaratlr, elemanlarna de§erler verilir
ve fonksiyonun sona ermesiyle yok edilir. Bu i³lemin her defasnda tekrar tekrar yaplmas
istenmiyorsa,
encoding
de§i³keni genel bir de§i³ken olarak tanmlanabilir:
char encoding[][5] = { ... };
int main(void)
{
...
}
char *encode(char *word)
{
...
}
136
Adres Aktarm
encoding de§i³keninin gereksiz
main fonksiyonundan da eri³ilebilir hale gelmesine yol açar. Daha düzgün bir çözüm,
encoding de§i³kenini encode fonksiyonunun içinde statik olarak tanmlanamaktr:
Genel de§i³ken tanmlamak sözü edilen sakncay giderir ama
yere
static char encoding[][5] = { ... };
Böyle yapld§nda
encoding dizisi genel bir de§i³ken gibi sürekli ya³ar ama encode fonksiyonu
d³nda kullanlamaz.
7.6
Adres Aktarm
Ba³vuru aktarm yöntemi C++ dilinde gelmi³ oldu§undan C dilinde bunun yerine adres aktarm yöntemi kullanlr, yani ça§rlan fonksiyona de§i³kenin adresi yollanr. Ça§rlan fonksiyon
bu adresi i³aretçi tipinden bir de§i³kene alr ve bu i³aretçinin gösterdi§i yerde de§i³ikli§i yapar.
Böylece de§i³iklik ça§ran fonksiyondaki de§i³keni do§rudan etkiler. Buna göre, Örnek 20'da
anlatlan ve düzeltilen
swap
fonksiyonu yöntemi Örnek 29'de oldu§u gibi de gerçeklenebilirdi:
Örnek 29 ki sayy adres aktarmyla takas eden fonksiyon ve kullanm.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
void swap(int *x, int *y)
{
int tmp;
}
tmp = *x;
*x = *y;
*y = tmp;
int main(void)
{
int m = 32, n = 154;
}
cout << m << " " << n << endl;
swap(&m, &n);
cout << m << " " << n << endl;
return EXIT_SUCCESS;
Bu örnekte
m
x
de§i³keni tamsayya i³aretçi (yani adres) tipinden bir de§i³ken olurdu ve de§eri
de§i³keninin adresi olurdu. Yani
yazlm³ olurdu (“ekil 7.7).
x
i³aretçisinin gösterdi§i yere yazlan de§er
m
de§i³kenine
137
³aretçiler
x
swap
y
2000
m
main
tmp
2004
xxx
n
32
2000
154
2004
(a)
x
swap
y
2000
m
main
tmp
2004
xxx
n
154
2000
32
2004
(b)
“ekil 7.7: Takas fonksiyonunda parametre aktarm.
Günümüzde neredeyse bütün C geli³tirme ortamlarnda C++ yetenekleri bulundu§undan,
giri³ parametrelerinde de§i³iklik yapmak istendi§inde adres aktarm yöntemini kullanmann
artk bir gere§i yoktur. Adres aktarm programc hatalarna daha elveri³li oldu§undan ancak
derleyiciniz C++ desteklemiyorsa ya da probleminiz açsndan daha uygunsa kullanmanz
önerilir.
Uygulama: ³aretçiler
Örnek 30. Seçerek Sralama
Kullancdan ald§ say kadar ö§rencisi olan bir snfta kullancnn girdi§i ö§renci notlarnn
ortade§erini bulan bir program yazlmas isteniyor. Bir dizinin ortade§eri, dizi sraland§nda
dizinin ortasnda yer alan de§erdir. Çift sayda eleman olan dizilerde dizinin ortasnda bir
eleman olmad§ndan ortadaki iki elemann aritmetik ortalamas ortade§er kabul edilir.
Dizinin ortade§erini bulmak için öncelikle diziyi sralamak gerekir. Örnekte kullanlan seçerek sralama yöntemi, en basit sralama algoritmalarndan biridir. Bu yöntemde, küçükten
büyü§e do§ru sralama yaplaca§ varsaymyla, bu algoritmann her admnda dizinin en büyük eleman bulunur ve sondaki elemanla yeri kar³lkl de§i³tirilir. Böylece en büyük eleman
en sona alnr ve dizinin boyu bir azaltlarak i³leme devam edilir.
geçen i³lem
n−1
n
elemanl bir dizide sözü
kere yinelenecektir. Örnek bir dizi üzerinde seçerek sralama algoritmasnn
çal³mas “ekil 7.8'de verilmi³tir.
•
Sralama i³lemini kabarck sralama algoritmas kullanacak ³ekilde düzenleyin.
138
Adres Aktarm
Örnek 30 Ö§renci notlarnn ortade§erini bulan program.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
void selsort(int *numbers, int count);
int main(void)
{
int *score = NULL;
float median;
int no_students, i;
cout << "Ö§renci says: ";
cin >> no_students;
score = new int[no_students];
for (i = 0; i < no_students; i++) {
cout << i + 1 << ". ö§rencinin notu: ";
cin >> score[i];
}
selsort(score, no_students);
median = (no_students % 2 == 1) ? score[no_students/2] :
(score[no_students/2] + score[no_students/2-1]) / 2.0;
cout << "Orta de§er: " << median << endl;
}
delete score;
return EXIT_SUCCESS;
void selsort(int *numbers, int count)
{
int round, max, i;
int tmp;
}
for (round = 0; round < count - 1; round++) {
max = 0;
for (i = 1; i < count - round; i++) {
if (numbers[max] < numbers[i])
max = i;
}
tmp = numbers[max];
numbers[max] = numbers[count - 1 - round];
numbers[count - 1 - round] = tmp;
}
139
³aretçiler
4
5
1
3
2
4
2
1
3
5
3
2
1
4
5
1
2
3
4
5
1
2
3
4
5
“ekil 7.8: Seçerek sralama örne§i.
Adres Aktarm
140
Sorular
1. Sezar ³ifrelemesi yönteminde ³ifrelenecek sözcükteki her harn yerine (ngilizce) abecede
kendisinden 3 sonra gelen harf konur (A yerine D, B yerine E, ..., V yerine Y, W yerine
Z, X yerine A, Y yerine B, Z yerine C). Buna göre HUNGRY sözcü§ünün kar³l§
KXQJUB olur.
(a) Bildirimi a³a§da verildi§i ³ekliyle bir sözcük alan ve bunun ³ifrelenmesi sonucu
olu³an yeni katar döndüren bir fonksiyon yazn:
char *caesar(const char s[]);
(b) Kullancdan ald§ bir sözcü§ü yukardaki fonksiyon yardmyla ³ifreleyen ve sonucu
ekrana yazan bir ana fonksiyon yazn.
(c) (a) ³kknda yazd§nz fonksiyonu öteleme miktar da bir parametre olacak ³ekilde
genelle³tirin ve (b) ³kknda yazd§nz fonksiyonu da uygun biçimde düzenleyin.
2. ngilizce'de 'q' harnden sonra ço§u zaman 'u' har gelir. Buna göre kendisine parametre
olarak gönderilen katarda 'q' harnden sonra 'u' har geliyorsa 'u' harni silen bir fonksiyon yazn. Sözgelimi, fonksiyona you must be quick katar parametre olarak gelirse
bu fonksiyon katar you must be qick diye de§i³tirmelidir (yeni bir katar üretmiyor,
geriye bir de§er döndürmüyor). Bu fonksiyonu denemek üzere bir ana fonksiyon yazn.
Bölüm 8
Giri³-Çk³
Bu bölümde öncelikle giri³-çk³ kitapl§ndaki fonksiyonlar kullanarak giri³-çk³ i³lemlerinin
nasl yapld§ gösterilecektir. Daha sonra dosyalar üzerinde okuma-yazma i³lemlerinin nasl
yapld§ anlatlacaktr.
8.1
Çk³
C dilinde
cout
birimi yoktur. Bunun yerine
printf
fonksiyonu kullanlr. Bu fonksiyonun
yaps ³u ³ekildedir:
printf(biçim katar, deyim1, deyim2, deyim3, ...);
Biçim katarnn temel i³levi yazdrlmas istenen iletileri belirtmektir. Sözgelimi:
cout < < Merhaba dünya! < < endl;
komutunun C'deki kar³l§ ³öyledir:
printf(Merhaba dünya!\n);
Bu örnekte ekrana herhangi bir de§i³ken ya da deyim de§eri yazdrlmamakta, yalnzca bir ileti
görüntülenmektedir. Katarn sonundaki
sa§lar (C++'daki
endl
'\n' simgesi katar sona erdi§inde alt satra geçilmesini
kar³l§).
Bir deyim de§erinin ekranda gösterilmesi isteniyorsa bu de§erin tipi de biçim katarnda belirtilmelidir. Her veri tipinin kendine özgü bir belirteci vardr. (bkz. Tablo 8.1).
Buna göre Örnek 1'de geçen
cout < < Alan: < < area < < endl;
komutunun kar³l§ ³u ³ekilde olur:
141
142
Çk³
Veri Tipi
Belirteç
Onlu düzende tamsay
Onlu düzende uzun tamsay
Onaltl düzende tamsay
Noktal gösterilimde kesirli say
Bilimsel gösterilimde kesirli say
Simge
Katar
%d
%ld
%x
%f
%e
%c
%s
Tablo 8.1: Biçim belirteçleri.
printf(Alan: %f\n, area);
Çktnn nasl olu³turulaca§n biçim katar belirler. Belirteçler d³nda kalan bölümler oldu§u
gibi çk³a aktarlr; bir belirteç ile kar³la³ld§nda deyim listesinde sradaki deyim hesaplanarak elde edilen de§er çk³a aktarlr. Dolaysyla, biçim katarnda geçen belirteçler ile deyim
listesindeki deyimlerin say ve tiplerinin birbirini tutmas gerekir.
Örnek. radius
de§i³keninin kesirli say tipinden oldu§u ve kullancnn giri³ srasnda
2.4
de§erini yazd§ varsaymyla
printf(Yarçap %f olan dairenin alan: %f\n,
radius, 3.14 * radius * radius);
fonksiyonunun i³leyi³i ³u ³ekilde olur:
•
Biçim katarnda ilk
% i³aretine kadar görülen her simge ekrana çkartlr (belirteçten
Yarçap önceki bo³luk dahil):
•
Biçim katarndan sonraki ilk deyimin de§eri kesirli say biçiminde ekrana çkartlr
(önce ve sonraki bo³luklar hariç):
•
2.4
Bir sonraki belirtece kadar görülen her simge ekrana çkartlr:
alan: •
olan dairenin
Biçim katarndan sonraki ikinci deyimin de§eri kesirli say biçiminde ekrana çkartlr:
• \n
18.07
simgesi nedeniyle sonraki satra geçilir.
Yüzde ve ters bölü i³aretleri biçim katarnda özel anlam ta³dklarndan bunlarn çk³a gönderilmesi istendi§inde özel bir yazm gerekir. Yüzde i³aretini çkarmak için '%%', ters bölü i³aretini
çkarmak içinse '\\' simgeleri kullanlmaldr.
Biçim katar de§i³ken de§erlerinin çk³a gönderilmesinde ayrntl denetim olana§ da sa§lar.
Örne§in say de§erlerinin belli bir uzunlukta olmas sa§lanabilir. %5d ³eklinde belirtilen
bir tamsay de§eri be³ haneliyse bo³luksuz, dört haneliyse bir bo³luk ve say, üç haneliyse
iki bo³luk ve say v.b. ³eklinde de§erlendirilerek çk³a gönderilir. Bu yöntem düzgün ³ekilde
altalta gelmi³ çktlar olu³turmak için yararldr. Kesirli saylarda da noktadan önce ve sonra
143
Giri³-Çk³
kaç hane bulundu§u belirtilebilir. Sözgelimi %20.12f belirteci saynn toplam 20 hane (nokta
dahil) yer tutaca§n ve bunun 12 hanesinin noktadan sonra olaca§n gösterir.
DÜZELT: daha fazla ayrnt
8.2
Giri³
Çk³ biriminde oldu§u gibi, C dilinde giri³ için kullanlabilecek
yerine
scanf
cin
birimi de yoktur. Bunun
fonksiyonu kullanlr. Bu fonksiyonun yaps ³u ³ekildedir:
scanf(biçim katar, &de§i³ken1, &de§i³ken2, &de§i³ken3, ...);
Biçim katar,
printf
fonksiyonundakine benzer bir i³lev görür ve okunacak de§erlerin tipinin
ne olaca§n belirler. Kullanlan veri tipi belirteçleri de ayndr.
Giri³ yaplrken kullancnn yazd§ de§erin alnaca§ de§i³ken
scanf
fonksiyonunda de§er
de§i³tirece§inden fonksiyona bu de§i³kenin adresi gönderilir (bkz. Bölüm 7.6). Bu nedenle,
scanf fonksiyonuna gönderilen de§i³kenlerin adlarnn ba³na adres i³leci olan & simgesi konur.
Örne§in
cin > > radius;
komutunun C dilindeki kar³l§ ³u ³ekildedir:
scanf(%d, &radius);
Katar tipinden olan de§i³kenlerde katarlar bir dizi olduklarndan ve adlar zaten dizinin ilk elemanna bir i³aretçi oldu§undan
katar tipinden bir
word
& simgesi kullanlmaz. Sözgelimi, kullancnn yazd§ sözcü§ü
de§i³kenine almak için a³a§daki komut kullanlr:
scanf(%s, word);
Örnek 31. statistik Hesaplar
Bu örnekte, Örnek 13'de yaplan ö§renci notlar üzerindeki istatistik hesaplar dosyalar yardmyla gerçeklenecektir. Ö§renci notlar bir dosyadan okunacak, i³lem sonuçlar da yine bir dosyaya yazlacaktr. Notlarn hangi dosyadan okunaca§ ve sonuçlarn hangi dosyaya yazlaca§
program çal³trlrken komut satrndan belirtilecek, böylelikle program çal³mas srasnda
kullancya hiçbir ³ey sormayacak, üretti§i hiçbir sonucu da ekranda göstermeyecektir. Bu
programn yazl oldu§u dosya
dosyann ad
stat3
stat3.cpp ve derleme ile ba§lama sonucu olu³an çal³trlabilir
olursa program
stat3 notlar.txt sonuclar.txt
gibi bir komutla ça§rlmaldr. Burada ilk belirtilen isim (örnekte
dosyay, ikinci isim (örnekte
notlar.txt)
okunacak
sonuclar.txt) sonuçlarn yazlaca§ dosyay gösterir ve herhangi
birinin eksik olmas durumunda program nasl çal³trlmas gerekti§ine ili³kin bir kullanm
iletisi görüntüler.
144
Giri³
Örnek 31 Dosyalar ile giri³/çk³ i³lemleri yaparak ö§renci notlar üzerinde istatistik hesaplar
yapan program (okuma bölümü).
#include
#include
#include
#include
<iostream>
<stdio.h>
<stdlib.h>
<math.h>
//
//
//
//
cin,cout,cerr,endl
fopen,fclose,fprintf,fscanf,feof
exit,EXIT_SUCCESS,EXIT_FAILURE
fabs,sqrt
using namespace std;
#define MAXSTUDENTS 100
int main(int argc, char *argv[])
{
int score[MAXSTUDENTS];
int no_students = 0;
float mean, variance, std_dev, abs_dev;
float total = 0.0, sqr_total = 0.0, abs_total = 0.0;
int i = 0;
FILE *infile, *outfile;
if (argc != 3) {
cout << "Kullanm: " << argv[0]
<< " giri³_dosyas çk³_dosyas" << endl;
return EXIT_FAILURE;
}
infile = fopen(argv[1], "r");
if (infile == NULL) {
cerr << "Giri³ dosyas açlamad." << endl;
exit(EXIT_FAILURE);
}
no_students = 0;
while (true) {
fscanf(infile, "%d", &score[no_students]);
if (feof(infile))
break;
total = total + score[no_students];
no_students++;
}
fclose(infile);
...
}
return EXIT_SUCCESS;
145
Giri³-Çk³
Örnek 32 Dosyalar ile giri³/çk³ i³lemleri yaparak ö§renci notlar üzerinde istatistik hesaplar
yapan program (yazma bölümü).
#include
#include
#include
#include
<iostream>
<stdio.h>
<stdlib.h>
<math.h>
//
//
//
//
cin,cout,cerr,endl
fopen,fclose,fprintf,fscanf,feof
exit,EXIT_SUCCESS,EXIT_FAILURE
fabs,sqrt
using namespace std;
#define MAXSTUDENTS 100
int main(int argc, char *argv[])
{
int score[MAXSTUDENTS];
int no_students = 0;
float mean, variance, std_dev, abs_dev;
float total = 0.0, sqr_total = 0.0, abs_total = 0.0;
int i = 0;
FILE *infile, *outfile;
...
mean = total / no_students;
for (i = 0; i < no_students; i++) {
sqr_total = sqr_total + (score[i] - mean) * (score[i] - mean);
abs_total = abs_total + fabs(score[i] - mean);
}
variance = sqr_total / (no_students - 1);
std_dev = sqrt(variance);
abs_dev = abs_total / no_students;
outfile = fopen(argv[2], "w");
if (outfile == NULL) {
cerr << "Çk³ dosyas açlamad." << endl;
exit(EXIT_FAILURE);
}
fprintf(outfile,
fprintf(outfile,
fprintf(outfile,
fprintf(outfile,
fprintf(outfile,
"Ö§renci says: %d\n", no_students);
"Ortalama: %f\n", mean);
"Varyans: %f\n", variance);
"Standart sapma: %f\n", std_dev);
"Mutlak sapma: %f\n", abs_dev);
fclose(outfile);
}
return EXIT_SUCCESS;
146
Ana Fonksiyona Parametre Aktarma
8.3
Ana Fonksiyona Parametre Aktarma
Ana fonksiyon da di§er fonksiyonlar gibi bir fonksiyon olmakla birlikte giri³ ve çk³ parametrelerinin aktarm bakmndan farkllk gösterir. Bir fonksiyonun giri³ parametreleri almas ve çk³ parametresi döndürmesi, o fonksiyonun ça§rlabilmesi anlamna gelir. Oysa ana fonksiyon
çal³mann ba³lad§ fonksiyon oldu§undan di§er fonksiyonlarca ça§rlmaz. Ana fonksiyonu
ça§ran i³letim sistemidir, yani ana fonksiyonun ça§rlmas programn i³letim sistemince yürütülmeye ba³lanmasna kar³ dü³er. Bu durumda ana fonksiyon giri³ parametrelerini i³letim
sisteminden alr, çk³ parametresini de i³letim sistemine döndürür.
Ana fonksiyonun çk³ parametresinin nasl belirtildi§i ³u ana kadarki bütün örneklerde görülmü³tü. Bu parametre programn çal³mas sonucu olu³an durumun i³letim sistemine bildirilmesi anlamn ta³r ve ba³ar durumunda
return EXIT_SUCCESS;
ba³arszlk durumunda
return EXIT_FAILURE;
komutlaryla belirtilir.
Ana fonksiyonun giri³ parametreleriyse kullancnn program çal³trrken belirtti§i parametrelerdir. Giri³ parametrelerinin okunabilmesi için ana fonksiyonun giri³ parametresi listesi
int argc, char *argv[]
³eklinde verilir. Burada
argc
parametre saysn,
argv
ise parametre dizisini gösterir. Para-
metre dizisinin her bir eleman, ba³lktan da görülebilece§i gibi, bir katardr.
Programn ad da parametreler arasnda sayld§ndan parametre says en az 1 olabilir. Yani
argc
de§i³keni program yalnzca
stat3
komutuyla ça§rlrsa 1, yukarda verilen ³ekilde ça§-
rlrsa 3 de§erini alr. Parametre de§erleri de
argv
dizisinin elemanlarn olu³tururlar. Yine
örnek üzerinden gidersek:
argv[0] = stat3
argv[1] = notlar.txt
argv[2] = sonuclar.txt
Örnekteki
if (argc != 3)
komutu programn do§ru sayda parametreyle çal³trlp çal³trlmad§n snamak için konmu³tur. Parametre saysnn hatal oldu§u durumda programn ekrana bir kullanm iletisi
basp sonlanmasn sa§lar.
Bütün giri³ parametrelerinin birer katar oldu§una dikkat edilmelidir. Komut satrndan verilen
de§erlerin say olarak kullanlabilmesi için uygun kitaplk fonksiyonlaryla (tamsaylar için
atoi,
kesirli saylar için
atof)
sayya çevrilmeleri gerekir.
147
Giri³-Çk³
8.4
Dosyalar
Dosyalar üzerinde i³lem yapmak için öncelikle dosyay programda temsil edecek bir de§i³ken
tanmlanmaldr. C dilinde bu de§i³ken dosya i³aretçisi olarak adlandrlr ve
FILE * tipinden
tanmlanr. Örnekte biri giri³ dosyasn (infile) di§eri de çk³ dosyasn (outfile) temsil
etmek üzere iki dosya i³aretçisi tanmlanm³tr. Dosya i³aretçisi sradaki okuma ya da yazma
i³leminin dosya üzerinde hangi noktada yaplaca§n belirler ve yaplan her i³lemle ileri ya da
geri do§ru hareket eder.
8.4.1
Dosya Açma - Kapama
Bir dosya üzerinde i³lem yapmadan önce ilk yaplmas gereken dosyann açlmasdr. Açma
i³lemi bildirimi a³a§da verilmi³ olan
fopen
fonksiyonu yardmyla yaplr:
FILE *fopen(const char *path, const char *mode );
Fonksiyon ba³l§nda görülen
path
parametresi, açlacak dosyann sistemdeki tam adnn be-
lirtilmesini sa§lar. kinci parametre olan
mode ise dosya üzerinde ne i³lem yaplmas istendi§ini
belirtmeye yarar. Bu parametre için verilebilecek örnek de§erler ³öyledir:
• r :
dosya yalnzca okunacak (dosya varsa sfrlanmaz, yoksa yaratlmaz)
• w :
dosyaya yalnzca yazlacak (dosya varsa sfrlanr, yoksa yaratlr)
• r+ :
dosyada hem okuma hem yazma yaplacak (dosya varsa sfrlanmaz, yoksa yaratl-
maz)
• w+ :
• a :
dosyada hem okuma hem yazma yaplacak (dosya sfrlanr, yoksa yaratlr)
dosyann sonuna ekleme yaplacak (dosya varsa sfrlanmaz, yoksa yaratlr)
Fonksiyon ba³l§ndan da görülebilece§i gibi bu fonksiyon geriye açt§ dosya için bir i³aretçi
döndürür, dosya üzerinde sonraki i³lemlerde bu i³aretçi kullanlacaktr.
Ekleme kipinde açma d³ndaki kiplerde dosya açma i³lemi dosya i³aretçisini dosyann ba³na
konumlandrr; yani ilk okuma ya da yazma dosyann ba³ndan yaplr.
Dosya üzerindeki i³lemler bittikten sonra da dosyann kapatlmas gerekir. Bu amaçla bildirimi
a³a§da verilmi³ olan
fclose
fonksiyonu kullanlr:
int fclose(FILE *stream );
Bu fonksiyon parametre olarak verilen dosya i³aretçisinin gösterdi§i dosyay kapatr. Ba³arl
olursa 0, ba³arsz olursa
EOF
de§erini döndürür.
148
Standart Giri³ / Çk³ Birimleri
8.4.2
Dosyada Okuma-Yazma
Her okuma ya da yazma i³lemi i³aretçiyi okunulan ya da yazlan miktar kadar ilerletir; böylelikle pe³pe³e okuma i³lemleri dosyann srayla okunmasn sa§lar (yazma için de benzer ³e-
fscanf ve fprintf fonksiyonlar kullanlabilir. Bu fonksiprintf fonksiyonlar ile ayndr; tek farklar ek olarak en ba³a
kilde). Okuma-yazma i³lemleri için
yonlarn kullanmlar
scanf
ve
bir dosya i³aretçisi parametresi almalardr.
Dosyadan ba³ka birimlerde okuma yapmak da istenebilir. Örne§in bir satrn bütün halinde
okunmas amacyla
gets fonksiyonuna benzer fgets fonksiyonu kullanlabilir. Bu fonksiyonun
bildirimi ³u ³ekildedir:
char *fgets(char *s, int size, FILE *stream );
Bu fonksiyon
duklarn
stream parametresi ile belirtilen dosyadan en fazla size - 1 simge okur ve oku-
s parametresi ile belirtilen katara yazar. Satr sonu ya da dosya sonuna raslarsa daha
NULL, ba³arl olursa s de§erini döndürür. Güvenlik açsndan
fazla okumaz. Ba³arsz olursa
gets
fonksiyonu yerine bu fonksiyonun kullanlmas önerilir.
Dosyadan tek bir simge okumak için
fgetc fonksiyonu kullanlabilir. Bu fonksiyonun bildirimi
³u ³ekildedir:
int fgetc(FILE *stream );
Bu fonksiyon
stream parametresi ile belirlenen dosyadan okudu§u sradaki simgeyi bir tamsay
olarak geri döndürür.
Dosya sonuna gelinip gelinmedi§ini ö§renmek amacyla
feof
fonksiyonundan yararlanlr. Bu
fonksiyon kendisine parametre olarak gönderilen dosya i³aretçisinin ilgili dosyann sonu olup
olmad§n snar ve sona gelindiyse do§ru de§erini döndürür.
8.5
Standart Giri³ / Çk³ Birimleri
Standart giri³, çk³ ve hata birimleri de birer dosya gibi davranrlar. Standart giri³ birimi
stdin adnda önceden tanmlanm³ özel bir de§i³kende tutulur. Benzer ³ekilde standart çk³
için stdout, standart hata için de stderr de§i³kenleri tanmlanm³tr. Basit bir örnek verecek
olursak
printf(biçim katar, deyimler);
komutu
fprintf(stdout, biçim katar, deyimler);
komutuyla ayn anlama gelir. Benzer ³ekilde a³a§daki ikisi de giri³ i³lemleri için e³de§erlidir:
scanf(biçim katar, de§i³kenler);
fscanf(stdin, biçim katar, de§i³kenler);
149
Giri³-Çk³
8.6
Hata letileri
Hata iletilerinin standart çk³ iletilerinden ayrlmasnn yararl bir al³kanlk oldu§u Bölüm 1.5'de söylenmi³ti. Bir C++ programnda bu i³lem iletinin
cout
de§il,
cerr
birimine
yönlendirilmesiyle sa§lanabilir. Örnekte dosyalarn açlamamas durumunda görüntülenen iletilerde bu i³lem görülebilir:
cerr < < Giri³ dosyas açlamad. < < endl;
C dilinde ise
cerr
birimi olmad§ndan ayn i³lem a³a§daki komutla gerçekle³tirilmelidir:
fprintf(stderr, .Giri³ dosyas açlamad.\n);
Hata olu³tu§unda programn ne yapaca§ durumdan duruma de§i³ebilir. Düzeltilemeyecek bir
hata olu³tuysa programlar
exit
fonksiyonuyla sonlandrlrlar. Bu fonksiyona
EXIT_FAILURE
de§eri gönderilirse programn ba³arsz sonland§ i³letim sistemine bildirilmi³ olur. Bu i³lemin
return
ile dönmeden fark hangi fonksiyondan ça§rlrsa ça§rlsn programn derhal sonlan-
masdr; return ise yalnzca ça§ran fonksiyona dönü³ü sa§lar.
Hata iletilerini standartla³trmak amacyla
perror
fonksiyonu tanmlanm³tr. Bu fonksiyon
son olu³an hataya göre uygun bir mesaj standart hata birimine gönderir. Kullanmnda gelenek
olarak hatann hangi fonksiyonda ortaya çkt§ belirtilir. Örnekte giri³ dosyas açlamad§nda
cerr
birimine yönlendirme yerine
perror(main: giri³ dosyas açlamad);
komutu kullanlsayd ve programn çal³trlmas srasnda belirtilen giri³ dosyas sistemde
bulunamasayd çal³ma annda ³öyle bir ileti görünürdü:
main: giri³ dosyas açlamad: No such file or directory
8.7
Katarlar ile Giri³-Çk³
Standart giri³-çk³ kitapl§ndaki
sprintf ve sscanf fonksiyonlar ayn i³lemlerin katarlar
printf ve scanf fonksiyonlarndan farklar, ilk pa-
ile yaplmasn sa§lar. Bu fonksiyonlarn
rametrelerinin okuma ya da yazma yaplacak katarlar belirtmeleridir. Örne§in dosyadan bir
satr bütün olarak okuyup, üzerinde belki baz denetlemeler yaptktan sonra de§erlerin de§i³kenlere aktarlmas isteniyorsa
fscanf ile do§rudan de§i³kenlere aktarmak yerine a³a§daki
teknik kullanlabilir:
// fp dosyasndan bir satr line katarna oku
// ilk de§eri x tamsay de§i³kenine,
// ikinci de§eri y kesirli de§i³kenine aktar
fgets(line, fp);
...
sscanf(line, %d %f, &x, &y);
kili Dosyalar
150
sprintf fonksiyonu da çktnn ekrana baslmadan bir katarda olu³turulmas i³leminde yararl
olur. Sözgelimi, x saysn strx katarna çevirmek için a³a§daki basit komut kullanlabilir:
sprintf(strx, %d, x);
8.8
kili Dosyalar
'b' bayra§
fread, fwrite, fseek
Uygulama: Dosyalar
Örnek 33. Graarn Enlemesine Taranmas
DÜZELT: YAZILACAK
graf tip tanm:
struct graph_s {
int nodes;
int adjacency[MAXNODES][MAXNODES];
};
typedef struct graph_s graph_t;
okuma fonksiyonu bildirimi:
void read_matrix(FILE *fp, graph_t &g);
Sorular
1. Biti³iklik matrisini komut satrnda belirtilen bir dosyadan okudu§u grafn ba§lant matrisini Warshall algoritmas yardmyla hesaplayan bir program yazn.
151
Giri³-Çk³
Örnek 33 Bir graf enlemesine tarayan program (ana fonksiyon).
int main(int argc, char *argv[])
{
FILE *fp;
graph_t graph;
int vertices[MAXNODES];
bool visited[MAXNODES];
int start_vertex, next_vertex;
int count, index, i;
if (argc != 3) {
cerr << "Kullanm: " << argv[0]
<< " matris_dosyas ba³langç_dü§ümü" << endl;
return EXIT_FAILURE;
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
cerr << "Matris dosyas açlamad." << endl;
exit(EXIT_FAILURE);
}
sscanf(argv[2], "%d", &start_vertex);
read_matrix(fp, graph);
for (i = 0; i < graph.nodes; i++)
visited[i] = false;
vertices[0] = start_vertex;
visited[start_vertex] = true;
count = 1;
index = 0;
while ((index < graph.nodes) && (count < graph.nodes)) {
next_vertex = vertices[index];
for (i = 0; i < graph.nodes; i++) {
if ((graph.adjacency[next_vertex][i] == 1)
&& (!visited[i])) {
vertices[count] = i;
visited[i] = true;
count++;
}
}
index++;
}
for (i = 0; i < graph.nodes; i++)
cout << vertices[i] << endl;
fclose(fp);
return EXIT_SUCCESS;
kili Dosyalar
Örnek 34 Bir graf enlemesine tarayan program (matris okuma fonksiyonu).
void read_matrix(FILE *fp, graph_t &g)
{
int c;
int i = 0, j = 0;
}
fscanf(fp, "%d\n", &g.nodes);
while (true) {
c = fgetc(fp);
if (c == EOF)
break;
if (c == '\n') {
i++;
j = 0;
continue;
}
g.adjacency[i][j] = c - '0';
j++;
}
152
Bölüm 9
Öni³lemci
Bir C kaynak dosyasndan çal³trlabilir dosya olu³turulmas için geçilen a³amalar derleme
ve ba§lama olarak belirtilmi³ti. Aslnda kaynak dosyas, derleyiciye verilmeden önce bir de
öni³lemciden geçirilir. Öni³lemcinin yaptklar ³öyle özetlenebilir:
•
Açklamalar ayklar:
/*
ile
*/
arasnda kalan ya da
//
i³aretinden satr sonuna kadar
olan bölümleri koddan siler; yani bu bölümler derleyiciye hiç gitmez.
•
Öni³lemci komutlarn i³ler:
#
simgesiyle ba³layan komutlar öni³lemci komutlardr ve
öni³lemci tarafndan i³lenirler.
En sk kullanlan öni³lemci komutlarn yeniden görelim:
#dene
De§i³mez ya da makro tanmlamakta kullanlr. Kodun içinde de§i³mezin adnn
geçti§i her yere de§erini yazar. Sözgelimi
yazan her yere
3.14
yazarak derleyiciye
#define PI 3.14 öni³lemci komutu, kodda PI
o haliyle gönderir; yani derleyici PI sözcü§ünü
görmez.
#include
Belirtilen dosyay o noktada kodun içine ekler. Sözgelimi
öni³lemci komutu,
stdlib.h
#include <stdlib.h>
isimli dosyay bularak kaynak kodun içine yerle³tirir. Kod
derleyiciye geldi§inde bu dosyann içeri§ini de barndrr.
9.1
Makrolar
Programn içinde skça yinelenmesi gerekebilecek, ancak bir fonksiyon haline getirmeye de
de§meyecek küçük kod parçalar makrolar yardmyla gerçeklenir. Makrolar da de§i³mez tanmlarna benzer ³ekilde
#define sözcü§üyle yaplrlar. ³leyi³leri de yine de§i³mez tanmlarna
benzer ³ekilde olur, yani makronun adnn geçti§i yere açlm konur.
Örnek 13'de geçen
sqr_total = sqr_total + (score[i] - mean) * (score[i] - mean);
153
154
Projeler
komutunu basitle³tirmek üzere bir deyimin karesini alan
#define sqr(x) (x) * (x)
makrosunu kullanarak komutu ³u ³ekle getirebiliriz:
sqr_total = sqr_total + sqr(score[i] - mean);
Bunun sonucunda makro tanmndaki
score[i] - mean
x
simgesinin yerine makronun kullandld§ yerdeki
deyimi konur (programc kendisi bu ³ekilde yazm³ gibi).
Bu i³lem bir sözcük ya da sözcük grubunun yerine ba³ka bir sözcük ya da sözcük grubunun
yerle³tirilmesi ³eklinde yürüdü§ünden kullanmna dikkat etmek gerekir. Örnekteki makro
#define sqr(x) x * x
³eklinde tanmlansayd makro açlmyla olu³acak (hatal) kod ³u ³ekilde olurdu:
sqr_total = sqr_total + score[i] - mean * score[i] - mean;
Örnek 35. Projeler
Bir saynn asal çarpanlarnn ekrana dökülmesini ve iki saynn en büyük ortak bölen ve
en küçük ortak katlarnn hesaplanmas i³lemlerini yapan bir program yazlmas isteniyor.
Programn örnek bir çal³mas “ekil 9.1'de verilmi³tir. Bu örnekte kaynak kodu birden fazla
dosyaya bölünecek, kullancyla etkile³im ksmn yürüten fonksiyon (ayn zamanda
siyonu)
project.cpp
dosyasna (Örnek 35), i³lemleri yapan fonksiyonlar
(Örnek 36) konacaklardr.
9.2
1
ops.cpp
main fonkdosyasna
Projeler
Yazlan programn kapsam büyüdükçe bütün kaynak kodunun tek bir dosyada toplanmas
zorla³maya ba³lar. Binlerce satrlk bir kaynak kodunun tek bir dosyada tutularak program
geli³tirilmesi son derece zordur. Böyle projelerde kaynak kodu farkl dosyalara bölünür. Birden fazla kaynak dosyasna bölünmü³ bir proje derlenirken önce her kaynak dosyas ayr ayr
derlenerek ara kodlar olu³turulur, sonra ba§layc bu ara kodlar ve varsa kullanlan kitaplklar
arasndaki ba§lantlar kurarak çal³trlabilir kodu üretir (“ekil 9.3).
Derleme süresi ba§lama süresinden çok daha uzun oldu§undan kaynak kodun bu ³ekilde bölünmesi çal³trlabilir dosyann üretilmesi için gereken zaman da azaltr. Tek bir büyük dosyadan
olu³an projelerde herhangi bir yordamdaki herhangi bir de§i³iklikte bütün yordamlarn yeniden derlenmeleri ve ba§lanmalar gerekir. Oysa kaynak dosyalar bölünürse yalnzca de§i³tirilen
1
Bu örne§in nasl derlenece§ini Ek B.2'de görebilirsiniz.
155
Öni³lemci
Say 1: 0
Say 2: 0
1.
2.
3.
4.
5.
6.
Say 1'i de§i³tir
Say 2'yi de§i³tir
Say 1'in çarpanlarn göster
En büyük ortak bölen bul
En küçük ortak kat bul
Çk
Seçiminiz: 1
Sayy yaznz: 9702
Say 1: 9702
Say 2: 0
1.
2.
3.
4.
5.
6.
Say 1'i de§i³tir
Say 2'yi de§i³tir
Say 1'in çarpanlarn göster
En büyük ortak bölen bul
En küçük ortak kat bul
Çk
Seçiminiz: 2
Sayy yaznz: 945
“ekil 9.1: Proje örne§i ekran çkts.
156
Projeler
Say 1: 9702
Say 2: 945
1.
2.
3.
4.
5.
6.
Say 1'i de§i³tir
Say 2'yi de§i³tir
Say 1'in çarpanlarn göster
En büyük ortak bölen bul
En küçük ortak kat bul
Çk
Seçiminiz: 3
2^1 3^2 7^2 11^1
Say 1: 9702
Say 2: 945
1.
2.
3.
4.
5.
6.
Say 1'i de§i³tir
Say 2'yi de§i³tir
Say 1'in çarpanlarn göster
En büyük ortak bölen bul
En küçük ortak kat bul
Çk
Seçiminiz: 4
En büyük ortak bölen: 1323
Say 1: 9702
Say 2: 945
1.
2.
3.
4.
5.
6.
Say 1'i de§i³tir
Say 2'yi de§i³tir
Say 1'in çarpanlarn göster
En büyük ortak bölen bul
En küçük ortak kat bul
Çk
Seçiminiz: 5
En küçük ortak kat: 145530
Say 1: 9702
Say 2: 945
1.
2.
3.
4.
5.
6.
Say 1'i de§i³tir
Say 2'yi de§i³tir
Say 1'in çarpanlarn göster
En büyük ortak bölen bul
En küçük ortak kat bul
Çk
Seçiminiz: 6
157
Öni³lemci
Örnek 35 Giri³/çk³ fonksiyonlarn içeren kaynak dosyas.
#include <iostream>
#include <stdlib.h>
#include "ops.h"
// std::xxx
// EXIT_SUCCESS
// gcd,lcm,...
int main(void)
{
int num1 = 0, num2 = 0;
factor_t factors[MAXFACTOR];
int n, i;
int choice;
while (true) {
std::cout << "Say 1: " << num1 << std::endl;
std::cout << "Say 2: " << num2 << std::endl << std::endl;
std::cout << "1. Say 1'i de§i³tir" << std::endl;
std::cout << "2. Say 2'yi de§i³tir" << std::endl;
std::cout << "3. Say 1'in çarpanlarn göster" << std::endl;
std::cout << "4. En büyük ortak bölen bul" << std::endl;
std::cout << "5. En küçük ortak kat bul" << std::endl;
std::cout << "6. Çk" << std::endl << std::endl;
std::cout << "Seçiminiz: ";
std::cin >> choice;
if (choice == 6)
exit(EXIT_SUCCESS);
switch (choice) {
case 1:
case 2:
std::cout << "Sayy yaznz: ";
if (choice == 1)
std::cin >> num1;
else
std::cin >> num2;
break;
case 3:
factorize(num1, factors, n);
for (i = 0; i < n; i++)
std::cout << factors[i].base << "^" << factors[i].power << " ";
std::cout << std::endl;
break;
case 4:
std::cout << "En büyük ortak bölen: " << gcd(num1, num2) << std::endl;
break;
case 5:
std::cout << "En küçük ortak kat: " << lcm(num1, num2) << std::endl;
break;
}
std::cout << std::endl;
}
return EXIT_SUCCESS;
158
Projeler
Örnek 36 Hesap fonksiyonlarn içeren kaynak dosyas.
#include <math.h>
#include "ops.h"
// sqrt,pow
// struct factor_s
#define max(x, y) (x) > (y) ? (x) : (y)
#define min(x, y) (x) > (y) ? (x) : (y)
void gcd_factors(const factor_t factors1[], int
const factor_t factors2[], int
factor_t factors[], int &n);
void lcm_factors(const factor_t factors1[], int
const factor_t factors2[], int
factor_t factors[], int &n);
n1,
n2,
n1,
n2,
int gcd(int number1, int number2)
{
...
}
int lcm(int number1, int number2)
{
...
}
bool is_prime(int cand)
{
...
}
int next_prime(int prime)
{
...
}
void factorize(int x, factor_t factors[], int &n)
{
...
}
void gcd_factors(const factor_t factors1[], int n1,
const factor_t factors2[], int n2,
factor_t factors[], int &n)
{
...
}
void lcm_factors(const factor_t factors1[], int n1,
const factor_t factors2[], int n2,
factor_t factors[], int &n)
{
159
Öni³lemci
derleme
baglama
kaynak kodu 1
ara kod 1
kaynak kodu 2
ara kod 2
kaynak kodu n
ara kod n
çalistirilabilir kod
kitapliklar
“ekil 9.3: Birden fazla kaynak kodlu projelerin derleme a³amalar.
yordamn bulundu§u kaynak dosyas yeniden derlenir ve ba§lama i³lemi yaplr; de§i³meyen
kaynak kodlarnn yeniden derlenmelerine gerek kalmaz.
Böyle bir çal³mada, dosyalardan yalnzca birinde
main fonksiyonu bulunabilece§i açktr; aksi
durumda ba§lama i³lemi belirsizlik nedeniyle ba³arsz olur. Ayrca farkl dosyalardaki fonksiyonlarn birbirlerini ça§rabilmeleri, dosyalar arasnda de§i³ken payla³abilmeleri gibi konular
için baz düzenlemeler yapmak gerekir.
Da§tmann yararl olabilmesi için fonksiyonlar, amaçlarna göre gruplanarak dosyalara bölünmelidir. Örnekte oldu§u gibi, kullancyla etkile³imi sa§layan (giri³/çk³ i³lemlerini yapan)
fonksiyonlarn hesaplamalar yapan fonksiyonlarla ayr dosyalara toplanmas sk kullanlan bir
bölümleme tekni§idir.
Hesap i³lemlerini yapan
factorize, gcd, lcm fonksiyonlar project.cpp dosyasnda bulunma-
dklarndan bu dosyann derlenmesi srasnda sorun çkar. Derlenebilmesi için bu üç fonksiyonun bildirimleri dosya ba³na eklenmelidir. Bildirimler elle yazlabilir ancak daha do§ru olan
yöntem,
ops.cpp
dosyasn bir kitaplk gibi dü³ünüp tanmlad§ fonksiyonlarn bildirimlerini
içeren bir ba³lk dosyas hazrlamak ve bu ba³lk dosyasn di§er dosyann içine almaktr. Böy-
ops.cpp ve ops.h dosyalar ba³ka projelerde de kullanlabilirler. Örnek projede ops.cpp
dosyas için ops.h ba³lk dosyas hazrlanm³ (Örnek 37) ve bu dosya
lelikle
#include ops.h
öni³lemci komutuyla her iki kaynak dosyasnn da içine alnm³tr. Burada
<>
simgeleri yerine
simgeleri kullanlmas, öni³lemcinin ba³lk dosyasn sistem klasörlerinden önce bulunulan
klasörde aramasn sa§lar.
Ba³lk dosyas, ilgili kitapl§n arayüzüdür; ba³ka dosyalardaki fonksiyonlarn gerek duyabilecekleri bilgileri barndrr. Bir fonksiyon yalnzca o dosya içinde kullanlyorsa ve d³ardan
160
Projeler
Örnek 37 Hesap fonksiyonlar için ba³lk dosyas.
#ifndef OPS_H
#define OPS_H
#define MAXFACTOR 50
struct factor_s {
int base, power;
};
typedef struct factor_s factor_t;
void factorize(int x, factor_t factors[], int &n);
int gcd(int number1, int number2);
int lcm(int number1, int number2);
#endif
fonksiyonlar tarafndan ça§rlmayacaksa (örnekteki
next_prime
ve
is_prime
fonksiyonlar
gibi) bildirimi ba³lk dosyasna yazlmaz.
Ba³lk dosyalar, fonksiyon bildirimlerinin d³nda, tip tanmlar da içerebilirler. Örnekte çarpanlar göstermek için kullanlan
factor_t
tipi
project.cpp
dosyasnda da gerek duyulan
bir tip oldu§undan ba³lk dosyasna alnm³tr. Program bir saynn asal çarpanlarn listeleme
i³ini yapmayacak olsayd, bu veri tipi ve
factorize
fonksiyonunun bildirimine
project.cpp
ops.cpp
dosyasnda gerek kalmayaca§ için ba³lk dosyasna yazlmayabilirlerdi. Bu veri tipi
dosyasnda da kullanld§ndan bu dosyann da ayn ba³lk dosyasn içermesi gerekir.
Benzer ³ekilde, de§i³mez ve makro tanmlar da ba³lk dosyalarnda yer alabilir. Örnekte ana
fonksiyon bir saynn asal çarpanlarn temsil etmek üzere statik bir dizi tanmlamaktadr. Bu
dizinin eleman saysna kendisi karar verebilece§i gibi, di§er fonksiyonlarla uyum açsndan bu
bilgiyi ba³lk dosyasndan almas daha uygundur.
Ba³lk dosyalarnda yaplmamas gereken iki önemli i³lem vardr:
•
Fonksiyon tanmlamak: Ba³lk dosyalarna fonksiyonlarn yalnzca bildirimleri yazlr,
gövdeleri yazlmaz. Bir ba³lk dosyas birden fazla C dosyas tarafndan alnabilece§inden
ayn fonksiyonun birden fazla kere tanmlanmas ba§lama a³amasnda hataya neden olur.
•
De§i³ken tanmlamak: Benzer ³ekilde, ba³lk dosyasnda tanmlanan de§i³kenler birden
fazla dosya tarafndan alnma durumunda ayn isimli genel de§i³kenler olarak de§erlendirilir ve ba§lama hatasna neden olurlar.
Farkl dosyalar arasnda payla³lacak genel de§i³ken tanmlanmak isteniyorsa bu de§i³ken
extern sakl sözcü§üyle bildirilmeli ve C kaynak dosyalarndan birinde
normal biçimde tanmlanmaldr. Örne§in, ba³lk dosyasnda extern int counter; ³eklinde bildirilebilir ve dosyalardan biri int counter; komutuyla tanmlayabilir.
ba³lk dosyasnda
161
Öni³lemci
Sorular
1.
x ← |y − z|
(a) bir
if
i³lemini gerçekle³tirmek üzere
komutu yazn.
(b) bir makro tanm yazn.
2. Üç saynn harmonik ortalamas ³öyle tanmlanr:
3
1
x1
+
1
x2
+
1
x3
(a) Üç saynn harmonik ortalamasn hesaplamak üzere kullanlabilecek harmonic(x,
y, z) makrosunun tanmn yaznz.
(b) Yazd§nz makro
b = harmonic(m - 1, n + 3, p);
³eklinde ça§rlrsa bu makronun açlm nasl olur?
Projeler
162
Bölüm 10
Ba§lantl Listeler
Örnek 38. En Büyük Ortak Bölen Bulma
Örnek 23'de gerçeklendi§i ³ekliyle, en büyük ortak bölen bulma programnda bir saynn çarpanlar statik bir diziyle temsil ediliyordu. Bu örnekte statik dizi yerine dinamik dizi kullanmak
bellek kullanmn etkinle³tirmek adna bir i³e yaramaz; çünkü dinamik dizilerde yaplan, eleman says belli olduktan sonra gerekti§i kadar yer ayrmaktr, oysa bu örnekte eleman says
ancak çarpanlarna ayrma algoritmasnn sona ermesiyle sonra belli olur.
Ba§lantl listeler, bu tip algoritmalarda dizilere göre daha uygun bir veri yapsdr. Bir ba§lantl liste, birbirinin e³i dü§ümlerden olu³ur; her dü§üm tutulmak istenen bilgileri ta³masnn
yansra listede kendisinden sonra gelen dü§üme de bir i³aretçi içerir. Böylece listenin ba³ biliniyorsa sonraki dü§ümü gösteren alanlar üzerinden ilerlenerek bütün dü§ümlere eri³ilebilir.
Listenin sonunu belirtmek üzere son dü§ümün sonraki alanna özel bir de§er (NULL) yazlr.
Bu yapda, dizilerin aksine, eleman saysn tutmann gere§i yoktur.
Örnek 38 ayn algoritmalar statik diziler yerine ba§lantl listeler üzerinde gerçekleyen bir
programdr.
Örnekteki ba§lantl liste yapsnn olu³turulmas için kullanlan yap tanm ³öyledir:
struct factor_s {
int base, power;
struct factor_s *next;
};
typedef struct factor_s factor_t;
Görüldü§ü gibi, bir dü§ümde asal çarpann de§eri ve üssüne ek olarak dü§ümün kendi tipine
i³aret eden bir i³aretçi alan vardr. Böyle bir yap üzerinde i³lem yapmak için tek gerekli
de§i³ken dizinin ilk elemanna i³aret eden bir de§i³ken tutmaktr, örnekteki
head
de§i³ken-
leri bu amaçla tanmlanm³tr. Listeye ekleme algoritmalarnda kolaylk sa§lamas için bir de
listenin son dü§ümünü (next alannda
NULL
yazan dü§üm) gösteren bir de
tail
de§i³keni
kullanlm³tr.
Bu tanma göre olu³turulan ba§lantl listelerde 9702 saysnn çarpanlarnn nasl gösterildi§i
“ekil 10.1'de verilmi³tir.
163
164
Örnek 38 Ba§lantl listeler kullanarak en büyük ortak bölen hesaplayan program (ana fonksiyon).
int main(void)
{
int number1, number2;
factor_t *factors1 = NULL, *factors2 = NULL, *factors3 = NULL;
long int gcd = 1L;
factor_t *f = NULL;
}
cout << "Saylar yaznz: ";
cin >> number1 >> number2;
factors1 = factorize(number1);
factors2 = factorize(number2);
factors3 = gcd_factors(factors1, factors2);
for (f = factors3; f != NULL; f = f->next)
gcd = gcd * (long int) pow((double) f->base,
(double) f->power);
delete_factors(factors1);
delete_factors(factors2);
delete_factors(factors3);
cout << "En büyük ortak bölen: " << gcd << endl;
return EXIT_SUCCESS;
tail
head
2
3
7
11
1
2
2
1
“ekil 10.1: Ba§lantl liste örne§i.
165
Ba§lantl Listeler
Bu veri yaps kullanld§nda bir sayy asal çarpanlarna ayran fonksiyonun giri³ parametresi
olarak yalnzca asal çarpanlarna ayrlacak sayy almas ve çk³ parametresi olarak olu³turdu§u çarpanlar listesinin ba³langç elemann döndürmesi yeterlidir:
factor_t *factorize(int x);
Benzer ³ekilde, ortak çarpanlar bulma algoritmas da iki çarpan listesini alarak ortak çarpanlar
listesini döndürür:
factor_t *gcd_factors(factor_t *factors1, factor_t *factors2);
Ba§lantl listeler dinamik olarak olu³turulduklarndan i³leri bitti§inde sisteme geri verilmeleri gerekir. Bu amaçla tanmlanan
delete_factors
fonksiyonu ilk dü§ümüne i³aretçi ald§
bir listenin bütün dü§ümlerini sisteme geri verir. Burada
head
i³aretçisi o anda geri veri-
lecek dü§ümün adresini tutarken p i³aretçisi bir sonraki dü§ümün unutulmamasn sa§lar. Bu
fonksiyon ³öyle yazlabilir:
void delete_factors(factor_t *head)
{
factor_t *p = NULL;
}
while (head != NULL) {
p = head->next;
delete head;
head = p;
}
Örnek programda kullanlan di§er fonksiyonlar olan
factorize ve gcd_factors fonksiyonlar
srasyla Örnek 39 ve Örnek 40'de verilmi³tir.
10.1
Yaplara ³aretçiler
Bir yapya i³aret eden bir de§i³ken tanmland§nda bu yapnn alanlarna eri³mek için
->
i³leci kullanlr. Örnekte ortak çarpanlardan en büyük ortak bölenin hesapland§ döngüdeki
f->base yazm buna bir örnektir. Bunun yerine önce * ile i³aretçinin ba³vurdu§u yere eri³ilip
daha sonra noktal gösterilimle istenen alann de§eri de alnabilir: (*f).base gibi. Ancak bu
ikinci gösterilim pek ye§lenmez.
Uygulama: Ba§lantl Listeler
Bu örnekte, Örnek 30'de yaplan ortade§er bulma program seçerek sralama algoritmas yerine
araya sokarak sralama algoritmasyla gerçeklenecektir.
Yaplara ³aretçiler
166
Örnek 39 Ba§lantl listeler kullanarak en büyük ortak bölen hesaplayan program (asal çarpanlara ayrma fonksiyonu).
factor_t *factorize(int x)
{
factor_t *head = NULL, *tail = NULL, *f = NULL;
int factor = 2;
}
while (x > 1) {
if (x % factor == 0) {
f = new factor_t;
f->base = factor;
f->power = 0;
while (x % factor == 0) {
f->power++;
x = x / factor;
}
f->next = NULL;
if (head == NULL)
head = f;
if (tail != NULL)
tail->next = f;
tail = f;
}
factor = next_prime(factor);
}
return head;
167
Ba§lantl Listeler
Örnek 40
Ba§lantl listeler kullanarak en büyük ortak bölen hesaplayan program (ortak
çarpanlar bulma fonksiyonu).
factor_t *gcd_factors(factor_t *factors1, factor_t *factors2)
{
factor_t *factors = NULL, *head = NULL, *tail = NULL, *p = NULL;
}
while ((factors1 != NULL) && (factors2 != NULL)) {
if (factors1->base < factors2->base)
factors1 = factors1->next;
else if (factors1->base > factors2->base)
factors2 = factors2->next;
else {
factors = new factor_t;
factors->base = factors1->base;
factors->power = min(factors1->power, factors2->power);
factors->next = NULL;
if (head == NULL)
head = factors;
if (tail != NULL)
tail->next = factors;
tail = factors;
factors1 = factors1->next;
factors2 = factors2->next;
}
}
return head;
Yaplara ³aretçiler
168
Örnek 41. Araya Sokarak Sralama
Araya sokarak sralama algoritmas, temel sralama yöntemlerinden biridir. Bu yöntemde, her
yeni gelen eleman o ana kadar gelen elemanlara göre sral olacak ³ekilde yerine yerle³tirilir.
Örne§in 45, 22, 91, 18, 62 saylar sralanacaksa ³u ³ekilde ilerlenir:
45
22
22
18
18
45
45 91
22 45 91
22 45 62 91
Bu yöntem statik diziler üzerinde gerçeklenmeye uygun de§ildir çünkü her yeni gelen eleman
eklendi§inde ondan büyük olan bütün elemanlarn bir konum sa§a kaydrlmalar gerekir. Örnekte 18 says dizinin en ba³na eklenece§inden üç elemann birden sa§a kaydrlmasna neden
olur. Oysa bu algoritma ba§lantl listeler üzerinde gerçeklenmeye gayet uygundur. Örnek 41'de
bir diziyi sral bir ba§lantl listeye çeviren program verilmi³tir.
•
Ekleme i³lemini yapan fonksiyonu ³u durumlar için inceleyin:
liste bo³
eleman en ba³a ekleniyor
eleman en sona ekleniyor
eleman arada bir yere ekleniyor
•
assert
•
core dump
169
Ba§lantl Listeler
Örnek 41 Ba§lantl liste üzerinde araya sokarak sralama program (ana fonksiyon).
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
struct node_s {
int value;
struct node_s *next;
};
typedef struct node_s node_t;
node_t *insertsort(int *numbers, int count);
void delete_nodes(node_t *head);
int main(void)
{
int *score = NULL;
node_t *head = NULL, *f = NULL;
float median;
int no_students, i;
cout << "Ö§renci says: ";
cin >> no_students;
score = new int[no_students];
for (i = 0; i < no_students; i++) {
cout << i + 1 << ". ö§rencinin notu: ";
cin >> score[i];
}
head = insertsort(score, no_students);
f = head;
for (i = 0; i < no_students / 2 - 1; i++)
f = f->next;
median = (no_students % 2 == 1) ? f->next->value :
(f->value + f->next->value) / 2.0;
cout << "Orta de§er: " << median << endl;
delete_nodes(head);
}
delete score;
return EXIT_SUCCESS;
Yaplara ³aretçiler
Örnek 42 Ba§lantl liste üzerinde araya sokarak sralama program (liste fonksiyonlar).
node_t *insert(node_t *head, int v)
{
node_t *p = head, *newnode = NULL, *last = NULL;
}
newnode = new node_t;
newnode->value = v;
while ((p != NULL) && (p->value < v)) {
last = p;
p = p->next;
}
newnode->next = p;
if (last == NULL)
return newnode;
last->next = newnode;
return head;
node_t *insertsort(int *numbers, int count)
{
node_t *head = NULL;
int i;
}
for (i = 0; i < count; i++)
head = insert(head, numbers[i]);
return head;
void delete_nodes(node_t *head)
{
node_t *p = NULL;
}
while (head != NULL) {
p = head->next;
delete head;
head = p;
}
170
Bölüm 11
Rekürsiyon
ki saynn en büyük ortak bölenini bulmak üzere kulland§mz Euclides algoritmas, a ile
b
saylarnn en büyük ortak böleni
b
ile
a % b
saylarnn en büyük ortak bölenine e³ittir
ilkesine dayanyordu. Problemin çözümünün, bu örnekte oldu§u gibi, kendisi cinsinden ifade
edilmesine rekürsif tanm ad verilir. Çözülmesi istenen problem, kendisi cinsinden daha küçük
bir probleme indirgenir. Sürekli indirgemeler yoluyla çözümü bilinen bir duruma (taban durum) ula³lmaya çal³lr. Euclides algoritmasnda taban durum küçük olan saynn 0'a gelmesi
durumuydu; bu durumda di§er say en büyük ortak bölen oluyordu. Aksi halde daha küçük
saylar üzerinde en büyük ortak bölen aranmaya devam ediliyordu. Bu ilkeyi gerçekleyen bir
fonksiyon ³u ³ekilde yazlabilir:
int gcd(int a, int b)
{
if (b == 0)
return a;
else
return gcd(b, a % b);
}
Rekürsiyona en çok verilen örneklerden biri de faktöryel hesaplanmasdr. Rekürsif olarak
faktöryel hesaplayan bir fonksiyon ³öyle yazlabilir:
int factorial(int x)
{
if (x == 0)
return 1;
else
return x * factorial(x - 1);
}
Bu iki örnek, C gibi blok yapl dillerde rekürsif gerçeklenmeye uygun örnekler de§ildir; çünkü
yinelemeli olarak gerçeklendiklerinde daha etkin çal³rlar. Rekürsif yazm bazen daha güzel
görünse ve matematikteki tanma daha yakn olsa da, ba³arm açsndan dezavantajl olabilir.
171
172
Örnek 43. Hanoi Kuleleri
Hanoi kuleleri probleminde 3 adet direk ve 64 adet ortas delik disk vardr. Diskler ba³langçta
birinci dire§e geçirilmi³ durumdadr. Çap en geni³ olan disk en altta, en dar olan en üstte yer
alr ve her disk kendisinden daha geni³ çapl bir diskin üzerinde durur. Amaç, diskleri teker
teker direkler arasnda ta³yarak ayn düzeni üçüncü direkte olu³turmaktr. Burada kural,
hiçbir diskin hiçbir a³amada kendisinden dar bir diskin üzerine konamamasdr. “ekil 11.1'de üç
direk ve üç diskli örnek verilmi³tir. Bu örne§in çözümünü yapan programn çkts “ekil 11.2'de
verilmi³tir.
A
B
C
“ekil 11.1: Hanoi kuleleri problemi ba³langç durumu.
Hanoi kuleleri probleminin genel çözümünü olu³turmaya en geni³ çapl diskin nasl ta³naca§n dü³ünmekle ba³layalm. Bu disk ba³ka hiçbir diskin üstüne konamayaca§ için üçüncü
diske ba³ka bir direk üzerinden aktarlarak geçemez, bir kerede götürülmelidir. Bunun yaplabilmesi için birinci diskte kendisinden ba³ka disk bulunmamal, üçüncü disk de bo³ olmaldr
(“ekil 11.3).
Bu durumda çözüm üç a³amal olarak görülebilir:
1. Dar 63 diski birinci diskten ikinci diske ta³.
2. En geni³ diski birinci diskten üçüncü diske ta³.
3. Dar 63 diski ikinci diskten üçüncü diske ta³.
Birinci ve üçüncü admlardaki ta³ma i³lemi aslnda 63 disk için ayn problemin çözülmesinden
ba³ka bir ³ey de§ildir. O halde problemimizi
n diskin a dire§inden b dire§ine c dire§i üzerinden
ta³nmas ³eklinde ifade ederek çözümü ³u ³ekilde yazabiliriz:
Bir
Bir
Bir
Bir
Bir
Bir
Bir
diski
diski
diski
diski
diski
diski
diski
1
1
3
1
2
2
1
dire§inden
dire§inden
dire§inden
dire§inden
dire§inden
dire§inden
dire§inden
3
2
2
3
1
3
3
dire§ine
dire§ine
dire§ine
dire§ine
dire§ine
dire§ine
dire§ine
ta³.
ta³.
ta³.
ta³.
ta³.
ta³.
ta³.
“ekil 11.2: Hanoi kuleleri problemini çözen programn ekran çkts.
173
Rekürsiyon
A
C
B
“ekil 11.3: Hanoi kuleleri problemi (en geni³ diskin ta³nmas).
1.
n - 1
2.
a
3.
n - 1
diski
a
dire§inden
dire§inde kalan diski
diski
c
b
dire§inden
c
dire§ine
b
dire§i üzerinden ta³.
dire§ine ta³.
b
dire§ine
a
dire§i üzerinden ta³.
Her seferinde direk says azald§ndan bu algoritma sonlanma ko³ulunu sa§lar. Taban durum,
ta³nacak disk saysnn 0 oldu§u durumdur, bu durumda hiçbir ³ey yaplmayacaktr. O halde
bu problemi çözen program Örnek 43'de görüldü§ü gibi yazlabilir.
Bu algoritmann en güzel yanlarndan biri, deneme-yanlma yöntemiyle de§il, herhangi bir
diski gereksiz yere bir direkten bir dire§e aktartmadan bir kerede çözümü bulmasdr.
Uygulama: Rekürsiyon
Örnek 44. Çabuk Sralama
DÜZELT: YAZILACAK
Sorular
174
Örnek 43 Hanoi kuleleri problemini çözen program.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
#define DISKS 3
void move(int n, int a, int b, int c);
int main(void)
{
move(DISKS, 1, 3, 2);
return EXIT_SUCCESS;
}
void move(int n, int a, int b, int c)
{
if (n > 0) {
move(n - 1, a, c, b);
cout << "Bir diski " << a << " dire§inden "
<< b << " dire§ine ta³." << endl;
move(n - 1, c, b, a);
}
}
175
Rekürsiyon
Örnek 44 Çabuk sralama algoritmasn gerçekleyen program.
#include <iostream>
#include <stdlib.h>
// cin,cout,endl
// EXIT_SUCCESS
using namespace std;
void quicksort(int arr[], int first, int last);
int main(void)
{
int numbers[] = { 26, 33, 35, 29, 19, 12, 22 };
int i;
}
quicksort(numbers, 0, 6);
for (i = 0; i < 7; i++)
cout << numbers[i] << endl;
return EXIT_SUCCESS;
void swap(int &x, int &y)
{
int tmp;
}
tmp = x; x = y; y = tmp;
int partition(int arr[], int first, int last)
{
int pivotloc = first;
int pivot = arr[first];
int i;
}
for (i = first + 1; i <= last; i++) {
if (arr[i] < pivot) {
pivotloc++;
swap(arr[pivotloc], arr[i]);
}
}
swap(arr[first], arr[pivotloc]);
return pivotloc;
void quicksort(int arr[], int first, int last)
{
int pivotloc;
if (first < last) {
pivotloc = partition(arr, first, last);
quicksort(arr, first, pivotloc - 1);
quicksort(arr, pivotloc + 1, last);
176
Ek A
Simgelerin Kodlanmas
Bilgisayarlarda di§er her ³ey gibi simgeler de saylarla gösterilirler. Bunun için hangi simgenin
hangi sayyla gösterilece§i (ya da tersine, hangi saynn hangi simgeye kar³ dü³ece§i) konusunda bir uzla³ma olmas gerekir. Bu amaçla tanmlanan kodlamalar, simgelere birer numara
verirler.
Yaygn kullanlan ilk kodlamalardan biri ASCII kodlamasyd (“ekil A.1). ASCII, 7 bitlik bir
kodlama oldu§undan 128 farkl simgenin kodlanmasna olanak verir. lk kodun numaras 0,
son kodun numaras 127'dir. Bunlardan ilk 32 simge (0-31) ve son simge (127) baslamaz
simgelerdir (satr sonu, bip sesi v.b.). Aradaki 95 simgeyse (32-126) ngilizce'nin bütün küçük ve büyük hareri, rakamlar, noktalama i³aretleri ve tu³takm üzerinde gördü§ünüz her
türlü özel simgeyi içerir. ASCII kodlamas günümüzde kullanlan bütün kodlamalarn temelini
olu³turur.
32
40
48
56
64
72
80
88
96
104
112
120
+0
+1
+2
+3
+4
+5
+6
+7
!
"
#
$
%
&
'
(
)
*
+
,
-
.
/
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\
]
^
_
`
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
~
Tablo A.1: ASCII kodlama çizelgesi.
ASCII kodlamas, ngilizce d³nda kalan abecelerin harerini içermedi§inden, her dil için
o dilde bulunan farkl simgeleri de içeren 8 bitlik kodlamalar olu³turulmu³tur; böylelikle
256 farkl simgenin kodlanmasna olanak sa§lanm³tr. Bütün bu kodlamalarda ilk 128 simge
177
178
ASCII çizelgesinde olann aynsdr, düzenlemeler ikinci 128 simge üzerinde yaplr. Bu kodlamalarn en bilineni ISO8859 standart ailesinde tanmlananlardr. ISO8859 kodlamalarnda da
128-159 aras saylar kullanlmaz.
•
ISO8859-1: Bat Avrupa dilleri (latin1 kodlamas adyla da bilinir)
•
ISO8859-2: Do§u Avrupa dilleri
•
ISO8859-9: Türkçe (latin5 kodlamas adyla da bilinir). ISO8859-1 kodlamasyla neredeyse ayndr, yalnzca ISO8859-1'deki zlandaca harerin yerine Türkçe harerin gelmesiyle olu³turulmu³tur. ki kodlama arasnda de§i³en 6 simge ³unlardr: ‡ §  “ ³.
Son yllarda, farkl diller konu³an, farkl ülkelerde ya³ayan insanlarn ortak kullandklar uygulamalarn says çok büyük bir hzla artt§ndan, bütün dillerin bütün simgelerini içeren bir
kodlamaya geçmek bir zorunluluk halini alm³tr. Bu amaçla geli³tirilen Unicode kodlamas
(resmi adyla ISO10646-1), 16 ve 32 bitlik sürümleri olan bir kodlamadr. Yeryüzünde bilinen
bütün dillerin simgelerini içermenin yansra daha pek çok ek simgenin tanmlanabilmesine
de olanak verir. Ancak bütünüyle bu kodlamaya geçmek için yaygn kullanlan bütün programlarda büyük miktarlarda de§i³iklik gerekecektir. Bu nedenle, yeni yazlan uygulamalarda
bu kodlamann yaln hali olan UTF-16 ya da UTF-32 kodlamalarna uyulmas öngörülürken,
kullanm süren eski uygulamalarla uyum sorununu azaltmak için bir geçi³ kodlamas olarak
UTF-8 geli³tirilmi³tir.
Bir de§erin bilgisayar belle§inde bir göze ham bir veri olarak yazld§ dü³ünülebilir. Sözgelimi,
bir bellek gözünde 240 says yer alyor olsun. Program bu gözü bir tamsay olarak de§erlendirirse 240 de§erini elde eder ve diyelim bu sayy ba³ka bir say ile toplayabilir. ISO8859-9
kodlamasnda bir simge olarak de§erlendiriyorsa '§' harni elde eder ve Türkçe kurallarna
göre sralama yapmada kullanabilir. ISO8859-1 kodlamasnda bir say olarak de§erlendiriyorsa harni elde eder ve zlandaca kurallarna göre sralamada kullanabilir. Ksacas, de§er
bellekte ham haliyle bulunur; nasl anlam verilece§i, ne amaçla kullanlaca§ programn belirleyece§i konulardr.
Ek B
Unix'de Program Geli³tirme
B.1
Yardmc Belgeler
Unix i³letim sistemlerinde ço§u zaman
man fonksiyon
komutuyla o fonksiyonla ilgili bilgi
alabilirsiniz. Bu komut fonksiyonun ne i³ yapt§n ve hangi ba³lk dosyasnda yer ald§n
söyleyecektir. Örnek:
man sqrt.
info
KDE: Konqueror ya da Alt-F2 #sqrt
B.2
Derleme
Unix ailesi i³letim sistemlerinde C/C++ dilinde geli³tirme yapmak için en çok GNU C Compiler (gcc) derleyicisi kullanlr. Temel kullanm ³öyledir:
gcc kaynak_dosyas -o çal³trlabilir_dosya
Kaynak dosyanz bir C++ koduysa
g++ kaynak_dosyas -o çal³trlabilir_dosya
komutuyla çal³trmanz gerekir. Bu komutun sonucunda kaynak dosya derlenir, ba§lanr ve
ismi verilen çal³trlabilir dosya olu³turulur.
Derleyici ba³lk dosyalarn
/usr/include,
kitaplk dosyalarnysa
/usr/lib
kataloglarnda
arar. Derleyicinin çal³mas baz bayraklar yardmyla denetlenebilir. A³a§daki örneklerde
kaynak dosyasnn adnn
da
main
•
main.cpp,
hedef dosya adnn
main.o,
çal³trlabilir dosya adnn
oldu§u varsaylrsa:
Kaynak dosyay yalnz derlemek istiyorsanz, yani ba§lamak istemiyorsanz
kullanabilirsiniz:
179
-c bayra§n
180
Derleme
g++ main.cpp -c -o main.o
•
Derleyicinin bütün uyarlarlarn görmek istiyorsanz
-Wall
bayra§n kullanabilirsiniz:
g++ main.cpp -Wall -o main
•
Ba³ka kataloglarda da ba³lk dosyas aramasn istiyorsanz
-I
bayra§yla bunu belirte-
bilirsiniz:
g++ main.cpp -I/usr/X11R6/include -o main
•
Ba³ka kataloglarda da kitaplk aramasn istiyorsanz
-L bayra§yla bunu belirtebilirsiniz:
g++ main.cpp -I/usr/X11R6/include -L/usr/X11R6/lib -o main
•
Optimizasyon: -O2
Birden fazla kaynak dosyasndan olu³an bir projenin derlenmesi birkaç a³amal olur. Örnek 35
üzerinde bir projenin nasl derlenece§ini görelim:
• project.cpp
dosyasn derle (ba§lamadan):
g++ -c project.cpp -o project.o
• ops.cpp
dosyasn derle (ba§lamadan):
g++ -c ops.cpp -o ops.o
•
ba§la
g++ project.o ops.o -o project
Kaynak dosyalarnn herhangi birinde bir de§i³iklik yaplrsa yalnzca o dosyann yeniden derlenmesi ve ba§lama yeterlidir.
Her seferinde elle derleme komutlarn yazmak zahmetli bir i³ oldu§undan derleme i³lemlerini
kolayla³trmak için make arac kullanlr. Bu araç, programcnn yazd§, derleme a³amalarn
belirten
Makefile
isimli bir dosya denetiminde çal³r.
Makefile
dosyas hedeerden olu³ur.
Her hedef için heden nelere ba§l oldu§u ve nasl olu³turulaca§ belirtilir. Örnek bir hedef
³öyle yazlabilir:
project: project.o ops.o
g++ project.o ops.o -o project
Bu yazmn anlam,
project
hedenin
project.o
ve
ops.o
dosyalarna ba§l oldu§u ve olu³-
turulmas için ikinci satrda yazlan komutun kullanlaca§dr.
1 Bir heden ba§l oldu§u dos-
yalarda de§i³me olursa (dosyann tarih ve saati hedenkinden yeniyse) heden yeniden olu³turulmas gerekti§ine karar verilir. Örnek projedeki di§er hedeer de ³öyle yazlabilir:
1
Hede olu³turmakta kullanlacak komutlar satr ba³ndan bir sekme içeriden ba³lamaldr. Bir hede olu³-
turmakta birden fazla komut kullanlabilir.
181
Unix'de Program Geli³tirme
project.o: project.cpp
g++ -c project.cpp -o project.o
ops.o: ops.cpp
g++ -c ops.cpp -o ops.o
make
komutu çal³trlrken hangi heden olu³turulmasnn istendi§i belirtilir. Hedef belirtil-
mezse dosyada bulunan ilk hedef olu³turulmaya çal³lr. Ba³langçta
project
dosyalarnn hiçbirinin olmad§n varsayarsak,
make project
project.o, ops.o
ve
komutunun çal³mas
³öyle olur:
1.
project
hede olu³turulmaya çal³lr. Bu hedef
project.o
ve
ops.o
hedeerine ba§l
oldu§u için ve bunlar henüz olu³turulmam³ oldu§u için srayla bunlar olu³turulmaya
çal³lr.
2.
project.o hede olu³turulmaya çal³lr. Bu hedef project.cpp dosyasna ba§l oldu§u
için olu³turulmasna geçilebilir ve
g++ -c project.cpp -o project.o
komutu yürütülür.
3.
ops.o hede olu³turulmaya çal³lr. Bu hedef ops.cpp dosyasna ba§l oldu§u için olu³turulmasna geçilebilir ve
g++ -c ops.cpp -o ops.o
komutu yürütülür.
4. Artk
project hedenin ba§l oldu§u iki dosya da olu³mu³ oldu§undan bu heden olu³-
turulmasna geçilebilir ve
g++ project.o ops.o -o project
komutu yürütülür.
leride
ops.cpp
dosyasnda bir de§i³iklik yapld§n ve
make project
komutunun yürütüldü-
project.o
ops.o
§ünü dü³ünelim:
1.
project
hede olu³turulmaya çal³lr. Bu hedef
ve
hedeerine ba§l
oldu§u için önce onlara baklr.
2.
project.o hede olu³turulmaya çal³lr. Bu hedef project.cpp dosyasna ba§ldr ancak project.cpp dosyasnn saati project.o dosyasndan eski oldu§u için bir i³lem
yaplmaz.
3.
ops.o
hede olu³turulmaya çal³lr. Bu hedef
dosyasnn saati
ops.o
ops.cpp
dosyasna ba§ldr ve
ops.cpp
dosyasndan yeni oldu§u için heden yeniden olu³turulmas ge-
rekti§ine karar verilir ve
182
Editörler
g++ -c ops.cpp -o ops.o
komutu yürütülür.
4.
project
hedene dönüldü§ünde
ops.o
dosyasnn saati artk
project
dosyasnn sa-
atinden yeni oldu§u için bu heden de yeniden olu³turulmas gerekti§ine karar verilir
ve
g++ project.o ops.o -o project
komutu yürütülür.
Makefile
dosyalarnda ayrca baz de§i³mezler tanmlanarak okunulurluk ve esneklik artrla-
bilir. Örnek proje için yazlm³ bir
Makefile
Örnek 45'de verilmi³tir. Bu dosya skça kullan-
lan, kaynak dosyalar d³nda kalan her ³eyi silen
clean
hedeni de içermektedir;
make clean
komutu sizin yazd§nz d³nda kalan bütün dosyalarn silinmesi için kullanlr.
Örnek 45 Örnek bir Makefile dosyas.
CXX=g++
CXXFLAGS=-O2 -Wall -g -pg
LDFLAGS=-pg
proje: proje.o ops.o
$(CXX) $(LDFLAGS) proje.o ops.o -o proje
proje.o: proje.cpp
$(CXX) $(CXXFLAGS) -c proje.cpp -o proje.o
ops.o: ops.cpp
$(CXX) $(CXXFLAGS) -c ops.cpp -o ops.o
clean:
rm -f *.o proje
Öni³lemci: cpp
B.3
Editörler
nedit kate mcedit: yazm renklendirme, ayraç e³le³tirme, makrolar, tab emülasyonu, kendili§inden girintileme
B.4
Hata Ayklayclar
Çal³trlabilir dosya üzerinde hata ayklama yapacaksanz
-g
bayra§n kullanmalsnz:
183
Unix'de Program Geli³tirme
g++ main.cpp -g -o main
Hata ayklama bilgilerini silmek için -s
strip
gdb ddd: adm adm çal³trma, de§i³ken de§erlerini izleme
³aretçilerle çal³rken yaplan hatalar sklkla programn çökmesine ve o anki bellek görüntüsünün bir dosyaya yazlmasna neden olurlar (core dump). Bu bellek görüntüsü programnzn
neden çöktü§üne ili³kin önemli bilgiler içerir ve hatann nedenini bulmanza yardmc olabilir.
Örnek 39'de
if (x % factor == 0) {
satrndan sonraki
f = new factor_t;
komutunu silerek program derleyin ve çal³trn. Program bellek hatas vererek çökecektir.
ddd hata ayklaycsnda önce Open Program komutuyla çal³trlabilir dosyay, sonra da
Open Core Dump... komutuyla yaratlan
core
dosyasn açn. Programn çöktü§ü anda
f->base = factor;
satrnda kald§n ve
B.5
f
i³aretçisinin de§erinin
NULL
oldu§unu göreceksiniz.
Ba³arm nceleme
Programnzdaki fonksiyonlarn kaçar kere ça§rldklarn ve hangi fonksiyonda ne kadar zaman
harcand§n ölçmek için gprof aracn kullanabilirsiniz. gprof 'un kullanlabilmesi için gcc/g++
derleyicisine hem derleme hem ba§lama a³amasnda
-pg
bayra§ verilmelidir. Örnek 23'de
hangi fonksiyonun kaç kere ça§rld§n görmek için:
g++ -pg lcm.cpp -o lcm
komutuyla program derlendikten sonra çal³trlr ve en küçük ortak kat hesaplanmak istenen
de§erler girilir. Bu çal³ma sonucunda
gmon.out
isimli bir dosya olu³ur ve
gprof lcm gmon.out
komutu programn çal³masyla ilgili bir rapor üretir. 32424 ve 563324 de§erlerinin girilmesiyle
olu³an örnek bir raporun baz bölümleri a³a§da verilmi³tir:
% cumulative
self self total
time
seconds seconds calls us/call
us/call
95.24
0.20
0.20 70516
2.84
2.84
4.76
0.21
0.01
2 5000.00 105000.00
0.00
0.21
0.00 13127
0.00
15.24
0.00
0.21
0.00
1
0.00
0.00
name
is_prime
factorize
next_prime
merge_factors
Download
Random flashcards
qweeqwqwe

5 Cards oauth2_google_78146396-8b44-4532-a806-7e25cc078908

En Mimar Architecture LTD ŞTİ XD

2 Cards asilyasar069

KIRIHAN GÜMÜŞ DEDEKTÖR

6 Cards oauth2_google_49cd8e53-7096-4be6-ba73-4ff7e4195b4b

321işletme

2 Cards oldcity

Terimler

2 Cards oauth2_google_ef32970e-e5f9-4595-9abe-394e9f6bc8d9

Create flashcards