Professional Documents
Culture Documents
H. Turgut Uyar
ubat 2004
ii
Önsöz
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.
Ö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.2 Kaytlar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.3 Diziler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2 Algoritmalar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.4 Soyutlama . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.6.3 Kitaplklar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.6.4 Standartlar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2 C Diline Giri³ 29
2.1 simler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.2 De§erler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.3 De§i³kenler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.5 De§i³mezler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
v
ÇINDEKILER vi
3 Ak³ Denetimi 45
3.1 Ko³ul Deyimleri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.2 Seçim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.2 Yaplar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
5 Diziler 85
5.1 Tek Boyutlu Diziler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
5.2 Katarlar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.5 Ba³vurular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
6 Fonksiyonlar 103
6.1 Fonksiyon Bildirimi ve Tanm . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
7 ³aretçiler 127
7.1 ³aretçi Tipinden De§i³kenler . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
8 Giri³-Çk³ 141
8.1 Çk³ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
9 Öni³lemci 153
9.1 Makrolar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
11 Rekürsiyon 171
Giri³
Bir problemi çözmek üzere bir bilgisayar program yazarken iki temel soruna çözüm getirmek
gerekir:
• 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
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
Istanbul Istanbul
Ankara Ankara
Izmir Izmir
(a) (b)
2. 1/4 kutu hindistan cevizi sütü, 1 tutam kekik ve a§z tadna göre tuz ve biber ekle.
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.
6. 5 dakika kaynat.
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.
1.1 Veriler
Ö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
"Istanbul" 41 29
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:
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
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)
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.
32 154 xxx
(a)
32 154 32
(b)
154 154 32
(c)
154 32 32
(d)
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.
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
enlem enlem
boylam boylam
(a) (b)
tem
yol
kod uzunluk
ilk_kent son_kent
isim isim
enlem enlem
boylam boylam
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).
notlar
1 2 3 50
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
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
üs 3 üs 1 üs 2 ...
1 2 3
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.
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.
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.
3. Sradaki ö§rencinin notu ³u ana kadarki en yüksek nottan büyükse bu yeni notu en
yüksek not olarak seç.
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:
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
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³
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.
1. söylenen ← taban
2. söylenen = tutulan ise buldun, dur
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.
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.
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
D
söylenen = tutulan
Y bas: söylenen
Y D dur
söylenen > tutulan
1. Hzlar: Hangi algoritma çözümü daha çabuk buluyor? Bu sorunun yant da iki durum
için incelenir:
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.
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.
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
blok
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
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.
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
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.
Yordamlar olabildi§ince genel amaçl yazlmaldr. Sözgelimi bir yordamn i³i BL105E 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 BL105E 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.
ki saynn en büyük ortak bölenini bulma i³i ³u ³ekilde alt i³lere bölünebilir:
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.
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
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.
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:
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
a ← sayi1 a ← sayi2
b ← sayi2 b ← sayi1
Y
b>0
D
bas: a
r←a%b
a←b
b←r
a b r
9702 945 252
945 252 189
252 189 63
189 63 0
Uygulama: Algoritmalar
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
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)
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 -
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
i1 ← i1 + 1, i2 ← i2 + 1
c1 ← carpanlar1i1, c2 ← carpanlar2i2
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.
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.
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
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.
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.
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:
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?
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.
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.
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
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
kitapliklar
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?
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³
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.
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.
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:
29
30
#define PI 3.14
int main(void)
{
float radius;
float circum, area;
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
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
biçiminde ya da
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.
circum = 2 * PI * radius;
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
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;
}
#include <iostream>
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:
• 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
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:
• 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.
• 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.
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
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
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.
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.
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.
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:
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³
• 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).
C'de deyimlerin hesaplanmasnda izlenen öncelik sras, matematikten al³k olunan sradr.
Yüksek öncelikliden alçak öncelikliye do§ru öncelik gruplar ³öyledir:
4. Toplama, çkarma
Örnek.
a+b+c+d+e
5
(a + b + c + d + e) / 5
a + b + c + d + e / 5
Tip Dönü³ümleri 38
C deyimi
e
a+b+c+d+
5
Örnek.
p * r % q + w / x - y
t1: p * r
t2: t1 % q
t3: w / x
t4: t2 + t3
t5: t4 - y
³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
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³
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
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:
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;
Bir atamann sa§ tarafndaki deyim, atamann sol tarafndaki de§i³keni içeriyorsa, yani
de§i³ken ◦= deyim;
Matematik Kitapl§ 40
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;
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
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.
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
y = x;
x++;
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:
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.
• Ö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.
10
Unix i³letim sistemlerinde derleme a³amalar ile ilgili bilgi için bkz. Ek B.2.
43 C Diline Giri³
#define PI 3.14
int main(void)
{
float x, y;
float x, y;
satrndaki 'x' harni 'X' ile de§i³tirin ve derleme sonucunda olu³an hatay gözleyin.
• Örnekteki
satrnn ardna
PI = 3.14159;
float x, y;
satrnn ardna
• 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.
8 + 17 % 3 * 5
45 / (4 + 7) - 5.0 / 2
1
2ab− cd efh−g
k←
x(y + z)
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.
√
−b ± b2 − 4ac
x1,2 =
2a
• 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.
45
46
int main(void)
{
float a, b, c;
float disc;
float x1, x2;
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.
• E³itlik: == i³leciyle gerçeklenir. ³lecin solundaki de§erle sa§ndaki de§er aynysa do§ru,
farklysa 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
(year % 4) == 0
age >= 18
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:
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):
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
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:
• DEL 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
• 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 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.
ya da
1
Aslnda burada kar³la³trlan bu iki simgenen ASCII kodlamasndaki sralardr.
Seçim 50
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
³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 {
...
...
...
}
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 ;
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.
DKKAT 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
Ko³ullu i³leç, bir ko³ulun gerçekle³ip gerçekle³memesine göre iki deyimden birini seçer.
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;
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.
³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
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
int main(void)
{
int num1, num2, result;
char op;
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
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.
Ö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.
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.
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
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.
• case 1 blo§unun sonundaki break komutunu silin ve program çal³trarak her iki dönü-
³üme de birer örnek deneyin
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.
while (ko³ul ) {
blok ;
}
Ko³ul Denetiminde Yineleme 60
int main(void)
{
int choice;
float inch, cm, f, c;
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
int main(void)
{
int num1, num2;
int a, b, r = 1;
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.
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);
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;
}
...
}
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.
• 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
i←i+1
int main(void)
{
int count, i;
float number;
int heads = 0, tails = 0;
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.
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.
• 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
• Artm miktar için artrma i³leci kullanlmas zorunlu de§ildir, herhangi bir C deyimi
kullanlabilir.
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
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
∞
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.
int main(void)
{
float x, error, term, result = 1.0;
int i = 1, f;
float fact;
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.
int main(void)
{
float x, error, term, result = 1.0;
int i = 1;
term = 1;
while (term > error) {
term = term * x / i;
result = result + term;
i++;
}
cout << "Hata: " << result << endl;
return EXIT_SUCCESS;
}
Sorular
(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];
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.
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.
n
X xi x0 x1 x2 x3 x4 x5
(−1)i = − + − + − + ...
i=0
(2i)! 0! 2! 4! 6! 8! 10!
(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
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
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:
Böylece int veri tipine score_t diye yeni bir isim verilmi³ olur. Daha sonra bu tipten de§i³ken
tanmlamak için
gibi bir komut yazlabilir. stenirse asl veri tipi isminin kullanlmasnda da bir saknca yoktur,
yani
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
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.
• Oyuncu ayn toplam veren zarlar bir daha atana kadar ya da att§ zarlarn toplam 7
olana kadar zar atmaya devam eder.
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.
1
Bu örnek, H.M. Deitel ve P.J. Deitel'in yazdklar C: How to Program kitabndan uyarlanm³tr.
75 Türetilmi³ Veri Tipleri
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;
}
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.
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:
Herhangi bir de§i³meze de§er verilirse onu izleyen de§i³mezlerin de§erleri birer artarak devam
eder:
Numaralandrma ile olu³turulmu³ bir de§i³mezler kümesine de topluca bir isim verilerek yeni
bir veri tipi olu³turulabilir:
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
komutu
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.
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.
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
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:
res equiv
nom nom
0
denom denom
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:
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
equiv.nom = res.nom;
equiv.denom = res.denom;
equiv = res;
yazlabilir.
Uygulama: Yaplar
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.
int main(void)
{
circle_t circle1;
point_t point1;
float p, deltaX, deltaY;
Sorular
1. Örnek 11'da equiv de§i³kenine farkl bir ba³langç de§eri verilebilir miydi? Örne§in
de§i³ken tanmlama komutu
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.
Ö§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
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
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;
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.
³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
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:
örtülü belirtim Diziye ba³langç de§eri verilirse eleman saysn belirtmek zorunlulu§u yok-
tur, yani
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ü
³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:
score
0 1 2 MAXSTUDENTS-1
(a)
score
0 1 2 MAXSTUDENTS
(b)
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
Kullancnn yazd§ tümceyi tersine çevirerek ekrana çkartan bir program yazlmas isteniyor.
Programn örnek bir çal³mas ekil 5.3'de verilmi³tir.
#define MAXLENGTH 80
int main(void)
{
char sentence[MAXLENGTH];
int len, i;
char tmp;
Ö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):
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
(b)
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.
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
komutu kullanlm³ olsayd programn çal³mas ekil 5.5'de görüldü§ü gibi olurdu.
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)
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.
• 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
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:
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
³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.
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.
Ç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
#define MAXDEGREE 50
int main(void)
{
float a[MAXDEGREE];
float x, b;
int n, i;
char response = 'E';
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
#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;
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
tanmlamas derleyicinin hata vermesine neden olur. Birinci boyut d³ndakiler belirtilerek
yazlrsa
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
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
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.
x1 + x2 = 3.5
x1 − x2 + 5x3 = 11
2x1 − x2 + x3 = 3.3
Gauss eliminasyon yöntemini kullanarak n bilinmeyenli bir denklem takmn çözen program
Örnek 17'da verilmi³tir.
Ba³vurular 100
#define MAXEQUATIONS 5
int main(void)
{
float a[MAXEQUATIONS][MAXEQUATIONS], b[MAXEQUATIONS];
float x[MAXEQUATIONS];
float pivot, f;
int n;
int i, j, k;
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:
Ç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-
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.
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
int main(void)
{
int number, factor = 2;
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;
}
while (!is_prime(cand))
cand += 2;
return cand;
}
Fonksiyon Bildirimi ve Tanm 106
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:
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:
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.
factor = next_prime(factor);
number factor
main 6468 2
prime cand
next_prime
cand count
is_prime
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;
Ö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)
number factor
main 6468 2
prime cand
next_prime 2 3
cand count
is_prime
number factor
main 6468 2
next_prime 2 3
true
cand count
is_prime 3 3
number factor
main 6468 2
prime cand
next_prime 2 3
cand count
is_prime 3 3
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.
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.
DKKAT Genel de§i³kenlere örnek vermek için programda baz de§i³iklikler yaplabilir. BU DEK-
LKLERN SONUCUNDA OLUACAK PROGRAM Y BR PROGRAM OLMAYACAK-
TIR. BU ÖRNEK YALNIZCA GENEL DEKEN KULLANIMINI AÇIKLAMAK AMA-
CIYLA VERLMTR. 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
³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.
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.
Örnek 19 Genel de§i³ken kullanarak bir sayy asal çarpanlarna ayran program.
#include <iostream> // cin,cout,endl
#include <stdlib.h> // EXIT_SUCCESS
int cand = 2;
void next_prime(void);
int main(void)
{
int number;
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
tmp = x;
x = y;
y = tmp;
}
int main(void)
{
int m = 32, n = 154;
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)
32 154
32 154
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:
Uygulama: Fonksiyonlar
m!
Bu örnekte Cnm = n!(m−n)! de§erinin hesaplanmas istenmektedir.
Ba³vuru Aktarm 114
int main(void)
{
int n, r;
f1 = fact(a);
f2 = fact(b);
f3 = fact(a - b);
return f1 / (f2 * f3);
}
int fact(int x)
{
int fx = 1;
int i;
int main(void)
{
int n, r;
if (b > a - b) {
first = a - b;
second = b;
}
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;
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:
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.
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:
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).
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);
}
}
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:
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.
Örnek 25 ki saynn en büyük ortak bölenini bulan program (ortak çarpanlar bulma fonk-
siyonu).
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
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 (xi ) + (x − xi )f 0 (xi ) = 0
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.
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
cn = bn
cn−1 = cn xi + bn−1
c1 = c2 xi + b1
#define MAXDEGREE 50
int main(void)
{
float a[MAXDEGREE];
int n, i;
float xi, xj, error;
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
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:
tmp = x;
x = y;
y = tmp;
}
tmp = x;
x = y;
y = tmp;
}
strcpy(tmp, s1);
strcpy(s1, s2);
strcpy(s2, tmp);
}
4
C dilinde ayn isimde birden fazla fonksiyon olamaz.
123 Fonksiyonlar
Ö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:
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
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.
(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.
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.)
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.
(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.
³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
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.
8000 12000
(a) (b)
³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.
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
namik diziler kullanlmasdr. Böylece snftaki ö§renci says kullancdan ö§renildikten sonra,
tam gerekti§i kadar eleman tutacak bir dizi tanmlanabilmi³tir.
³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
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.
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:
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;
no_students*sizeof(int)
score
6500
6500
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;
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 DKKAT
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
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.
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:
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.
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
str2
9450
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.
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.
str1
3200
str2
9450
(b)
#define MAXLENGTH 80
int main(void)
{
char word[MAXLENGTH];
char *morse = NULL;
morse[0] = '\0';
for (i = 0; s[i] != '\0'; i++) {
strcat(morse, encoding[s[i] - 'a']);
strcat(morse, " ");
}
return morse;
}
135 ³aretçiler
³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.
Ö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:
int main(void)
{
...
}
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:
Böyle yapld§nda encoding dizisi genel bir de§i³ken gibi sürekli ya³ar ama encode fonksiyonu
d³nda kullanlamaz.
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:
tmp = *x;
*x = *y;
*y = tmp;
}
int main(void)
{
int m = 32, n = 154;
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)
Uygulama: ³aretçiler
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.
int main(void)
{
int *score = NULL;
float median;
int no_students, i;
selsort(score, no_students);
delete score;
return EXIT_SUCCESS;
}
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
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:
(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³
8.1 Çk³
C dilinde cout birimi yoktur. Bunun yerine printf fonksiyonu kullanlr. Bu fonksiyonun
yaps ³u ³ekildedir:
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).
cout < < Alan: < < area < < endl;
141
Çk³ 142
Ç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
• 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.
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:
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
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);
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
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ü).
if (argc != 3) {
cout << "Kullanm: " << argv[0]
<< " giri³_dosyas çk³_dosyas" << endl;
return 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ü).
...
fclose(outfile);
return EXIT_SUCCESS;
}
Ana Fonksiyona Parametre Aktarma 146
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.
³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.
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.
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:
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+ : dosyada hem okuma hem yazma yaplacak (dosya varsa sfrlanmaz, yoksa yaratl-
maz)
• w+ : dosyada hem okuma hem yazma yaplacak (dosya sfrlanr, 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:
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
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:
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:
Bu fonksiyon stream parametresi ile belirlenen dosyadan okudu§u sradaki simgeyi bir tamsay
olarak geri döndürür.
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
komutu
komutuyla ayn anlama gelir. Benzer ³ekilde a³a§daki ikisi de giri³ i³lemleri için e³de§erlidir:
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:
C dilinde ise cerr birimi olmad§ndan ayn i³lem a³a§daki komutla gerçekle³tirilmelidir:
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:
'b' bayra§
Uygulama: Dosyalar
DÜZELT: YAZILACAK
struct graph_s {
int nodes;
int adjacency[MAXNODES][MAXNODES];
};
typedef struct graph_s graph_t;
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³
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);
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++;
}
fclose(fp);
return EXIT_SUCCESS;
kili Dosyalar 152
Ö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:
#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.
153
Projeler 154
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
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
Seçiminiz: 1
Sayy yaznz: 9702
Say 1: 9702
Say 2: 0
Seçiminiz: 2
Sayy yaznz: 945
Say 1: 9702
Say 2: 945
Seçiminiz: 3
2^1 3^2 7^2 11^1
Say 1: 9702
Say 2: 945
Seçiminiz: 4
En büyük ortak bölen: 1323
Say 1: 9702
Say 2: 945
Seçiminiz: 5
En küçük ortak kat: 145530
Say 1: 9702
Say 2: 945
Seçiminiz: 6
157 Öni³lemci
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
derleme baglama
kitapliklar
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
#define MAXFACTOR 50
struct factor_s {
int base, power;
};
typedef struct factor_s factor_t;
#endif
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.
Sorular
3
1 1 1
x1 + x2 + x3
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 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;
tail
head
2 3 7 11
1 2 2 1
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:
Benzer ³ekilde, ortak çarpanlar bulma algoritmas da iki çarpan listesini alarak ortak çarpanlar
listesini döndürür:
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:
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.
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).
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.
liste bo³
• 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
struct node_s {
int value;
struct node_s *next;
};
typedef struct node_s node_t;
int main(void)
{
int *score = NULL;
node_t *head = NULL, *f = NULL;
float median;
int no_students, i;
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;
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 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
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.
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).
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:
C B
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.
Uygulama: Rekürsiyon
DÜZELT: YAZILACAK
Sorular
174
#define DISKS 3
int main(void)
{
move(DISKS, 1, 3, 2);
return EXIT_SUCCESS;
}
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;
}
tmp = x; x = y; y = tmp;
}
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 { | } ~
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.
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 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
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:
179
Derleme 180
• 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:
• ba§la
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:
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:
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
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
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:
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
komutu yürütülür.
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
strip
³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;
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
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: