You are on page 1of 191

Programlamaya Giri³ Ders Notlar

H. Turgut Uyar

“ubat 2004
ii
Önsöz

(C) 2001-2004, H. Turgut Uyar <uyar@cs.itu.edu.tr>

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 za-
manda 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 ge-
tirdi§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 sayfa-
snda 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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

1.2.1 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
ÇINDEKILER vi

3 Ak³ Denetimi 45
3.1 Ko³ul Deyimleri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

3.1.1 Kar³la³trma ³lemleri . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

3.1.2 Mantksal ³lemler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

3.2 Seçim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

4 Türetilmi³ Veri Tipleri 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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

6.9 Varsaylan Parametreler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

7.5 Statik De§i³kenler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

7.6 Adres Aktarm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

8.7 Katarlar ile Giri³-Çk³ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

8.8 kili Dosyalar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182

B.5 Ba³arm nceleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183


Ç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 karayol-
laryla 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 stanbul-
Ankara 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 yeterli-
dir; bu durumda da do§ru parçalaryla modellemek yolun uzunlu§unun bulunmasnda
zorluk çkaracaktr.

Istanbul Istanbul

Ankara Ankara

Izmir 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) anlatabil-
meniz 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§lanma-
ldr:

• Her admda ne yaplaca§ açk olarak belli olmal, hiçbir ³ekilde yorum gerektir-
memelidir. 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 prog-


ramda 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 isim, enlem bilgisini enlem
ve boylam bilgisini boylam 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 ³eh-
rini temsil etmek için isim de§i³kenine stanbul, enlem de§i³kenine 41, boylam de§i³kenine
29 de§erleri verilmelidir (“ekil 1.2).
1

isim enlem boylam

"Istanbul" 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:
2

enlem ← 41. 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

Atama i³lemi bir matematiksel e³itlik de§ildir. Örne§in 41 ← enlem atamasnn bir anlam
yoktur. Benzer ³ekilde, i ← i + 1 atamas, i de§i³keninin de§erinin o anki de§erine göre bir
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-
mektir. Sözgelimi, say1 de§i³keninin de§eri 32 ve say2 de§i³keninin de§eri 154 ise bu i³lem-
den sonra say1 de§i³keninin 154, say2 de§i³keninin de 32 de§erini almas istenir (“ekil 1.3).
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 isim de§i³keni
New York, boylam de§i³keni -74, enlem de§i³keni 40 de§erini almaldr.
2
Bu i³lem için programlama dilleri genelde = ya da := i³aretini kullanrlar.
Veriler 4

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, say2 de§i³ke-
ninde ise bir de§i³iklik olmaz. kinci atama i³lemi (“ekil 1.4b) ise say2 de§i³kenine say1
de§i³keninin o anki de§erini atad§ndan say2 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³

Birinci atama (“ekil 1.5a) sonucunda ara de§i³keni 32 de§erini alr. kinci atamada (“ekil 1.5b)
say1 de§i³kenine 154, üçüncü atama (“ekil 1.5c) sonucunda da 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
yoktur.

sayi1 sayi2 ara

32 154 xxx

(a)

sayi1 sayi2 ara

32 154 32

(b)

sayi1 sayi2 ara

154 154 32

(c)

sayi1 sayi2 ara

154 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 orta-
lamas, bir saynn karekökü gibi bilgiler.
Veriler 6

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.

simge Birinin adnn ba³ har, programn çal³mas srasnda  Devam etmek istiyor
musunuz (E/H)? 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 bir-
birine 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: Den-
nis 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 tam-
saylardr ancak bunlar tamsay olarak temsil etmenin bir anlam yoktur çünkü
ö§renci numaralar üzerinde aritmetik i³lem yapmak gerekmeyecektir (iki ö§renci-
nin 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 tip-
ten 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
ve boylam) üç alan olacaktr (“ekil 1.6a). Bu tipten diyelim bir ba³kent de§i³keni tanmlan-
d§nda, de§i³kenin alanlarna eri³mek için  ba³kent kentinin ismi, ba³kent kentinin enlemi
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 ← Ankara ve
tem.kod ← E-6 gibi).

1.1.3 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 not1, not2,
· · ·, not50 gibi ayr ayr 50 tamsay de§i³ken tanmlanaca§na, notlar adnda 50 elemanl

3
Bu de§erler örneklerde D ve Y ³eklinde ksaltlacaktr.
7 Giri³

baskent
kent kent

isim isim "Ankara"

enlem enlem

boylam boylam

(a) (b)

“ekil 1.6: Kayt tipinden de§i³ken örne§i.

tem

yol
kod uzunluk

ilk_kent son_kent
isim isim

enlem enlem

boylam boylam

“ekil 1.7: çiçe kaytlar tipinden de§i³ken örne§i.


Veriler 8

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 notlar22 ← 95 ³eklinde
4
gösterilir .

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 adsoyad1
büyüklü§ünün de§eri 'D', adsoyad7 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³ çize-
neklerinde ³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 bulu-
nan 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 yu-
varlak 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.


Algoritmalar 10

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 ise 3. adma, de§ilse 5. adma git.

3. notlari > max ise max ← notlari


4. i ← i + 1 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

Y
i ≤ 50

D bas: max

D
notlari > max
dur

Y 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 i i ≤ 6 notlari > max


43 2 D (2 < 6) D (74 > 43)
74 3 D (3 < 6) Y (65 < 74)
4 D (4 < 6) Y (58 < 74)
5 D (5 < 6) D (82 > 74)
82 6 D (6 = 6) Y (37 < 82)
7 Y (7 > 6)

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§i-
nizde 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 ise buldun, dur

3. söylenen ← söylenen + 1 ve 2. adma dön

Algoritma 2. 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:
Algoritmalar 12

basla

alt ← taban
üst ← tavan

söylenen ← (alt + üst) / 2

D
söylenen = tutulan

Y bas: söylenen

Y D dur
söylenen > tutulan

alt ← söylenen + 1 üst ← söylenen - 1

“ekil 1.12: Say tahmin etme algoritmasnn ak³ çizene§i.

alt üst söylenen söylenen = tutulan


1 63 32 Y (32 > 19)
31 16 Y (16 < 19)
17 24 Y (24 > 19)
23 20 Y (20 > 19)
19 18 Y (18 < 19)
19 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 al-
goritmann ö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 kul-
landklarna 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 konu-


sudur. 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 uy-
gulamalarda 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.
Soyutlama 14

D Y Y
blok1 kosul
kosul

blok2 blok1 blok2 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 söylenen > tutulan ko-
³uluyla belirlenen seçim yaps, söylenen = tutulan 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 prog-
ramlamada yineleme için özel yaplar vardr ve goto komutunun kullanlmamas özendirilir.
5

1.4 Soyutlama

Programlamann temel düzeneklerinden biri soyutlama kavramdr. Soyutlama, programn ya-


paca§ 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 yuka-
rdan 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 üst-
yordam, 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³l-


maz; 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 http://www.acm.org/classics/oct95/ adresinde bulabilirsiniz.
6
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-3

alt-is-1a 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 (üst-
yordamla 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 yorda-
mn 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:


Soyutlama 16

1. 9702 = 2 * 3 * 3 * 7 * 7 * 11 = 2
1 * 32 * 72 * 111

2. 945 = 3 * 3 * 3 * 5 * 7 = 3
3 * 51 * 71

3. ortak çarpanlar: 3
2 * 71

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 or-
taya ç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

1. sayinin
2. sayi çarpanlari

2. sayinin
çarpanlari

1. sayinin
ortak
çarpanlari
çarpanlar
2. sayinin
asal çarpanlari ortak
çarpanlara çarpanlari
ayir 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

asal 33 × 5 × 7
ortak
çarpanlara çarpanlari
ayir 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 r1 = 0 ise iki saynn en büyük ortak böleni b'dir. De§ilse a
ile b saylarnn en büyük ortak böleni b ile r1 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

Her denklem için en büyük ortak böleni alnacak saylardan büyük olann a, küçük olann b
de§i³keninde, bu ikisinin bölümünden kalan de§eri de r de§i³keninde tutarsak (kalan i³lemi %
i³aretiyle gösterilsin), bu algoritma bir yineleme yapsyla gerçeklenebilir. Bir bölme i³leminde
Soyutlama 18

her zaman kalan, bölenden küçük olaca§ için her yinelemede a de§i³keni b'nin, b de§i³keni
de r'nin de§erini alarak ilerlenir ve b 0 oldu§unda en büyük ortak bölen a 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

sayi1 > sayi2


D Y

a ← sayi1 a ← sayi2
b ← sayi2 b ← sayi1

Y
b>0

D
bas: a

r←a%b
a←b
b←r

“ekil 1.17: Euclides algoritmasnn ak³ çizene§i.

a b r
9702 945 252
945 252 189
252 189 63
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 x asal çarpanlarna ayrlacak sayy, c çarpan olup olmad§ o anda
7
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

Y
x>1

Y
x%c=0

c bir carpandir
u←0

Y
x%c=0

u←u+1
c ← sonraki asal sayi
x←x/c

“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 çarpanla-
rn 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 çarpa-
nn, 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.
Soyutlama 20

x c x > 1 x % c = 0 carpan u
945 2 D (945 > 1) Y (945 mod 2 = 1)
3 D (945 > 1) D (945 mod 3 = 0) 3 0
D (945 mod 3 = 0) 1
315 D (315 mod 3 = 0) 2
105 D (105 mod 3 = 0) 3
35 Y (35 mod 3 = 2)
5 D (35 > 1) D (35 mod 5 = 0) 5 0
D (35 mod 5 = 0) 1
7 Y (7 mod 5 = 2)
7 D (7 > 1) D (7 mod 7 = 0) 7 0
D (7 mod 7 = 0) 1
1 Y (1 mod 7 = 1)
11 Y (1 = 1)

Tablo 1.4: Asal çarpanlarna ayrma algoritmasnn i³leyi³i.

c1 c2 taban us carpan
2
1 3
3 2 < 3
3
2 3= 3 2 < 3 3
2

7
2 5
1 7 > 5
7
1 7= 7 1 < 2 7
1

11
1 -

Tablo 1.5: Ortak çarpanlar bulma algoritmasnn i³leyi³i.


21 Giri³

c1 ← carpanlar11, c2 ← carpanlar21
i1 ← 1, i2 ← 1

c1 ve c2 Y
bos değil 1

D i1 ← i1 + 1
c1.taban < c2.taban
c1 ← carpanlar1i1

D i2 ← i2 + 1
c1.taban > c2.taban
c2 ← carpanlar2i2

D Y
c1.us < c2.us

c1 bir carpandir c2 bir carpandir

i1 ← i1 + 1, i2 ← i2 + 1
c1 ← carpanlar1i1, c2 ← carpanlar2i2

“ekil 1.19: Ortak çarpanlar bulma algoritmas.


Giri³ / Çk³ 22

1.5 Giri³ / Çk³

Bir programlama dilinin kullanlabilir olmas için dilde blok yapl programlamann kavramla-
rn desteklemenin d³nda baz gereklilikler de yerine getirilmelidir:

Giri³ Bir program her seferinde ayn veri de§erleri üzerinde çal³maz, i³leyece§i verileri ça-
l³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çe-
nekler 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 denetle-
yen 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 giril-
mesi, 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 kulla-
ncnn 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, prog-
ramn 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-
liyle yazlr. Bunun sonucunda yazlmn kaynak kodu olu³ur.
8 Kaynak kodunu bilgisayar

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³ program-
larda 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 ku-
rallarna uymuyordur.

2. Mantk hatalar: Programcnn yazd§ kod dilin kurallar açsndan do§rudur ama ça-
l³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, bil-
gisayardan bilgisayara ve i³letim sisteminden i³letim sistemine göre farkllklar gösterir. Sözge-
limi, 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 üze-
rinde 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 prog-
ram 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 bilgisa-
yar 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 maki-
nay 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 yapl-


d§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 ilerleye-
bilir. 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 tasarlan-
m³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 prog-
ramc, 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 program-
cya 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 k-
smlarna 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 stan-
dartla³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 kitap-
lklarda 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 ara-
sndaki 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
Program Geli³tirme 26

kitaplklar geli³tirmi³lerdir. Dolaysyla bu kitaplklar kullanlarak yazlan programlar tam an-


lamyla ta³nabilir olmamakta, yalnzca bu kitapl§n destekledi§i ortamlara ta³nabilmekte-
dir. 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 baglama

kaynak kodu 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 yor-
damnn 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


durum de§erlerini kendiniz çkarn. Alt snrn 1, üst snrn 2
n - 1 ³eklinde verildi§i genel

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 hesap-
lamak için bir algoritma geli³tirin.
27 Giri³

4. Euclides algoritmasnda iki saydan büyük olannn hangisi oldu§una baklmakszn a


de§i³kenine say1, b say2 de§erleri atanarak yineleme yapsna girildi§ini
de§i³kenine
varsayalm. Ba³langçta say1 > say2 ya da say1 < say2 olmas durumlarnda al-
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çeklen-
dikleri ü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 veril-
mi³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 kulla-
nld§ 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 ³e-
kilde yazlabilir:

• Birinci yöntemde, açklamann ba³na bölü-yldz, sonuna yldz-bölü simgeleri ko-


nur. Bu ³ekildeki açklamalar birden fazla satr sürebilir. Örnekteki birinci açk-
lama birinci satrdaki  lk C programm sözcükleriyle ba³lar ve üçüncü satrdaki
 alann hesaplar. 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> // cout,cin,endl için


#include <stdlib.h> // 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 /* gö-
zard edilir ve gelen ilk */ açklamay sona erdirir; yani açklamay b ve c bölgeleri
olu³turur. Bundan sonra gelen bölüm (d bölgesi) normal C kodu gibi de§erlendiri-
lece§inden hataya yol açar.

• kinci yöntemde, açklama çift bölü ile ba³lar ve satrn sonuna kadar sürer.
1 Ksa

açklamalar için bu yöntem daha kullan³ldr. Örnekteki ikinci açklama be³inci


satrdaki  cout,cin,endl için sözcüklerinden olu³ur. Üçüncü açklama da altnc
satrdaki  EXIT_SUCCESS için sözcüklerini kapsar.

Komutlar 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 (girinti-
leme ). 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, 2 * PI * radius deyiminin sonucunu circum de§i³ke-


nine atar.
2
1
Bu açklama yöntemi C++ ile getirilmi³ bir yeniliktir, C dilinde geçerli de§ildir.
2
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;
simler 32

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 ge-
rekir. Bu bilgilerin yer ald§ ba³lk dosyalar program ba³nda #include komutuyla
belirtilir. Örne§in cout birimi iostream ba³lk dosyasnda bulundu§undan örnek prog-
ramda

#include <iostream>

komutu yer almaktadr.


3 Benzer ³ekilde, EXIT_SUCCESS sözcü§ünün kullanlabilmesi için
stdlib.h dosyas içerilmelidir.

Bir kitaplktan yararlanaca§nz zaman gerekli bilgilerin hangi ba³lk dosyalarnda yer al-
d§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. Stan-
dartlara girmemi³ fonksiyonlar içinse kulland§nz derleyici ve kitaplklarn yardmc
belgelerine ba³vurmalsnz.
4

2.1 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 pi, weight, weight1 ve weight_1 geçerli isimlerdir, ancak π , a§rlk ve
weight-1 geçerli isimler de§ildir.

• smin ilk simgesi bir rakam olamaz. Bu kurala göre 2weight geçerli bir isim de§ildir.

3
C standardnda ba³lk dosyalarna .h uzants verilir. C++ standardnda ise baz ba³lk dosyalarnn uzan-
ts bulunmayabilir. Örnekteki iostream ba³lk dosyas C++ ile tanmlanm³ yeni ba³lk dosyalarna bir ör-
nektir.
4
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 olma-
yan iki ismin farkl olaca§ kesindir ama aynlarsa derleyici bu iki ismin farkl olmad-
population_increase_between_years_2000_and_2001 ile
§na karar verebilir. Örne§in
population_increase_between_years_2001_and_2002 isimli iki de§i³ken tanmlanrsa
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 cout isimli bir de§i³ken kullanlabilir ancak
bu durumda çkt için kullanlan cout kitaplk biriminden artk yararlanlamaz.

Büyük projelerde isim çak³malar sorun yaratmaya ba³lar. Bu durumu düzeltmek ama-
cyla 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 ve endl de§erlerine kolay eri³imi sa§lar;
kullanlmazsa bu de§erlere eri³im için ba³larna std:: eklemek gerekir:

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 x4szb gibi
anlamsz ya da height gibi yanltc isimler verilmez.

• Anlaml isimler verilmek istendi§inde bazen birden fazla sözcü§e gereksinim duyulabi-
lir. Bu durumda ya ismi olu³turan iki sözcük bir altçizgi i³aretiyle birle³tirilir (örne§in
birth_month) ya da ikinci sözcük büyük hare ba³lar (örne§in birthMonth).

2.2 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.
De§i³kenler 34

Kesirli saylarn do§al gösterilimi noktal gösterilimdir, ancak istenirse bilimsel gösterilim
(mantis * 10
us ) de kullanlabilir. Örnekte 3.14 says noktal gösterilimde yazlm³ bir ke-

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 circum ve area de§i³kenlerinin her ikisine de 0.0 de§eri verilir,
radius de§i³kenine bir ba³langç de§eri verilmez.

Gelenek 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
lacak bütün de§i³kenlerin tanmlar bittikten sonra komutlar ba³lar.
5 Tanmlarn sona erdi§i

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):

