Bilgisayar ve Programlamaya Giriş · Ders Notu

Akış Diyagramları

Bir algoritma ilk kez kâğıda dökülürken çoğu zaman yazıdan önce bir çizim yapılır. Kutular adımları, oklar adımların sırasını gösterir. Bu çizime akış diyagramı denir. Not, akış diyagramlarında kullanılan simgeleri ve iyi bir diyagramın kurallarını tanıtır. Ardından her algoritmanın yapı taşı olan üç akış türü gelir. Sıralı akışta adımlar arka arkaya çalışır. Koşullu akışta yol bir soruya göre ayrılır. Tekrarlı akışta bir grup adım tekrar tekrar çalışır. Her yapı küçük örneklerle adım adım yürütülür; değişkenlerin her adımdaki değeri izleme tablolarında verilir. Sayaç, biriktirici ve bekçi değer gibi döngü kalıpları, iç içe döngüler, erken çıkış ve bayrak da ayrı ayrı ele alınır. Son kesimler diyagramın Java koduna nasıl çevrildiğini ve bir diyagramın hangi girdilerle test edildiğini gösterir.

Öğrenme çıktıları

Simgeler
Temel akış diyagramı simgelerini (başla/bitir, işlem, karar, giriş/çıkış, ok, bağlayıcı) ve ek simgeleri tanımak; her adım için doğru simgeyi seçmek.
Akış
Oklarla işlem sırasını kurmak; okunabilir bir diyagramın kurallarını uygulamak; aynı algoritmayı akış diyagramı ve sözde kodla anlatmak.
Kontrol
Sıralı, koşullu ve tekrarlı akışı diyagramda göstermek; karar zinciri, bileşik koşul, sayaç, biriktirici, bekçi değer, iç içe döngü, son koşullu döngü, erken çıkış ve bayrak kalıplarını kullanmak; bir diyagramı izleme tablosuyla adım adım yürütmek.
Dönüşüm
Diyagramı sözde koda ve Java programına çevirmek; büyük bir diyagramı alt süreçlere bölmek; diyagramı normal, sınır ve döngünün sıfır, bir, çok kez döndüğü girdilerle test etmek.

4.1Akış diyagramı

Bir algoritma, bir problemi çözmek için izlenecek açık ve sonlu adımlar dizisidir. Adımlar düz yazıyla da anlatılabilir. Ancak yazı uzadıkça hangi adımın hangisinden sonra geldiği, hangi durumda bir adımın atlandığı ya da tekrarlandığı gözden kaçar. Akış diyagramı bu sırayı göze görünür kılar.

4.1.1Akış diyagramı nedir?

Tanım 4.1

Akış diyagramı (flowchart), bir algoritmanın adımlarını standart simgelerle, adımların çalışma sırasını da oklarla gösteren çizimdir. Simgenin biçimi adımın türünü (başlangıç, işlem, karar, giriş/çıkış), içine yazılan kısa ifade adımın ne yaptığını, ok da yürütmenin hangi adıma geçtiğini söyler.

Günlük bir örnek tanımı somutlaştırır. Bir apartman kapısında şifreli kilit vardır. Kilidin içindeki küçük bilgisayar her seferinde aynı işi yapar: tuşlanan şifreyi okur, doğru olup olmadığına bakar, doğruysa kapıyı açar, değilse bir uyarı sesi verir. Şekil 4.1 bu işi akış diyagramıyla gösterir.

EvetHayırBaşlaşifreyi okudoğru mu?kapıyı açuyarı verBitir
Şekil 4.1: Kapı şifresi algoritmasının akış diyagramı. Karar kutusundan iki yol çıkar: şifre doğruysa “kapıyı aç”, değilse “uyarı ver” çalışır. İki yol alttaki küçük dairede birleşir ve Bitir'e ulaşır.

Diyagram yukarıdan aşağıya okunur. Yürütme Başla yazan yuvarlak uçlu kutudan başlar. Ok, yürütmeyi “şifreyi oku” kutusuna götürür. Ardından eşkenar dörtgen biçimindeki karar kutusu gelir. İçinde bir soru vardır: “doğru mu?” Sorunun cevabına göre iki oktan biri izlenir. Evet okunu izleyen yol kapıyı açar, Hayır okunu izleyen yol uyarı verir. Her iki yol da sonunda aynı noktada buluşur ve Bitir kutusuna ulaşır.

Bu küçük çizimde akış diyagramının üç temel özelliği görülür. Birincisi, her adımın türü biçiminden anlaşılır; okuma işi ile karar işi farklı kutulardadır. İkincisi, adımların sırası oklarla bellidir; okur hangi adımın önce geldiğini tahmin etmek zorunda kalmaz. Üçüncüsü, bir karar kutusundan çıkan yollar ayrı ayrı izlenebilir; her çalıştırmada bu yollardan yalnızca biri kullanılır.

4.1.2Neden diyagram çizilir?

Akış diyagramı bir programlama dilinden bağımsızdır. Aynı diyagram Java, Python ya da C ile yazılabilir. Bu yüzden bir algoritmanın mantığı, henüz hangi dille kodlanacağı belli değilken tartışılabilir. Bir ekipte programcı olmayan kişiler de, örneğin bir laboratuvar sorumlusu ya da bir iş süreci yöneticisi, diyagramı okuyup “bu durumda ne olacak?” diye sorabilir.

Diyagram çizmenin ikinci yararı hataların erken görülmesidir. Bir karar kutusundan yalnızca bir ok çıkıyorsa öbür durumda ne olacağı düşünülmemiştir. Hiçbir yerden ok gelmeyen bir kutu hiç çalışmaz. Geri dönen bir okun yolunda hiçbir şey değişmiyorsa döngü sonsuza kadar sürer. Bu tür eksikler kodda satırlar arasına gizlenir; diyagramda ise çizimin biçiminden fark edilir.

Üçüncü yarar öğrenmeyle ilgilidir. Programlamaya yeni başlayan biri için en zor kavramlardan biri yürütmenin sırasıdır. Bilgisayar satırları tek tek ve sırayla çalıştırır. Bir koşula göre bazı satırları atlar, bazılarını tekrar eder. Akış diyagramında bu sıra parmakla izlenebilir. Not boyunca her diyagram bu yolla, kutu kutu yürütülecektir.

4.2Simgeler

Akış diyagramının simgeleri uluslararası bir standartla belirlenmiştir: ISO 5807. Standart 1985'te yayımlandı ve bugün de kullanılan çizim araçlarının çoğu ona uyar. Küçük bir algoritma için beş temel simge yeter. Diyagram büyüdüğünde ya da dosya, rapor gibi dış ortamlar gösterilmek istendiğinde ek simgelere başvurulur.

4.2.1Temel simgeler

Başla / BitirBaşlangıç / bitişHer diyagramda bir başla, en az bir bitirtoplam = a + bİşlemHesaplama, atamaa > b ?KararEvet / Hayır iki çıkışa değerini okuGiriş / çıkışVeri alma (oku), gösterme (yaz)Akış çizgisiYürütme yönü; uçtaki ok önemlidirABağlayıcıYolların birleşmesi / sayfa geçişi
Şekil 4.2: Temel akış diyagramı simgeleri. Üst sırada başlangıç/bitiş (oval), işlem (dikdörtgen) ve karar (eşkenar dörtgen); alt sırada giriş/çıkış (paralelkenar), akış çizgisi (ok) ve bağlayıcı (küçük daire).

Şekil 4.2 temel simgeleri bir arada gösterir. Her birinin görevi aşağıda tek tek açıklanır.

Tanım 4.2

Başla/bitir simgesi (terminal symbol) oval ya da yuvarlak uçlu dikdörtgendir. Algoritmanın nereden başlayıp nerede bittiğini gösterir. Her diyagramda tek bir Başla ve en az bir Bitir bulunur.

Başla simgesine ok girmez, yalnızca ok çıkar. Bitir simgesine ok girer, ondan ok çıkmaz. Bir diyagramda birden fazla Bitir olabilir. Örneğin sayı tahmin oyununda doğru tahmin yapıldığında oyun hemen biter; bu durumda “Bildin” yazısından sonra ayrı bir Bitir çizmek diyagramı sadeleştirir. Yine de çoğu durumda yolları birleştirip tek bir Bitir'e götürmek okumayı kolaylaştırır.

Tanım 4.3

İşlem simgesi (process symbol) dikdörtgendir. Bir hesaplamayı ya da bir atamayı (assignment) gösterir. Atama, bir değişkene yeni bir değer verilmesidir: toplam = a + b ifadesi, sağdaki a + b değerini hesaplar ve sonucu toplam adlı değişkene yazar.

Burada değişken (variable) sözcüğü ilk kez geçiyor. Değişken, bellekte adı olan bir kutu gibi düşünülebilir. Kutunun içinde her an tek bir değer bulunur. Yeni bir değer yazıldığında eskisi silinir. Atamadaki eşittir işareti matematikteki eşitlikten farklıdır. i = i + 1 matematikte anlamsızdır, çünkü hiçbir sayı kendisinin bir fazlasına eşit olamaz. Akış diyagramında ve programda ise bu ifade “i'nin şimdiki değerine 1 ekle, sonucu yeniden i'ye yaz” demektir. i önce 4 ise, bu kutu çalıştıktan sonra 5 olur.

Tanım 4.4

Karar simgesi (decision symbol) eşkenar dörtgendir. İçine cevabı “evet” ya da “hayır” olan bir soru, yani bir koşul (condition) yazılır: a > b ?. Karar simgesine bir ok girer, ondan iki ok çıkar; çıkan oklar Evet ve Hayır diye etiketlenir.

Koşul bir karşılaştırmadır. Akış diyagramlarında ve Java'da altı karşılaştırma operatörü vardır. Bunlar < (küçük), <= (küçük ya da eşit), > (büyük), >= (büyük ya da eşit), == (eşit) ve != (eşit değil) operatörleridir. Eşitlik sorusu için iki eşittir işareti kullanılır. Bunun nedeni tek eşittir işaretinin atamaya ayrılmış olmasıdır. Bazı kitaplar ≤, ≥ ve ≠ işaretlerini de kullanır; anlam aynıdır.

Tanım 4.5

Giriş/çıkış simgesi (input/output symbol) paralelkenardır. Algoritmanın dışarıdan veri almasını (“a değerini oku”) ya da dışarıya sonuç vermesini (“toplamı yaz”) gösterir. Dışarıdan alınan veriye girdi (input), dışarıya verilen sonuca çıktı (output) denir.

“Oku” sözcüğü verinin klavyeden, bir dosyadan ya da bir algılayıcıdan gelmesini kapsar. Akış diyagramı verinin nereden geldiğiyle ilgilenmez; yalnızca o noktada bir değerin algoritmaya girdiğini söyler. “Yaz” da aynı biçimde ekrana, yazıcıya ya da bir dosyaya yazmayı kapsar.

Tanım 4.6

Akış çizgisi ya da kısaca ok (flow line), iki simgeyi birleştirir ve yürütmenin yönünü gösterir. Bağlayıcı (connector) küçük bir dairedir; birden fazla yolun birleştiği noktayı ya da diyagramın başka bir yerde sürdüğünü gösterir.

Okun ucu önemlidir. Uçsuz bir çizgi iki kutunun bağlı olduğunu söyler ama hangisinin önce çalıştığını söylemez. Bu yüzden her akış çizgisinin ucunda bir ok başı bulunur. Bağlayıcı, Şekil 4.1'de olduğu gibi bir karardan ayrılan iki yolun yeniden buluştuğu yeri belirginleştirir. İçine bir harf yazılan bağlayıcı ise aynı harfi taşıyan başka bir bağlayıcıyla eşleşir. Böylece sayfanın bir köşesinden öbür köşesine uzun bir ok çekmek gerekmez.

Tablo 4.1: Temel simgeler, görevleri ve içlerine yazılabilecek örnek ifadeler.
SimgeBiçimGörevÖrnek
OvalBaşlangıç ya da bitişBaşla
Dikdörtgenİşlem (hesaplama, atama)toplam = a + b
Eşkenar dörtgenKarar (koşul)a > b ?
ParalelkenarGiriş / çıkışa değerini oku
OkYürütme yönüsonraki adıma geç

4.2.2Simgenin içine ne yazılır?

Simgenin biçimi adımın türünü zaten söylediği için içine yalnızca o adımın kısa ifadesi yazılır. Karar simgesine bir soru yazılır: a > b ?. İşlem simgesine bir emir yazılır: toplam = a + b. Giriş/çıkış simgesine okunan ya da yazılan şey yazılır: “a değerini oku”, “toplamı yaz”. Bu ayrım bir diyagramı okuyan kişinin, kutunun içini okumadan önce bile o adımda ne olacağını bilmesini sağlar.

Soru biçiminin bir kuralı daha vardır: cevabı iki seçenekli olmalıdır. “a ile b'den hangisi büyük?” sorusunun cevabı “a” ya da “b” olur ama eşitlik durumunu açıkta bırakır. a > b ? sorusunun cevabı ise her zaman evet ya da hayırdır: a = b ise cevap hayırdır. Bu yüzden karar kutusuna her zaman bir karşılaştırma yazılır.

Örnek 4.1

Bir algoritma, öğrencinin vize ve final notundan ortalama hesaplayıp geçme durumunu yazıyor. Adımları şunlardır: vize notunu al; final notunu al; ortalamayı vize × 0,4 + final × 0,6 olarak hesapla; ortalama 50 ya da üstü mü diye bak; sonucu ekrana yaz. Her adım hangi simgeye konur, içine ne yazılır?

Çözüm. “Vize notunu al” bir girdidir: paralelkenar, içine “vize değerini oku”. Final de aynı biçimde paralelkenara girer. Ortalama hesabı bir atamadır: dikdörtgen, içine ort = vize × 0,4 + final × 0,6. “50 ya da üstü mü” bir sorudur: eşkenar dörtgen, içine ort >= 50 ?. Sonucu yazmak bir çıktıdır: Evet ve Hayır dallarında birer paralelkenar, içlerine “Geçti” yaz ve “Kaldı” yaz. En başa Başla, en sona Bitir eklenir. Vize 40, final 60 ise ortalama 40 × 0,4 + 60 × 0,6 = 16 + 36 = 52 olur; 52 ≥ 50 olduğu için Evet yolu izlenir ve “Geçti” yazılır.

Sık yapılan hata

Hesaplamayı paralelkenara yazmak. toplam = a + b ekranla ya da klavyeyle ilgili değildir; bellekte bir değer hesaplar. Bu yüzden işlem simgesine, yani dikdörtgene aittir. Paralelkenar yalnızca dış dünyayla veri alışverişi içindir. Benzer bir karışıklık karar kutusuna emir yazıldığında görülür: “a'yı b ile karşılaştır ve büyüğü yaz” cümlesi bir soru değildir ve iki işi bir arada yapar. Doğrusu karar kutusuna a > b ? yazmak, yazma işlerini dallardaki paralelkenarlara taşımaktır.

4.2.3Ek simgeler

Beş temel simge küçük algoritmalar için yeterlidir. Bazı durumlarda ISO 5807'deki ek simgelere başvurulur. Büyük bir diyagram birkaç sayfaya bölünebilir, ayrı çizilmiş bir alt süreç çağrılabilir ya da bir dosya veya rapor gösterilmek istenebilir. Tablo 4.2 en sık karşılaşılan altısını özetler.

Tablo 4.2: Ek simgeler.
SimgeAdGörevÖrnek
Sayfa dışı bağlayıcıDiyagram başka sayfada sürer; içine sayfa ve nokta yazılır.2-A
Önceden tanımlı işlemAyrıca çizilmiş bir alt süreci çağırır.Ortalama hesapla
HazırlıkDöngü sayacının başlangıcını ve sınırını tek simgede verir.i = 1 → n
BelgeYazdırılan çıktı ya da rapor.Not çizelgesi
Veri deposuDiskte ya da veri tabanında saklanan veri.Öğrenci kayıtları
AçıklamaKesikli çizgiyle bir simgeye not ekler; akışa katılmaz.not 0–100 arası

Sayfa dışı bağlayıcı, sayfa içindeki bağlayıcının bir benzeridir. İçindeki “2-A” etiketi “ikinci sayfadaki A noktasında devam ediyor” anlamına gelir. Önceden tanımlı işlem simgesi, kenarlarında iki dikey çizgi bulunan bir dikdörtgendir. Bu simge büyük diyagramları parçalara bölmenin aracıdır: alt süreç bir kez çizilir, ana diyagramda gerektiği her yerde bu simgeyle çağrılır. Hazırlık simgesi altıgendir ve bir sayaçlı döngünün başlangıç değerini, sınırını ve artış miktarını tek kutuda toplar. Açıklama simgesi akışa katılmaz; bir kutuya kesikli bir çizgiyle bağlanır ve okura bilgi verir. Örneğin “not 0–100 arası” açıklaması, girdinin hangi aralıkta olması gerektiğini hatırlatır.

4.3Diyagram tasarımı

Simgeleri tanımak bir diyagram çizmeye yetmez. Bir problemden diyagrama giden yolun belli adımları vardır. Bu adımlar izlendiğinde hem eksik bir durum kalmaz hem de ortaya okunması kolay bir çizim çıkar.

4.3.1Adım adım bir diyagram: iki sayının büyüğü

Problem kısadır: iki sayı veriliyor, büyük olanı yazılacak. Diyagram beş adımda kurulur.

  1. Girdi ve çıktıyı belirle. Algoritmanın dışarıdan ne aldığı ve dışarıya ne verdiği önce yazılır. Girdi iki sayıdır: a ve b. Çıktı büyük olan sayıdır. İkisi de paralelkenarla gösterilir: “a, b değerlerini oku” ve “büyüğü yaz”.
  2. Adımları sırala. Başla ve Bitir eklenir. Adımlar yukarıdan aşağıya dizilir: önce okuma, en son yazma. Okunmamış bir değer karşılaştırılamaz; bu yüzden okuma kutusu her zaman kararın üstündedir.
  3. Kararları ayır. Hangi sayının yazılacağı bir soruya bağlıdır: a, b'den büyük mü? Araya a > b ? karar kutusu girer. Tek “büyüğü yaz” kutusu artık iki kutuya ayrılır: “a yaz” ve “b yaz”.
  4. Okları bağla. Her kutu bir sonrakine okla bağlanır. Karardan çıkan iki ok Evet ve Hayır diye etiketlenir. İki dal alttaki bir bağlayıcıda birleşir ve Bitir'e gider.
  5. Örnekle izle. Diyagram bir girdiyle elle yürütülür. a = 4, b = 9 için 4 > 9 yanlıştır; Hayır yolu izlenir, “b yaz” kutusu çalışır ve 9 yazılır. Sonuç doğrudur.
1. Girdi ve çıktıyı belirle2. Adımları sırala3. Kararları ayır4. Okları bağla5. Örnekle izleBaşlaa, b değerlerini okua > b ?a yazb yazBitir 1. Girdi ve çıktıyı belirle2. Adımları sırala3. Kararları ayır4. Okları bağla5. Örnekle izleEvetHayırBaşlaa, b değerlerini okua > b ?a yazb yazBitir
Şekil 4.3: İki sayının büyüğünü bulan diyagramın kuruluşu. (a) 3. adım: karar eklenince çıktı iki kutuya ayrılır; oklar henüz yoktur. (b) 5. adım: oklar bağlanmış, a = 4, b = 9 için izlenen yol renkle gösterilmiştir: Hayır yolu, “b yaz” ve 9.

Beşinci adım çoğu zaman atlanır ama en değerli adımdır. Elle izleme sırasında yalnız bir girdi denemek yetmez. a = 9, b = 4 ile Evet yolu da denenmelidir; bu durumda 9 yazılır. Peki a = b = 5 ise? 5 > 5 yanlış olduğu için Hayır yolu izlenir ve b, yani 5 yazılır. İki sayı eşitken hangisinin yazıldığı önemli değildir; diyagram bu durumda da doğru sonucu verir. Bu küçük deneme, karar kutusuna > yerine >= yazılsaydı da sonucun değişmeyeceğini gösterir.

4.3.2Okunabilirlik kuralları

Aynı algoritma iyi ya da kötü çizilebilir. Şekil 4.4 aynı iki sayı problemini iki biçimde gösterir. Soldaki çizimde oklar birbirini keser, karar kutusunun çıkışları etiketsizdir ve bir kutuya “b yaz, bitir, a=b” gibi üç ayrı iş sıkıştırılmıştır. Sağdaki çizim yukarıdan aşağıya akar, kararın çıkışları etiketlidir ve her kutuda tek bir iş vardır.

Başlaa > bb yaz, bitir, a=ba yazBitir EvetHayırBaşlaa > b ?a yazb yazBitir
Şekil 4.4: Okunaksız ve okunaklı diyagram. Solda kesişen oklar, etiketsiz karar ve bir kutuda üç işlem; sağda yukarıdan aşağı akış, Evet/Hayır etiketli karar ve kutu başına tek işlem.

Kurallar üç başlıkta toplanır:

  • Akışın yönü. Akış mümkün olduğunca yukarıdan aşağıya ve soldan sağa ilerler. Okur gözünü bu yönde gezdirir; ters yöne giden oklar yalnız döngülerde, geri dönüşü göstermek için kullanılır. Kesişen oklar azaltılır; kesişme kaçınılmazsa bağlayıcı kullanılır.
  • Karar etiketleri. Karardan çıkan her ok Evet/Hayır (ya da Doğru/Yanlış) gibi anlamlı bir etiket taşır. Etiketsiz bir kararda hangi yolun hangi durumda seçildiği tahmine kalır.
  • Kutu başına bir iş. Bir simgeye tek bir temel işlem yazılır. Bir kutuya üç işlem sıkıştırılırsa hangi işlemin önce yapıldığı belirsizleşir ve kutu bir karar içeriyorsa bu karar gözden kaçar. Diyagram büyüyüp sayfaya sığmaz hâle gelirse alt süreçlere bölünür.
Sık yapılan hata

Karardan yalnızca bir ok çıkarmak. Öğrenci aklındaki durumu, örneğin “not 60'tan büyükse Geçti yaz” durumunu çizer, öbür durumu unutur. Not 45 olduğunda yürütmenin nereye gideceği diyagramda yazmaz; akış kopar. Bir karar kutusundan her zaman iki ok çıkar. Öbür durumda yapılacak bir iş yoksa Hayır oku doğrudan birleşme noktasına gider.

4.3.3Akış diyagramı ve sözde kod

Algoritma anlatmanın ikinci yaygın yolu sözde koddur.

Tanım 4.7

Sözde kod (pseudocode), bir algoritmanın adımlarını programlama diline benzeyen ama dilin kurallarına bağlı olmayan kısa cümlelerle yazma biçimidir. Satırlar sırayla okunur; bir kararın ya da döngünün içindeki satırlar girintiyle gösterilir.

Şekil 4.5 bir sayının mutlak değerini bulan algoritmayı iki biçimde gösterir. Sayı negatifse işareti değiştirilir, değilse olduğu gibi kalır.

EvetHayırBaşlax değerini okux < 0 ?x = −xx değerini yazBitir
Şekil 4.5: Mutlak değer algoritmasının akış diyagramı: x okunur, x < 0 ise x = −x yapılır, sonra x yazılır.
oku x
eğer x < 0 ise
    x = −x
yaz x

İki gösterim aynı algoritmayı anlatır ve biri öbürüne satır satır çevrilebilir. “oku x” paralelkenara, “eğer x < 0 ise” karar kutusuna, girintili x = −x satırı kararın Evet dalındaki dikdörtgene, “yaz x” son paralelkenara karşılık gelir. Kararın Hayır dalında hiçbir kutu yoktur; ok doğrudan yazma kutusuna gider. Sözde kodda bu durum, “eğer” satırının altında girintili tek bir satır bulunmasıyla gösterilir.

Tablo 4.3: Akış diyagramı ile sözde kodun karşılaştırılması.
Akış diyagramıSözde kod
BiçimSimgeler ve oklarGirintili kısa cümleler
Güçlü yanıDallanma ve döngü bir bakışta görülürHızlı yazılır, koda çok yakındır
Zayıf yanıBüyüyünce sayfaya sığmaz, değiştirmek zahmetlidirAkışın yapısı girintiye bağlıdır
Uygun olduğu yerÖğrenme, sunum, iş süreçleriUzun algoritmalar, kodlamadan hemen önce

Sözde kodun bir standardı yoktur. Kimi kitaplar “eğer … ise”, kimi “if … then” yazar; kimi atama için =, kimi ← kullanır. Önemli olan her adımın açık olmasıdır. Bu notta sözde kod Türkçe sözcüklerle ve Java'ya yakın işaretlerle yazılır: atama =, eşitlik sorusu ==, kalan %.

4.3.4Yapısal programlamanın üç yapısı

Akış diyagramında oklar istenen her yere çizilebilir. Bir okun diyagramın ortasındaki rastgele bir kutuya atlaması da teknik olarak mümkündür. 1960'larda büyüyen programlarda bu serbestlik ciddi sorunlar doğurdu. Oklar birbirine dolanıyor, bir kutuya kaç farklı yoldan gelindiği izlenemiyordu. Böyle çizimlere ve programlara, birbirine dolanmış makarnaya benzetilerek spagetti akış (spaghetti code) adı verildi.

Çözüm, okları rastgele çizmek yerine yalnızca üç kalıp kullanmaktır. Şekil 4.6 bu üç kalıbı gösterir.

SıraA işlemiB işlemiSeçimkoşul ?ABEvetHayırTekrarkoşul ?gövdeEvetHayır
Şekil 4.6: Yapısal programlamanın üç yapısı. Sıra: A işlemi, ardından B işlemi. Seçim: koşula göre A ya da B. Tekrar: koşul doğru oldukça gövde tekrar çalışır. Her yapının tek girişi ve tek çıkışı vardır.
Tanım 4.8

Yapısal programlama (structured programming), algoritmaları yalnızca üç kontrol yapısıyla kurma yaklaşımıdır. Sıralı yapı (sequence): adımlar arka arkaya çalışır. Karar yapısı ya da seçim (selection): bir koşula göre iki yoldan biri çalışır. Döngü yapısı ya da tekrar (repetition): bir koşul doğru oldukça bir grup adım tekrar çalışır.

Teorem 4.1 (Böhm–Jacopini)

Her algoritma yalnızca sıra, seçim ve tekrar yapılarıyla yazılabilir. Corrado Böhm ve Giuseppe Jacopini bu sonucu 1966'da yayımladı.

Teoremin söylediği şey güçlüdür: rastgele atlayan oklara hiçbir zaman gerek yoktur. Spagetti biçimde çizilmiş her diyagramın aynı işi yapan yapısal bir karşılığı vardır. Gerekirse bir iki ek değişken (ör. bir bayrak) kullanılır.

Üç yapının ortak özelliği tek giriş, tek çıkış kuralıdır. Her yapıya yukarıdan tek bir ok girer, aşağıdan tek bir ok çıkar. Bu özellik sayesinde bir yapı, başka bir yapının içindeki herhangi bir kutunun yerine konabilir. Örneğin bir döngünün gövdesindeki dikdörtgen yerine bütün bir karar yapısı yerleştirilebilir. Buna iç içe (nested) yapılar denir. Büyük algoritmalar bu yolla, küçük yapılar iç içe geçirilerek kurulur. Diyagramın herhangi bir parçası kendi giriş ve çıkış okuyla ayrı ayrı anlaşılabilir ve test edilebilir.

Programlama dilleri de bu fikri benimsedi. Eski dillerde programın herhangi bir satırına atlayan goto deyimi yaygındı. Java'da goto ayrılmış bir sözcüktür, yani değişken adı olarak kullanılamaz, ama dilde hiçbir işe yaramaz. Java'da yürütmenin akışı yalnızca sıralı satırlarla, if/else ile ve while, do, for döngüleriyle kurulur.

4.3.5Çizim araçları

Akış diyagramı çizmek için özel bir araç şart değildir. Seçim, diyagramın ne için kullanılacağına bağlıdır:

  • Kâğıt ve kalem: İlk taslak için en hızlı yoldur; silip yeniden çizmek kolaydır. Sınavlarda da diyagram elle çizilir.
  • Word ve PowerPoint: Ekle → Şekiller menüsündeki Akış Çizelgesi grubunda bütün temel simgeler bulunur. Bağlayıcı oklar kutulara yapıştığı için bir kutu taşındığında ok da birlikte kayar.
  • draw.io (diagrams.net): Ücretsizdir ve tarayıcıda çalışır. Hazır akış diyagramı şekilleri sunar; çizim PNG, SVG ya da PDF olarak dışa aktarılabilir.
  • Microsoft Visio: Kurumsal süreç ve iş akışı diyagramları için kullanılan ticari bir araçtır.
  • Flowgorithm: Diyagramı yalnızca çizmez, çalıştırır. Değişkenlerin değerini adım adım gösterir ve diyagramı Java dahil birçok dilde koda çevirir.
  • Mermaid: Diyagram metinle tanımlanır, araç onu çizer. Belgelerde ve kod depolarında sık kullanılır.

Araç ne olursa olsun simgelerin anlamı ve okunabilirlik kuralları aynıdır. Dersin Akış Diyagramı Yürütücü simülatörü de Flowgorithm gibi diyagramı adım adım yürütür; bu nottaki örneklerin çoğu orada da denenebilir.

4.4Sıralı akış

Üç yapının en basiti sıralı yapıdır. Kontrol yapılarının hepsi bu temel üzerine kurulur: bir karar ya da döngü olmayan her kesim, kendi içinde sıralı akıştır.

4.4.1Sıralı yapı

Tanım 4.9

Sıralı akış (sequential flow), adımların yazıldıkları sırayla, her biri bir öncekinin bitmesinden sonra ve tam bir kez çalıştığı akıştır. Dallanma ya da tekrar içermez; tek girişi ve tek çıkışı vardır.

Şekil 4.7 iki sayıyı okuyup toplamlarını yazan diyagramı gösterir. Diyagramdaki bütün oklar aşağı doğrudur; hiçbir kutudan birden fazla ok çıkmaz.

Başlaa değerini okub değerini okutoplam = a + btoplamı yazBitir
Şekil 4.7: Sıralı akış: Başla, a oku, b oku, toplam = a + b, toplamı yaz, Bitir.
Başla
  a değerini oku
  b değerini oku
  toplam = a + b
  toplamı yaz
Bitir

Sözde kodda Başla ile Bitir arasındaki dört satır girintilidir; her satır diyagramdaki bir kutuya karşılık gelir.

4.4.2Sıralı akışı adım adım yürütmek

Bir diyagramı yürütmek, bilgisayarın yapacağı işi elle yapmaktır. Başla kutusundan başlanır. Her adımda yalnızca bir kutu çalışır. Kutu çalıştıktan sonra değişkenlerin yeni değerleri ve varsa çıktı not edilir, sonra okun gösterdiği kutuya geçilir. Bu notlar bir tabloda toplanırsa ortaya bir izleme tablosu (trace table) çıkar. Tablo 4.4 a = 4, b = 7 girdisiyle yürütmenin izleme tablosudur.

Tablo 4.4: Sıralı akışın a = 4, b = 7 için izleme tablosu. Tire, değişkenin henüz bir değeri olmadığını gösterir.
AdımÇalışan kutuabtoplamÇıktı
1Başla———
2a değerini oku4——
3b değerini oku47—
4toplam = a + b4711
5toplamı yaz471111
6Bitir471111
Başlaa değerini okub değerini okutoplam = a + btoplamı yazBitir Başlaa değerini okub değerini okutoplam = a + btoplamı yazBitir Başlaa değerini okub değerini okutoplam = a + btoplamı yazBitir
Şekil 4.8: Sıralı akışın üç adımı; o anda çalışan kutu vurgulanmıştır. (a) 2. adım: a = 4 okunur. (b) 4. adım: toplam = 4 + 7 = 11. (c) 6. adım: Bitir'e ulaşılır.

Tablo sıralı akışın iki özelliğini açıkça gösterir. Birincisi, altı kutunun her biri tam bir kez çalışır; tabloda tekrar eden ya da atlanan bir satır yoktur. İkincisi, bir değişken değer aldıktan sonra değiştirilmedikçe o değeri korur: a, 2. adımda 4 olur ve sona kadar 4 kalır. Tablo okunurken her satır, “bu kutu çalıştıktan hemen sonra” durumunu anlatır.

Diyagramın Java karşılığı da aynı sırayı izler:

import java.util.Scanner;

public class Toplam {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int a = giris.nextInt();          // a değerini oku
        int b = giris.nextInt();          // b değerini oku
        int toplam = a + b;               // toplam = a + b
        System.out.println(toplam);       // toplamı yaz
    }
}

Programın yapısı birkaç sözcükle özetlenebilir. public class Toplam satırı programın adını verir. main metodu programın başladığı yerdir; diyagramdaki Başla kutusunun karşılığı onun açılan küme parantezi, Bitir'in karşılığı kapanan küme parantezidir. Scanner, Java'nın klavyeden veri okumak için sunduğu hazır sınıftır; giris.nextInt() klavyeden bir tam sayı okur. Bu yüzden her “oku” paralelkenarı bir nextInt() çağrısına dönüşür. Atama dikdörtgeni aynen int toplam = a + b; satırına, “yaz” paralelkenarı System.out.println(toplam); satırına karşılık gelir. Satır sonlarında // ile başlayan açıklamalar vardır. Derleyici bunları yok sayar; burada her satırın diyagramdaki karşılığını hatırlatırlar.

Program 4 ve 7 girdisiyle çalıştırıldığında 11 yazar. −3 ve 10 girdisiyle 7 yazar. Sıralı bir programda girdiler değişse bile çalışan satırlar ve sıraları hiç değişmez; değişen yalnızca değerlerdir.

4.4.3Sıra neden önemlidir?

Sıralı akışta kutuların yeri keyfî değildir. Toplam kutusu okuma kutularının üstüne taşınsa a ile b'nin henüz değeri olmaz ve toplam hesaplanamaz. Bu hata kolay fark edilir. Daha sinsi hatalar, iki atamanın yer değiştirmesinden doğar.

Örnek 4.2

İki değişkenin değerleri yer değiştirecek; bu işleme takas denir. a = 4, b = 7 ise işlemden sonra a = 7, b = 4 olmalıdır. Bir öğrenci diyagrama iki kutu koyar: önce a = b, sonra b = a. Sonuç ne olur? Doğru diyagram nasıl kurulur?

Çözüm. Önerilen diyagram adım adım yürütülür. a = b kutusu çalışınca a, b'nin değerini alır: a = 7, b = 7. a'nın eski değeri 4 artık hiçbir yerde yoktur. b = a kutusu çalışınca b, a'nın şimdiki değerini alır: b = 7. Sonuç a = 7, b = 7 olur; takas başarısızdır.

Sorun, ilk atamanın a'nın eski değerini silmesidir. Çözüm, bu değeri önce üçüncü bir değişkende saklamaktır. Böyle kısa süreli kullanılan değişkene geçici değişken (temporary variable) denir. Doğru sıra üç kutudur: gecici = a, a = b, b = gecici. Yürütme: gecici = 4; a = 7; b = 4. Sonuç a = 7, b = 4'tür.

import java.util.Scanner;

public class Takas {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int a = giris.nextInt();
        int b = giris.nextInt();
        int gecici = a;                   // a'nın değeri saklanır
        a = b;
        b = gecici;
        System.out.println(a + " " + b);
    }
}

Program 4 7 girdisiyle çalıştırıldığında 7 4 yazar. Örnek, sıralı akışın temel kuralını gösterir: her kutu, bir öncekinin bıraktığı değerlerle çalışır. Bir atama, sağ tarafındaki değişkenin o anki değerini okur; eski ya da gelecekteki değerini değil.

Sık yapılan hata

Atamayı matematikteki eşitlik gibi okumak. a = b “a ile b eşittir” demek değildir, “b'nin şimdiki değerini a'ya kopyala” demektir. Kopyalamadan sonra b değişse a değişmez; a değiştirilse b değişmez. İki değişken yalnızca atama anında aynı değeri taşır.

4.5Koşullu akış

Sıralı bir algoritma her girdide aynı adımları yapar. Oysa gerçek problemlerin çoğunda yapılacak iş duruma göre değişir: not 60'ın altındaysa öğrenci kalır, şifre yanlışsa kapı açılmaz, sıcaklık sıfırın altındaysa uyarı verilir. Bu tür seçimler karar simgesiyle gösterilir.

4.5.1İki yollu karar

Tanım 4.10

Koşullu akış (conditional flow), bir karar simgesinde sorulan koşulun sonucuna göre iki yoldan birinin izlendiği akıştır. Koşul doğruysa Evet yolu, yanlışsa Hayır yolu çalışır. Bu yollara dal (branch), yolun ikiye ayrılmasına dallanma (branching) denir. Dallar bir bağlayıcıda yeniden birleşir.

Şekil 4.9 bir sınav notuna göre “Geçti” ya da “Kaldı” yazan diyagramı gösterir. Geçme sınırı 60'tır; 60 ve üstü geçer.

EvetHayırBaşlanot değerini okunot >= 60 ?"Kaldı" yaz"Geçti" yazBitir
Şekil 4.9: Koşullu akış: not 60 ya da üstüyse “Geçti”, değilse “Kaldı” yazılır. Yollar alttaki bağlayıcıda birleşir.
Başla
  not değerini oku
  not >= 60 ?
    Evet → "Geçti" yaz
    Hayır → "Kaldı" yaz
Bitir

Diyagramda üç nokta özellikle önemlidir. Karar simgesinden iki yol çıkar ama her çalıştırmada bu yollardan yalnızca biri izlenir. “Geçti” ve “Kaldı” kutuları aynı çalıştırmada asla birlikte çalışmaz. Yollar alttaki bağlayıcıda (●) yeniden birleşir; bu nokta, karar yapısının tek çıkışıdır. Son olarak koşulun sınır değeri ayrıca önem taşır. Geçme sınırı “60 ve üstü” olduğu için koşul not >= 60 biçiminde yazılır. not > 60 yazılsaydı tam 60 alan öğrenci kalırdı.

4.5.2Kararı adım adım yürütmek

Koşullu bir diyagramı tam olarak anlamak için onu en az iki kez yürütmek gerekir. Girdilerden biri Evet yolunu, öbürü Hayır yolunu çalıştırmalıdır. Tablo 4.5 diyagramı üç girdiyle özetler: not = 72, not = 45 ve sınır değeri not = 60.

Tablo 4.5: Geçti/Kaldı diyagramının üç çalıştırması. Her çalıştırmada kutulardan biri hiç çalışmaz.
notKararİzlenen okÇalışan kutuHiç çalışmayan kutu
7272 >= 60 → doğruEvet"Geçti" yazHayır dalı
4545 >= 60 → yanlışHayır"Kaldı" yazEvet dalı
6060 >= 60 → doğruEvet"Geçti" yazHayır dalı

Birinci çalıştırmada kullanıcı 72 girer ve not = 72 olur. Karar kutusunda 72 >= 60 sorulur; cevap doğrudur. Akış Evet okundan devam eder ve “Geçti” yazılır. “Kaldı” kutusu bu çalıştırmada hiç çalışmaz. Yol bağlayıcıda ana akışa döner ve Bitir'e ulaşılır. İkinci çalıştırmada not = 45 olur. 45 >= 60 yanlıştır; Hayır yolu izlenir, “Kaldı” yazılır ve bu kez “Geçti” kutusu çalışmaz. İki çalıştırma birlikte diyagramdaki her kutuyu en az bir kez çalıştırmış olur.

EvetHayırBaşlanot değerini okunot >= 60 ?"Kaldı" yaz"Geçti" yazBitir EvetHayırBaşlanot değerini okunot >= 60 ?"Kaldı" yaz"Geçti" yazBitir
Şekil 4.10: Aynı diyagramın iki çalıştırması. (a) not = 72: Evet dalındaki “Geçti” yaz kutusu çalışır. (b) not = 45: Hayır dalındaki “Kaldı” yaz kutusu çalışır.

Üçüncü satır sınır değeridir. 60 girildiğinde 60 >= 60 doğrudur ve “Geçti” yazılır. Bu satır, koşulda >= yerine yanlışlıkla > yazılmış bir diyagramı hemen ele verir: o diyagram 60 için “Kaldı” yazardı. 72 ve 45 bu hatayı yakalayamaz, çünkü iki diyagram bu girdilerde aynı sonucu verir.

Diyagramın Java karşılığı if/else deyimidir:

import java.util.Scanner;

public class GectiKaldi {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int not = giris.nextInt();        // not değerini oku
        if (not >= 60) {                  // not >= 60 ?
            System.out.println("Geçti");  // Evet dalı
        } else {
            System.out.println("Kaldı");  // Hayır dalı
        }
    }
}

if sözcüğünden sonra parantez içinde koşul yazılır. Koşul doğruysa ilk küme parantezinin içi, yanlışsa else sözcüğünden sonraki küme parantezinin içi çalışır. Karar simgesi parantezdeki koşula, Evet dalı ilk bloğa, Hayır dalı else bloğuna karşılık gelir. Kapanan son küme parantezi de bağlayıcının yerini tutar: iki blok bittikten sonra yürütme aynı noktadan sürer. Program 72, 60 ve 100 için “Geçti”; 45, 59 ve 0 için “Kaldı” yazar.

4.5.3Tek yollu karar

Bazı kararlarda dallardan yalnızca birinde yapılacak iş vardır. Şekil 4.5 üzerindeki mutlak değer diyagramı buna örnektir: sayı negatifse işareti değiştirilir, negatif değilse hiçbir şey yapılmaz. Bu durumda karardan yine iki ok çıkar ama Hayır oku hiçbir kutuya uğramadan doğrudan birleşme noktasına gider. Java'da bu yapı else kısmı olmayan bir if ile yazılır:

import java.util.Scanner;

public class MutlakDeger {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int x = giris.nextInt();
        if (x < 0) {                      // Hayır dalında kutu yok: else gerekmez
            x = -x;
        }
        System.out.println(x);
    }
}

Program −5 için 5, 8 için 8, 0 için 0 yazar. Üç girdi bilinçli seçilmiştir: −5 Evet dalını, 8 Hayır dalını, 0 ise sınırı dener. 0 < 0 yanlış olduğu için 0 olduğu gibi kalır; zaten mutlak değeri de 0'dır.

Karar yapısının sık görülen bir başka örneği tek/çift sınamasıdır. Bir sayının çift olup olmadığı, 2'ye bölümünden kalana bakılarak anlaşılır. Kalan (remainder) işlemi Java'da % ile yazılır: 7 % 2 değeri 1, 12 % 2 değeri 0'dır. Karar kutusuna x % 2 == 0 ? yazılır; Evet dalı “çift”, Hayır dalı “tek” yazar.

import java.util.Scanner;

public class TekCift {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int x = giris.nextInt();
        if (x % 2 == 0) {                 // x % 2 == 0 ?
            System.out.println("çift");
        } else {
            System.out.println("tek");
        }
    }
}
Sık yapılan hata

Tek sayıyı x % 2 == 1 ? koşuluyla sınamak. Bu koşul pozitif sayılarda doğru çalışır ama Java'da kalanın işareti bölünen sayının işaretini izler: -3 % 2 değeri 1 değil, −1'dir. Bu yüzden −3 için x % 2 == 1 yanlış çıkar ve tek bir sayı “çift” diye yazılır. x % 2 == 0 ? sorusu ise −3 için de doğru cevabı verir: -3 % 2 == 0 yanlıştır ve “tek” yazılır. Kalan sıfırla karşılaştırıldığında işaret sorunu ortadan kalkar.

4.5.4Üç sayının en büyüğü

İki sayının büyüğünü bulmak tek karar ister. Üç sayıda kararlar çoğalır ve diyagramın nasıl kurulacağı önem kazanır. Çok kullanılan bir yöntem “aday” fikridir. İlk sayı şimdilik en büyük kabul edilir. Sonra diğer sayılar tek tek bu adayla karşılaştırılır; daha büyüğü çıkarsa aday değişir.

EvetHayırEvetHayırBaşlaa, b, c değerlerini okuenb = ab > enb ?enb = bc > enb ?enb = cenb değerini yazBitir
Şekil 4.11: Üç sayının en büyüğü. enb = a ile başlanır; b daha büyükse enb = b, sonra c daha büyükse enb = c yapılır.
Başla
  a, b, c değerlerini oku
  enb = a
  b > enb ?  Evet → enb = b
  c > enb ?  Evet → enb = c
  enb değerini yaz
Bitir

Şekil 4.11 yöntemin diyagramıdır. İki karar arka arkaya gelir ve her birinin yalnız Evet dalında bir kutu vardır; Hayır dalları doğrudan bir sonraki adıma geçer. Yani diyagram, iki tek yollu kararın sıralı yapı içinde arka arkaya dizilmesinden oluşur. Yapıların birbirine eklenerek büyümesinin güzel bir örneğidir.

Örnek 4.3

Diyagram önce (a, b, c) = (4, 9, 7), sonra (3, 2, 8) için yürütülecek. Her kararda hangi yol izlenir, enb nasıl değişir?

Çözüm. Birinci çalıştırmada üç sayı okunur ve enb = 4 olur. İlk kararda 9 > 4 doğrudur; enb = 9 olur. İkinci kararda 7 > 9 yanlıştır; enb değişmez ve 9 yazılır.

(4, 9, 7) için izleme
Çalışan kutuKararenb
enb = a—4
b > enb ?9 > 4 → Evet4
enb = b—9
c > enb ?7 > 9 → Hayır9
enb değerini yazçıktı: 99

İkinci çalıştırmada enb = 3 ile başlanır. 2 > 3 yanlıştır; ilk kararın Evet kutusu çalışmaz. 8 > 3 doğrudur; enb = 8 olur ve 8 yazılır.

(3, 2, 8) için izleme
Çalışan kutuKararenb
enb = a—3
b > enb ?2 > 3 → Hayır3
c > enb ?8 > 3 → Evet3
enb = c—8
enb değerini yazçıktı: 88

İki çalıştırma birlikte her iki kararın her iki dalını da denemiş olur. Her karar yalnızca bir kez sorulur. Sayı sayısı artsa da yöntem değişmez: on sayı için dokuz karar arka arkaya dizilir.

import java.util.Scanner;

public class EnBuyuk {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int a = giris.nextInt(), b = giris.nextInt(), c = giris.nextInt();
        int enb = a;                      // ilk aday
        if (b > enb) {
            enb = b;
        }
        if (c > enb) {
            enb = c;
        }
        System.out.println(enb);
    }
}

Program (4, 9, 7) için 9, (3, 2, 8) için 8 yazar. En büyük sayının başta olduğu (9, 4, 7) girdisinde iki karar da Hayır olur ve 9 yazılır. Üç sayı eşitse, örneğin (5, 5, 5), kararlar yine Hayır olur; enb = 5 kalır.

Sık yapılan hata

Adayı ilk sayı yerine sabit bir değerle, örneğin enb = 0 ile başlatmak. Girdiler pozitif oldukça bu da doğru sonuç verir; hata ancak bütün girdiler negatif olduğunda ortaya çıkar. (−2, −7, −1) için −2 > 0, −7 > 0 ve −1 > 0 yanlıştır; aday hiç değişmez ve 0 yazılır. Oysa 0 girdilerden biri bile değildir. Doğru diyagram enb = a ile başlar ve bu girdide −1 yazar.

4.5.5Çok yollu karar: karar zinciri

Bir karar kutusunun yalnızca iki çıkışı vardır. Seçenek sayısı ikiden fazlaysa kararlar bir zincir gibi dizilir: her karar bir öncekinin Hayır dalına yerleştirilir. Buna çok yollu karar (multi-way decision) denir.

EvetHayırEvetHayırEvetHayırs değerini okus < 0 ?"Donma" yazs < 15 ?"Soğuk" yazs < 25 ?"Ilık" yaz"Sıcak" yazBitir
Şekil 4.12: Karar zinciri: sıcaklık s < 0 ise “Donma”, s < 15 ise “Soğuk”, s < 25 ise “Ilık”, değilse “Sıcak” yazılır.

Şekil 4.12 bir sıcaklık değerini dört sınıftan birine ayırır. Zincirin çalışma kuralı şudur: kararlar yukarıdan aşağıya sırayla sorulur; ilk doğru koşulun dalı çalışır ve ondan sonraki kararlar hiç sorulmaz. Hiçbir koşul doğru değilse en alttaki Hayır dalı çalışır.

Tablo 4.6: Karar zincirinin beş girdiyle yürütülmesi. Sorulan karar sayısı, ilk doğru koşulun konumuna bağlıdır.
sSorulan kararlarKarar sayısıÇıktı
−5s < 0 ? Evet1Donma
10s < 0 ? Hayır · s < 15 ? Evet2Soğuk
15s < 0 ? Hayır · s < 15 ? Hayır · s < 25 ? Evet3Ilık
18s < 0 ? Hayır · s < 15 ? Hayır · s < 25 ? Evet3Ilık
30s < 0 ? Hayır · s < 15 ? Hayır · s < 25 ? Hayır3Sıcak

Tablo 4.6'daki s = 18 satırı adım adım şöyle okunur. İlk karar 18 < 0 sorusudur; yanlıştır ve Hayır dalı ikinci karara gider. 18 < 15 de yanlıştır. Üçüncü karar 18 < 25 doğrudur; “Ilık” yazılır. s = −5 için ise ilk karar doğrudur ve öbür iki karar hiç sorulmaz.

Zincirdeki her karar yalnızca üst sınırı denetler. s < 15 sorusu sorulurken s'nin 0 ya da daha büyük olduğu kesindir; öyle olmasaydı yürütme bu karara hiç gelmezdi. Bu yüzden “0 ≤ s ve s < 15” gibi iki taraflı bir koşula gerek kalmaz. Sınır değerlerinin hangi sınıfa düştüğü de bu kuraldan anlaşılır: s = 15 için 15 < 15 yanlıştır, karar zincirde ilerler ve 15 “Ilık” olur. s = 0 ise “Soğuk”tur.

Kararların sırası önemlidir. Kararlar ters sırada dizilse, yani en başta s < 25 ? sorulsa, s = −5 için −5 < 25 doğru çıkar ve “Ilık” yazılır; “Donma” dalına hiç ulaşılmaz. s = 10 için de aynı şey olur. Genel kural kısadır: dar koşul önce, geniş koşul sonra sorulur. Seçenek sayısı n ise n − 1 karar gerekir; dört sınıf için üç karar vardır.

Java'da karar zinciri if … else if … else biçiminde yazılır. Her else if bir önceki koşulun Hayır dalıdır; son else hiçbir koşulun tutmadığı durumdur:

import java.util.Scanner;

public class Sicaklik {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int s = giris.nextInt();
        if (s < 0) {
            System.out.println("Donma");
        } else if (s < 15) {
            System.out.println("Soğuk");
        } else if (s < 25) {
            System.out.println("Ilık");
        } else {
            System.out.println("Sıcak");
        }
    }
}

Program −5 için “Donma”, 0 ve 10 için “Soğuk”, 15 ve 18 için “Ilık”, 25 ve 30 için “Sıcak” yazar. Bu yedi girdi zincirin dört çıkışını ve her sınır değerini dener.

4.5.6Bileşik koşul: VE ve VEYA

Bazı kararlar iki koşulun birlikte değerlendirilmesini ister. Araç kiralayan bir şirket, müşterinin hem 18 yaşını doldurmuş olmasını hem de ehliyetinin bulunmasını şart koşar. Bir takvim uygulaması, gün cumartesi ya da pazar ise “Hafta sonu” yazar. İki koşulu birleştiren böyle ifadelere bileşik koşul (compound condition) denir.

Tanım 4.11

VE ile bağlanan bileşik koşul, iki koşul da doğruysa doğrudur; biri bile yanlışsa yanlıştır. VEYA ile bağlanan bileşik koşul, koşullardan en az biri doğruysa doğrudur; ikisi de yanlışsa yanlıştır. Java'da VE &&, VEYA || operatörüyle yazılır.

Bileşik koşul tek bir karar kutusuna yazılabilir: yaş >= 18 VE ehliyet var ?. Diyagramda ayrıntı gerekiyorsa iki ayrı karara açılır. Şekil 4.13 iki bağlacın iki kararla nasıl çizildiğini gösterir.

VE: ikisi de Evet olmalıyaş >= 18 ?ehliyet var ?EvetKiralanabilirEvetKiralanamazHayırHayırVEYA: biri Evet yetergün == Cmt ?gün == Paz ?HayırHafta içiHayırHafta sonuEvetEvet
Şekil 4.13: Bileşik koşulun iki kararla çizimi. Solda VE: iki kararın da Evet olması gerekir. Sağda VEYA: kararlardan biri Evet ise yeter.

VE yapısında ikinci karar, birincinin Evet dalına yerleştirilir. Birinci karar Hayır ise sonuç zaten Hayır'dır ve ikinci karar hiç sorulmaz. VEYA yapısında ikinci karar birincinin Hayır dalındadır. Birinci karar Evet ise sonuç zaten Evet'tir ve ikinciye gerek kalmaz. Tablo 4.7 ile Tablo 4.8 bu davranışı bütün durumlar için gösterir.

Tablo 4.7: VE kararı. Birinci karar Hayır olunca ikinci karar sorulmaz.
yaşehliyetyaş >= 18 ?ehliyet var ?Sonuç
20varEvetEvetKiralanabilir
20yokEvetHayırKiralanamaz
16varHayırsorulmazKiralanamaz
16yokHayırsorulmazKiralanamaz
Tablo 4.8: VEYA kararı. Birinci karar Evet olunca ikinci karar sorulmaz.
güngün == Cmt ?gün == Paz ?Sonuç
CmtEvetsorulmazHafta sonu
PazHayırEvetHafta sonu
SalHayırHayırHafta içi
Tanım 4.12

Kısa devre değerlendirme (short-circuit evaluation), bileşik koşulun sonucu ilk koşuldan belli olduğunda ikinci koşulun hiç hesaplanmamasıdır. A && B ifadesinde A yanlışsa B'ye bakılmaz; A || B ifadesinde A doğruysa B'ye bakılmaz.

Java'daki && ve || operatörleri, Şekil 4.13'teki iki kararlı diyagramlarla aynı biçimde çalışır. Bu davranış zaman kazandırmakla kalmaz, bazı hataları da önler. sayac > 0 && toplam / sayac > 50 koşulunda sayac 0 ise ikinci kısım hiç hesaplanmaz; böylece sıfıra bölme hatası oluşmaz.

import java.util.Scanner;

public class Kiralama {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int yas = giris.nextInt();
        boolean ehliyet = giris.nextBoolean();   // true: ehliyet var
        String gun = giris.next();               // Pzt, Sal, ..., Cmt, Paz
        if (yas >= 18 && ehliyet) {
            System.out.println("Kiralanabilir");
        } else {
            System.out.println("Kiralanamaz");
        }
        if (gun.equals("Cmt") || gun.equals("Paz")) {
            System.out.println("Hafta sonu");
        } else {
            System.out.println("Hafta içi");
        }
    }
}

Program “20 true Cmt” girdisiyle “Kiralanabilir” ve “Hafta sonu”; “16 true Paz” girdisiyle “Kiralanamaz” ve “Hafta sonu” yazar. Bir bileşik koşulu test etmek için her kararın iki çıkışı da denenir. VE örneğinde (20, var), (20, yok) ve (16, —) girdileri üç farklı yolu çalıştırır. 16 yaşında birinin ehliyeti olup olmaması sonucu değiştirmez, çünkü ikinci karar sorulmaz.

4.5.7Artık yıl

Karar zincirinde sıranın önemini gösteren klasik örnek, artık yıl kuralıdır. Gregoryen takvimde kural üç parçalıdır: 4'e bölünen yıllar artık yıldır; ama 100'e bölünenler artık değildir; 400'e bölünenler ise yine artıktır. Artık yılda şubat 29 gün çeker.

Kuralın istisnaları vardır, istisnaların da istisnası vardır. Böyle bir kural diyagrama çevrilirken en dar koşul en başa konur. 400'e bölünme, 100'e bölünmenin; 100'e bölünme de 4'e bölünmenin özel bir durumudur. Bu yüzden kararlar 400, 100, 4 sırasıyla sorulur.

EvetHayırEvetHayırEvetHayırBaşlayıl değerini okuyıl % 400 == 0 ?"Artık" yazyıl % 100 == 0 ?"Değil" yazyıl % 4 == 0 ?"Artık" yaz"Değil" yazBitir
Şekil 4.14: Artık yıl diyagramı: yıl % 400, yıl % 100 ve yıl % 4 kararlarından oluşan üç kararlı zincir; dört çıkış.
Başla
  yıl değerini oku
  yıl % 400 == 0 ?  Evet → "Artık" yaz
  yıl % 100 == 0 ?  Evet → "Değil" yaz
  yıl % 4 == 0 ?    Evet → "Artık" yaz
  Hayır → "Değil" yaz
Bitir
Tablo 4.9: Artık yıl diyagramının dört girdiyle yürütülmesi. Her hücrede kalan ve kararın sonucu yazılıdır.
yılyıl % 400yıl % 100yıl % 4Sorulan kararÇıktı
202424 → Hayır24 → Hayır0 → Evet3Artık
1900300 → Hayır0 → Evetsorulmaz2Değil
20000 → Evetsorulmazsorulmaz1Artık
202323 → Hayır23 → Hayır3 → Hayır3Değil

Tablo 4.9 dört girdinin her birinin hangi yoldan geçtiğini gösterir. 2024 için 2024 % 400 = 24 ve 2024 % 100 = 24 sıfır değildir; iki karar da Hayır'dır. 2024 % 4 = 0 olduğu için üçüncü karar Evet'tir ve “Artık” yazılır. 1900'de 1900 % 400 = 300 sıfır değildir ama 1900 % 100 = 0'dır. İkinci karar Evet olur, “Değil” yazılır ve üçüncü karar hiç sorulmaz. 1900, 4'e bölündüğü hâlde artık yıl değildir; yalnız yıl % 4 == 0 sorusuna bakan bir diyagram burada yanılırdı. 2000'de ilk karar Evet'tir: 2000, 100'e bölündüğü hâlde 400'e de bölündüğü için artık yıldır. 2023 ise üç kararın da Hayır olduğu son dalı çalıştırır.

EvetHayırEvetHayırEvetHayırBaşlayıl değerini okuyıl % 400 == 0 ?"Artık" yazyıl % 100 == 0 ?"Değil" yazyıl % 4 == 0 ?"Artık" yaz"Değil" yazBitir EvetHayırEvetHayırEvetHayırBaşlayıl değerini okuyıl % 400 == 0 ?"Artık" yazyıl % 100 == 0 ?"Değil" yazyıl % 4 == 0 ?"Artık" yaz"Değil" yazBitir
Şekil 4.15: Artık yıl zincirinde iki erken çıkış. (a) 1900: ikinci karar (yıl % 100 == 0) Evet; üçüncü karar sorulmaz. (b) 2000: ilk karar Evet; kalan iki karar sorulmaz.

Dört girdi, diyagramın dört çıkışının hepsini birer kez çalıştırır. Bir karar zincirini test ederken amaç tam olarak budur. Java karşılığı yine bir if … else if … else zinciridir:

import java.util.Scanner;

public class ArtikYil {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int yil = giris.nextInt();
        if (yil % 400 == 0) {
            System.out.println("Artık");
        } else if (yil % 100 == 0) {
            System.out.println("Değil");
        } else if (yil % 4 == 0) {
            System.out.println("Artık");
        } else {
            System.out.println("Değil");
        }
    }
}

Program 2024 ve 2000 için “Artık”, 1900 ve 2023 için “Değil” yazar. Yakın geleceğin ilk istisnası 2100 yılıdır: 2100, 100'e bölünür ama 400'e bölünmez; program bu yıl için “Değil” yazar. 1600 ise 400'e bölündüğü için artık yıldır.

Sık yapılan hata

Zinciri geniş koşulla başlatmak. Önce yıl % 4 == 0 ? sorulup Evet dalına doğrudan “Artık” yazılırsa 1900 ve 2100 de artık yıl sayılır. 100 ve 400 kuralları yalnızca 4'e bölünen yılları ilgilendirdiği için bu kurallara hiç sıra gelmez. Zincirdeki kararlar dar koşuldan geniş koşula doğru dizilmelidir.

4.6Tekrarlı akış

Bilgisayarı güçlü kılan şey, aynı işi yorulmadan binlerce kez yapabilmesidir. Bir sınıftaki 30 öğrencinin notunu toplamak, 30 kez aynı iki adımı yapmaktır: notu oku, toplama ekle. Bu adımları diyagrama 30 kez çizmek yerine bir kez çizip geri dönen bir okla tekrar ettirmek gerekir.

4.6.1Döngü yapısı

Tanım 4.13

Tekrarlı akış (repetitive flow) ya da döngü (loop), bir grup adımın bir koşul doğru oldukça tekrar tekrar çalıştığı akıştır. Tekrarlanan adımlara döngü gövdesi (loop body), gövdenin bir kez çalışmasına tur (iteration) denir. Gövdenin sonundan koşula geri dönen ok döngüyü oluşturur.

Şekil 4.16 1'den 5'e kadar sayıları yazan diyagramı gösterir. Diyagramda üç parça vardır. i = 1 kutusu sayacın ilk değerini verir. i <= 5 ? karar kutusu döngünün devam edip etmeyeceğine karar verir. Evet dalındaki iki kutu, yani “i değerini yaz” ve i = i + 1, döngü gövdesidir. Gövdenin sonundan çıkan ok sola döner ve yeniden karar kutusuna girer.

EvettekrarHayırBaşlai = 1i <= 5 ?i değerini yazi = i + 1Bitir
Şekil 4.16: Tekrarlı akış: i = 1 ile başlanır; i <= 5 oldukça i yazılır ve 1 artırılır. Soldaki “tekrar” oku döngüyü oluşturur.
Başla
  i = 1
  i <= 5 ?
    Evet → i değerini yaz
            i = i + 1
            karara dön
    Hayır → Bitir

Bu diyagramda koşul gövdeden önce sorulur. Koşul daha ilk denemede yanlışsa gövde hiç çalışmaz. Böyle döngülere ön koşullu döngü (pre-test loop) denir. Koşul yanlış olduğunda Hayır dalı döngünün dışına, Bitir'e çıkar.

Döngünün bir gün bitmesi için tekrar yolunda koşulu değiştiren bir işlem bulunmalıdır. Burada bu işlem i = i + 1'dir. i her turda büyür ve sonunda 5'i geçer. Bu kutu unutulsa i hep 1 kalır, 1 <= 5 her seferinde doğru çıkar ve diyagram durmadan 1 yazar. Böyle bitmeyen döngüye sonsuz döngü (infinite loop) denir.

4.6.2Döngüyü adım adım yürütmek

Döngüde aynı kutular tekrar tekrar çalıştığı için izleme tablosunda her tur bir satırla gösterilir. Tablo 4.10 diyagramın bütün turlarını verir.

Tablo 4.10: 1'den 5'e sayıları yazan döngünün izleme tablosu. Son satır, döngüden çıkılan son karardır.
Turi (karardan önce)KararYazılani (turun sonunda)
111 <= 5 → doğru12
222 <= 5 → doğru23
333 <= 5 → doğru34
444 <= 5 → doğru45
555 <= 5 → doğru56
—66 <= 5 → yanlış——

Yürütme şöyle ilerler. Sayaç ilk değerini alır: i = 1. Karar kutusunda 1 <= 5 sorulur; doğrudur ve Evet dalına, yani döngü gövdesine girilir. 1 yazılır. i = i + 1 kutusu i'yi 2 yapar. Geri dönen ok yürütmeyi yeniden karar kutusuna götürür. 2 <= 5 de doğrudur; 2 yazılır, i = 3 olur. Aynı döngü 3, 4 ve 5 için de tekrarlanır. 5 yazıldıktan sonra i = 6 olur. Karar kutusunda 6 <= 5 sorulur; bu kez cevap yanlıştır ve Hayır dalı Bitir'e götürür.

EvettekrarHayırBaşlai = 1i <= 5 ?i değerini yazi = i + 1Bitir EvettekrarHayırBaşlai = 1i <= 5 ?i değerini yazi = i + 1Bitir
Şekil 4.17: Döngünün iki anı. (a) 1. turun sonu: i = 1 + 1 = 2 olur; geri dönen ok karara götürür. (b) Son karar: 6 <= 5 yanlış; Hayır dalı döngüden çıkar.

Tablodan iki sayım çıkar. Gövde 5 kez çalıştı ama koşul 6 kez soruldu. Bu her ön koşullu döngü için geçerlidir: karar, gövdeden bir fazla çalışır, çünkü son deneme döngüyü bitiren yanlış cevaptır. Döngüden çıkıldığında i'nin değeri 5 değil 6'dır. Sayacın döngüden sonraki değeri sık sık sorulan ve sık sık yanlış cevaplanan bir sorudur.

Java'da ön koşullu döngü while ile yazılır. Parantezdeki koşul doğru oldukça küme parantezinin içi tekrar çalışır; kapanan küme parantezi geri dönen okun yerini tutar:

public class BirdenBese {
    public static void main(String[] args) {
        int i = 1;                        // sayacın ilk değeri
        while (i <= 5) {                  // karar: i <= 5 ?
            System.out.print(i + " ");    // i değerini yaz
            i = i + 1;                    // sayacı güncelle
        }                                 // geri dönen ok: karara dön
        System.out.println();
    }
}

Program 1 2 3 4 5 yazar. System.out.print, println'den farklı olarak satır sonu eklemez; sayılar bu yüzden aynı satırda, aralarında birer boşlukla yazılır. Döngüden sonraki System.out.println() satırı yalnızca satırı bitirir.

4.6.3Sayaç ve biriktirici

Döngülerin çoğunda iki tür değişken bulunur. Biri döngünün kaçıncı turda olduğunu sayar, öbürü turdan tura biriken sonucu tutar.

Tanım 4.14

Sayaç (counter), kaç tekrar yapıldığını izleyen değişkendir; her turda 1 artar. Biriktirici (accumulator), kısmi sonucu tutan değişkendir; her turda yeni değer ona eklenir (ya da onunla çarpılır). Biriktiricinin başlangıç değeri işleme göre seçilir: toplam için 0, çarpım için 1.

Başlangıç değerinin seçimi rastgele değildir. Toplama için 0 seçilir, çünkü bir sayıya 0 eklemek onu değiştirmez; ilk turdan sonra toplam, ilk sayının kendisi olur. Çarpım için aynı rol 1'indir. Çarpım biriktiricisi yanlışlıkla 0 ile başlarsa her turda 0 ile çarpılır ve sonuç hep 0 çıkar. Örneğin 1'den 5'e sayıların çarpımı 1 × 1 × 2 × 3 × 4 × 5 = 120'dir; biriktirici 0 ile başlarsa 0 × 1 × 2 × 3 × 4 × 5 = 0 bulunur.

EvetHayırBaşlasayac = 0, toplam = 0sayac < 3 ?x değerini okutoplam = toplam + xsayac = sayac + 1toplamı yazBitir
Şekil 4.18: Sayaç ve biriktirici: üç sayı okunur ve toplanır. sayac < 3 oldukça x okunur, toplam = toplam + x ve sayac = sayac + 1 yapılır.
Başla
  sayac = 0, toplam = 0
  sayac < 3 ?
    Evet → x değerini oku
            toplam = toplam + x
            sayac = sayac + 1
            karara dön
    Hayır → toplamı yaz
Bitir

Şekil 4.18 üç sayı okuyup toplamını yazan diyagramdır. sayac sayaç, toplam biriktiricidir. İkisi de döngüden önce, bir kez 0 değerini alır. Tablo 4.11 girdiler 4, 7 ve 2 iken her turun sonundaki değerleri verir.

Tablo 4.11: Girdiler 4, 7, 2 için sayaç ve biriktiricinin tur tur değerleri.
AnxsayactoplamSonraki karar
başlangıç—000 < 3 → doğru
1. tur4141 < 3 → doğru
2. tur72112 < 3 → doğru
3. tur23133 < 3 → yanlış

Birinci turda x = 4 okunur. Biriktirici toplam = 0 + 4 = 4 olur, sayaç sayac = 0 + 1 = 1 olur ve ok karara döner. İkinci turda x = 7 okunur; toplam = 4 + 7 = 11, sayac = 2. Üçüncü turda x = 2 okunur; toplam = 11 + 2 = 13, sayac = 3. Karar kutusunda 3 < 3 sorulur; yanlıştır ve döngüden çıkılır. Toplam yazılır: 13. Sayaç döngünün kaç kez döndüğünü, biriktirici sonucu tuttu.

sayac3+1 her turdatoplam13+x her turda
Şekil 4.19: Döngü bittiğinde sayaç 3, biriktirici 13'tür. Sayaç her turda 1, biriktirici her turda x kadar artmıştır.
import java.util.Scanner;

public class UcSayiToplami {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int sayac = 0, toplam = 0;
        while (sayac < 3) {
            int x = giris.nextInt();      // x değerini oku
            toplam = toplam + x;          // biriktirici
            sayac = sayac + 1;            // sayaç
        }
        System.out.println(toplam);
    }
}

Program 4 7 2 girdisiyle 13, 10 −3 5 girdisiyle 12 yazar. Java kodunda x değişkeni döngünün içinde tanımlanmıştır. Her turda yeni bir değer okunur ve önceki tur için x'in değeri artık gerekmez.

Sık yapılan hata

Biriktiriciyi döngünün içinde sıfırlamak. toplam = 0 kutusu yanlışlıkla döngü gövdesinin başına çizilirse her tur, önceki turların toplamını silerek başlar. Girdiler 4, 7, 2 için tablo şöyle olur:

Hatalı diyagramın izlemesi: toplam her turda sıfırlanıyor.
Turxtoplam (sıfırlandıktan sonra)toplam (eklemeden sonra)sayac
1. tur4041
2. tur7072
3. tur2023

13 yerine 2 yazılır, yani yalnız son değer kalır. Başlangıç değeri veren kutular döngüden önce, bir kez çalışmalıdır.

4.6.41'den n'e toplam

Sayaç ve biriktiricinin birlikte kullanıldığı klasik bir örnek, 1'den n'e kadar sayıların toplamıdır. Bu kez sayaç yalnızca tur saymakla kalmaz, toplanacak sayının kendisi olur.

EvetHayırBaşlan değerini okutoplam = 0, i = 1i <= n ?toplam = toplam + ii = i + 1toplamı yazBitir
Şekil 4.20: 1'den n'e toplam. n okunur; toplam = 0, i = 1 ile başlanır; i <= n oldukça toplam = toplam + i ve i = i + 1 yapılır.
Başla
  n değerini oku
  toplam = 0, i = 1
  i <= n ?
    Evet → toplam = toplam + i
            i = i + 1
            karara dön
    Hayır → toplamı yaz
Bitir

Diyagramda i sayaç, toplam biriktiricidir. Tablo 4.12 n = 4 için yürütmeyi gösterir. Beklenen sonuç 1 + 2 + 3 + 4 = 10'dur.

Tablo 4.12: 1'den n'e toplam diyagramının n = 4 için izleme tablosu.
TuriKarartoplami (güncellenen)
1. tur11 <= 4 → doğru0 + 1 = 12
2. tur22 <= 4 → doğru1 + 2 = 33
3. tur33 <= 4 → doğru3 + 3 = 64
4. tur44 <= 4 → doğru6 + 4 = 105
çıkış55 <= 4 → yanlış10—

Tablonun her satırı bir turdur. İlk turda 1 <= 4 doğrudur; toplam 0 + 1 = 1 olur, i 2'ye çıkar. İkinci turda toplam 1 + 2 = 3, üçüncüde 3 + 3 = 6, dördüncüde 6 + 4 = 10 olur. i = 5 olduğunda 5 <= 4 yanlıştır ve döngüden çıkılır. Gövde n = 4 kez, karar n + 1 = 5 kez çalıştı. Ekrana 10 yazılır.

Sonuç bir formülle de denetlenebilir. 1'den n'e sayıları bir kez artan, bir kez azalan sırada alt alta yazıp sütun sütun toplamak, formülü adım adım verir. n = 4 için:

1'den 4'e toplamın iki kez yazılması
artan1234
azalan4321
sütun toplamı5555

Her sütunun toplamı n + 1 = 5'tir ve n = 4 sütun vardır. İki satırın toplamı 4 × 5 = 20 eder. Bu, aranan toplamın iki katıdır; aranan toplam 20 ÷ 2 = 10 olur. Genel formül n(n + 1) / 2'dir. Formül, diyagramın doğru çalıştığını bağımsız bir yoldan doğrular.

n = 0 girilirse ne olur? i = 1 iken 1 <= 0 sorusu ilk denemede yanlıştır. Gövde hiç çalışmaz ve 0 yazılır. Bu da doğru cevaptır: hiç sayı toplanmamıştır. Formül de 0 × 1 / 2 = 0 verir. Ön koşullu döngünün “gövde hiç çalışmayabilir” özelliği burada işe yarar.

4.6.5Sayaçlı ve bekçi değerli döngü

Şimdiye kadarki döngülerin kaç kez döneceği önceden biliniyordu: 5 kez, 3 kez, n kez. Bazı işlerde bu sayı bilinmez. Kasadaki görevli kaç ürün okutacağını önceden bilmez; ürünler bittiğinde “bitti” tuşuna basar. Bir öğretmen notları girerken not sayısını saymak yerine sona özel bir değer yazar. Böyle bir özel değere bekçi değer denir.

Tanım 4.15

Sayaçlı döngü (counter-controlled loop), tekrar sayısının önceden bilindiği ve bir sayaçla denetlendiği döngüdür. Bekçi değer (sentinel value), verinin bittiğini bildiren ve gerçek veride görülemeyecek biçimde seçilen özel bir değerdir. Bekçi değerli döngü (sentinel-controlled loop), bekçi değer okunana kadar dönen döngüdür.

Tablo 4.13: Sayaçlı ve bekçi değerli döngünün karşılaştırılması.
Sayaçla denetlenenBekçi değerle denetlenen
Tekrar sayısıÖnceden bilinir (n kez)Bilinmez; özel bir değer gelince durur
Karari <= n ?x == −1 ? (bekçi geldi mi?)
ÖrnekSınıftaki 30 öğrencinin notunu okuKasada okutulan ürünler; “bitti” tuşuna kadar
Java'da çoğunluklaforwhile

Bekçi değerin seçimi veriye bağlıdır. Notlar 0 ile 100 arasındaysa −1 uygun bir bekçidir, çünkü hiçbir öğrenci −1 almaz. 0 ise uygun değildir: bir öğrencinin notu gerçekten 0 olabilir ve bu not yanlışlıkla “veri bitti” diye yorumlanır.

HayırEvetBaşlatoplam = 0, sayac = 0x değerini okux == −1 ?toplam = toplam + xsayac = sayac + 1ort = toplam / sayacort değerini yazBitir
Şekil 4.21: Bekçi değerli döngü: x == −1 olana kadar oku, topla, say; sonra ortalamayı yaz. Geri dönen ok oku kutusuna döner.
Başla
  toplam = 0, sayac = 0
  x değerini oku
  x == -1 ?  Evet → 7. satıra git
  toplam = toplam + x
  sayac = sayac + 1;  3. satıra dön
  ort = toplam / sayac
  ort değerini yaz
Bitir

Şekil 4.21 bekçi değerli döngünün iki önemli ayrıntısını gösterir. Birincisi, karar kutusu oku kutusunun hemen ardından, toplama ve saymadan önce gelir. Böylece bekçi değer okunduğunda toplama da sayaca da katılmadan döngüden çıkılır. İkincisi, geri dönen ok karar kutusuna değil, oku kutusunun önüne döner. Her turda yeni bir sayı okunmalıdır; ok karara dönseydi aynı x tekrar tekrar işlenirdi.

Tablo 4.14: Girdiler 80, 64, 90, −1 için bekçi değerli döngünün izleme tablosu.
Okunan xx == −1 ?toplamsayac
80Hayır801
64Hayır1442
90Hayır2343
−1Evet (bekçi)2343

Tablo 4.14 girdiler 80, 64, 90, −1 iken yürütmeyi verir. Her okunan not önce bekçiyle karşılaştırılır. 80, 64 ve 90 gerçek nottur; toplama eklenir ve sayılır. −1 okunduğunda karar Evet olur ve döngü biter. Ortalama 234 / 3 = 78'dir. Gövde 3 kez, karar 4 kez çalıştı. Kaç not girileceği önceden bilinmiyordu; döngüyü verinin kendisi durdurdu.

İlk girdi bekçi değerse gövde hiç çalışmaz ve sayaç 0 kalır. Bu durumda ortalama hesabı sıfıra bölmeye dönüşür. Bu yüzden bölmeden önce sayac > 0 ? diye sorulur. Java karşılığı bu denetimi de içerir:

import java.util.Scanner;

public class NotOrtalamasi {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int toplam = 0, sayac = 0;
        int x = giris.nextInt();          // ilk not döngüden önce okunur
        while (x != -1) {                 // bekçi değer geldi mi?
            toplam = toplam + x;
            sayac = sayac + 1;
            x = giris.nextInt();          // sonraki not: geri dönen ok oku kutusuna
        }
        if (sayac > 0) {
            double ort = (double) toplam / sayac;
            System.out.println(ort);
        } else {
            System.out.println("Not girilmedi");
        }
    }
}

Java kodunda ilk not döngüden önce bir kez okunur, sonraki notlar gövdenin sonunda okunur. Diyagramdaki “geri dönen ok oku kutusuna gider” ayrıntısının while ile yazılışı budur. Ortalama ondalıklı çıkabileceği için double türünde hesaplanır; (double) toplam ifadesi bölmeden önce toplamı ondalıklı sayıya çevirir. Program 80 64 90 −1 için 78.0, 55 70 −1 için 62.5, yalnızca −1 için “Not girilmedi” yazar. Java ondalıklı sayıları ekrana nokta ile yazar; metinde aynı değerler 78,0 ve 62,5 diye okunur.

Sık yapılan hata

Bekçi değeri işlemden sonra sorgulamak. Karar kutusu toplama ve sayma kutularının altına çizilirse −1 de veri gibi işlenir:

Hatalı sıra: önce topla ve say, sonra bekçiyi sor.
Okunan xtoplamsayacx == −1 ?
80801Hayır
641442Hayır
902343Hayır
−12334Evet

Toplam 234 yerine 233, sayaç 3 yerine 4 olur ve ortalama 78 yerine 233 / 4 = 58,25 çıkar. Bekçi değerin kararı, değeri kullanan her işlemden önce gelmelidir.

4.6.6İç içe döngüler

Yapısal programlamanın tek giriş, tek çıkış kuralı bir yapıyı başka bir yapının içine koymaya izin verir. Bir kararın dalında başka bir karar bulunabilir. Bir döngünün gövdesinde ikinci bir döngü bulunabilir.

Tanım 4.16

İç içe döngü (nested loop), gövdesinde başka bir döngü bulunan döngüdür. Dıştakine dış döngü (outer loop), içtekine iç döngü (inner loop) denir. Dış döngünün her turunda iç döngü baştan sona çalışır.

Çarpım tablosu iç içe döngünün en tanıdık örneğidir. Dış döngü satırları (i), iç döngü sütunları (j) dolaşır; her hücreye i × j yazılır. Şekil 4.22 3 × 3'lük tabloyu gösterir. Dış döngü 3 tur döner, iç döngü de her dış turda 3 tur döner. İç gövde toplam 3 × 3 = 9 kez çalışır.

iç döngü: j = 1, 2, 3 →dış döngü: i = 1, 2, 3 ↓j=1j=2j=3i=1123i=2246i=3369
Şekil 4.22: İç içe döngü ızgarası. Dış döngü satırları (i = 1, 2, 3), iç döngü sütunları (j = 1, 2, 3) dolaşır; hücrelerde i × j yazılıdır. Vurgulu satır i = 2 iken j'nin üç turudur.

Diyagramı küçük tutmak için 2 × 2'lik tablo çizilir. Şekil 4.23 iki döngünün birbirine nasıl yerleştiğini gösterir.

HayırHayırBaşlai = 1i <= 2 ?j = 1j <= 2 ?i × j yazj = j + 1i = i + 1BitirEvetEvet
Şekil 4.23: İç içe döngü: i 1'den 2'ye, j 1'den 2'ye; iç gövde i × j yazar. İç döngü bitince i artar ve dış karara dönülür.
Başla
  i = 1
  i <= 2 ?  (Hayır → Bitir)
    j = 1
    j <= 2 ?  (Hayır → i = i + 1)
      i × j yaz
      j = j + 1, iç karara dön
    satır sonu (println), i = i + 1, dış karara dön
Bitir

Dış döngünün gövdesi üç parçadır: j = 1, iç döngünün tamamı ve i = i + 1. j = 1 kutusunun dış gövdenin içinde olması önemlidir. Her dış turda j yeniden 1 olur; böylece iç döngü her satıra baştan başlar.

Tablo 4.15: 2 × 2 iç içe döngünün izleme tablosu. Her satır bir iç karar sorusudur.
ijİç kararİş
111 <= 2 → doğru1 × 1 = 1
122 <= 2 → doğru1 × 2 = 2
133 <= 2 → yanlışsatır sonu
211 <= 2 → doğru2 × 1 = 2
222 <= 2 → doğru2 × 2 = 4
233 <= 2 → yanlışsatır sonu

Tablo 4.15 yürütmeyi verir. i = 1 iken dış karar 1 <= 2 doğrudur. j = 1 olur; iç karar doğrudur ve 1 × 1 = 1 yazılır. j = 2 olur; 1 × 2 = 2 yazılır. j = 3 olduğunda iç karar yanlıştır ve iç döngü biter. Satır sonu yazılır, i = 2 olur ve dış karara dönülür. İkinci dış turda j yeniden 1'den başlar ve aynı yol izlenir: 2 ve 4 yazılır. i = 3 olduğunda dış karar 3 <= 2 yanlıştır ve Bitir'e gidilir. Çıktı küçük bir çarpım tablosudur:

1 2
2 4

İç gövde 2 × 2 = 4 kez çalıştı. Genel olarak dış döngü n, iç döngü m tur dönüyorsa iç gövde n × m kez çalışır. Sayılar büyüdükçe bu çarpım hızla büyür: 1000 × 1000'lik bir tabloda iç gövde bir milyon kez çalışır.

public class CarpimTablosu {
    public static void main(String[] args) {
        int i = 1;
        while (i <= 2) {                  // dış karar
            int j = 1;                    // iç sayaç her dış turda yeniden 1
            while (j <= 2) {              // iç karar
                System.out.print(i * j + " ");
                j = j + 1;
            }
            System.out.println();         // satır sonu
            i = i + 1;
        }
    }
}

Program iki satır yazar: 1 2 ve 2 4. Java kodunda int j = 1; satırı dış döngünün küme parantezinin içindedir. Bu satır dış döngüden önceye taşınırsa j ikinci dış turda 3'te kalır, iç karar ilk denemede yanlış çıkar ve ikinci satır boş yazılır.

Çok sayıda iç içe yapı, algoritmanın bir parçasının ayrı bir alt süreç olarak çizilmesi gerektiğini gösterebilir. Üç dört düzey iç içe geçmiş kararlar ve döngüler, diyagramı da kodu da okunmaz hâle getirir.

4.6.7Sayı tahmin oyunu

Bilgisayar 1 ile 100 arasında gizli bir sayı tutar. Oyuncu tahmin eder; bilgisayar “Daha büyük” ya da “Daha küçük” diye ipucu verir. Oyun, doğru tahmin yapılınca biter ve kaç denemede bilindiği yazılır. Döngünün kaç tur döneceğini oyuncunun tahminleri belirler; bu açıdan oyun, bekçi değerli döngünün bir türüdür.

EvetHayırEvetHayırBaşlagizli = 37, deneme = 0tahmin değerini okudeneme = deneme + 1tahmin == gizli ?tahmin < gizli ?"Daha büyük" yaz"Daha küçük" yaz"Bildin" yazBitir
Şekil 4.24: Sayı tahmin oyunu: tahmin gizli sayıya eşit olana kadar ipucu verilerek tekrar okunur. Doğru tahminde “Bildin” yazılır ve oyun biter.
Başla
  gizli = 37, deneme = 0
  tahmin değerini oku
  deneme = deneme + 1
  tahmin == gizli ?
    Evet → "Bildin (" deneme ". deneme)" yaz, Bitir
  tahmin < gizli ?
    Evet → "Daha büyük" yaz
    Hayır → "Daha küçük" yaz
  3. satıra (oku) dön
Bitir

Diyagramda iki karar vardır. Birincisi tahmin == gizli ? sorusudur ve döngüyü sona erdirir. İkincisi tahmin < gizli ? sorusudur ve hangi ipucunun verileceğine karar verir. İkinci karar birincinin Hayır dalındadır; tahmin doğruysa ipucu sorusu hiç sorulmaz. İki ipucu kutusunun ardından ok yeniden oku kutusuna döner. Gizli sayı normalde rastgele seçilir; izlemenin tekrarlanabilmesi için burada 37 alınmıştır.

Tablo 4.16: Gizli sayı 37, tahminler 50, 25, 37 için izleme tablosu.
tahmindenemetahmin == 37 ?tahmin < 37 ?Çıktı
501HayırHayırDaha küçük
252HayırEvetDaha büyük
373EvetsorulmazBildin (3. deneme)

Oyuncu önce 50 girer; deneme = 1 olur. 50 == 37 yanlıştır, ipucu sorusuna geçilir. 50 < 37 de yanlıştır; tahmin büyük olduğu için “Daha küçük” yazılır. İkinci tahmin 25'tir; 25 < 37 doğrudur ve “Daha büyük” yazılır. Üçüncü tahmin 37'dir; eşitlik doğru çıkar ve “Bildin (3. deneme)” yazılır.

import java.util.Scanner;

public class SayiTahmin {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int gizli = 37;                   // oyunda: new java.util.Random().nextInt(100) + 1
        int deneme = 0;
        int tahmin = giris.nextInt();
        deneme = deneme + 1;
        while (tahmin != gizli) {         // tahmin == gizli ? Hayır dalı döngüde kalır
            if (tahmin < gizli) {
                System.out.println("Daha büyük");
            } else {
                System.out.println("Daha küçük");
            }
            tahmin = giris.nextInt();
            deneme = deneme + 1;
        }
        System.out.println("Bildin (" + deneme + ". deneme)");
    }
}

Java programı diyagramı biraz farklı bir düzenle yazar. İlk tahmin döngüden önce okunur ve döngünün koşulu tahmin != gizli olur. Sonraki tahmin gövdenin sonunda okunur. Bu, bekçi değerli döngüdeki düzenin aynısıdır. Program 50 25 37 girdisiyle “Daha küçük”, “Daha büyük” ve “Bildin (3. deneme)”; 20 40 37 girdisiyle “Daha büyük”, “Daha küçük” ve “Bildin (3. deneme)” yazar. İlk tahminde 37 girilirse döngü gövdesi hiç çalışmaz ve “Bildin (1. deneme)” yazılır.

Oyunun iyi bir stratejisi vardır: her seferinde kalan aralığın ortasını tahmin etmek. 1–100 aralığında ilk tahmin 50 olur; ipucu “Daha küçük” ise aralık 1–49'a, “Daha büyük” ise 51–100'e iner. Her tahmin aralığı yaklaşık yarıya böler. Aralık en kötü durumda 100, 50, 25, 12, 6, 3, 1 diye küçülür; bu yüzden 7 tahmin her zaman yeter. Bunun nedeni 27 = 128'in 100'den büyük olmasıdır.

4.6.8Son koşullu döngü

Bazı işlerde döngü gövdesinin en az bir kez çalışması gerekir. Kullanıcıdan 1 ile 5 arasında bir sayı istenir; girilen sayı geçersizse yeniden sorulur. Sayı okunmadan geçerli olup olmadığı sorulamaz. Bu durumda koşulu gövdenin sonuna koymak daha doğaldır.

Tanım 4.17

Son koşullu döngü (post-test loop), koşulun gövdeden sonra sorulduğu döngüdür. Gövde önce çalışır, sonra koşula bakılır; bu yüzden gövde en az bir kez çalışır. Java'da do { … } while (koşul); biçiminde yazılır.

EvetHayırBaşlasayı değerini oku1 <= sayı <= 5 ?sayıyı yazBitir"Geçersiz" yaz
Şekil 4.25: Son koşullu döngü ile girdi doğrulama: sayı okunur; 1 ≤ sayı ≤ 5 değilse “Geçersiz” yazılır ve yeniden okunur.
Başla
  sayı değerini oku
  1 <= sayı <= 5 ?
    Hayır → "Geçersiz" yaz, oku'ya dön
    Evet → sayıyı yaz
Bitir

Şekil 4.25 diyagramında yürütme Başla'dan sonra doğrudan oku kutusuna girer; arada bir karar yoktur. Karar, okumanın ardından gelir. Geçersiz bir sayıda Hayır dalı “Geçersiz” yazar ve ok yeniden oku kutusuna döner. Bu tür kullanıma girdi doğrulama (input validation) denir.

Tablo 4.17: Girdiler 7, 0, 3 için son koşullu döngünün izleme tablosu.
TurOkunan sayı1 ≤ sayı ≤ 5 ?Çıktı
17yanlış → HayırGeçersiz
20yanlış → HayırGeçersiz
33doğru → EvetGeçerli: 3

İlk turda koşul henüz hiç sorulmadan 7 okunur. Sonra karar gelir: 1 ≤ 7 ≤ 5 mi? 7, 5'ten büyük olduğu için cevap yanlıştır; “Geçersiz” yazılır. İkinci turda 0 okunur; 0, 1'den küçük olduğu için yine geçersizdir. Üçüncü turda 3 okunur; 1 ≤ 3 ≤ 5 doğrudur ve “Geçerli: 3” yazılır. Gövde 3 kez çalıştı, koşul da 3 kez soruldu. Ön koşullu döngüden farklı olarak burada karar sayısı gövde sayısına eşittir.

Diyagramdaki 1 <= sayı <= 5 koşulu matematikteki gösterimdir. Java bu yazımı kabul etmez; iki karşılaştırma bir bileşik koşulla birleştirilir. Geçersizlik koşulu “sayı 1'den küçük VEYA 5'ten büyük” olur:

import java.util.Scanner;

public class GirdiDogrulama {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int sayi;
        do {
            sayi = giris.nextInt();               // gövde: önce oku
            if (sayi < 1 || sayi > 5) {
                System.out.println("Geçersiz");
            }
        } while (sayi < 1 || sayi > 5);           // koşul sonda sorulur
        System.out.println("Geçerli: " + sayi);
    }
}

Program 7 0 3 girdisiyle iki kez “Geçersiz”, sonra “Geçerli: 3” yazar. İlk girdi 4 ise gövde bir kez çalışır ve doğrudan “Geçerli: 4” yazılır. Kodda geçersizlik koşulu iki kez yazılmıştır: bir kez uyarı için if içinde, bir kez döngü koşulunda. Diyagramdaki tek karar kutusu kodda iki ayrı soruya dönüşür.

Sık yapılan hata

while ile do-while arasındaki farkı yalnız yazım farkı sanmak. Fark, koşul ilk denemede yanlış olduğunda ortaya çıkar. 1'den n'e toplam diyagramı son koşullu çizilseydi, n = 0 için gövde bir kez çalışır, toplam 1 olurdu; oysa doğru cevap 0'dır. Gövdenin hiç çalışmaması gerekebilecek her durumda ön koşullu döngü seçilir.

4.6.9for döngüsünün diyagramı

Sayaçlı döngülerde her zaman aynı dört parça bulunur: sayacın başlangıç değeri, koşul, gövde ve sayacın güncellenmesi. Java bu kalıp için daha kısa bir yazım sunar: for döngüsü.

EvetHayıri = 1i <= n ?toplam = toplam + ii = i + 1toplam yaz1234
Şekil 4.26: for döngüsünün dört parçası: (1) başlangıç i = 1, (2) koşul i <= n, (3) gövde toplam = toplam + i, (4) güncelleme i = i + 1.
for (i = 1; i <= n; i++) {
    toplam = toplam + i;
}
  1. Başlangıç (i = 1): döngüye girerken yalnızca bir kez çalışır.
  2. Koşul (i <= n): her turdan önce sorulur; for, ön koşullu bir döngüdür.
  3. Gövde: koşul doğruysa çalışır.
  4. Güncelleme (i++): gövdeden sonra çalışır; ardından ok koşula döner. i++, i = i + 1'in kısa yazılışıdır.

Şekil 4.26 bir while diyagramından farksızdır. for, yalnızca 1, 2 ve 4 numaralı parçaları tek satırda toplar. Bazı kaynaklar bu üç parçayı ek simgelerden hazırlık simgesinde (altıgen, “i = 1 → n”) gösterir.

public class ForToplam {
    public static void main(String[] args) {
        int n = 4, toplam = 0;
        for (int i = 1; i <= n; i++) {    // başlangıç; koşul; güncelleme
            toplam = toplam + i;          // gövde
        }
        System.out.println(toplam);
    }
}

Program n = 4 için 10 yazar; while ile yazılan 1'den n'e toplam programıyla aynı sonucu verir. Hangi döngünün seçileceği okunabilirlik sorunudur. Tekrar sayısı önceden belliyse for, döngüyü veri durduruyorsa while daha açık okunur.

4.6.10Erken çıkış, bayrak ve atla

Bir dizide ilk negatif sayı aranıyor olsun: a = [4, 7, −2, 5, −8]. Aranan sayı bulunduğunda kalan turlara gerek kalmaz. Gövdenin içinden döngünün dışına giden ikinci bir ok, döngüyü hemen bitirir.

Tanım 4.18

Erken çıkış (early exit), döngünün koşulu henüz yanlış olmadan gövdenin içinden döngüden çıkılmasıdır; Java'da break (çık) deyimiyle yapılır. Bayrak (flag), bir olayın olup olmadığını tutan doğru/yanlış değerli değişkendir. Atla (continue) ise döngüden çıkmaz; o turun kalanını atlayıp güncellemeye ve koşula döner.

EvetHayırHayırEveti = 1i <= n ?a[i] < 0 ?i = i + 1a[i] yaz"Yok" yazBitirerken çıkış
Şekil 4.27: İlk negatif sayıyı arayan döngü. Döngünün iki çıkışı vardır: biri koşuldan (i <= n yanlış: “Yok” yaz), biri gövdeden (a[i] < 0: a[i] yaz, erken çıkış).

Diyagramda dizinin elemanları a[i] ile gösterilir: a[1] dizinin ilk, a[2] ikinci elemanıdır. Dizi, aynı türden değerlerin sıralı bir listesidir; burada beş sayı vardır, yani n = 5.

Tablo 4.18: a = [4, 7, −2, 5, −8] için ilk negatif arama.
ia[i]i <= n ?a[i] < 0 ?Yapılan
141 <= 5 → EvetHayıri = 2
272 <= 5 → EvetHayıri = 3
3−23 <= 5 → EvetEvet−2 yaz, döngüden çık

i = 1'de 4, i = 2'de 7 negatif değildir. i = 3'te −2 bulunur ve yazılır; döngü erken çıkışla biter. 5 ve −8'e hiç bakılmaz. Dizide hiç negatif olmasaydı döngü i = 6'da koşuldan çıkar ve “Yok” yazılırdı.

Erken çıkışlı döngünün iki çıkışı vardır ve bu, yapısal programlamanın tek çıkış kuralına uymaz. Tek çıkış isteniyorsa bayrak kullanılır. bulundu = yanlış ile başlanır, aranan bulununca bulundu = doğru yapılır ve döngü koşulu i <= n VE bulundu değil ? olur. Döngü bitince bayrağa bakılarak sonuç yazılır. Java'da iki yol da kullanılır:

public class IlkNegatif {
    public static void main(String[] args) {
        int[] a = {4, 7, -2, 5, -8};
        // 1. yol: break ile erken çıkış (iki çıkışlı döngü)
        int i = 0;
        while (i < a.length) {
            if (a[i] < 0) {
                break;                    // aranan bulundu: döngüden çık
            }
            i = i + 1;
        }
        if (i < a.length) {
            System.out.println(a[i]);
        } else {
            System.out.println("Yok");
        }
        // 2. yol: bayrak ile tek çıkışlı döngü
        boolean bulundu = false;
        int k = 0;
        while (k < a.length && !bulundu) {
            if (a[k] < 0) {
                bulundu = true;
            } else {
                k = k + 1;
            }
        }
        System.out.println(bulundu ? a[k] + "" : "Yok");
    }
}

İki yol da −2 yazar. Java'da dizi elemanları 0'dan numaralanır: a[0] 4, a[2] −2'dir. Bu yüzden kodda sayaç 0'dan başlar ve koşul i < a.length olur; a.length dizinin eleman sayısıdır (5). Bayraklı sürümde !bulundu ifadesi “bulundu değil” anlamına gelir. Koşul k < a.length && !bulundu bir bileşik koşuldur ve kısa devre değerlendirmeyle çalışır.

Atla ise döngüyü bitirmez, yalnız o turun kalanını geçer. Örneğin dizideki negatif olmayan sayıların toplamı istenirse, negatif bir sayıya gelindiğinde toplama adımı atlanır:

public class AtlaOrnegi {
    public static void main(String[] args) {
        int[] a = {4, 7, -2, 5, -8};
        int toplam = 0;
        for (int i = 0; i < a.length; i++) {
            if (a[i] < 0) {
                continue;                 // negatifi atla, sonraki tura geç
            }
            toplam = toplam + a[i];
        }
        System.out.println(toplam);
    }
}

Program 4 + 7 + 5 = 16 yazar. −2 ve −8'de continue çalışır; toplama satırı atlanır, i++ çalışır ve koşula dönülür. Diyagramda atla, gövdenin ortasından güncelleme kutusuna giden bir okla gösterilir.

4.7Diyagramdan Java koduna

Akış diyagramının değeri, sonunda çalışan bir programa dönüşebilmesinden gelir. Önceki kesimlerde her yapının Java karşılığı ayrı ayrı verildi. Bu kesim çeviriyi bir kural listesi olarak toplar ve tam bir örnek üzerinde satır satır uygular.

4.7.1Simgelerin kod karşılıkları

Tablo 4.19: Akış diyagramı öğelerinin Java karşılıkları.
Diyagram öğesiJava karşılığı
Başla / Bitirmain metodunun açılan ve kapanan küme parantezi
Giriş (oku)int a = giris.nextInt(); ya da sabit bir değerle değişken tanımı
İşlem (atama)Atama deyimi: toplam = toplam + i;
Çıkış (yaz)System.out.println(…);
Karar, iki dal birleşiyorif (koşul) { … } else { … }
Karar zinciriif … else if … else
Karar + gövdeye dönen ok (koşul önce)while (koşul) { … } ya da for
Gövde + karara dönen ok (koşul sonda)do { … } while (koşul);
Gövdeden döngü dışına okbreak;
Önceden tanımlı işlemMetot çağrısı: ortalama(a, b, c)

Kuralların en önemlisi döngü çevirisidir. Bir karar kutusunun Evet dalından başlayıp yeniden aynı karara dönen bir ok varsa, o karar bir while koşuludur ve oka kadar olan kutular döngü gövdesidir. Gövdenin hangi kutularda bittiğini bulmak için geri dönen okun nereden çıktığına bakılır.

4.7.21'den n'e toplam Java'da

EvetHayırBaşlan değerini okutoplam = 0, i = 1i <= n ?toplam = toplam + ii = i + 1toplamı yazBitir
Şekil 4.28: Java'ya çevrilecek diyagram: 1'den n'e toplam.
public static void main(String[] args) {
    int n = 3;
    int toplam = 0, i = 1;
    while (i <= n) {
        toplam = toplam + i;
        i = i + 1;
    }
    System.out.println(toplam);
}

Çeviri yukarıdan aşağıya kutu kutu yapılır:

  1. Başla simgesi metodun başlangıcıdır: main açılır.
  2. “n değerini oku” girdi simgesidir. Örneği kısa tutmak için girdi sabit alınmıştır: int n = 3;. Klavyeden okumak istenirse bu satır int n = giris.nextInt(); olur.
  3. “toplam = 0, i = 1” işlem simgesi iki değişkenin başlangıç değeridir: int toplam = 0, i = 1;.
  4. i <= n ? kararından Evet dalı iki kutuya gider ve ok yeniden karara döner. Bu bir döngüdür: while (i <= n).
  5. Evet dalındaki iki dikdörtgen döngü gövdesidir. İkisi de küme parantezinin içine, diyagramdaki sırayla yazılır.
  6. Geri dönen ok, gövde bloğunun kapanan küme parantezidir. Yürütme oradan koşula döner.
  7. Hayır dalındaki “toplamı yaz” çıkış simgesi döngünün dışındadır: System.out.println(toplam);.
  8. Bitir simgesi metodun kapanışıdır.

Program n = 3 için çalıştırıldığında yürütme diyagramla adım adım aynı yolu izler. İlk koşul denemesi 1 <= 3 doğrudur; toplam 0 + 1 = 1, i = 2 olur. Ardından toplam 3 ve 6 olur. i = 4 olduğunda 4 <= 3 yanlıştır; Hayır yolu izlenir ve yürütme döngü bloğunun dışına çıkar. Ekrana 6 yazılır. Sonuç formülle de doğrulanır: 3 × 4 / 2 = 6.

EvetHayırBaşlan değerini okutoplam = 0, i = 1i <= n ?toplam = toplam + ii = i + 1toplamı yazBitir EvetHayırBaşlan değerini okutoplam = 0, i = 1i <= n ?toplam = toplam + ii = i + 1toplamı yazBitir
Şekil 4.29: Karar simgesinin kod karşılığı. (a) İlk deneme: while (i <= n), 1 <= 3 doğru; gövdeye girilir. (b) Son deneme: 4 <= 3 yanlış; Hayır yolu döngü bloğunun dışına çıkar.

Çevirinin sonunda her simgenin bir kod karşılığı vardır, her kod satırının da bir simge karşılığı. Bu birebir eşleme, diyagramın doğru çevrildiğini denetlemenin en kolay yoludur. Programda karşılığı olmayan bir simge ya da diyagramda karşılığı olmayan bir satır varsa çeviride bir şey eksik ya da fazladır.

Sık yapılan hata

Gövde kutularından birini döngü bloğunun dışına yazmak. while (i <= n) { toplam = toplam + i; } i = i + 1; yazılırsa sayacın artışı döngünün dışında kalır. i hiç değişmez, koşul hep doğru çıkar ve program sonsuz döngüye girer. Diyagramda Evet dalındaki her kutu, geri dönen ok çıkmadan önceki son kutuya kadar, küme parantezlerinin içindedir.

4.7.3Alt süreçle modüler diyagram

Diyagramlar büyüdükçe tek sayfaya sığmaz hâle gelir. Bir işin birkaç yerde tekrarlandığı da olur. Bu durumda işin bir kısmı ayrı bir diyagram olarak çizilir ve ana diyagramdan çağrılır.

Tanım 4.19

Alt süreç (subprocess), ayrı çizilmiş ve bir adla anılan diyagramdır. Ana diyagramda önceden tanımlı işlem (predefined process) simgesiyle çağrılır. Alt süreç bitince akış ana diyagramda, çağrıldığı noktadan sürer. Java'da her alt süreç bir metot (method) olur.

Ana diyagramAlt süreçBaşlaa, b, c okuort = Ortalama(a, b, c)ort değerini yazBitirOrtalama(x, y, z)t = x + y + zDöndür t / 3çağır: x=70, y=85, z=91dön: 82
Şekil 4.30: Ana diyagram alt süreci çağırır, alt süreç değer döndürür. a = 70, b = 85, c = 91 için Ortalama(70, 85, 91) çağrılır ve 82 döner.

Şekil 4.30'daki alt diyagram Başla yerine adı ve parametreleriyle, “Ortalama(x, y, z)” ile başlar. Bitir yerine “Döndür” ile biter. Parametreler, alt sürecin çağrıldığı yerden aldığı değerlerdir. Ana diyagram ort = Ortalama(a, b, c) kutusunda a, b ve c'nin değerlerini x, y ve z'ye gönderir. a = 70, b = 85, c = 91 için alt süreçte t = 70 + 85 + 91 = 246 hesaplanır ve 246 / 3 = 82 döndürülür. Ana diyagram bu değeri ort değişkenine yazar ve bir sonraki kutudan devam eder.

Alt sürecin iki yararı vardır. Birincisi, aynı alt süreç birçok yerden çağrılabilir ama yalnızca bir kez çizilir. Ortalama hesabında bir hata bulunursa tek bir yerde düzeltilir. İkincisi, ana diyagram kısalır ve “ne yapıldığını” anlatır; “nasıl yapıldığı” alt diyagramda kalır.

import java.util.Scanner;

public class AltSurec {
    // alt süreç: Ortalama(x, y, z)
    static int ortalama(int x, int y, int z) {
        int t = x + y + z;
        return t / 3;                     // Döndür t / 3
    }

    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int a = giris.nextInt(), b = giris.nextInt(), c = giris.nextInt();
        int ort = ortalama(a, b, c);      // önceden tanımlı işlem simgesi
        System.out.println(ort);
    }
}

static int ortalama(int x, int y, int z) satırı alt diyagramın başlığıdır: metodun adı, üç parametresi ve döndürdüğü değerin türü (int). return t / 3; satırı Döndür simgesinin karşılığıdır. Program 70 85 91 girdisiyle 82 yazar.

Sık yapılan hata

Tam sayı bölmesini unutmak. Java'da iki tam sayının bölümü de tam sayıdır; küsurat atılır. 70, 85, 91 için toplam 246 tam olarak 3'e bölündüğü için sorun görünmez. 50, 60, 71 için toplam 181'dir; gerçek ortalama yaklaşık 60,33 iken program 60 yazar. Ondalıklı sonuç gerekiyorsa metot double döndürmeli ve bölme t / 3.0 biçiminde yazılmalıdır.

4.8Doğrulama

Bir diyagramın doğru olduğu, birkaç girdiyle elle yürütülerek sınanır. Hangi girdilerin seçileceği rastgele değildir. İyi seçilmiş az sayıda girdi, kötü seçilmiş çok sayıda girdiden daha fazla hata yakalar.

4.8.1Diyagramı test etmek

Tanım 4.20

Test durumu (test case), bir girdi ile o girdi için beklenen çıktının ikilisidir. Diyagram girdiyle yürütülür ve bulunan çıktı beklenenle karşılaştırılır. Sınır değeri (boundary value), bir koşulun cevabının değiştiği noktadaki girdidir; örneğin not >= 60 için 60.

Test girdileri beş kurala göre seçilir:

  1. Normal bir girdi seçilir ve oklar adım adım izlenir.
  2. Her kararın her çıkışını çalıştıracak girdiler seçilir. Diyagramdaki her kutu en az bir kez çalışmalıdır.
  3. Sınır değerleri ayrıca denenir.
  4. Her döngü için gövdenin sıfır, bir ve çok kez çalıştığı durumlar denenir.
  5. Başlangıca dönmeyen ya da Bitir'e ulaşmayan yollar aranır.
EvetHayırBaşlanot değerini okunot >= 60 ?"Kaldı" yaz"Geçti" yazBitir EvetHayırBaşlanot değerini okunot >= 60 ?"Kaldı" yaz"Geçti" yazBitir EvetHayırBaşlanot değerini okunot >= 60 ?"Kaldı" yaz"Geçti" yazBitir
Şekil 4.31: Geçti/Kaldı diyagramının testi. (a) Normal girdi not = 72: Evet yolu. (b) not = 45: Hayır yolu; artık her kutu en az bir kez denendi. (c) Sınır değeri not = 60: 60 >= 60 doğru, “Geçti”.

Şekil 4.31 kuralların Geçti/Kaldı diyagramına uygulanışını gösterir. 72 normal girdidir ve Evet yolunu çalıştırır. 45 öbür dalı çalıştırır; iki girdiyle her kutu denenmiş olur. 60 ise sınır değeridir ve karar kutusunda >= yerine > yazılmış olsaydı hatayı ortaya çıkaran tek girdi olurdu.

Döngüler için kural 4'ün nedeni şudur: döngü hataları çoğu zaman uçlarda saklanır. Biriktiricinin başlangıç değeri yanlışsa bu en çok gövdenin hiç çalışmadığı durumda görünür. Koşuldaki bir </<= karışıklığı ise genellikle bir tur eksik ya da fazla dönmeye yol açar ve bir turluk durumda kolay fark edilir. Tablo 4.20 1'den n'e toplam diyagramı için bu üç durumu verir.

Tablo 4.20: 1'den n'e toplam diyagramının döngü testleri. Beklenen değer formülden, çıktı diyagramın yürütülmesinden gelir.
nDurumGövde kaç kez çalışırBeklenen (n(n+1)/2)Diyagramın çıktısı
0sıfır tekrar000
1bir tekrar111
5çok tekrar51515

Üç satırda da çıktı beklenenle aynıdır. Koşul yanlışlıkla i < n yazılmış olsaydı n = 1 için gövde hiç çalışmaz ve 0 yazılırdı; n = 5 için 1 + 2 + 3 + 4 = 10 yazılırdı. Hata üç girdinin ikisinde hemen görünür. Negatif bir n ise geçersiz girdidir. Diyagram bu durumda da 0 yazar; bunun istenen davranış olup olmadığı problemin tanımına bağlıdır.

4.8.2İzleme tablosuyla elle izleme

İzleme tablosu bu notta sık sık kullanıldı. Kalıbı kısaca şöyle özetlenebilir: her değişken bir sütun, her tur bir satırdır; karar sonucu da ayrı bir sütuna yazılır. Tablo özellikle değişkenlerin birbirine bağlı biçimde değiştiği algoritmalarda vazgeçilmezdir. Öklid algoritması bunun güzel bir örneğidir.

Öklid algoritması iki sayının en büyük ortak bölenini (EBOB, greatest common divisor) bulur. Fikri şudur: a ile b'nin ortak bölenleri, b ile a'nın b'ye bölümünden kalanın ortak bölenleriyle aynıdır. Bu yüzden (a, b) çifti (b, a % b) çiftiyle değiştirilir. Kalan her turda küçülür ve sonunda 0 olur. O anda a, aranan EBOB'dur.

EvetHayıra, b değerlerini okub != 0 ?k = a % ba = bb = ka yaz
Şekil 4.32: Öklid algoritması: b sıfır olana kadar k = a % b, a = b, b = k yapılır; sonunda a yazılır.
Tablo 4.21: Öklid algoritmasının (48, 18) için izleme tablosu. Son sütun, satırdaki değerlerle sorulan bir sonraki karardır.
Anabkb != 0 ?
başlangıç4818—18 != 0 → doğru
1. tur18121212 != 0 → doğru
2. tur12666 != 0 → doğru
3. tur6000 != 0 → yanlış

Başlangıçta a = 48, b = 18'dir ve 18 != 0 doğrudur. Birinci turda k = 48 % 18 = 12 olur (48 = 2 × 18 + 12); a = 18, b = 12 yapılır. İkinci turda k = 18 % 12 = 6; a = 12, b = 6. Üçüncü turda k = 12 % 6 = 0; a = 6, b = 0. Karar 0 != 0 yanlıştır; döngüden çıkılır ve 6 yazılır. EBOB(48, 18) = 6'dır. Denetim: 48 = 8 × 6, 18 = 3 × 6 ve 8 ile 3'ün 1'den büyük ortak böleni yoktur.

Döngü 3 tur döndü, karar 4 kez soruldu: her ön koşullu döngüde olduğu gibi karar, gövdeden bir fazla çalıştı. Tablo diyagramdaki sıranın önemini de gösterir. Gövdedeki a = b ve b = k kutuları yer değiştirseydi, yani önce b = k, sonra a = b yapılsaydı ne olurdu?