tamsay int sakl sözcü§üyle belirtilir. Bu veri tipi short ve long belirteçleriyle geli³tirile-
rek ksa tamsay (short int) ve uzun tamsay (long int) tipleri olu³turulabilir.
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-
lir) de§er alacaksa i³aretsiz olarak tanmlamak için unsigned sözcü§ü kullanlabi-
lir. Ksacas, 6 adet tamsay tipi vardr: int, short int, long int, unsigned int,
unsigned short int ve unsigned long int.
kesirli say float 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 true ya da false de§erini
alabilirler.
6

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 tanmlama-
malsnz. 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
C++ dilinde komutlar ba³ladktan sonra da de§i³ken tanmlanabilir. C dilinde buna izin verilmez.
6
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.
De§i³mezler 36

2.5 De§i³mezler

Programda kullanlan baz bilgiler de programn farkl çal³malar arasnda de§er de§i³tirmez-
ler. Ö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.
Örnekte yaplan 3.14 saysna PI ismini vermektir. Bu bildirimin sonucu, programcnn
kod içinde PI geçen her yere kendisinin 3.14 de§erini yazm³ olmasyla ayndr. Bu ³ekilde
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 long int varsaylrlar. De§erlerinin sonuna l ya da L hareri
eklenirse long, u ya da U eklenirse unsigned belirteci seçilmi³ olur.

#define MAXSHORT 0x7FFF


#define MAXUSHORT 65535U

Kesirli de§i³mezlerin de§erlerinin sonuna f ya da F eklenmemi³se double tipinden ol-


duklar varsaylr. l ya da L eklenirse long double tipinden olurlar.

#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
hata verir.
7

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: + i³leciyle gerçeklenir.

• Çkartma: - i³leciyle gerçeklenir.

• Çarpma: * i³leciyle gerçeklenir.

• Bölme: / i³leciyle gerçeklenir.

• Kalan: % i³leciyle gerçeklenir. Yalnzca iki tamsay arasnda yaplabilir, kesirli saylarda
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
Tip Dönü³ümleri 38

C deyimi

e
a+b+c+d+
5

aritmetik deyimine kar³ dü³er.

Örnek.

p * r % q + w / x - y

deyimi ³u srayla hesaplanr:

t1: p * r
t2: t1 % q
t3: w / x
t4: t2 + t3
t5: t4 - y

2.7 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 quotient de§i³keni 3.0 de§erini alr. ³lemin do§ru olarak yaplmasn sa§la-
mak için num1 ve num2 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 is-
tenen 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 ti-
pinden 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;
Matematik Kitapl§ 40

³eklinde ksaltlabilir. Örne§in:

a += 5; // a = a + 5;
a /= 2; // a = a / 2;
a *= c + d; // a = a * (c + d);

Buna göre, bir de§i³kenin de§erini artrmak ya da azaltmak için a³a§daki komutlar kullan-
labilir:

a = a + 1; a += 1;
a = a - 1; a -= 1;

Ancak artrma ve azaltma i³lemleri programlarda skça gereksinim duyulan i³lemlerden olduk-
larndan C'de bunlar için özel i³leçler tanmlanm³tr. ++ i³leci, önüne ya da arkasna yazld§
de§i³kenin de§erini 1 artrr; -- i³leciyse önüne ya da arkasna yazld§ i³lecin de§erini 1 azaltr.
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 fonk-
siyonlardaki 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) trigonometrik fonksiyonlar


asin(x) acos(x) atan(x) ters trigonometrik fonksiyonlar
sinh(x) cosh(x) tanh(x) hiperbolik trigonometrik fonksiyonlar
exp(x) ex
log(x) log10(x) e ve 10 tabannda logaritma fonksiyonlar
pow(x,y) xy

sqrt(x) x
floor(x) ceil(x) alt ve üst snr fonksiyonlar: bxc dxe
fabs(x) |x|

Tablo 2.1: Matematik kitapl§ fonksiyonlar.

Trigonometrik fonksiyonlarda giri³ parametresi derece de§il radyan cinsinden verilmelidir; ör-
ne§in sin(30) deyimi 0.5 de§il -0.988032 de§erini üretir. 30 derecenin sinüsünü almak için
sin(30*3.141529/180) ya da sin(3.141529/6) deyimini yazmak gerekir.
Alt ve üst snr fonksiyonlarnn çal³masnda giri³ parametresinin pozitif ya da negatif olma-
sna 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 cin biriminden alnrken, çktlar cout, hatalar da cerr biriminebirimine
gönderilir.
9

Ö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).
Giri³ / Çk³ 42

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 belir-
tilebilir. 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 de-
yimlerin 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
satra geçer. Programda circum ve area de§i³kenleri tanmlanmadan ve atama komutlar
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 veril-


mesi istenmektedir. Grak bir editör (kate) tantlacak ve C derleyicisinin nasl kullanlaca§
ö§retilecektir. Basit hatalarda derleyicinin hangi mesajlar üretti§i gözlenecektir.
10

Ö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. x için 0.002 de§erini verdi§inizde
y'nin 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.

• De§i³ken tanmlarnn yapld§

10
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> // cout,cin.endl
#include <stdlib.h> // EXIT_SUCCESS
#include <math.h> // 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 PI de§i³mezinin tanmland§


#define 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.
Giri³ / Çk³ 44

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:

1
2ab− cd efh−g
k←
x(y + z)

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

kinci dereceden (ax


2 + bx + c = 0 ³eklinde) bir denklemin köklerinin yerlerini belirleyen bir
program yazlmas isteniyor. Diskriminantn b2 − 4ac ³eklinde tanmland§n ve köklerin


−b ± b2 − 4ac
x1,2 =
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 kul-
lancya bildirilir.

• Denklemin iki farkl gerçel kökü varsa (diskriminant pozitifse) bunlar hesaplanarak ek-
rana ç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> // cout,cin,endl
#include <stdlib.h> // EXIT_SUCCESS
#include <math.h> // 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 verilme-
sinin sa§lanmas gerekti§i görülmü³tü (bkz. Bölüm 1.3). Ko³ullar, ko³ul deyimleriyle gösteri-
lirler. 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'


Ko³ul Deyimleri 48

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 say-
lar 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 ol-
maz. Ö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 olur-
lar. 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.
Seçim 50

(year % 400 == 0) || (year % 4 == 0) && (year % 100 != 0)

biçiminde de yazlabilirdi.
2

3.2 Seçim

C dilinde seçim yaplar, if/else bloklaryla gerçeklenir. Verilen ko³ul deyimi do§ru de§erini
alyorsa if 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)


deyiminde (year % 4 == 0) ko³ulu yanl³ de§erini verirse deyimin geri kalanna baklmaya gerek kalmayaca-
§ndan (year % 100 != 0) ko³ulu snanmaz. Benzer ³ekilde
(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³ olma-
sna 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§erlendi-
rilirler. 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 ;
}
Seçim 52

³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 else'in
kendinden önce gelen son if ko³uluna ba§land§dr, yani örnekte blok2 , ko³ul1 do§ru ve
ko³ul2 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 yan-
l³, 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³trmala-
rnda 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 belirtil-
di§inden age de§i³kenine 18 atanr, deyimin de§eri 18 olarak bulunur ve 0'dan farkl oldu§u
için do§ru saylarak blok1 yürütülür. Oysa == simgesi kullanlsayd age de§i³keninin de§eri
de§i³mez ve blok2 yürütülürdü.
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 prog-
ram 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 kodu ³u tip bir ³ey olurdu:

if (op == '+') {
...
} else {
Çoklu Seçim 54

Örnek 4 Kullancnn belirtti§i i³lemi yapan program.


#include <iostream> // cin,cout,endl
#include <stdlib.h> // 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: ...
...
}
Çoklu Seçim 56

D
case 1 blok 1 break

D
case 2 blok 2 break

D
case n blok n break

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 break komutlarnn unutulmasdr.


Örne§in birinci blo§un sonuna konmas gereken break komutu unutulursa switch komutu
“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 break ile switch
sonlanr. Yani, ba³arl olan ilk kar³la³trmadan ba³lanarak break komutu görülene kadar
gelen bütün bloklar yürütülür.
3

Örnek programdaki hiçbir 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 Dev-
C++) 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).
Çoklu Seçim 58

D
case 1 blok 1

D
case 2 blok 2 break

D
case n blok n break

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 ya-
zlmas 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 sözcü§üyle kurulur:

while (ko³ul ) {
blok ;
}
Ko³ul Denetiminde Yineleme 60

Örnek 5 ngiliz-metrik birim dönü³ümü yapan program.


#include <iostream> // cout,cin,endl
#include <stdlib.h> // 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> // cin,cout,endl
#include <stdlib.h> // 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;
}
Döngü Denetimi 62

Ö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 sonlan-
masnn 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
düzenlenebilseler de, yineleme yaps kurmak için genelde while kullanlmas önerilir.

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;
}
...
}

Bu örnekte if ile belirtilen ko³ul sa§lanyorsa birtakm i³lemlerin gerçekle³tirilmesinden sonra


döngünün ba³na dönülür. Yani if blo§undan sonra gelen komutlar atlanarak i de§i³keninin
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 count
de§i³keniyle belirlenir.
Sayaç Denetiminde Yineleme 64

basla

oku: count

i←1
heads ← 0
tails ← 0

Y
i ≤ count

D bas: heads
bas: tails

Tura Yazi
at

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> // cin,cout,endl
#include <stdlib.h> // EXIT_SUCCESS,srand,rand,RAND_MAX
#include <time.h> // 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;
}
Sayaç Denetiminde Yineleme 66

• Kaçar kaçar saylaca§: Örnekte sayacn birer birer artrlaca§ belirtilmi³tir.

for 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


küçük veya e³it oldu§u sürece blo§u her yürütü³ünden sonra i de§i³keninin de§erini
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 for, ko³ul denetiminde
yinelemeler için while 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 i
de§i³keninin 1, 2, ..., count 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.

C standart kitapl§ndaki rand fonksiyonu 0 ile RAND_MAX arasnda bir rasgele tamsay üretir.
RAND_MAX standart kitaplkta tanmlanm³ bir de§erdir ve sistemden sisteme farkllk göstere-
bilir. rand fonksiyonundan gelen say RAND_MAX de§erine bölünürse 0 ile 1 arasnda bir rasgele
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 sa-
ydan ü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.
Sayaç Denetiminde Yineleme 68

Örnek 8. Seri Toplam

Bu uygulamada görülecek programlarda, ex fonksiyonunun hesaplanmas için a³a§daki seri


toplamndan yararlanlacaktr:


X xi x2 x3 x4
f (x) = =1+x+ + + + ···
i=0
i! 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> // cin,cout,endl
#include <stdlib.h> // EXIT_SUCCESS
#include <math.h> // 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) yapla-
xi
bilece§i görülecektir. Serinin genel teriminin ai = i! oldu§u gözönüne alnd§nda dizide bir
ai
elemann kendisinden önceki elemana bölümü
ai−1 = xi olarak hesaplanabilir. Yani her terim,
kendisinden önceki terimin x ile çarplp i'ye 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> // cin,cout,endl
#include <stdlib.h> // 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) mantksal deyimini

(a) do§ru yapacak bir x de§eri verin.

(b) yanl³ yapacak bir x de§eri verin.


Sayaç Denetiminde Yineleme 70

(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³ çi-
zene§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ü: bsa = h0.725 ∗ w0.425 ∗ 71.84 ∗ 10−4


Boyde formülü: bsa = h0.3 ∗ w(0.7285−0.0188 log w) ∗ 3.207 ∗ 10−4
Her iki formülde de h de§i³keni cm cinsinden boyu ve bsa de§i³keni de m2 cinsinden beden
alann gösterirken, w de§i³keni kütleyi DuBois formülünde kg, Boyde formülündeyse
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 4

0 1
1 1 1
(
1 j =0∨j =i
2 1 2 1 binomi,j =
binomi−1,j−1 + binomi−1,j aksi durumda
3 1 3 3 1
4 1 4 6 4 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 xi x0 x1 x2 x3 x4 x5
(−1)i = − + − + − + ...
i=0
(2i)! 0! 2! 4! 6! 8! 10!

(a) Bu serinin i. 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 sa-
ylarn ü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 boyutla-
rna göre büyük zorluklar çkarabilir.

Örnek 10. Barbut

Barbut oyununun kurallar ³öyledir:


1

• 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.

Verilen örnek, bu oyunu simüle eden bir programdr. Bu örne§in ilginç bir yönü switch yaps-
nn baz durumlarnda kastl olarak break kullanlmamasdr. Böylelikle durumlar gruplanarak
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 = 5
Say: 5
Zarlar: 5 + 1 = 6
Zarlar: 5 + 5 = 10
Zarlar: 6 + 5 = 11
Zarlar: 4 + 1 = 5
Oyuncu kazanr.

“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> // cin,cout,endl
#include <stdlib.h> // EXIT_SUCCESS,srand,rand
#include <time.h> // 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;
Numaralandrma 76

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ön-
temi 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 enum status_e isimli bir tip olu³turulmu³, daha sonra
da bu tipe typedef 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 numa-
ralandrmayla 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
1 1 1
R1 + R2 + ··· + Rn

Buna göre, kullancdan ald§ dirençlerin paralel e³de§erini hesaplayarak sonucu ekrana çkar-
tan 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§eri-
nin 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 uy-
gun ³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 kullan-
labilir.
Numaralandrma 78

Örnek 11 Paralel direnç e³de§eri hesaplayan program.


#include <iostream> // cin,cout,endl
#include <stdlib.h> // 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 ol-
du§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 typedef komutuyla
yeni bir isim verilmi³tir.
3

Yap tipinden de§i³ken tanmlanrken istenirse künyeli isim, istenirse 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 res ve equiv isimlerinde, her biri birer rasyonel say
yapsnda olan iki de§i³ken tanmlarlar ve 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.
Yaplar 80

rational_t res, equiv = { 0, 1 };


struct rational_s res, equiv = { 0, 1 };

res equiv

nom nom

0
denom denom

“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 x ve y , daire
merkezinin koordinatlar xc ve yc , dairenin yarçap r ile gösterilirse:
p
(x − xc )2 + (y − yc )2 < r ise nokta dairenin içinde
p
(x − xc )2 + (y − yc )2 > r ise nokta dairenin d³nda
p
(x − xc )2 + (y − yc )2 = r ise nokta dairenin üzerindedir.

• Program yazarak çal³trn.

• Merkez noktasnn koordinatlarn (2.1,5.664), yarçapn 3.2, aranan noktann koordinat-


larn (5.3,5.664) olarak verin. Bu nokta dairenin neresindedir? Program ne çkt veriyor?
Hatalysa neden hataldr ve nasl düzeltilebilir?
Yaplar 82

Örnek 12 Noktann daireye göre konumunu bulan program.


#include <iostream> // cout,cin,endl
#include <stdlib.h> // 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³medik-


lerini 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 “e-
kil 5.1'de verilmi³tir.

Ö§renci says n, i. ö§rencinin notu si , ortalama m, varyans v, standart sapma sd, mutlak
sapma ad ile gösterilirse:

Pn
i=1 si
m =
Pn
n
i=1 (si − m)2
v =
n−1

sd = v
Pn
i=1 |si − m|
ad =
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³it-
P
likteki i³aretine kar³ dü³er).

3. Varyans ve standart sapma için gereken, her bir notun ortalamayla farklarnn karelerinin
P
toplamn hesaplamakta kullanlan döngü (ikinci e³itlikteki i³aretine kar³ dü³er).

4. Mutlak sapma için gereken, her bir notun ortalamayla farklarnn mutlak de§erlerinin
P
toplamn hesaplamakta kullanlan döngü (dördüncü e³itlikteki i³aretine kar³ dü³er).

85
86

Örnek 13 Çe³itli istatistik hesaplar yapan program.


#include <iostream> // cin,cout,endl
#include <stdlib.h> // EXIT_SUCCESS
#include <math.h> // 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 bun-
lar 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§in-
den 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 yitiriliyor-
lard. 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
kaç eleman bulundu§unu, veri_tipi ise her bir elemann hangi tipten oldu§unu belirtir.
Ö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:
Tek Boyutlu Diziler 88

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³ama-
snda 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 de§i³keniyle gösterilmektedir, yani dizinin
no_students 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, dizi-
nin 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 prog-
ramn 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 belirt-
mek 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
geçerli elemann sra numarasno_students - 1 olacaktr:

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 snrla-
rndan 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 bu-
lunursa 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.
Tek Boyutlu Diziler 90

Ö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 <iostream> // cin,cout,endl
#include <stdlib.h> // EXIT_SUCCESS
#include <stdio.h> // gets
#include <string.h> // 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 algo-
ritmasn 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öz-
konusu 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[0] eleman 'D', sentence[6] eleman
' ', sentence[13] eleman '.', sentence[14] eleman '\0' de§erlerini alrlar.
Katar Kitapl§ 92

Katar tipinden de§i³kenlerin cout birimi yardmyla çktya gönderilmelerinde herhangi bir
sorun olmazken, 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
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³tr-
mak 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 fgets
fonksiyonunun kullanlmas önerilir (bkz. Bölüm 8).
2
Daha ayrntl açklama için bkz. Bölüm .7.3.
93 Diziler

Ad ³levi

strlen(s) katar uzunlu§u


strcopy(dest,src) strncpy(dest,src,n) katar kopyalama
strcmp(s1,s2) strncmp(s1,s2,n) katar kar³la³trma
strcat(dest,src) strncat(dest,src,n) 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 katarnn de§erini dest katarnn üstüne yazarken, strncpy
fonksiyonu da ayn i³levi görür, ancak en fazla n simgeyi kopyalar. Güvenlik açsndan uzunluk
denetimi yapan fonksiyonlarn kullanlmas önerilir.
3

Katar kar³la³trma fonksiyonlar giri³ parametresi olan katarlar arasnda ngilizce dilinin ku-
rallarna 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);