Tablo 4.22: Gövdede b = k ile a = b yer değiştirince (48, 18) için izleme.
Anabkb != 0 ?
başlangıç4818—18 != 0 → doğru
1. tur12121212 != 0 → doğru
2. tur0000 != 0 → yanlış

İlk turda b = 12 olur, ardından a = b ile a da 12 olur. a, b'nin eski değerini değil yeni değerini almıştır. İkinci turda 12 % 12 = 0 bulunur ve ikisi de 0 olur. Sonuç 6 yerine 0 çıkar. Bu, Örnek 4.2'deki takas hatasının aynısıdır: bir atama, daha sonra gerekecek bir değeri silmiştir.

import java.util.Scanner;

public class Oklid {
    public static void main(String[] args) {
        Scanner giris = new Scanner(System.in);
        int a = giris.nextInt(), b = giris.nextInt();
        while (b != 0) {
            int k = a % b;
            a = b;
            b = k;
        }
        System.out.println(a);
    }
}

Program (48, 18) için 6, (270, 192) için 6, (36, 84) için 12 yazar. a < b olsa da algoritma çalışır. (18, 48) için ilk turda 18 % 48 = 18 bulunur ve a ile b yer değiştirir; sonuç yine 6'dır.

4.8.3Sık hatalar

Öğrencilerin akış diyagramlarında en sık yaptığı hatalar birkaç kalıba indirgenebilir. Tablo 4.23 çizimle ilgili, Tablo 4.24 mantıkla ilgili hataları toplar.

Tablo 4.23: Çizim hataları.
HataSonuçDüzeltme
Etiketsiz karar yoluHangi koşulun seçildiği belirsizEvet/Hayır yaz
Güncellenmeyen sayaçSonsuz döngüSayaç adımı ekle
Bağlantısız simgeAkış koparOkla bağla
Bir simgede çok işlemOkunabilirlik azalırAdımlara böl
EvetHayıri = 1i <= 3 ?i yazBitir EvetHayıri = 1i <= 3 ?i yazi = i + 1Bitir
Şekil 4.33: Güncellenmeyen sayaç. (a) Hatalı: i hep 1 kalır, ekrana 1 1 1 1 … yazılır ve Bitir'e hiç ulaşılmaz. (b) Doğru: i = i + 1 eklenince 1 2 3 yazılır, sonra Bitir'e gidilir.

Şekil 4.33 en tehlikeli çizim hatasını gösterir. Soldaki diyagramda geri dönen okun yolunda i'yi değiştiren bir kutu yoktur. Koşul her seferinde aynı cevabı verir ve döngü bitmez. Bir döngü çizildiğinde ilk sorulacak soru şudur: tekrar yolundaki hangi kutu koşulu bir gün yanlış yapacak?

Tablo 4.24: Mantık hataları, belirtileri ve düzeltmeleri.
HataBelirtiDüzeltme
Biriktirici döngünün içinde sıfırlanıyor4, 7, 2 için 13 yerine 2 yazılır: yalnız son değer kalırtoplam = 0 kutusunu döngüden önceye al
Geri dönen ok oku kutusunu atlıyorAynı x tekrar tekrar işlenir; bekçi değer hiç gelmezOk, oku kutusunun önüne döner
Karar kutusunda atama: x = 0 ?Soru mu, atama mı belirsizKarşılaştırma yaz: x == 0 ?
Bekçi değer işlemden sonra sorgulanıyor−1 toplama katılır, sayaç bir fazla olurKararı toplama ve saymadan önce sor
Karar zincirinde geniş koşul önceAlttaki dallar hiç çalışmazDar koşuldan genişe sırala
Karardan tek ok çıkıyorDiğer durumda akış koparİki çıkışı da çiz, Evet/Hayır yaz
Bölmeden önce sıfır denetimi yokHiç veri girilmezse 0'a bölmesayac > 0 ? kararı ekle

Tablodaki hataların çoğu bu notun önceki kesimlerinde izleme tablolarıyla gösterildi. Ortak noktaları şudur: hepsi diyagram en az bir uygun girdiyle elle yürütüldüğünde hemen fark edilir. Biriktirici hatası 4, 7, 2 girdisiyle, bekçi hatası 80, 64, 90, −1 girdisiyle ortaya çıkar. Zincir sırası hatasını −5, sıfır denetimi eksikliğini yalnız −1'den oluşan girdi gösterir. Bir diyagram çizildikten sonra onu birkaç iyi seçilmiş girdiyle yürütmek, bu hataların hepsine karşı en etkili önlemdir.

4.9Özet

  • Akış diyagramı, bir algoritmanın adımlarını standart simgelerle, yürütme sırasını oklarla gösterir. Programlama dilinden bağımsızdır; mantığı koddan önce tartışmayı ve hataları erken görmeyi sağlar.
  • Beş temel simge vardır: başla/bitir (oval), işlem (dikdörtgen: hesaplama, atama), karar (eşkenar dörtgen: Evet/Hayır sorusu), giriş/çıkış (paralelkenar: oku, yaz) ve ok. Yollar bağlayıcıda birleşir. Ek simgeler (sayfa dışı bağlayıcı, önceden tanımlı işlem, hazırlık, belge, veri deposu, açıklama) büyük diyagramlarda kullanılır.
  • Karar simgesine soru, işlem simgesine emir yazılır. Atama (=) ile eşitlik sorusu (==) farklıdır.
  • İyi bir diyagram yukarıdan aşağıya akar, karar çıkışlarını etiketler ve her kutuda tek iş yapar. Aynı algoritma sözde kodla da anlatılabilir; iki gösterim birbirine satır satır çevrilir.
  • Böhm–Jacopini teoremine göre her algoritma yalnızca sıra, seçim ve tekrar yapılarıyla yazılabilir. Her yapının tek girişi ve tek çıkışı vardır; bu yüzden yapılar iç içe kullanılabilir.
  • Sıralı akışta her kutu tam bir kez ve sırayla çalışır. Kutuların sırası sonucu değiştirir; takas için geçici değişken gerekir.
  • Koşullu akışta her çalıştırmada dallardan yalnızca biri izlenir. Çok seçenekte kararlar karar zinciri olarak, dar koşuldan geniş koşula dizilir; n seçenek için n − 1 karar gerekir. Bileşik koşulda VE ve VEYA, Java'da && ve ||, kısa devre değerlendirilir.
  • Tekrarlı akışta geri dönen ok döngüyü oluşturur. Ön koşullu döngüde karar, gövdeden bir fazla çalışır; tekrar yolunda koşulu değiştiren bir işlem yoksa sonsuz döngü oluşur.
  • Sayaç tur sayısını, biriktirici kısmi sonucu tutar; biriktirici toplam için 0, çarpım için 1 ile ve döngüden önce başlar. Bekçi değer gerçek veride görülemeyecek bir değerdir; kararı veriyi işleyen kutulardan önce sorulur.
  • İç içe döngüde dış döngünün her turunda iç döngü baştan çalışır; iç gövde n × m kez çalışır. Son koşullu döngüde (do-while) gövde en az bir kez çalışır. for, başlangıç, koşul ve güncellemeyi tek satırda toplayan ön koşullu döngüdür.
  • Erken çıkış (break) döngüye ikinci bir çıkış ekler; tek çıkış isteniyorsa bayrak kullanılır. Atla (continue) yalnız o turun kalanını geçer.
  • Diyagram Java'ya simge simge çevrilir: oku → nextInt(), işlem → atama, karar → if, karar + geri dönen ok → while, yaz → println, alt süreç → metot.
  • Diyagram, her kararın her çıkışını çalıştıran girdilerle, sınır değerleriyle ve döngünün sıfır, bir, çok kez döndüğü durumlarla test edilir. İzleme tablosunda her değişken bir sütun, her tur bir satırdır.

4.10Kavram listesi

Terimlerin İngilizce karşılıkları ve öteki sunumlardaki kullanımları terim sözlüğünde bulunur.

4.11Kendini Dene

  1. Aşağıdaki adımların her biri hangi simgeyle çizilir? (a) ort = toplam / 3 (b) Sayı negatif mi? (c) Sonucu ekrana yaz. (d) Ayrı bir sayfada çizilmiş “Not ortalaması hesapla” sürecini kullan.

    Cevap

    (a) bir atamadır: işlem simgesi, dikdörtgen. (b) cevabı evet ya da hayır olan bir sorudur: karar simgesi, eşkenar dörtgen; içine x < 0 ? yazılır. (c) dışarıya veri verir: giriş/çıkış simgesi, paralelkenar. (d) ayrıca çizilmiş bir alt süreci çağırır: önceden tanımlı işlem simgesi, kenarlarında dikey çizgiler olan dikdörtgen.

  2. Sıralı bir diyagram a = 5 okuyor, sonra sırasıyla b = a * 2, a = b + a, c = a + b kutularını çalıştırıp a, b ve c'yi yazıyor. Her kutudan sonra değişkenler ne olur, çıktı nedir?

    Cevap

    b = a * 2: b = 5 × 2 = 10; a = 5. a = b + a: a = 10 + 5 = 15; a'nın eski değeri 5 artık yoktur. c = a + b: c = 15 + 10 = 25. Çıktı 15 10 25'tir. c hesaplanırken a'nın yeni değeri (15) kullanılır.

  3. Sıcaklık zincirindeki kararlar ters sırada dizilmiş: önce s < 25 ? (Evet → “Ilık”), sonra s < 15 ? (Evet → “Soğuk”), sonra s < 0 ? (Evet → “Donma”, Hayır → “Sıcak”). s = −5, 10, 20 ve 30 için ne yazılır? Hangi çıkışlar hiç çalışamaz?

    Cevap

    −5, 10 ve 20 için ilk karar doğrudur ve üçü de “Ilık” yazar. 30 için ilk karar yanlıştır. Yürütme ikinci karara gelir; 30 < 15 ve 30 < 0 yanlıştır ve “Sıcak” yazılır. “Soğuk” ve “Donma” dallarına hiçbir girdiyle ulaşılamaz: ikinci karara yalnızca s ≥ 25 iken gelinir ve böyle bir s ne 15'ten ne 0'dan küçüktür. Doğru sıra dar koşuldan genişe, yani s < 0, s < 15, s < 25 sırasıdır.

  4. i = 10 ile başlanan bir döngüde karar i > 0 ?'dır; Evet dalında i yazılır ve i = i − 3 yapılır. Çıktı nedir? Gövde ve karar kaçar kez çalışır, döngü bittiğinde i kaçtır?

    Cevap

    i sırasıyla 10, 7, 4, 1 iken koşul doğrudur; bu değerler yazılır: 10 7 4 1. 1 yazıldıktan sonra i = 1 − 3 = −2 olur ve −2 > 0 yanlıştır. Gövde 4 kez, karar 5 kez çalışır; döngüden i = −2 ile çıkılır.

  5. 1'den 5'e kadar sayıların çarpımını bulan bir diyagramda biriktirici carpim = 0 ile başlatılmış; gövde carpim = carpim * i. Diyagram ne yazar? Düzeltilmiş diyagram ne yazar?

    Cevap

    İlk turda 0 × 1 = 0 olur ve sonraki her tur 0 ile çarptığı için sonuç 0'dır. Çarpımda etkisiz değer 1'dir; carpim = 1 ile başlanınca turlar 1, 2, 6, 24, 120 değerlerini verir ve 120 yazılır.

  6. Bekçi değerli not ortalaması diyagramına sırasıyla 70, 85, 0, −1 giriliyor. Toplam, sayaç ve ortalama ne olur? Bekçi değer olarak −1 yerine 0 seçilseydi ne olurdu?

    Cevap

    70, 85 ve 0 gerçek nottur: toplam 70 + 85 + 0 = 155, sayaç 3 olur. −1 okununca döngü biter. Ortalama 155 / 3 ≈ 51,67'dir. Bekçi 0 olsaydı üçüncü girdi “veri bitti” diye yorumlanırdı: toplam 155, sayaç 2 ve ortalama 77,5 çıkardı. 0 gerçek bir not olabileceği için bekçi değer olarak uygun değildir.

  7. İç içe bir döngüde dış sayaç i 1'den 3'e, iç sayaç j ise i'den 3'e kadar dönüyor. İç gövde bir “*” yazıyor; her dış turun sonunda satır sonu yazılıyor. Çıktı nedir, toplam kaç yıldız yazılır?

    Cevap

    i = 1 iken j = 1, 2, 3: üç yıldız. i = 2 iken j = 2, 3: iki yıldız. i = 3 iken j = 3: bir yıldız. Çıktı alt alta ***, **, * satırlarıdır. Toplam 3 + 2 + 1 = 6 yıldız yazılır. İç döngünün başlangıcı dış sayaca bağlı olduğu için iç gövde 3 × 3 = 9 değil, 6 kez çalışır.

  8. sayac = 10 ile başlayan bir döngünün gövdesi sayacı yazıp 1 artırıyor; koşul sayac < 5. Döngü ön koşullu (while) ve son koşullu (do-while) çizildiğinde ne yazılır?

    Cevap

    Ön koşullu döngüde koşul gövdeden önce sorulur: 10 < 5 yanlıştır ve gövde hiç çalışmaz; hiçbir şey yazılmaz. Son koşullu döngüde gövde önce çalışır: 10 yazılır, sayac 11 olur. Sonra 11 < 5 sorulur, yanlıştır ve döngü biter. Çıktı yalnızca 10'dur. İki döngü, koşul ilk denemede yanlış olduğunda farklı davranır.

  9. Öklid algoritması (84, 36) için yürütülüyor. Her turda a, b ve k ne olur? Döngü kaç tur döner, karar kaç kez sorulur, ne yazılır?

    Cevap

    Başlangıç: a = 84, b = 36; 36 != 0 doğru. 1. tur: k = 84 % 36 = 12 (84 = 2 × 36 + 12); a = 36, b = 12. 2. tur: k = 36 % 12 = 0; a = 12, b = 0. 0 != 0 yanlış; döngü biter. 2 tur, 3 karar; 12 yazılır. Denetim: 84 = 7 × 12, 36 = 3 × 12 ve 7 ile 3'ün 1'den büyük ortak böleni yoktur.

4.12İleri okuma

  • C. Böhm, G. Jacopini, “Flow Diagrams, Turing Machines and Languages with Only Two Formation Rules”, Communications of the ACM, 9(5), 1966: her akış diyagramının sıra, seçim ve tekrardan oluşan yapısal bir karşılığı olduğunu gösteren özgün makale.
  • E. W. Dijkstra, “Go To Statement Considered Harmful”, Communications of the ACM, 11(3), 1968: rastgele atlayan deyimlerin programları neden anlaşılmaz kıldığını tartışan, yapısal programlama tartışmasını başlatan iki sayfalık mektup.
  • R. Sedgewick, K. Wayne, Computer Science: An Interdisciplinary Approach (Addison-Wesley, 2016), Kesim 1.3: koşullar ve döngüler Java'da, izleme tablolarıyla ve çok sayıda kısa programla anlatılır.
  • A. B. Downey, C. Mayfield, Think Java (2. baskı, O'Reilly, 2019): koşullar, mantıksal operatörler ve döngüler programlamaya yeni başlayanlar için sade bir dille anlatılır; kitabın çevrim içi sürümü ücretsizdir.

4.13Kaynaklar

  1. ISO 5807:1985, Information processing — Documentation symbols and conventions for data, program and system flowcharts, program network charts and system resources charts.
  2. P. Deitel, H. Deitel, Java: How to Program, Early Objects, 11. baskı, Pearson, 2018.
  3. R. Sedgewick, K. Wayne, Computer Science: An Interdisciplinary Approach, Addison-Wesley, 2016: 1.3 Conditionals and Loops.
  4. Oracle, The Java Tutorials: Control Flow Statements.
  5. A. B. Downey, C. Mayfield, Think Java, 2. baskı, O'Reilly, 2019.

İlgili sayfalar: Akış Diyagramları sunumu · Çalışma soruları · Akış Diyagramı Yürütücü simülatörü · Terim sözlüğü · © Sercan Külcü. Tüm hakları saklıdır.