Derleyici author1 katarna 6 simgelik, author2 katarnaysa 7 simgelik yer ayracaktr. Daha
sonra author1 katarnn üstüne author2 katar yazlmaya kalkld§nda author1 katarnda
yeterli yer olmad§ için bu de§i³kenin snrlarndan ta³lr. Benzer ³ekilde, biti³tirme i³lem-
lerinde 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.
Çok Boyutlu Diziler 94

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 x de§eri için p(x)'in hesaplanmas
n(n+1)
2 adet çarpma ve n 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

O halde bir b de§eri, ba³langçta b = an ve i. admda b = bx+an−i olacak ³ekilde hesaplanarek


gidilirse a0 katsaysnn da toplanmasyla elde edilecek b de§eri hesaplanmak istenen p(x) de§eri
olur. Yaplmas gereken i³lem says da n çarpma ve n toplamaya iner.

• Ç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 mat-
risi ç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> // cin,cout,endl
#include <stdlib.h> // 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;
}
Çok Boyutlu Diziler 96

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> // cin,cout,endl
#include <stdlib.h> // 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;
}
Ba³vurular 98

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 } };

" #
1 2 1
tanm m= matrisini olu³turur. Tek boyutlu dizilerdekine benzer ³ekilde { 0 }
3 5 1
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

Ba³vurular, ayn de§i³kene ikinci bir isim verilmesini sa§larlar.


4 Örnekte sol matrisin satr

says ile sa§ matrisin sütun saylarnn ayn olmas zorunlulu§u nedeniyle bu bilgiyi tek bir
de§i³kenle temsil etmek yeterli görülmü³ ve cl de§i³keni tanmlanm³tr. Ancak döngülerde
anla³lrl§ artrmak amacyla rr de§i³keninin de tanmlanmasnn yararl olaca§ dü³ünülerek
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
durumda cl de§i³keni kullancdan okunduktan sonra rr = cl ³eklinde bir atamayla i³lem sür-
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
i = 2, 3, . . . , n. denklemlerinden x1 yok edilir (birinci denklem aa11
i1
ile çarplp i. denklem-
den ç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 denk-
leme 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 de§eri n. denklemden do§rudan hesaplanr. Bu de§er n − 1. denklemde yerine ko-


nursa xn−1 bulunur ve böylece geriye do§ru yerine koyma i³lemleriyle bütün bilinmeyen
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:


   
1 1 0 3.5
ba³langçta: a =  1 −1 5  b =  11 
   
2 −1 1 3.3
   
1 1 0 3.5
x1 'in yok edilmesinden sonra: a =  0 −2 5  b =  7.5 
   
0 −3 1 −3.7
   
1 1 0 3.5
x2 'nin yok edilmesinden sonra: a =  0 −2 5  b =  7.5 
   
0 0 −6.5 −14.95
Son denklemden x3 = 2.3 elde edilir. Bu de§er ikinci denklemde yerine konursa:−2x2 + 5x3 =
7.5 denkleminden x2 = 2 ve bu de§er birinci denklemde yerine konursa x1 + x2 = 3.5 denkle-
minden x1 = 1.5 bulunur.

Gauss eliminasyon yöntemini kullanarak n bilinmeyenli bir denklem takmn çözen program
Örnek 17'da verilmi³tir.
Ba³vurular 100

Örnek 17 Gauss eliminasyon yöntemiyle denklem takm çözen program.


#include <iostream> // cin,cout,endl
#include <stdlib.h> // 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ükle-
rin ö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 ola-
bilir. Ö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 kav-
ramnn ö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 üret-
ti§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(); // do§rudan atama


number = rand() % 6; // deyimde kullanma
srand(time(NULL)); // ba³ka fonksiyona gönderme

Çk³ parametrelerinin kullanmnda tip uyumuna dikkat edilmelidir. Sözgelimi, rand fonksi-
yonu tamsay tipinden bir de§er döndürdü§üne göre number de§i³keni de tamsay tipinden
olmaldr, katar tipinden olamaz.
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 yol-
lamaldr.

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 iste-
niyor. 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 sa-
ylarn 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
Aslnda bu durumlarn hepsi deyimde kullanma olarak de§erlendirilebilir.
2
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> // cin,cout,endl
#include <stdlib.h> // 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;
}
Fonksiyon Bildirimi ve Tanm 106

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 belir-
tilmesi 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. Gi-
ri³ 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 an-
cak 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 bildiril-
mesini 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§lay-
cnn görevidir.
107 Fonksiyonlar

• Fonksiyonun gövdesi, fonksiyonun yapaca§ i³leri belirten bloktan olu³ur, yani fonksi-
yonun i³ini NASIL yapt§n anlatr. Bir fonksiyonun bütününün, yani giri³/çk³ para-
metrelerinin 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.
Ça§rlan fonksiyon üretti§i de§eri ça§ran fonksiyona return komutu yardmyla döndü-
rür. 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ür-
mektedir. next_prime fonksiyonuysa tamsay tipinden tanmlanm³tr ve döndürdü§ü
de§eri tutan de§i³ken de (cand) tamsay tipindendir.

Bir fonksiyon ça§rsnn yaplabilmesi için ça§rlan fonksiyonun ya bildirimi ya da tanm ça-
§ran fonksiyondan önce yaplmaldr. Örnekte main next_prime fonksiyonunu,
fonksiyonu
next_prime fonksiyonu da is_prime fonksiyonunu ça§rr. Birinci ça§r, next_prime fonksiyo-
nunun 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
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 fonksi-


yonun ba³l§nda belirtilen liste uyumlu olmaldr. Ça§rda yazlan her de§er, ça§rlan fonk-
siyonun 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. Fonksiyo-
nun 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 de§i³keninin de§eri is_prime
fonksiyonunun giri³ parametresi olan cand de§i³kenine atanr.
Tipi uygun oldu§u sürece parametre olarak herhangi bir deyim belirtilebilir. Sözgelimi a³a§-
daki ça§rlar geçerlidir:
Yerel De§i³kenler 108

number factor
main 6468 2

prime cand

next_prime

cand count

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


fonksiyonunun giri³ parametresi olan prime de§i³kenine ,  next_prime fonksiyonundaki cand
de§i³keninin de§eri is_prime fonksiyonunun giri³ parametresi olan cand de§i³kenine gibi
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. main fonksiyonun-
daki factor de§i³keni ile next_prime fonksiyonundaki prime 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: next_prime fonksiyonundaki cand
de§i³keniyle is_prime fonksiyonundaki cand de§i³keni de farkl de§i³kenlerdir.

Örnekte ilk fonksiyon ça§rlar ³öyle gerçekle³ir.main fonksiyonunda factor de§i³kenine ba³-
langçta atanm³ olan 2 de§eri 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³ para-
metre 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³ sonu-
cunu ü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
(“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 factor
main 6468 2

prime cand

next_prime 2 3

cand count

is_prime

“ekil 6.3: Parametre aktarm örne§i - 2. adm.

number factor
main 6468 2

prime cand !is_prime(cand)

next_prime 2 3

true
cand count

is_prime 3 3

“ekil 6.4: Parametre aktarm örne§i - 3. adm.

number factor
main 6468 2

prime cand

next_prime 2 3

cand count

is_prime 3 3

“ekil 6.5: Parametre aktarm örne§i - 4. adm.


Genel De§i³kenler 110

snrlanr. Örnekteki bütün fonksiyonlarn iki³er (main: number ve factor, is_prime: cand
ve count, next_prime: prime ve 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‡“K-
LKLERN SONUCUNDA OLU“ACAK PROGRAM Y BR PROGRAM OLMAYACAK-
TIR. BU ÖRNEK YALNIZCA GENEL DE‡“KEN KULLANIMINI AÇIKLAMAK AMA-
CIYLA VERLM“TR. next_prime ve is_prime fonksiyonlar aslnda cand de§i³kenini para-
metre olarak aktarmak yerine ortak bir bellek gözünde payla³abilirler. Bu durumda is_prime
fonksiyonunun i³levi bu de§i³kenin de§erinin asal olup olmad§n belirlemek, next_prime
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 ak-
tarmyla 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 cand de§i³keninin yannda bir de
yerel olan cand de§i³keni olu³urdu ve is_prime fonksiyonunun içindeyken genel olan cand
de§i³kenine ula³lamazd.

Genel de§i³kenler parametre aktarm yerine kullanlabilecek bir yöntem olmakla birlikte prog-
ramn anla³lrl§n azalttklar ve fonksiyonlar birbirlerine ba§ml kldklar için gerekme-
dikçe kullanlmamalar önerilir. Soyutlamann kazandrdklarndan birinin ileride bir fonk-
siyonda 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³ik-
likler 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> // cin,cout,endl
#include <stdlib.h> // 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;
}
Ba³vuru Aktarm 112

Örnek 20 ki sayy takas eden fonksiyon ve kullanm (hatal).


#include <iostream> // cin,cout,endl
#include <stdlib.h> // 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 y tmp
swap 32 154 xxx

m n
main 32 154

(a)

x y tmp
swap 154 32 xxx

m n
main 32 154

(b)

“ekil 6.6: Takas fonksiyonunda parametre aktarm.

32 154
32 154

Programn neden istendi§i gibi çal³mad§n inceleyelim: 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 (“e-
kil 6.6a). swap fonksiyonunda x ve y de§i³kenlerinin de§erleri takas edilir ancak ça§ran fonksi-
yondaki m ve n de§i³kenleri bu takastan etkilenmezler ve fonksiyon ça§rsndan dönüldü§ünde
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ös-
termek üzere yaplmas gereken tek ³ey ça§rlan fonksiyondaki girdi parametre de§i³keninin
adnn ba³na & simgesi koymaktr. Yani örnekteki tek de§i³iklik swap fonksiyonunun ba³lk
satrnn ³u ³ekle getirilmesi olacaktr:

void swap(int &x, int &y)

Uygulama: Fonksiyonlar

Örnek 21. Kombinasyon Hesab

m!
Bu örnekte Cnm = n!(m−n)! de§erinin hesaplanmas istenmektedir.
Ba³vuru Aktarm 114

Örnek 21 Kombinasyon hesab (yava³).


#include <iostream.h> // cout,cin
#include <stdlib.h> // 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> // cout,cin
#include <stdlib.h> // 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);
}
Giri³ Parametreleri Üzerinden De§er Döndürme 116

Ö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 pa-
rametre 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, factors3, n3);
for (i = 0; i < n3; i++)
gcd = gcd * (long int) pow((double) factors3[i].base,
(double) factors3[i].power);
cout << "En büyük ortak bölen: " << gcd << endl;
return EXIT_SUCCESS;
}

6.6 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³ para-
metresi 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³ paramet-
resi 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 gcd_factors fonksiyonunun i³levi ³u ³ekilde yazlabilir:

3
Bunun nedeni Bölüm 7'de açklanacaktr.
Dizilerin Fonksiyonlara Aktarlmas 118

Örnek 24 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ör-
dü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++;
}
}
}
Dizilerin Fonksiyonlara Aktarlmas 120

Örnek 26. Newton-Raphson Yöntemiyle Polinom Kökü Bulunmas

Bir f (x) fonksiyonunun kökü, f (x) = 0 ko³ulunu sa§layan x de§eridir. Bu de§ere x dersek
f (x) fonksiyonunun x civarnda Taylor açlmnn ilk iki terimi ³öyle yazlabilir

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

f (xi )
x = xi −
f 0 (xi )

yazlabilir. Bu formülde x yerine xi+1 konursa, fonksiyonun kökü ard³l yerine koyma yön-
temiyle hesaplanabilir. Yani her admda o admdaki x de§eri formüldeki xi de§erinin yerine
konarak bir sonraki admda kullanlacak x de§eri hesaplanr.

Bu yöntemin p(x) = an xn + an−1 xn−1 + · · · + a1 x + a0 ³eklinde n. dereceden bir polinoma


uyguland§n varsayalm. O halde yineleme formülü

p(xi )
xi+1 = xi −
p0 (xi )

olacaktr. Bir polinomun hesaplanmasnn içiçe çarpma ve toplama yöntemiyle nasl hzland-
rlaca§ Ö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> // cin,cout,endl
#include <stdlib.h> // EXIT_SUCCESS
#include <math.h> // 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;
E³ simli Fonksiyonlar 122

• 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

isimlerin ayn olmasna izin verilmese iki tamsayy takas edecek fonksiyona swap_int, iki
kesirli sayy takas edecek fonksiyona swap_float, iki katar takas edecek fonksiyona swap_str
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];

strcpy(tmp, s1);
strcpy(s1, s2);
strcpy(s2, tmp);
}
4
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. ko-
numdan 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;

for (i = start; s[i] != '\0'; i++) {


if (s[i] == c) {
index = i;
break;
}
}
return index;
}

Örnekte 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') // 1


find_char(Dennis Ritchie, 'e', 4) // 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
Varsaylan Parametreler 124

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 kona-
caksa 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. Fonksi-
yonun 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 kendi-
leri 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 fonk-
siyon 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 kulla-


ncdan alarak notlarn kipini bulan ve ekrana çkartan bir ana fonksiyon (main)
yazn.

5. Polar sistemde düzlemde bir nokta kutuptan olan uzakl§n belirten r ve kutup eksenine
yapt§ θ de§erleriyle belirtilir. Ayn noktann kartezyen sistemdeki koordinatlar x ve y
ise x = r · cosθ ve y = r · sinθ e³itlikleri geçerlidir.

(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 po-
lar 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 tanm-
lanrsa 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 snr-
lamas 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
gösterilmi³tir. Burada p 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. 422 de§erinin ya-
zl oldu§u bellek gözünün adresinin 8000 oldu§u varsaymyla, p de§i³keninin 8000 de§erini
ta³d§ görülür. Adres de§erlerinin (bu örnekteki 8000 says) ne olduklar programcy ilgi-
lendirmez, bunlar i³letim sistemi belirler. Programc adres de§erlerinin ne olaca§ konusunda
bir varsaymda bulunamaz.

422 422 8000

8000 12000

(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 * i³leci kullanlr. “ekildeki
örnekte p deyiminin de§eri 8000, *p deyiminin de§eriyse 422'dir. ³aretçilerle i³lem yaparken,
i³aretçinin kendisiyle mi, yoksa i³aret etti§i alanla m i³lem yapld§na dikkat edilmelidir.
Örne§in p++ komutu p i³aretçisinin bir sonraki (diyelim 8001) bellek gözüne i³aret etmesine
neden olur. Oysa 422 de§erinin bir artrlmas isteniyorsa (*p)++ komutu kullanlmaldr.
³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 p de§i³keninin adresi 12000
oldu§undan &p deyiminin de§eri 12000'dir. Örnekteki de§erleri toparlarsak:

• &p: 12000

• p: 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 NULL olan bir
i³aretçi de§i³keninin * 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 be-
lirtilen tipten bir de§er bulunaca§dr. Buradaki * i³areti, i³aretçinin gösterdi§i bellek gözünün
içeri§i anlamna gelen * 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 NULL atanr.

7.2 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 ]


Bellek Yönetimi 130

Örnek 27 Örnek 13'in dinamik dizilerle gerçeklenmesi.


#include <iostream> // cin,cout,endl
#include <stdlib.h> // EXIT_SUCCESS
#include <math.h> // 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

no_students*sizeof(int)
score

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 no_students * sizeof(int) kadar-


lk bir alan ayrlr ve bu alann ba³langç adresi score 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; // 8000 oldu§u varsaylyor


*p = 422;

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; p
i³aretçisi ise bu bellek gözünün adresini ta³r. Önemli olan x ile *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 bulun-
durulmasdr. Örnekte p de§i³keni için yer ayrlmad§ndan burann delete ile geri verilmesi
de sözkonusu de§ildir; böyle bir deneme hataya neden olacaktr.
³aretçi - Dizi li³kisi 132

Bellek yönetimi için new ve delete i³leçleri C++ dilinde getirilmi³ yeniliklerdir. C dilinde ayn
i³lemleri yapmak için malloc ve free fonksiyonlarn kullanmak gerekir. Buna göre örnekteki
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]; int *p;


... p = new int[10];
for (i = 0; i < 10; i++) ...
...p[i]... 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 tip-
ten 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
p[1] *(p + 1)
p[n] *(p + n)
133 ³aretçiler

Katarlar da birer dizi olduklarndan katarlar arasndaki atama ve kar³la³trma gibi i³lemle-
rin neden beklendi§i gibi çal³mayacaklarna tekrar dönelim. “ekil 7.4'deki yapda str1 ile
str2 de§i³kenleri kar³la³trlrsa (str1 == str2), 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 fonksiyonu-
nun 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.


³aretçi Tipinden Parametreler 134

Örnek 28 Morse kodlamas yapan program.


#include <iostream> // cin,cout,endl
#include <stdlib.h> // EXIT_SUCCESS
#include <stdio.h> // gets
#include <string.h> // 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 üret-
ti§i katar geri döndürdü§üdür. Fonksiyonun gövdesinde tanmlanan morse de§i³keni, kodlan-
m³ sözcü§ü tutar ve fonksiyon sonunda return ile geri döndürülür.

Burada önemli olan bir nokta, morse encode fonksiyonunun, geri


katar için yer ayrma i³ini
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
tanmland§nda bu bir yerel de§i³ken olaca§ndan fonksiyonun sona ermesiyle onun için ay-
rlm³ 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)


{
...
}
Adres Aktarm 136

Genel de§i³ken tanmlamak sözü edilen sakncay giderir ama encoding de§i³keninin gereksiz
yeremain 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:

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 akta-
rm 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> // cin,cout,endl
#include <stdlib.h> // 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 x de§i³keni tamsayya i³aretçi (yani adres) tipinden bir de§i³ken olurdu ve de§eri
m de§i³keninin adresi olurdu. Yani x i³aretçisinin gösterdi§i yere yazlan de§er m de§i³kenine
yazlm³ olurdu (“ekil 7.7).
137 ³aretçiler

x y tmp
swap 2000 2004 xxx

m n
main 32 154

2000 2004

(a)

x y tmp
swap 2000 2004 xxx

m n
main 154 32

2000 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çe-
rek 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. n elemanl bir dizide sözü
geçen i³lem n−1 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.


Adres Aktarm 138

Örnek 30 Ö§renci notlarnn ortade§erini bulan program.


#include <iostream> // cin,cout,endl
#include <stdlib.h> // 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 fonk-
siyon 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 '\n' simgesi katar sona erdi§inde alt satra geçilmesini
sa§lar (C++'daki endl kar³l§).

Bir deyim de§erinin ekranda gösterilmesi isteniyorsa bu de§erin tipi de biçim katarnda belir-
tilmelidir. 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
Çk³ 142

Veri Tipi Belirteç

Onlu düzende tamsay %d


Onlu düzende uzun tamsay %ld
Onaltl düzende tamsay %x
Noktal gösterilimde kesirli say %f
Bilimsel gösterilimde kesirli say %e
Simge %c
Katar %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 hesapla-
narak 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
önceki bo³luk dahil): Yarçap 
• 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:  olan dairenin
alan: 
• Biçim katarndan sonraki ikinci deyimin de§eri kesirli say biçiminde ekrana çkar-
tlr: 18.07
• \n 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önde-
rilmesi 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 cin birimi de yoktur. Bunun
yerine scanf 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 ele-
manna bir i³aretçi oldu§undan & simgesi kullanlmaz. Sözgelimi, kullancnn yazd§ sözcü§ü
katar tipinden bir word 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 yard-
myla gerçeklenecektir. Ö§renci notlar bir dosyadan okunacak, i³lem sonuçlar da yine bir dos-
yaya 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 stat3.cpp ve derleme ile ba§lama sonucu olu³an çal³trlabilir
dosyann ad stat3 olursa program

stat3 notlar.txt sonuclar.txt

gibi bir komutla ça§rlmaldr. Burada ilk belirtilen isim (örnekte notlar.txt) okunacak
dosyay, ikinci isim (örnekte 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.
Giri³ 144

Örnek 31 Dosyalar ile giri³/çk³ i³lemleri yaparak ö§renci notlar üzerinde istatistik hesaplar
yapan program (okuma bölümü).

#include <iostream> // cin,cout,cerr,endl


#include <stdio.h> // fopen,fclose,fprintf,fscanf,feof
#include <stdlib.h> // exit,EXIT_SUCCESS,EXIT_FAILURE
#include <math.h> // 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 <iostream> // cin,cout,cerr,endl


#include <stdio.h> // fopen,fclose,fprintf,fscanf,feof
#include <stdlib.h> // exit,EXIT_SUCCESS,EXIT_FAILURE
#include <math.h> // 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, "Ö§renci says: %d\n", no_students);


fprintf(outfile, "Ortalama: %f\n", mean);
fprintf(outfile, "Varyans: %f\n", variance);
fprintf(outfile, "Standart sapma: %f\n", std_dev);
fprintf(outfile, "Mutlak sapma: %f\n", abs_dev);

fclose(outfile);

return EXIT_SUCCESS;
}
Ana Fonksiyona Parametre Aktarma 146

8.3 Ana Fonksiyona Parametre Aktarma

Ana fonksiyon da di§er fonksiyonlar gibi bir fonksiyon olmakla birlikte giri³ ve çk³ parametre-
lerinin 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ül-
mü³tü. Bu parametre programn çal³mas sonucu olu³an durumun i³letim sistemine bildiril-
mesi 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 paramet-


relerdir. 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 kon-
mu³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+ : dosyada hem okuma hem yazma yaplacak (dosya sfrlanr, yoksa yaratlr)

•  a : 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.
Standart Giri³ / Çk³ Birimleri 148

8.4.2 Dosyada Okuma-Yazma

Her okuma ya da yazma i³lemi i³aretçiyi okunulan ya da yazlan miktar kadar ilerletir; böy-
lelikle pe³pe³e okuma i³lemleri dosyann srayla okunmasn sa§lar (yazma için de benzer ³e-
kilde). Okuma-yazma i³lemleri için fscanf ve fprintf fonksiyonlar kullanlabilir. Bu fonksi-
yonlarn kullanmlar scanf ve printf fonksiyonlar ile ayndr; tek farklar ek olarak en ba³a
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 stream parametresi ile belirtilen dosyadan en fazla size - 1 simge okur ve oku-
duklarn s parametresi ile belirtilen katara yazar. Satr sonu ya da dosya sonuna raslarsa daha
fazla okumaz. Ba³arsz olursa NULL, ba³arl olursa s de§erini döndürür. Güvenlik açsndan
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 ile-
tilerde 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


ile yaplmasn sa§lar. Bu fonksiyonlarn printf ve scanf fonksiyonlarndan farklar, ilk pa-
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 mat-
risini 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 152

Ö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++;
}
}
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 #define PI 3.14 öni³lemci komutu, kodda PI
yazan her yere 3.14 yazarak derleyiciye o haliyle gönderir; yani derleyici PI sözcü§ünü
görmez.

#include Belirtilen dosyay o noktada kodun içine ekler. Sözgelimi #include <stdlib.h>
öni³lemci komutu, 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 ta-
nmlarna 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
Projeler 154

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 x simgesinin yerine makronun kullandld§ yerdeki


score[i] - mean 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 main fonk-
siyonu) project.cpp dosyasna (Örnek 35), i³lemleri yapan fonksiyonlar ops.cpp dosyasna
(Örnek 36) konacaklardr.
1

9.2 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. Bir-
den 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ün-
mesi ç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 yeni-
den 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. Say 1'i de§i³tir


2. Say 2'yi de§i³tir
3. Say 1'in çarpanlarn göster
4. En büyük ortak bölen bul
5. En küçük ortak kat bul
6. Çk

Seçiminiz: 1
Sayy yaznz: 9702

Say 1: 9702
Say 2: 0

1. Say 1'i de§i³tir


2. Say 2'yi de§i³tir
3. Say 1'in çarpanlarn göster
4. En büyük ortak bölen bul
5. En küçük ortak kat bul
6. Çk

Seçiminiz: 2
Sayy yaznz: 945

“ekil 9.1: Proje örne§i ekran çkts.


Projeler 156

Say 1: 9702
Say 2: 945

1. Say 1'i de§i³tir


2. Say 2'yi de§i³tir
3. Say 1'in çarpanlarn göster
4. En büyük ortak bölen bul
5. En küçük ortak kat bul
6. Çk

Seçiminiz: 3
2^1 3^2 7^2 11^1

Say 1: 9702
Say 2: 945

1. Say 1'i de§i³tir


2. Say 2'yi de§i³tir
3. Say 1'in çarpanlarn göster
4. En büyük ortak bölen bul
5. En küçük ortak kat bul
6. Çk

Seçiminiz: 4
En büyük ortak bölen: 1323

Say 1: 9702
Say 2: 945

1. Say 1'i de§i³tir


2. Say 2'yi de§i³tir
3. Say 1'in çarpanlarn göster
4. En büyük ortak bölen bul
5. En küçük ortak kat bul
6. Çk

Seçiminiz: 5
En küçük ortak kat: 145530

Say 1: 9702
Say 2: 945

1. Say 1'i de§i³tir


2. Say 2'yi de§i³tir
3. Say 1'in çarpanlarn göster
4. En büyük ortak bölen bul
5. En küçük ortak kat bul
6. Çk

Seçiminiz: 6
157 Öni³lemci

Örnek 35 Giri³/çk³ fonksiyonlarn içeren kaynak dosyas.


#include <iostream> // std::xxx
#include <stdlib.h> // EXIT_SUCCESS
#include "ops.h" // 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;
Projeler 158

Örnek 36 Hesap fonksiyonlarn içeren kaynak dosyas.


#include <math.h> // sqrt,pow
#include "ops.h" // 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 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);

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 çalistirilabilir kod

kaynak kodu 2 ara kod 2

kaynak kodu n ara kod n

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 fonksi-
yonlarn 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 üç fonksiyo-
nun 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
lelikle
dosyas için ops.h ba³lk dosyas hazrlanm³ (Örnek 37) ve bu dosya

#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 duyabi-
lecekleri bilgileri barndrr. Bir fonksiyon yalnzca o dosya içinde kullanlyorsa ve d³ardan
Projeler 160

Ö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 çar-
panlar 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
dosyasnda gerek kalmayaca§ için ba³lk dosyasna yazlmayabilirlerdi. Bu veri tipi ops.cpp
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§erlen-
dirilir ve ba§lama hatasna neden olurlar.

Farkl dosyalar arasnda payla³lacak genel de§i³ken tanmlanmak isteniyorsa bu de§i³ken


ba³lk dosyasnda extern sakl sözcü§üyle bildirilmeli ve C kaynak dosyalarndan birinde
normal biçimde tanmlanmaldr. Örne§in, ba³lk dosyasnda extern int counter; ³ek-
linde bildirilebilir ve dosyalardan biri int counter; komutuyla tanmlayabilir.
161 Öni³lemci

Sorular

1. x ← |y − z| i³lemini gerçekle³tirmek üzere

(a) bir if komutu yazn.

(b) bir makro tanm yazn.

2. Üç saynn harmonik ortalamas ³öyle tanmlanr:

3
1 1 1
x1 + x2 + 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 çar-
panlar 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, ele-
man 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§lan-
tl 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³ bi-
liniyorsa 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 fonk-
siyon).

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³tur-
du§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 verilme-
leri 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 çar-
panlara 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 45
22 45 91
18 22 45 91
18 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. Ör-
nekte 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> // cin,cout,endl
#include <stdlib.h> // 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 170

Ö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;
}
}
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 du-
rum) 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.

“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 yapla-
bilmesi 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 diski 1 dire§inden 3 dire§ine ta³.


Bir diski 1 dire§inden 2 dire§ine ta³.
Bir diski 3 dire§inden 2 dire§ine ta³.
Bir diski 1 dire§inden 3 dire§ine ta³.
Bir diski 2 dire§inden 1 dire§ine ta³.
Bir diski 2 dire§inden 3 dire§ine ta³.
Bir diski 1 dire§inden 3 dire§ine ta³.

“ekil 11.2: Hanoi kuleleri problemini çözen programn ekran çkts.


173 Rekürsiyon

C B

“ekil 11.3: Hanoi kuleleri problemi (en geni³ diskin ta³nmas).

1. n - 1 diski a dire§inden c dire§ine b dire§i üzerinden ta³.

2. a dire§inde kalan diski b dire§ine ta³.

3. n - 1 diski c dire§inden 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> // cin,cout,endl
#include <stdlib.h> // 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> // cin,cout,endl
#include <stdlib.h> // 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) konu-
sunda 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.

+0 +1 +2 +3 +4 +5 +6 +7
32 ! " # $ % & '
40 ( ) * + , - . /
48 0 1 2 3 4 5 6 7
56 8 9 : ; < = > ?
64 @ A B C D E F G
72 H I J K L M N O
80 P Q R S T U V W
88 X Y Z [ \ ] ^ _
96 ` a b c d e f g
104 h i j k l m n o
112 p q r s t u v w
120 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 kodla-
malarn 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 nere-


deyse ayndr, yalnzca ISO8859-1'deki zlandaca harerin yerine Türkçe harerin gel-
mesiyle 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 uy-
gulamalarn 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 prog-
ramlarda 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§erlen-
dirirse 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§erlendiri-
yorsa  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 belir-
leyece§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 Com-
piler (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 main.cpp, hedef dosya adnn main.o, çal³trlabilir dosya adnn
da main oldu§u varsaylrsa:

• Kaynak dosyay yalnz derlemek istiyorsanz, yani ba§lamak istemiyorsanz -c bayra§n


kullanabilirsiniz:

179
Derleme 180

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 der-
lenmesi 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.o, ops.o ve
project dosyalarnn hiçbirinin olmad§n varsayarsak, make project 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ü-
§ünü dü³ünelim:

1. project hede olu³turulmaya çal³lr. Bu hedef project.o ve ops.o 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 an-


cak 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 ops.cpp dosyasna ba§ldr ve ops.cpp


dosyasnn saati ops.o dosyasndan yeni oldu§u için heden yeniden olu³turulmas ge-
rekti§ine karar verilir ve
Editörler 182

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 f i³aretçisinin de§erinin NULL oldu§unu göreceksiniz.

B.5 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 name
95.24 0.20 0.20 70516 2.84 2.84 is_prime
4.76 0.21 0.01 2 5000.00 105000.00 factorize
0.00 0.21 0.00 13127 0.00 15.24 next_prime
0.00 0.21 0.00 1 0.00 0.00 merge_factors

You might also like