Soru - Personel Bilgi Sistemi

Report
GENEL PROGRAMLAMA BİLGİSİ
Bir programcının program yazabilmesi için yapması gereken
çalışmalar ve bilmesi gereken ön bilgilere ihtiyaç vardır. Çünkü
bir problemin bilgisayar ortamında çözülmesi maalesef
hazırlıksız olarak ve hızlı bir şekilde gerçekleşemez. Her
şeyden önce programla bir süreçtir ve programın yazılıp
bitmesi ile bitmez çoğunlukla programın yaşadığı süre
içerisinde değişik şekillerde devam eder.
Bu nedenle program yazılmadan veya program yazılmadan veya
problem çözülmeye başlamadan önce bazı adımları sağlam
atmak
gerekir.
Birçok
zaman
bu
adımlar
raporlarla
belgelendirilir. Çünkü yazılımın yaşam döngüsü boyunca bu
raporlara ve başlangıç adımlarına ihtiyaç duyulabilir.
Bunu sağlayabilmek ve sağlam temelli programlar
yazabilmek için mutlaka ön çalışmalar kağıt üzerinde
gerçekleştirilir ve elde edilen donelere göre program yazılır.
Ancak programlamada yeni iseniz hemen program
yazmanız oldukça zor olacaktır. Öncelikle programlama
mantığını ve problem çözme ön sezisini edinmeniz
gerekecektir. İşte bu ders notları siz öğrencilerin bu sezgiyi
kazanmasını ve bu mantığı oluşturmanızı sağlayacak bilgiler
sunmaktadır.
Ne var ki bu ders notu sadece temel bilgileri verir.
Bahsettiğimiz mantık ve sezgiler program yazdıkça gelişir.
Birçok kişi tarafından programlama yeteneğinin doğuştan bir
yetenek olduğu söylense de bu yeteneği edinmek resim
yapma yeteneğini edinmekten ya da güzel sanatlardan biri ile
ilgili bir yeteneği kazanmaktan çok daha kolaydır.
Bu ders notları her türlü programlama dilinden bağımsız
olarak
hazırlanmaya
çalışılmıştır.
Gerekli
görüldüğü
yerlerde dillere ait detay veya farklılık bilgileri verilmiştir.
Ancak esas olan programlama dilinin üzerinde temel
programlama mantığına sahip olmanızdır. Çünkü bu sizin
programlamacı sıfatınız için temel teşkil edecek bilgiler
sunmaktadır.
Programlama dilleri zaman içerisinde gelişmiş, değişmiş,
kaybolmuş
veya
yenileri
çıkmıştır.
Bu
nedenle
programlama bilginizi asla programlama diline bağlı
tutmayın. Eğer programlama mantığınız ve önsezileriniz
oldukça
iyi
gelişmişse
algoritmaları
kolay
kurup
algılayabiliyorsanız çok karmaşık sorunlar üzerinde fikir
yürütüp çözüm üretebiliyorsanız bildiğiniz programlama
dilinin fazlaca bir önemi kalmamaktadır.
Çünkü çoğunlukla 1-2 hafta gibi kısa bir sürede bir
programlama dilini kısa sürede öğrenebilirsiniz.
En doğrusu da tabii ki her derde çözüm olabilecek
temel bir programlama dilini çok iyi bir şekilde
öğrenip her çözüme uyarlayabilmenizdir. Ancak
önemli olan programlama mantığını kapmış
olmanızdır.
Dikkat
ettiyseniz
programlama
dilinde
alternatiflerden bahsettik ancak programlamanın
alternatifi bulunmamaktadır. Yani bir program
yazılacaksa mutlaka programlamanın kurallarına
göre yazılmalıdır.
TANIMLAR
Dersin daha iyi anlaşılması için şu tanım ve kavramların
bilinmesinde fayda bulunmaktadır.
Bilgisayar nedir?
Verileri işleyerek özet bilgiler şekline sokabilen, bu veri ve
bilgileri yüksek kapasitelerde saklayıp başka ortamlara
iletebilen elektronik cihazlarıdır.
Bu işlemleri yaparken çok yüksek hızlarda bıkmadan
usanmadan tekrarlı olarak aynı işleri yapar. Ancak tek başına
bir bilgisayar donanımı bu işleri gerçekleştirecek durumda
değildir. Bu işlemler donanım tarafından yapılsa da asıl iş
yazılımlar tarafından geliştirilmektedir
Yukarıdaki çizimde görülen her bir adımı gerçekleştiren yazılımdır.
Bilgisayar Organizasyonu
Bir elektronik bilgisayar yukarı şekildeki gibi temel birimlere
sahiptir. Bu şekilde bir önce ki konuda bahsettiğimiz giriş,
çıkış işlemleri, veri işleme ve veri saklama işlemleri
gerçekleştirilir.
Giriş Birimi
Klavye, fare, mikrofon, kamera vb cihazlardan biri veya daha fazlasından
oluşur. Veri ve komutların bilgisayara yollanmasını sağlar.
Bellek Birimi
Veri, komut ve programların saklandığı donanımları temsil eder.
Ana bellek çoğunlukla REM olarak anılır ve SIMM gibi donanımlarla
belirlenir.
Yan ve ikinci bellek ise Floppy ve sabit diskleri ifade eder ve bilgilerin daha
kalıcı saklanmasını sağlayan alanları temsil eder.
Aritmetik mantık Birimi
Bilgisayardaki tüm aritmetik ve mantıksal işlemlerin yapıldığı birimdir. Tüm
işlemleri yapan ana birimdir.
Denetim Birimi CPU
Bilgisayar
programının
çalışmasını
denetleyen
programda
yapılan
hesaplamalara göre hangi işlerin yapılacağına karar veren birimdir. Makine
diline çevrilmiş bir programda komutları teker teker ve sırayla ana işlem
birimine getirip yorumlar ve sonuçta komutu çalıştırır.
Çıkış Birimi
Bilgisayar ortamında oluşan verilerin dış ortama verilmesini sağlayan
birimlerdir. Ekran, yazıcı gibi birimlerdir.
Bir programcı genel olarak bu birimlerin hangilerinin ne işe
yaradığını ve neleri temsil ettiğini bilmelidir. Özellikle
aritmetik-mantık işlem birimi ve denetim birimi bir
bilgisayarın beynini oluşturduğu için nasıl davrandığını iyi
bilmek zorundadır.
Bilgisayarın Tarihçesi
M.Ö.500
Abaküs
1642
Pascalın Mekanik Toplama Makinesi
1827
Babbage’ in çıkarma makiesi
1941
İkili>İkili Mekanik Hesaplayıcı (Zuse)
1944
Ondalık Elektromekanik Hesaplayıcı (Aiken)
1945-54
İlk kuşak Vakum Tüpler ve ışınlar
1955-64
İkinci Kuşak Tranzistörler ve Manyetik Bellekler
1965-71
Üçüncü kuşak Tümleşik devreler
1971-90
Dördüncü kuşak VLSI Devreler
1982
IBM PC& MS-DOS
1984
MAC
1990’lar
Paralel işlemciler, Yapay Zeka, İnternet ve WWW
Bilgisayar Türleri
Bilgisayarlar kullanım amaçlarına göre büyüklük ve kapasite
bakımından şu şekilde sınıflandırılabilirler.
 Süper bilgisayarlar
 Mainframe tipi bilgisayarlar
 Workstation tipi bilgisayarlar(İş istasyonları)
 Mikrobilgisayarlar
 Kişisel bilgisayarlar
Problem nedir?
Bir işlemin otomasyonunun ya da bilimsel hesaplamanın
bilgisayarla çözülmesi fikrinin ortaya çıkmasına problem
denir. Bu tip fikirlerde insanların bu sorunları beyinle
çözmeler ya imkânsızdır ya da çok zor ve zaman alıcıdır. Bu
tip bir sorunu bilgisayarla çözebilme fikrinin ortaya çıkması
bir bilgisayar probleminin ortaya çıkmasına neden olmuştur.
Bazen de bir işletme veya yönetim otomasyonunu sağlamak
amacı ile bu tip problemler tanımlanır.
Problem Çözümü
Problemi çözebilmek için öncelikle sorunun çok net olarak
programcı tarafından anlaşılmış olması gerekir. Tüm
ihtiyaçlar ve istekler belirlenmelidir. Gerekiyorsa bu işlem
için birebir görüşmeler planlanmalı ve bu görüşmeler
gerçekleştirilebilmelidir.
Problemin çözümüne ilişkin zihinsel alıştırmalar yapılır. Bu
alıştırmaların
bilgisayar
çözümüne
yakın
olması
hedeflenmelidir. Bir sorunun tabii ki birden fazla çözümü
olabilir. Bu durumda bilgisayar ile en uygum çözüm
seçilmelidir. Çünkü bazen pratik çözümler bilgisayarlar için
uygun olmayabilir.
Oluşturulan çözüm algoritma dediğimiz adımlarla ifade
edilmelidir.
Bu algoritmanın daha anlaşılır olması için akış şeması
oluşturulmalıdır.
Uygun bir programlama dili seçilmeli ve oluşturulan
algoritma ve akış çizgesi bu programlama dili aracılığıyla
bilgisayar programına aktarılmalıdır.
Oluşturulan program bir takım verilerle ve mümkünse gerçek
ortamında test edilir. Oluşabilecek sorunlarla ilgili kısımlar
gözden
geçirilerek
düzeltilir.
Bu
gerçekleştirilmek zorunda kalınabilir.
adımlar
defalarca
Program nedir?
Problem çözümü kısmında anlatılan adımlar uygulandıktan
sonra ortaya ve sorunumuzu bilgisayar ortamında çözen
ürüne program denir. Bazı durumlarda bu ürüne yazılım
denebilir.
Programlama nedir?
Problem çözümünde anlatılan adımların tümüne birden
programlama denilebilir.
anlatılan
kısım
Ancak
gerçekte
çoğunlukla sistem
analizi
ilk
paragrafta
veya sistem
çözümleme olarak anlatılır. Diğer adımlar programlama diye
tanımlanabilir. Ancak son paragrafta anlatılan adıma kısaca test
aşaması denir.
Çoğunlukla çok iyi tanımlanmış bir sorunun çözümüne dair
adımlar ile çözümün oluşturulup bunun bir programlama dili
ile
bilgisayar
adlandırılır.
ortamına
aktarılması
programlama
diye
Algoritma nedir?
Bir sorunu çözebilmek için gerekli olan sıralı mantıksal
adımların tümüne denir. Doğal dille yazılabileceği için
aşağıdaki ifadelerin mutlaka doğrulanması gereklidir.
Her adım son derece belirleyici olmalıdır. Hiçbir şey şansa
bağlı olmamalıdır.
Belirli bir sayıda adım sonunda algoritma sonlanmalıdır.
Algoritmalar karşılaşılabilecek tüm ihtimalleri ele alabilecek
kadar genel olmalıdır.
Akış çizgesi nedir?
Bir algoritmanın daha görsel gösterimidir. Çizgiler, dörtgen, daire
vb. geometrik şekillerle algoritmanın gösterilmesini sağlar. Doğal
dille yazılmadığı için daha formal olduğu düşünülebilir.
Programlama dili nedir?
Bir problemin algoritmik çözümünün bilgisayara anlatılmasını
sağlayan, son derece sıkı sıkıya kuralları bulunan kurallar dizisidir.
Derleyici nedir?
Bir programlama dili ile bilgisayara aktarılan programın
bilgisayarın anlayabileceği makne diline çevirmeyi sağlayan ve
yazılan programda söz dizim hatalarının olup olmadığını bulan
olu olmadığını bulan yazılımlardır.
Her programlama dili için olması gerekmektedir.
Yorumlayıcı Nedir?
Derleyici gibi çalışan ancak yazılmış programları o anda
makine diline çeviren yazılımlardır. Bu tür bir yazılımda
programın makine dili ile oluşturulmuş kısmı bilgisayarda
tutulmaz. Programın her çalıştırılmasında her adım için
makine dili karşılıkları oluşturulur ve çalıştırılır
YAZILIM GELİŞTİRME
Yazılı
geliştirilirken
bir
programcı
ve
yazılım
gurubunun takip edeceği
adımlar şu şekildedir.
Bu çizgeden anlaşılacağı gibi adımlardan
birinde bir sorunla karşılaşılırsa bu sorunu
çözebilmek için bir önceki adıma geri
dönmek gerekecektir. Bu geri dönüş bazen
birkaç adım olabilir.
Sistem Analizi: Sorunun çözülebilmesi için tamamen anlaşılmasını
sağlayan çalışmalardır.
Tasarım: İsteklerle ilgili olarak belirlenen bir takım çözümlerin
tanımlanmasıdır.
Program Stili: Her yiğidin yoğurt yiyişi farklıdır. Aynı şekilde her
programcı programındaki mantığı farklı kurar ki bu her programcının
kendine özgün bir stili var anlamına gelir. Ancak bunun yanında her
programcının program sağlığı bakımından dikkat etmesi gereken şeyler
vardır.
Örneğin
kodlar
açık
olmalıdır.
Kullanılan
değişkenler
kullanıldıkları amacı anlatır tarzda isimlendirilmelidir. Program içi
dökümantasyona mutlaka önem verilmelidir.
Algoritma: Çözümün adımlarla ifade edilmesidir.
Akış çizgesi: Algoritmanın şekillerle ifade edilmesidir.
Programlama dili seçimi: Çözümün netleşmesinden
sonra yapılacak işlemleri kolay bir şekilde bilgisayar
ortamına aktaracak dilin seçilmesidir. Önemli olan bu
dilin
özelliklerinin
bilinmesidir.
programcı
tarafından
iyi
Programın yazılması: Seçilen programlama dilinin
kuralları kullanılarak program yazılmaya başlanır. BU
amaçla çoğunlukla sade bir metin editörü kullanılır.
Bazı durumlarda Syntax highlighting denilen bir
özelliğe sahip olan daha akıllı editörler de kullanılabilir.
Bazen de editör ile programlama dilinin derleyicisinin
bağlayıcısının
hatta
bulunduğu
IDE
hata
ayıklayıcısının
(Integrated
iç
içe
Development
Environment) denilen türde derleyiciler kullanılır.
Derleme: Programlama dili ile yazılmış programın yazım hatalarının
olup olmadığının kontrol edilmesini ve ara kod olarak obje kodun
üretilmesini sağlama adımıdır.
Bağlama: Derlenmiş ara kod diğer kütüphane ve parça programlarla
birleştirilerek makine dilinde programın oluşturulması adımıdır.
Ancak bazı IDE ortamlarda ve derleyicilerde derleme ve bağlama bir
bütündür ve beraberce halledilirler. Programcının ayrıca bir bağlama
işlemi yapması gerekmez.
Çalıştırma: Oluşturulan makine dili programın çalıştırılması
adımıdır. Yukarıdaki adımların hepsi yolunda gittiyse program
sorunsuz olarak çalışabilmelidir.
Test: Programın mantıksal olarak test edilmesini sağlar ve
içerik olarak her ihtimal için doğru sonuçlar üretip
üretmediğini kontrol etmenizi sağlar.
Yaşam döngüsünün sağlanması: Yukarıdaki akış çizgesi
dikkat edilirse aslında bir döngüdür. Hatta test aşamasında
sorun çıkmazsa bile sorunun tanımında yani ihtiyaçlarda
bazı değişiklikler olursa adımlar baştan aşağı tekrar
incelenmek zorunda kalınır. Bu çizgeye bir yazılımın yaşam
döngüsü de denir. Bu çizimde yazılımın bakım süreci göz
önüne alınmamıştır.
Hata yakalama ve Hata Ayıklama
Bir programın bilgisayar başında geçen geliştirme süreci yukarıdaki gibidir.
Alttaki kutucuklar hata durumlarını göstermektedir.
Syntax error: Yazılan programda programlama dili
kurallarına
aykırı
bir
takım
ifadelerden
dolayı
karşılaşılabilecek hatalardır. Düzeltilmesi son derece basit
hatalardır. Hatanın bulunduğu satır derleyici tarafından
rapor edilir. Hatta bazı derleyiciler hatanın ne olduğunu ve
nasıl düzeltilmesi gerektiğini dahi bildirebilirler. Bazen
Syntax Error tipi hataları bağlama zamanında da ortaya
çıkarabilir.
Eğer bir derlemede Syntax Error alındı ise obje kod
üretilmemiş demektir.
Soru: Bir derleyici hatanın nasıl düzeltileceğini bildirebildiğine
göre kendisi niçin düzeltmemektedir?
Run-time error: Programın çalıştırılması sırasında karşılaşılan
hatalardır. Programcını ele almadığı bir takım aykırı durumlar
ortaya çıktığında programın işletim sistemi tarafından kesilmesi
ile ortaya çıkar. Bu tip hatalarda hata mesajı çoğunlukla işletim
sisteminin dili ile verilir. Eğer bu tip hataları kullanıcı ele almışsa,
program programcının vereceği mesajlarla ve uygun şekilde
sonlandırılabilir.
Bu tip hataların nerelerde ve hangi şartlarda ortaya çıkabileceğini bazen
kestirmek zor olabilir. Çoğunlukla işletim sistemi ve donanım
kaynakları ile ilgili sorunlarda bu tip hatalar ortaya çıkar demiştik.
Örneğin olmayan bir dosya açmaya çalışmak varolan bir dosyanın
üzerine yazmaya çalışmak olmayan bir bellek kaynağından bellek
ayırtmaya çalışmak, olmayan bir donanıma ulaşmaya çalışmak gibi.
Logical error: Karşılaşabileceğimiz en tehlikeli hatadır.
Programlama mantığında bir takım şeylerin yanlış
düşünülmesinden kaynaklanır. Hata test aşamasında
ortaya çıkar. Hesaplanması gereken veya bulunması
gereken değerlerin eksik veya yanlış hesaplanması ile
tespit edilir. Bu sorunun giderilebilmesi için tasarım hatta
çözümleme aşamasına geri dönülmesi gerekebilir. Bazen
bu hatanın nereden kaynaklandığını bulabilmek çok zor
olmaktadır.
Bug: Logical error diyebileceğimiz mantıksal hatalara verilen adlar bug
yani böcek olarak tanımlanmış olabilir. Bu tip hatalar eğer çok net değil
ve zamanla ortaya çıkabiliyor ise veya nedeni çok net olarak
anlaşılamamışsa bug diye adlandırılır. Gerek serbest yazılım gerek ticari
yazılımların tümünde bug dediğimiz mantıksal hatalar bulunur. Çünkü
hatasız program yazabilmek çok zordur. İlk seferde yazılan bir
programın tamamen hatasız olmasını beklemek son derece hatalıdır.
Günümüzde en meşhur yazılım firmaları bile yazılımlarında bug
olduğunu kabul eder ve zaman zaman bu bugları giderebilmek için ya
yazılımlarına yama yazılımı üretirler yada o yazılımın bir versiyonunu
piyasaya sürerler.
Debug: Mantıksal hataları giderebilmek ve yazılımdaki
bugları bulabilmek için yapılan işlemin adıdır. Genellikle
yazılan
programın
adım
adım
ve
denetim
altında
çalıştırılmasıdır. Programın her adımında ilgili değişkenlerin
hangi değere sahip olduğunu görmeyi sağlar. Bu işlemi
gerçekleştirebilmek için bazı IDE ortamlarında debugger
dediğimiz yardımcı komut veya yazılım gereklidir.
Algoritmalar
Bir
bilgisayar
programı
aslında
sıra
düzensel
olara
tanımlanmış bir dizi komuttan başka bir şey değildir. Bu
açıdan bizim yazmaya çalışacağımız programda bir dizi komut
yani eylem topluluğudur. Her programda bu eylemler
yazıldıkları sırada gerçekleştirilir veya çalıştırılırlar. Aslında
bizim günlük hayattaki yaşantı tarzımız dahi düzenli olarak
bir takım işlemlerin sıra ile yapılması şeklindedir. Yani bir iş
yapabilmek için bir takım alt iş veya olayları peşpeşe
gerçekleştiririz.
Algoritmanın tanımını daha önce vermiştik. Burada bu tanımı
tekrar etmek faydalı olacaktır. Bir sorunu çözebilmek için
gerekli olan sıralı mantıksal adımların tümüne algoritma
denir. Bir algoritmadan beklenen bir takım özellikler
olduğunu
da
yine
daha
önceki
tanımlar bölümünde
bahsetmiştik. Biz şimdi mümkün olduğu kadar bu tanım ve
özelliklerden yola çıkarak örneklerle birkaç algoritma vermeye
çalışacağız.
Öncelikle bir ev hanımının pasta yapmak istediğini varsayalım. Bu pastanın
yapılabilmesi için gerekli bir takım işlemler ve alt adımlar bellidir. Bir ev
sıra ile bu adımları uygulayarak bu pastayı yapar. Şöyle ki:
1. Pastanın yapımı için gerekli malzemeler hazırla
2. Yağı bir kaba koy
3. Şekeri aynı kaba yağın üzerine koy
4. Yağ ve şekeri çırp
5. Karışımın üzerine yumurtayı kır
6. Tekrar çırp
7. Kıvama geldi mi diye kontrol et
8. A. Kıvamlı ise 9.adıma devam et B. Değilse 6. Adıma dön.
9. Karışıma un koy
10. Karışıma vanilya kabartma tozu koy
11. Karışımı kıvama gelinceye kadar çırp
12. Pastayı kek kalıbına koy
13. Yeteri kadar ısına fırına pastayı koy.
14. Pişmiş mi diye kontrol et
15. A. Pişmişse 16.adıma devam et b. Değilse 14. Adıma dön
16. Keki fırından çıkart
17. Fırını kapat
18. Keki kapat
19. Kekin soğumasını bekle
20. Servis yap
Bu algoritma günlük hayattan bir örnektir. Gerçekte biz
her işimizi algoritmik olarak yaparız ancak bunun farkına
varmayız. Yukarıdaki algoritmayı inceleyecek olursak bir
kekin yapılması için gerekli tüm adımlar sıra ile yer almış
durumdadır. Gerçi algoritma anlatacağımız konuların
daha iyi anlaşılabilmesi için biraz farklı ele alınmıştır ama
gerçek bir pasta yapım aşamasını içerir. Bu algoritma ve
diğer tüm algoritmalar için bilmemiz gereken bazı konular
bulunmaktadır.
Her adım son derece belirleyici olmalıdır. Hiçbir şey şansa bağlı
olmamalıdır.
Belirli bir adım sonunda algoritma sonlanmalıdır.
Algoritmalar karşılaşabilecekleri tüm ihtimalleri ele alabilecek kadar
genel olmalıdır.
Algoritmada algoritmanın genel işleyişini etkileyebilecek hiçbir
belirsizlik olmamalıdır. ( Bu örnekte öyle bir belirsizlik var. Bir fırının
yeteri kadar ısınabilmesi hangi koşula bağlıdır, bu fırın ne zaman
açılmış olmalıdır ve kaç dereceye ayarlanmış olmalıdır gibi)
Algoritmada bazı adımlar yerdeğiştirebilir. Ancak bir çok adımın
kesinlikle yerdeğiştiremeyeceğini bilmeliyiz. Yanlış sıradaki adımlar
algoritmanın yanlış çalışmasına neden olacaktır. (9 ve 10. Adımlar
değiştirilebilir. 2-3. Adımlar yerdeğiştirebilir) Ancak 13-16. Adımlar
kesinlikle yerdeğiştiremezler.
Peki bilgisayarda çözülecek bir sorunu nasıl algoritma ile ifade
ederiz? Bunun için öncelikle bir sorun tanımlayalım. Başlangıçta
basit olması için şöyle bir problem üzerinde düşünelim. Bilgisayara
verilecek iki sayıyı toplayıp sonucu ekrana yazacak bir program için
algoritma geliştirmek isteyelim.
Sorun son derece basit ancak sistem tasarımının net yapılabilmesi
için sorun hakkında anlaşılamayan tüm belirsiz noktalar açıklığa
kavuşturulmalıdır. Örneğin sayılar bilgisayara nereden verilecek?
Klavye, dosya veya başka bir ortamdan. Bu ve buna benzer soru ve
tereddütleriniz varsa sorun sahibine bunları sormalı ve sistem analizi
yapmalısınız.
Sonra bulacağımız çözümü algoritma haline dönüştürebiliriz.
•BAŞLA
•A sayısını oku
•B sayısını oku
•TOPLAM= A+B işlemin yap
•TOPLAM değerini ekrana yaz
•SON
Biraz daha karmaşık bir sorun şöyle olsun: Klavyeden girilecek iki sayıdan
büyük olanından küçük olanını çıkarıp sonucu ekrana yazacak program için
bir algoritma geliştiriniz.
A. BAŞLA
B. A sayısını oku
C. B sayısını oku
D.Eğer A büyüktür B SONUC= A-B; değilse
Sonuc= B-A
E.SONUC değerini ekrana yaz
F. SON
Gerçekte bir algoritma genellikle üç ana bölümden oluşur.
Bunlar:
1- Algoritmanın giriş ve ilk işlemlerinin yapıldığı bölüm
2- Döngüsel bir bölümün olduğu kesim. Bu bölüm
iterasyonlarla bir işlemin sürekli tekrar edilerek sonuca
ulaşmayı sağlayan bölümdür.
3- Son işlemlerin yapıldığı bölümdür. Bu bölüm elde edilen
sonuçların ekrana yazılmasını sağlayan bölümdür
Örneğin bir klavyeden girilen bir n değerine kadar sayıları toplayan ve sonucu
ekrana yazan bir algoritmayı geliştirelim.
1. BAŞLA
2. N oku
3. T=0
4. X=1
5. T=T+X
6. X=X+1
7. Eğer X<=N ise 5.adıma git
8.T YAZ
Bu algoritmalar oldukça basit algoritmalar olup algoritma kavramının
yerleşmesini sağlayan örneklerdir.
AKIŞ ÇİZGELERİ
Bir algoritmanın şekillerle görsel gösterimidir. Dikkat
edildiyse algoritma doğal dille yazıldığı için herkes
tarafından anlaşılamayabilir ya da istenmese de başka
anlamlar çıkarılabilir. Ancak akış çizgelerinde her bir şekil
standart
anlam
taşıdığı
için
farklı
yorumlanıp
anlaşılamaması mümkün değildir. Bir algoritmanın ifade
edilmesi için kullanılan şekiller ve anlamları şöyledir:
Bu şekiller kullanılarak algoritma ile oluşturulan çözümler akış çizgelerine çevrilir.
ÖRN: Bu örnekte 1’ den N değerine kadar sayıları sayıları toplayıp ekrana yazan bir
akış çizgesi çizilmiştir
ÖRN: Fibonecci sayılarının 100 e kadar olanlarını listeleyen akış çizgesidir.
ARİTMETİK VE MANTIKSAL İFADELER
Bir takım işlemlerin yapılabilmesi için aritmetik işlemlerin
nasıl tanımlandığını bilmeniz gerekir. Program akışının
doğru bir şekilde sağlanabilmesi için bazı yerlerde karar
verilmesi gereklidir. Bu kararların verilmesini sağlayacak
mantıksal ifadeler bilgisayarlar tarafından yapılabilmelidir.
Aritmetik İfadeler
Bir programın istenilen işleri yerine getirebilmesi için hesap
yapabilmesi ve bu hesaplar sonucunda elde edilen değerleri
saklayabilmesi gerekmektedir. Genel olarak tüm programlama
dillerinde aritmetik işlemler şu şekilde tanımlanmıştır:
Bu tip bir gösterimde “değer” denilen kesim sabit bir değeri
temsil eder. “Değişken ise içerisinde her an farklı bir değer
tutabilecek bir tanım ifade eder. Aritmetik operatör ise
aritmetik işlemin özünü oluşturan bir işleçtir.
Aritmetik operatör
Kısaca dört işlem olarak da ifade edebileceğimiz işleçlerdir. Çoğunlukla dört
tanedirler ve cebirde kullanılan öncelikleri aynı şekilde kullanırlar.
*
Çarpma işlemini gösteren işleçtir. Bölme ile eş önceliklidir.
/
Bölme işlemini gösteren işleçtir. Çarpma ile eş önceliklidir.
+
Toplama işlemini gösteren işleçtir. Çıkarma ile eş önceliklidir.
-
Çıkarma işlemini gösteren işleçtir. Toplama ile eş önceliklidir.
Temel olarak bu işleçler her programlama dilinde bulunur.
Öncelikleri yukarıdaki sırada olduğu gibidir. Eş öncelikli
aritmetik ifadeler bulunursa bu ifadelerde işlem soldan
sağa doğru yapılır.
Bu işlem önceliklerini değiştirmek için her programlama
dilinde “(“,”)”(parantez aç-kapa) ifadelerini bulabilirsiniz.
Bunlardan hariç olarak bazen üst alma operatörlerinden
bahsedilebilir, bazen de mod operatörü ve tam bölme
operatörü gibi değişik ve standart olmayan operatörler
alabiliyor.
Aritmetik operand
Aritmetik ifadelerde işleme giren tarafların her birine aritmetik
operand yani aritmetik işlenen denir. Yukarıdaki tanımda
DeğerIDeğişken ikilisinin her biri işlenen yani operand tanımını
sağlar. Bir aritmetik ifadede de bir çift operand ve bir operatör
minimum olması gereken ifadelerdir. Ancak daha fazla aritmetik
işlenen ve işleç olabilecektir. Örneğin A*B+(12+B) işlemi de bir
aritmetik ifadedir.
Değer aktarma deyimi
Genellikle bir aritmetik ifade ile hesaplanan değer başka bir
değişkene aktarılır. Bu işlem çoğunlukla “=” sembolü ile
gerçekleştirilir. Ancak başka bir komut, sembol veya ifade ile
de bu değer aktarılması yapılabilir.
Mantıksal ifadeler
Bir değerin başka bir değer ile karşılaştırılması sonucu doğru
veya yanlış sonuç elde edebilen ifadelerdir.
Mantıksal operatörler ve karşılaştırma operatörlerinin değişik
alternatiflerle bir araya gelmesinden oluşur şu şekillerde ifade
edilir:
Karşılaştırma Operatörü
İki değer veya aritmetik ifadeyi birbiriyle karşılaştırmayı sağlayan
sembollerdir.
=
>,>=
<,<=
<>
İki değerin eşit olup olmadığını karşılaştıran işleçtir.
İki değerden soldakinin sağdakine oranla büyük
olup olmadığını veya büyük eşit olup olmadığını
kontrol eden operatördür
İki değerden soldakinin sağdakine oranla küçük
olup olmadığını veya küçük eşit olup olmadığını
kontrol eden operatördür
İki değerin farklı olup olmadığını karşılaştıran
işleçtir
A>= 8 ifadesi A değişkeni içindeki değerin 8’ den büyük eşit mi
diye karşılaştırır.
A<> 12 ifadesi A değişkeni içindeki değer 12’den farklı mı diye
karşılaştırır.
Mantıksal Operatör
Birden fazla mantıksal karşılaştırma deyiminin birleştirilmesini
sağlayan işleçlerdir. VE, VEYA gibi ifadelerdir. Bu operatörler
mantıksal ifadelerdir. Bu operatörler mantıksal ifadelerden iki
veya daha fazlasının mantıksal doğruluk tablolarına göre
birleştirilmesini sağlar.
VEYA için doğruluk tablosu
P
D
D
Y
Y
Q
D
Y
D
Y
P VEYA Q
D
D
D
Y
VE için doğruluk tablosu
P
D
D
Y
Y
Q
D
Y
D
Y
P VE Q
D
Y
Y
Y
Son mantıksal operatör DEĞİL operatörü olup tel işlenen alır ve
aldığı işlenenin mantıksal değilini alır. Yani doğru olan değeri yanlışa
yanlış olan değeri doğruya çevirir.
P
D
Y
DEĞİL(P)
Y
D
Örneğin bir değişken içindeki değerin 1 ile 10 arasında olup
olmadığını kontrol eden ifade şu şekildedir: (A>=1 VE
A<=10). Bu tür ifadeler yazılırken dikkat edilmelidir. Örneğin
(A>=1 VE A<=10) yerine (A>=1 VEYA A<=10) yazılması her
zaman yanlış sonuç üretecektir. Yada (A=3 VE A=8) gibi bir
ifade de asla doğru olmayacaktır.
Değişken ve Dizi Tanımlama
Bilgisayarda yapılacak hesaplar sonucu elde edilecek
değerleri
ve
dışarıdan
bilgisayara
girilecek
değerler
değişkenlerde tutulur. Değişkenler içlerinde tuttukları
değerlerin türlerine göre sınıflandırılır. Bu değişkenler bazen
basit şekilde olmaz kayıt yapısında ya da dizi yapısında
olabilirler.
Sabit nedir?
Programın her yerinde aynı değeri ifade eden değerlerdir.
Değişkenlerde olduğu gibi sabitler de tür kavramına sahiptir.
Yazılış tarzına bakarak sabitin türünü anlamak mümkündür.
Tam Sayı Sabitleri
Sadece rakamlardan oluşan ifadelerdir. Bu tip sayıların
içerisinde sadece rakam ve gerekiyorsa işaret sembolü
olabilir. Aritmetik işlemlere girebilirler.(12, 1233,-3422
gibi)
Kesirli sayı sabitleri
Rakam ve ondalık ayıracı olarak (.) nokta sembolü
kullanılabilir. Ayrıca işaret sembolü olarak (-) kullanılabilir.
Aritmetik işlemlere girebilirler. (3.14, 2.41, -2.11221)
Dizgi Sabitleri
Tırnak içerisinde yazılan her ifade dizgi sabiti olarak
algılanır. Programlama dillerinde farklı tırnak sembolleri
kullanılabilir. Çoğunlukla “ sembolü tercih edilir. Aritmetik
işlemlere giremez. (“Malatya”, “merhaba”, “dünya”,”1322”
gibi)
Değişken nedir?
Her
seferinde
farklı
değerler
alabilen
yapıdır.
Programlarda değişkenleri kutu olarak sembolize ederek
çözümlemek mümkündür. Değişkenler de sabitlerde
olduğu gibi türlere sahiptir. Sabitlerdeki türler aynen
geçerlidir.
Dizi nedir?
Bazı durumlarda kullanım amacı aynı olan birden fazla,
hatta oldukça fazla sayıda değişkene ihtiyaç duyulur. Bu
tip bir durumda bu değişkenler tek tek tanımlanmak
yerine bir ad altında indisle tanımlanırlar. Bu tanıma dizi
denir. Bazı sorunların çözümü için bu tanımlar zorunludur.
Mesela 1000 sayıyı sıralamak için basit değişken
tanımlama işlemi başarısız olacaktır. Veya bir sınıf
listesinin tümünü bilgisayarda tutmak isterseniz basit
değişkenler uygun değildir.
Çoğunlukla bu tip bir tanımda dizinin bir adı vardır. Erişmek
istediğiniz dizinin eleman indis değeri ile bu dizi içerisinde
istediğiniz elemana ulaşabilirsiniz.
A Dizisi
A(1) A(2)
A(9)
A(3)
A(4)
A(5)
A(6)
A(7)
A(8)
A(10)
Bu dizi bu şekilde düşünülebilir. Her bir eleman yukarıdaki
gibi isimlendirilir. Bunun bize sağlayacağı avantaj indis
değerlerinin değişkenlerle ifade edilmesinde yatmaktadır.
Yani tek bir satır komut ile tüm dizi elemanları mesela
ekranda yazdırılabilir.
Algoritma Çalıştırma
Bazen bir takım algoritmaların ne işe yaradığını
anlamak veya algoritmanın doğru çalışıp çalışmadığını
test etmek için algoritmayı çalıştırmak gereklidir.
Algoritmayı çalıştırmak demek algoritmanın adımlarını
sıra ile uygulamak, oluşan değişken değerlerini bir
tablo üzerinde göstermek demektir
1. BAŞLA
2. A OKU
3. B OKU
4. C OKU
5. TOP= 0
6. SAY= A
7. TOP = TOP + SAY
8. SAY = SAY + C
9. EĞER SAY<= B İSE 7.ADIMA GİT
10.TOP YAZ
11.SON
Şeklinde verilmiş bir algoritmamız olsun. Bu algoritma için A3,
B12 ve C2 değerleri girilince SAY ve TOP değişkenlerinde hangi
değerlerin oluşacağını algoritmayı adımlayarak gösterelim.
Değişkenlerinin her birinin
değeri
A
B
C TOP SAY
3
12
2
0
3
8
15
24
35
AÇIKLAMA
6.adıma kadar programın ilk çalıştırılışında
değişkenlerin elde ettiği değer
7.ve 8.adımların çalıştırılmasından sonra ki
5
değerler
7 7.ve 8.değerler tekrar çalıştırılıyor
9 9<=12 olduğu için 7. Ve 8. Tekrar çalıştırılıyor.
11 11<=12 olduğu için 7. Ve 8. Tekrar çalıştırılıyor.
12<=12 olmadığı için algoritma 10. Satırdan
13 çalışmaya devam edecektir. Ve 10.satırdaki
ifadeden dolayı ekrana 35 değeri yazılacaktır.
3
Sayı Sistemleri
Bir bilgisayar siteminde tüm bilgi kayıtları ve işlemleri
elektriksel devreler üzerinden gerçekleştiği için tek bilinen
gerçek elektrik akımının varlığı veya yokluğudur. Bu da
matematiksel ve mantıksal olarak ikili sayılı sistemine karşılık
gelir. Çoğunlukla ikili sayı sistemindeki 0 değeri elektrik
olmadığını 1 değeri ise bir elektriksel gerilimin olduğunu
anlatır. Bu iki sayısal değer (0 ve 1) ikili sayı sisteminin
rakamlarıdır. Ve bilgisayarda oluşan tüm değer ve sonuçlar
gerçekte bu rakamlar ile anlatılabilirler. Ancak bizim bu sayısal
değerleri anlamamız zor olduğu için sayısal olarak onluk sayı
sistemini kullanırız.
Tabandan tabana çevrim
Böyle olunca sayıların gerektiği durumlarda tabandan
tabana çevrilebilmesi gereklidir. İlköğrenim düzeyinde
görmüş olabileceğiniz yöntemlere burada değinmekte
fayda bulunmaktadır. Bu rakamların her biri bilgisayarda
bit denilen alanlarda tutulmaktadır.
İkili sayı sisteminden onlu sayı sistemine çevrim
Elimizdeki ikili sayının en sağındaki basamak sıfırıncı basamak
olmak kaydıyla tüm basmaklarımız sola doğru numaralandırılır.
Sonra her basamaktaki sayısal değeri 2basamak değeri ile çarpar ve
bulunan tüm değerleri toplarız.
7 6 5 4 3 3 1 0
1 0 0 1 1 0 1 1
= 1*20 + 1*21 + 1*23 + 1*24 + 0*25 + 0*26 + 1*27
=1 +2 + 0 + 8 + 16 + 0 +0 128
= 155
Onlu sayı sisteminden ikili sayı sistemine çevrim
Eldeki onlu sayı sürekli 2 değerine bölünerek işlem yapılır.
Bölme işlemi en son bölümün 0 olduğu noktaya kadar devam
eder. Elde edilen bölme tablosunda en son kalanlar sondan
başa doğru yan yana yazılır ve sayının ikilik tabandaki karşılık
bulunmuş olur.
Örneğin elimizde 156 gibi sayısal bir değer olsun.
İşlem
155/2
77/2
38/2
19/2
9/2
4/2
2/2
1/2
Bölüm
77
38
19
9
4
2
1
0
Kalan
1
1
0
1
1
0
0
1
Sonuç kalan sütunundaki değerlerin aşağıdan yukarı dizilmesi ile 1 0 0 1 1 0 1 1 olarak
elde edilir.
Diğer sayı sistemleri
0….X şeklinde bir dizi rakama sahip olan sayı sistemleri X+1’ li sayı
sistemi olarak anılır. Örneğin 0…7 arasında rakamlarla ifade edilen
sayı sistemi 8’ li sayı sistemidir. Bunun gibi bir programcının bilmesi
gerekebilecek 16’ lı sayı sistemi vardır. Bu sistemde sayılar 0…9’ a
kadar gider ve sonrasında A,B,C,D,E,F gibi rakamları da 10, 11, 12,
13, 14, 15 gibi değerleri ifade etmek için kullanılır.
Bu sayı sistemleri haricinde 3’lü, 5’ li vb sistemler
bulunabilir/bulunur. Ancak bir bilgisayar programcısı ikili, sekizli,
onlu onaltılık sistemleri kullanır ve bu sistemlerden haberdardır.
Veri İşleme
Bilgisayarımızda anlatmak, görmek, duymak istediğimiz her bilgi
veya medya bilgisayar ortamında sayısal olarak saklanır. Bunların
üzerinde yapacağınız işlemlerin çoğu da aslında matematiksel
veya mantıksal işlemlerdir. Örneğin bir çizim bilgisayarda nokta
nokta
saklanır.
İki
boyutlu
bir
düzlem
üzerinde
(0,0)
koordinatındaki noktanın rengi sayısal olarak verilir. Örneğin bu
değer 0 ise renk 65555 ise renk beyazdır. Bu sayısal değeri
değiştirerek (0,0) koordinatındaki noktanın rengini değiştirmiş
olursunuz.
Aynen bu şekilde tüm bilgiler bilgisayar ortamında uygun sayısal
veriler şeklinde tutulur. Yapılacak işlemler bu verilerin üzerinde
matematiksel ve mantıksal yollarla yapılan işlemlerdir. Bir resmin
büyültülüp küçültülmesi resimlerin üzerine efekt eklenmesi, ses
efektlerinin eklenmesi video görüntülerinde istenilen ekleme ve
çıkarmaların yapılması, bir nesnenin üç boyutlu görüntüsünün
elde edilip hareket kazandırılması gibi onlarca konu veri işleme
esaslarına dayanan hesaplamalarla elde edilir. Bu tip kavramların
her biri için internetten algoritma vb. aratılıp kullanılabilir.
Algoritma örnekleri ve sorular
•Soru
Klavyeden girilecek X değerinden N değerine kadar tüm doğal
sayıları listeleyen algoritmayı geliştiriniz.
Çözüm: X değişkeni ve N değişkeni klavyeden girilecek olup X’
den N’ e kadar elde edilecek her bir değer ekrana yazılacaktır.
1.
2.
3.
4.
5.
6.
X OKU
N OKU
X YAZ
X=X+1
EĞER X<=N İSE 3.ADIMA GİT
SON
•Soru
Klavyeden girilecek bir N değerine kadar fibonecci dizisini bulan
algoritmayı geliştiriniz. Fibonecci dizisi 1 1 değerleri ile başlar ve
yeni değer kendinden bir öndeki iki değerin toplamı olarak
bulunur. (1 1 2 3 5 8 13 21…)
Çözüm: Fibonecci dizisi a, b, c şeklinde 3 değişken ile
hesaplanabilecek bir dizidir. Çünkü sürekli a ve b toplanarak c
üretilir ve sonra bu a,b, c değişkenleri kaydırılır.
1. N OKU
2. A=1
3. B=1
4. A, B YAZ
5. C= A+B
6. EĞER C> N İSE 11.ADIMA GİT
7. C YAZ
8. A=B
9. B=C
10.5.ADIMA GİT
11.SON
•Soru
Klavyeden girilen bir sayının tüm tam bölenlerini bulup listeleyen
(ekrana yazan) bir algoritma geliştiriniz.
Çözüm: Bu örneği çözebilmek için böleni kalma operatörünün
varlığını kabul edeceğiz. Bu amaçla C dilinde kullanılan %
operatörünü kalanı bulma operatörü olarak kullanacağız.
1.
2.
3.
4.
5.
6.
N OKU
X=1
EĞER N%X =0 İSE YAZ
X= X+1
EĞER X<=N İSE 3. ADIMA GİT
SON
•Soru
Klavyeden girilen üç sayıdan büyüklük sıralamasına göre
ortadakini bulup ekrana yazan program için algoritma yazınız.
Çözüm: Bu algoritma üç sayının klasik yollarla sıralanmasını yada
büyüklük sıralamasının bulunmasının ne denli zor olduğunu
anlatmaya çalışan bir örnektir.
1.
2.
3.
4.
5.
6.
7.
A, B, C OKU
EĞER A>B VE B>C İSE B YAZ
EĞER C>B VE B>A İSE B YAZ
EĞER B>A VE A>C İSE A YAZ
EĞER C>A VE A> B İSE C YAZ
EĞER B>C VE C>A İSE C YAZ
SON
•Soru
Klavyeden girilen A ve B gibi iki sayının bölme işlemi kullanmadan
sadece toplama ve çıkarma kullanarak kalanlı bölme yapan
algoritmayı yazınız.
Çözüm: Bu örnek çok eski işlemcilerde çarpma işleminin tanımlı
olmadığı durumlar için çarpma yada bölme yapmak amacıyla
kullanılan algoritma olarak karşımıza çıkmıştır.
1.
2.
3.
4.
5.
6.
7.
8.
A, B OKU
BOLUM=0
KALAN=0
EĞER A<B İSE KALAN A, 8.ADIMA GİT
A=A-B
BOLUM=BOLUM+1
4.ADIMA GİT
BOLUM, KALAN YAZ
•Soru
Sıfır-0 girilinceye kadar klavyeden okutulan değerlerin
ortalamasını hesaplayıp ekrana yazan algoritmayı geliştiriniz.
Çözüm: Bu örnekte bir toplam değerini tutabilecek iki
değişkene ihtiyaç vardır. Klavyeden girilen her değer sıfır ile
karşılaştırılacak değilse işleme devam edilecektir. Sıfır ise
ortalama hesaplanıp ekrana yazılacaktır.
1.
2.
3.
4.
5.
6.
7.
8.
9.
T= 0
SAY= 0
X OKU
EĞER X=0 İSE 8.ADIMA GİT
T=T+X
SAY=SAY+X
3.ADIMA GİT
ORT= T/SAY
ORT YAZ
•Soru
Klavyeden girilecek 20 sayının tek olanlarını ayrı çift
olanlarını ayrı toplayıp sonuçları ekrana yazan algoritmayı
geliştiriniz.
Çözüm: Bu algoritma yine % operatörünün kalanı bulan
operatör olarak kullanılacağını varsayıyoruz. Çünkü bu
algoritmada bir sayının çift mi tek mi olduğunu anlamak
ancak ve ancak o sayının ikiye bölümünden kalanın 1 mi 0 mı
olduğuna bağlıdır.
1.
2.
3.
4.
5.
6.
7.
8.
9.
ÇİFT= 0
TEK= 0
SAY= 0
X OKU
SAY=SAY+1
EĞER X%2=0 İSE ÇİFT=ÇİFT+X DEĞİLSE TEK=TEK+X
SAY=SAY+1
EĞER SAY< 20 İSE 4.ADIMA GİT
TEK, ÇİFT YAZ
•Soru
Bir n değeri için
şeklindeki fonksiyonun değerini hesaplayıp ekrana yazan
algoritmayı geliştiriniz.
Çözüm: Bu algoritma oldukça basit bir şekle sahip olup benzer
şekildeki tüm fonksiyonları küçük değişikliklerle rahatça
hesaplayabilecek bir algoritmadır. Sadece 4. Adımı değiştirerek
oldukça fazla sayıda algoritma veya sorun türetilebilir.
1.
2.
3.
4.
5.
6.
7.
N OKU
F= 0
X= 1
F= F+1/ (X*X)
X=X+1
EĞER X<=N İSE 4.ADIMA GİT
F YAZ
•Soru
şeklindeki bir fonksiyon için f(x)>=kk şartını sağlayan en küçük n
değerini bulabilecek bir algoritma geliştiriniz. Kk ve n değerlerinin
klavyeden girildiğini düşünelim.
1.
2.
3.
4.
5.
6.
7.
8.
KK OKU
N OKU
F=0
X=1
F=F+1/(X*X)
X=X+1
EĞER F<KK İSE 5.ADIMA GİT
F, X YAZ
C PROGRAMLAMA DİLİ
C ve C++ adını bilgisayarla az çok ilgili olan herkes en az bir kez
duymuş olup mühendislikte önemli bir yeri vardır. Bilgisayar çok
basit düşündüğümüzde üç ana görevi yerine getirir. Girilen bilgiyi
alır (INPUT), işler (PROCESSING) ve bu işlenmiş veriden ve bu
işlenmiş veriden bir sonuç (OUTPUT) çıkarır. Bilgisayar sadece
donanım olarak çalışmaz.
Çünkü yazılım olmadan donanım ne yapacağını bilmez. Yapacağı
görevleri ona anlatan komutlara program diyebiliriz. Ancak
programcı bilgisayarın bütün özelliklerini bilmesi gerekmez. Yani
yazacağınız bir program için o bilgisayarın özelliklerini
bilmeseniz de olur.
Bilgisayarın anladığı tek dil makine dilidir. Bu 16’ lık
(hexadecimal) sistemden oluşan bu programlama tipidir.
Makine dilini anlamak zordur ve bu dili kullanmak için o
bilgisayarın donanım özelliklerini mutlaka bilmek gerekir. C de
ekrana yazı yazmanızı sağlayan “printf();” gibi çok basit bir
fonksiyon, makine dilinde 1 A BB 0D BC D5 FF C2 F7 gibi çok
daha karmaşık ve hiçbir anlam ifade etmeyen bir hale dönüşür.
Makine dili programlama dilleri arasında en alt seviyedir.
Makine dilinden sonra “Assembler Dili” gelir. Makine dilinin
kullanma
zorluğu
ve
karmaşası
üzerine
geliştirilen
“assembler” daha basir bir yapıdadır. Ama yinede C ile
mukayese ederseniz çok daha zordur ve kullandığınız
bilgisayarın donanımına dair halen bilgiye gereksinim
duyarsınız. Aşağıdaki assembler e bir basit kodlama örneği
verilmiştir.
SEGMENT COM WORD PUBLIC
‘CODE’
ASSUME CS: COMDS: COM
ORG 100H
ENTRY: MOV DVX, OFFSET MSG
MOV AH, g
.
.
.
C, orta seviye bir programlama dilidir. Bunun anlamı, hem
yazması kolay, hem de üst seviye dillere göre daha çok erişim
hakkınızın olduğudur. Üst seviye programlama dilleri ise
BASIC, PASCAL gibi dillerdir. Üst seviye dillerde yazılım göreceli
olarak daha kolay olsa da özellikle mühendislikte C ile
yapabileceklerimiz daha çoktur.
Program yazmak için ne gerekir?
Program yazmak için Windows’un not defterini veya Linux’ ta
Gedit, Kwrite gibi bir program bile kullanabilirsiniz. Önemli
olan yazılan programın derlenmesidir. Derlemeye “compile”
ve derleme işini yapan derleyici ise “compiler” denir. C çin
internet üzerinden birçok compiler bulabilirsiniz. Burada
program uygulamaları GCC üzerindendir. GCC gelmiş geçmiş
en iyi derleyicilerden biri olduğu için özgür yazılımdır. Richard
Stallman tarafından açık kaynak koduyla sunulmuştur ve
istenildiği taktirde sonuna kadar değişiklik yapma imkanınız
vardır.
Şayet Windows işletim sisteminiz varsa GCC kurmanız biraz
sıkıntılı olabilir. Ancak basit bir Google araştırmasıyla, Bloodshed
DEV-C++
adında
gerçekleştirebilirsiniz.
br
program
ile
C
uygulamalarını
Algoritma Geliştirmek
C dilini ve komutlarını öğrenmek programlamaya başlamak için
şarttır ama algoritma oluşturmadığınız müddetçe bir program
oluşturamazsınız. Algoritma mantıktır. Yani neyi nasıl yapacağınızı
belirler. Algoritma programlamanın belkemiğidir. C dilinde kullanılan
komutlar BASIC veya FORTRAN gibi başka dillerde işe yaramaz.
Programlama mantığı iyi öğrenilirse C komutlarının yerine pekala
başka dillere ait komutları da öğrenebilir ve büyük zorluk çekmeden
diğer dillerde de program yazabilirsiniz.
Temel Giriş/Çıkış işlemleri (BASIC I/O):
C ile ilgili olarak bu ve önümüzdeki yazılarda birçok komut ve
fonksiyon göreceğiz. Ama hep kullanacağımız ve ilk öğrenmemiz
gerekenler temel giriş çıkış fonksiyonlarıdır. C de klavyeden bir
değer alabilmek için scanf(); fonksiyonunu kullanırız. Ekrana
herhangi bir şey yazdırmak içinse printf(); fonksiyonu kullanılır.
Bir örnekle görelim;
#include<stdio.h>
int main( void )
{
Printf(“hello world”);
}
Eğer bunu derleyicinizde yazıp derlerseniz ve sonrasında
çalıştırırsanız ekrana “hello world” yazacaktır. #include<stdio.h>
standart giriş çıkış başlık dosyasını, programa dahil et gibi bir
anlam taşır. C’ de (ve hemen hemen bütün programlama
dillerinde) bir kütüphaneyi dahil etmek rutin bir iştir. Aksi halde
giriş çıkış fonksiyonlarını
tanımlamamız gerekirdir.
dahi her seferinde bizim baştan
main(); bir programdaki ana fonksiyondur. Ondan sonra gelen
ayraç standarttır. Bir bloğu temsil eder. İki ayraç işareti arasındaki
alan main fonksiyonuna ait bir bloğu oluşturur. printf ise
yazdığımız metini ekrana bastırmaya yarayan standart bir
fonksiyondur. Çift tırnak işaretleri içerisine yazdığımız her şey
printf sayesinde ekrana basılır.
Her satır sonuna noktalı virgül koyduk. Aslında her satır değil
her komuttan sonra noktalı virgül koyduğumuzu söylemek daha
doğru olacaktır. Çünkü noktalı virgül C dilinde komut ayıracı
anlamına gelir.
Şimdi yukarıda yazdığımız basit programı geliştirelim:
#include<stdio.h>
int main( void )
{
printf(“hello world\n”);
printf(“merhaba dünya”);
return 0;
}
Burada birkaç yeni satır görüyorsunuz. Sırayla ne olduklarını
açıklayınız. Az önce yazdığımız “hello world” yazısının sonuna “\n”
ekledik.
“\n” bir alt satıra geç anlamına geliyor. Eğer “\n” yazmazsak, ekranda
“hello worldmerhaba dünya” şeklinde bir yazı çıkar. “\n” kullanırsak,
“hello world” yazıldıktan sonra bir alt satıra geçilir ve ikinci satıra
“merhaba dünya” yazdırılır. En altta “ return 0;” adında yeni bir
komut olduğuna dikka edelim. Bunu eklemezseniz program yine
çalışır ancak uyarı verir. Çünkü main fonksiyonu geriye bir tamsayının
dönmesini beklemektedir. Yazmış olduğumuz return ifadesiyle bu
uyarılardan kurtulabilirsiniz. Burada detayına girmek için henüz
erken olup return konusuna ileride detaylı olarak değineceğiz.
Yukarıdaki programın aynısını şöyle yazabilirdik;
#include<stdio.h>
int main( void )
{
printf(“hello world”);
printf(“\n merhaba dünya”);
return 0;
}
Bir önce ve şimdi yazdığımız programları ekran çıktısı aynıdır. Bu
örnekle anlatmak istediğim, printf() fonksiyonunda ‘\n’ konulan
yerden sonrasının bir alt satıra düşeceğidir.
#include<stdio.h>
int main( void )
{
printf(“hello world\n merhaba dünya”);
return 0;
}
Gördüğünüz gibi tek bir printf(); kullanarak aynı işlemi yaptırdık.
Varsayalım ki ekrana çok uzun bir cümle yazmamız gerekti. Örneğin;
#include<stdio.h>
int main( void )
{
printf(“benim adım Çağatay Çebi ve yazılım
mühendisiyim.\n”);
return 0;
}
Bu yazdığımız program hata vermemesine karşın çalışma
verimini azaltır. Çünkü yazacaklarınız editör penceresine
sığmazsa yazılanı okumak daha zahmetli olur. Önemsiz bir detay
gibi
gelebilir,
ama
kod
yazma
düşüreceğinden emin olabilirsiniz.
verimini
ciddi
oranda
Bu programı aşağıdaki gibi yazmamız daha uygundur:
#include<stdio.h>
int main( void )
{
printf(“benim adım”
“ Çağatay Çebi”
“ve yazılım mühendisiyim.\n”);
return 0;
}
Tek bir printf(); fonksiyonu kullanılmıştır. Ancak alt alta yazarak,
metni tek seferde görülebilir hala getirdik. Programı derleyip
çalıştırırsanız alt alta üç satır yazılmaz. Cümle bütün olarak
gösterilir ve bir önce ki örnekle tamamen aynıdır. (Satırların alt
alta görünmesini isteseydik; daha önce bahsettiğimiz gibi ‘\n’
koymamız gerekirdi)
Ekrana, Ali:”Naber, nasılsın?” dedi. Şeklinde bir yazı yazdırmamız
gerekiyor diyelim. Bu konuda ufak bir problem yaşayacağız. Çünkü
pirintf(); fonksiyonu gördüğü ilk iki çift tırnak üzerinden işlem
yapacaktır. Böyle bir şeyi ekrana yazdırmak için aşağıdaki gibi bir
program yazmamız gerekir:
#include<stdio.h>
int main( void )
{
printf(“Ali:\”Naber, nasılsın?\dedi.\n”);
return 0;
}
printf(); fonksiyonunun kullanımı böylece iyice anlaşıldığını
sanıyoruz. Şöyle özetlersek; printf( yazıp sonra çift tırnak açıyor,
yazmak istediklerimizi yazıyor, çift tırnağı sonra da parantezi
kapatıyor, sonuna noktalı virgül ekliyoruz. Alt satıra geçmek
içinse yazdıklarımızın sonuna ‘\n’ ekliyoruz. Çift tırnaklı bir şey
kullanmak içinse \”…\” kullanıyoruz.
scanf(); fonksiyonu ise başta bahsedildiği gibi giriş (INPUT)
fonksiyonudur.
3 nisan notları
eklenencek
Kodlarınıza açıklama koymak
Yazılım mühendislerinin en büyük sıkıntısı kod yazmak değildir.
Yazılmış bir kodu okuyup anlamak –hele ki büyük bir projeden söz
ediyorsak- asıl başınıza bela olacak konudur. Bundan korunmak için
kodlarımıza açıklama/yorum koyarız.
.
C programlama dilinde iki şekilde açıklama koymak mümkündür.
Bunlardan bir tanesi satır bazında yapılır. Diğeriyse belirli bir bloğu
yorumlamaya yarar. Compiler her iki şekilde de açıklama olarak
belirlemiş yerleri işlemeyecektir. Aşağıdaki örnekte satır ve blok
olarak nasıl kodlarınıza açıklama getirebileceğinizi görebilirsiniz
/*Çok satırlı bir açıklama.
Yıldızlar arasında kalan bütün
alan, yorum olarak değerlendirilir
ve derleyici (compiler) tarafından
işlenmez.
*/
#include<stdio.h>
int main (void)
{
//Tek satırlık bir açıklama.
printf (“Hello World\n”);
}
Cast Operatör
Cast operatör’ ü şu şekilde açıklayabiliriz. Bir değişken tipini
örneğin (Tamsayı-int), bir başka tipe (virgüllü sayı-float) gibi
dönüştürmek isterseniz, o zaman Cast operatör kullanırız.
Aşağıdaki kodu yazıp derleyin.
#include<stdio.h>
int main (void)
{
int bolunen = 12, bolen=8;
float bolum;
bolum=bolunen/bolen;
printf(“Sonuc:%f\n”, bolum);
return 0;
}
Program çıktısı; “Sonuc:1.000000” olacaktır.
Normalde 1.5 çıkmasını beklediğiniz sonucun 1.000000
çıkmasının nedeni casting kullanmamızdır. Bir tamsayıyı, bir
başka tamsayıya bölerseniz sonuç bir başka tamsayı çıkar. Ve C
programlama dili bir virgüllü sayıyı tamsayıya atamaya
kalktığınızda herhangi bir yuvarlama işlemi yapmadan virgülden
sonrası atar.
Elimizdeki bu bilgiye göre programımızı tekrar yazalım.
#include<stdio.h>
int main( void )
{
int bolunen = 12, bolen= 8;
float bolum;
bolum= (float)bolunen/bolen;
printf(“Sonuc: %f\n”, bolum);
return 0;
}
Cast operatör
(tip)degisken_2;
şu
şekilde
kullanılmalıdır:
degisken_1=
Elimizdeki bu bilgiye göre programımızı tekrar yazalım.
#include<stdio.h>
int main( void )
{
int bolunen = 12, bolen= 8;
float bolum;
bolum= (float)bolunen/bolen;
printf(“Sonuc: %f\n”, bolum);
return 0;
}
Sonuç beklediğimiz gibi 1.5 çıkacaktır.
Aşağıdaki örneği inceleyelim.
#include<stdio.h>
int main( void )
{
printf (“Sonuc: % f\n”, 2 / 4);
return 0
}
Öğrendiğimiz üzere, bunun da sonucu 0.5 yerine, 0 olarak
gözükecektir. Sonucu doğru yazdırmak için (float)2/4 şeklinde
yazmanız yeterlidir. Ancak basit bir yöntem olarak 2/4.0 veya
2.0/4 yazarsanız yine aynı sonucu elde edersiniz. Çünkü bu
durumda sayılardan bir tanesi float olmaktadır.
Kullanılan değişken tiplerinden hangisi büyükse, sonuç o değişkenin
tipine döner. Yüksek değişken bellekte daha fazla yer kaplamaktadır.
Bunun bir sonucu olarak da domine eden o’ dur. Değişkenlerin
büyüklüğü daha önce verilmişti, ancak hatırlamak açısından aşağıya
bakabilirsiniz.
(DÜŞÜK) char<-> int <-> long <-> float <_> double (YÜKSEK)
Çıkan sonucu daha düşük bir değişken tipine atamaya kalkarsanız o
zaman veri kaybı yaşanır. Ve örneğin float 1.5 olan sonucu int
değişkene 1.0 olarak kaydedilir.
Öğrendiklerimizin pekişmesi için bir program yazalım. Bu programda,
klavyeden girilen, bir virgül sayının, yuvarlanıp, tam sayı olması
gösterilsin.
#include<stdio.h>
int main (void)
{
float girilen sayı;
printf (“lütfen bir sayı giriniz>”);
scanf(“%f”, &girilen_sayı);
printf(“Sayının yuvarlanmış hali: %d\n”,
(int)(girilen_sayı+0.5);
return 0;
}
Koşullu (Conditional) İfadeler
İf
Bilgisayarda yapılan bütün mantıksal işlemler kaba bir temele
dayanır. Şartlar sağlandığı halde yapılacak işlemler belirlenir. Ve
şartlar sağlandığında bu işlemler yapılır. Şartların kontrol
edilmesini, C (ve daha birçok) programlama dilinde if operatörü
kullanarak yaparız.
İf operatörünün genel kullanım yapısı şu şekildedir:
if ( koşul ) {
komut (lar)
}
Eğer if’ in altında birden çok komut varsa ayraç işareti (veya küme
parantezi) koymamız gerekir. Şayet if’ ten sonra, tek komut
bulunuyorsa, ayraç koyup koymamak size kalmıştır. Zorunluluğu
yoktur.
Örnek bir program yazalım. Bu programda kullanıcının klavyeden,
bir tam sayı girsin. Ve bizde girilen sayı, 100’ den büyükse ekrana
yazdıralım:
#include<stdio.h>
int main (void)
{
int girilen sayı;
printf(“Lütfen bir tam sayı giriniz>”);
scanf(“%d”,&girilen_sayi);
if( girilen_sayi>100)
printf(“Girilen sayı 100’den büyüktür\n”);
return 0;
}
if-else:
Bazı durumlarda bir koşulun doğruluğuna göre sonuç yazdırmak
yetmez. Aksi durumda da ne yapacağımızı bilmek isteriz. Bunun
için if-else yapısını kullanırız. Bu yapı şu şekildedir:
if( koşul ) {
komut(lar)
}
else {
komut(lar)
}
Önce ki yazdığımız programda sonuç 100’ den büyük olduğunda
ekrana çıktı alıyorduk. Burada bu programa bir özellik daha
ekleyelim ve 100’ den küçükse bunu da söyleyen bir yapıyı
oluşturalım.
#include<stdio.h>
int main (void)
{
int girilen sayı;
printf(“Lütfen bir tam sayı giriniz>”);
scanf(“%d”,&girilen_sayi);
if( girilen_sayi>100)
printf(“Girilen sayı 100’den büyüktür\n”);
else
printf(“Girilen sayı 100’den küçüktür\n”);
return 0;
}
Örnekte gördüğümüz gibi, bir koşulun doğruluğunu program
kontrol ediyor ve buna doğru olursa, bazı işlemler yapıyor. Şayet
verilen koşul yanlışsa o zaman daha başka bir işlem yapıyor. Ancak
ikisini de yapması gibi bir durum söz konusu değildir. Aşağıdaki
akış diyagramlarında (floxchart) her iki durumu da görebilirsiniz.
İlişkisel (Relational) Operatörler
Koşullu operatörlerde koşulun doğruluğunu kontrol ederken
kullandığımız ilişkisel operatörler aşağıda verilmiştir:
<
>
==
<=
>=
!=
Küçüktür
Büyüktür
Eşittir
Küçük eşittir
Büyük eşittir
Eşit değildir
Birleşik (Compound) Operatörler
Bazı durumlarda, kontrol edeceğimiz koşul, tek bir parametreye
bağlı değildir. Örneğin, bir kişinin yaşının 65’ ten küçük olup
olmadığına bakabiliriz. Ama 65’ ten küçük ve 18 yaşından büyük
olup olmadığına karar vermek istersek, o zaman birleşik/birleştirici
operatörler kullanmamız uygun olacaktır.
Compound operatörler aşağıdaki gibidir:
&&
II
!
and
or
not
ve
veya
tersi
Bu operatörlerin mantıksal (logical) doğruluk tablosu da şu
şekildedir:
p
0
0
1
1
q
0
1
0
1
p&&q
0
0
0
1
pIIq
0
1
1
1
!p
1
1
0
0
İç İçe geçmiş ( Nested) ifadeler
Daha önce ki kısımlarda koşullu ifadeleri görmüştük.
Hatırlatmak için tekrar edersek, if ile bir ifadeyi kontrol
ediyor ve doğruysa buna göre işlemler yapıyorduk. Bir de
if-else yapısı vardı. İf-else yapısında da koşulu gene
kontrol ediyor doğruysa if bloğunun altında kalanları
yapıyorduk; yanlışsa else bloğunda olan kodlar işleme
alınıyordu. Son derece basit bir mantıkla kurulmuş bu
yapıyla yapılamayacak kontrol yoktur, ancak böyle
durumlar da vardır ki if-else yapısı yeterli verimliliği
sunamaz.
Diyelim ki birden fazla kontrol etmeniz gereken bir
durum oluştu. Hatta örnek vererek konuyu daha
somutlaştıralım. İstenilen bir programda klavyeden
size yaş bilgisi veriliyor. Siz de bu bilgiye göre yaş 18’
den küçükse çocuk, 18-30 yaş arası genç, 30-50 orta
yaş diye bir mesaj bastırıyorsunuz.
Şimdi bunu sadece if yapısıyla kuruyor olsaydık her
seferinde yaşın uygun aralıklara düşüp düşmediğini
kontrol eder ve ona göre sonucu ekrana bastırırdık. Ama
bu son derece verimsiz bir yöntem olurdu. Çünkü zaten
yaş bilgisinin genç olduğuna dair bir karar vermişsek
sonrasında bunu yaşlı olup olmadığını kontrol etmenin
bir anlamı olmayacaktır.
İf-else if merdiveni
İf-else if merdiveni doğru bir şey bulduğu zaman
kontrolü orada keser ve diğer koşulları kontrol etmeden
blok sonlandırılır. Aşağıda bu yapının akış diyagramını
bulabilirsiniz:
İf-else if yapısı
İf (koşul 1) {
Komut(lar) 1
}
Else if (koşul 2) {
Komut(lar) 2
}
.
.
.
Else if (koşul n) {
Komut(lar) n
}
Else {
Komut(lar) n
}
if-else if akış diyagramı
İf-else if ile söylenebilecek son bir şey sonundaki else dir.
Else koymak zorunlu değildir. Ancak hiçbir koşula
uymayan durumla karşılaştığınızda, else devreye girer.
Örneğin yukarıda anlatıp kodunu vermiş olduğumuz
programda, belirtilen yaş aralıklarında değer girilmezse
hiçbir şey ekrana bastırılmayacaktır. Çünkü programa
tanınmayan yaş aralığında ne yapılacağı öğretilmemiştir.
Şimdi bu durumu da içerecek şekilde programımızı if-else
if yapısıyla yazalım:
#include<stdio.h>
int main (void)
{
int girilen_yas;
printf(“lütfen yaşınızı giriniz>”);
scanf(“%d”, &girilen_yas);
if(girilen_yas < 18)
printf(“Daha çocuk yaştasınız, hayatın başındasınız.\n”);
else if (girilen_yas> 18 && grilen_yas <= 30 )
printf(“Gençliğin güzelliğin başka!\n”);
else if (girilen_yas> 30 && grilen_yas <= 50 )
printf(“Hepsini boşverin, olgunluk orta yaşta
başlar!\n”);
else
printf(“HATA: Girilen yaş tanımlı değildir!\n”);
return 0
}
Switch-case
İf-else if yapısına oldukça benzerdir. Ancak aralarında iki
fark vardır. Birincisi bu yapıda aralık değeri girmezsiniz.
Direkt olarak ifadelerin bir şeylere eşit olup olmadığına
bakarsınız. İkinci farksa switch-case yapılarında illa ki
uygun koşulun sağlanmasıyla yapının kesilmek zorunda
olmayışıdır. “break” komutu kullanmadığınız taktirde diğer
şartların içindeki işlemleri de yapma imkanınız olabilir.
Switch-case en tepeden başlayarak şartları tek tek kontrol
eder.
Uygun şart yakalanırsa bundan sonraki ifadeleri kontrol
etmeden doğru kabul eder. Ve şayet siz break
koymamışsanız eşitlik uygun olsun olmasın alt tarafta
kalan case lere ait komutlarda çalıştırılacaktır. İf-else if ise
daha önce söylemiş olduğumuz gibi böyle değildir. Uygun
koşul sağlandığında yapı dışına çıkılır.
switch case yapısındaki durumu aşağıdaki tabloda
görebilirsiniz.
switch (değişken) {
casesabit 1:
komut(lar)
[break]
casesabit 2:
komut(lar) 1
[break]
.
.
casesabit N
komut(lar)
[break]
default:
komut(lar);
}
Switch case akış diyagramı
Yapı olarak şimdiye kadar görmüş olduğumuz if else
gibi gözükmese de bir örnekten sonra arasında pek
fark olmadığını göreceksiniz. Her komut sonunda
koyulan break komutu zorunlu değildir ve o yüzden
köşeli parantezle belirtilmiştir. Break koyduğunuz
taktirde uygun koşul sağlandıktan sonra daha fazla
kontrol yapılmayacak ve aynen if-else if yapısında
olduğu gibi program orada kesilecektir.
Ama break koymazsanız altında kalan bütün işlemler bir
sonra ki break’ a kadar yapılacaktır.
Kodun sonunda görmüş olduğunuz default komutu if-else
if yapısında ki sonuncu else gibidir. Uygun hiçbir şart
bulunamazsa default komutu çalışır.
Şimdi bir örnekle pekiştirelim: Bir not değerlendirme
sistemi olsun. 100-90 arası A, 89-80 arası B, 79-70 arası C,
69-60 arası D, 59 ve altıysa F olsun. Eğer 100’ den büyük
veya negatif bir sayı girilirse, o zaman program hatalı bir
giriş yapıldığı konusunda bizleri uyarsın. Bunu şimdiye
kadar öğrendiğimiz bilgilerle if-else if yapısını kullanarak
rahatlıkla yanıtlayabilirsiniz. Ama şu an konumuz switchcase olduğundan aşağıda bunun cevabını öyle verelim.
#include<stdio.h>
int main (void)
{
int not;
printf(“Lütfen notu giriniz>”);
scanf(“%d”,&not);
switch (not / 10 ) {
case 10:
case 9: printf (“NOT: A\n); break;
case 8: printf (“NOT: A\n); break;
case 7: printf (“NOT: A\n); break;
case 6: printf (“NOT: A\n); break;
case 5:
case 4:
case 3:
case 2:
case 1:
case 0: printf (“NOT: F\n); break;
default:
printf(“HATA: Bilinmeyen bir değer girdiniz!\n”);
}
return 0
}
Algoritmaya bakalım: Önce sayıyı alıyor ve 10’ a
bölüyoruz. Yani girilen not 5 ise 5.7 sonucunu elde
ediyoruz. Ancak iki tam sayının sonucu bir virgüllü sayı
veremez, tıpkı işleme giren değişkenler gibi tam sayı
olarak döner. Dolayısıyla bilgisayarı elde edeceği sonuç 5.7
değil sadece 5’ tir. Switch cae yapısında koşullar yukarıdan
başlayarak kontrol ediliyor. Case 5’ e gelindiğinde eşitlik
sağlanıyor. Ama break olmadığından case 0’ a kadar bu
böyle sürüyor. Ve case 0’ da ekrana bie çıktı alıp sawitch
case yapısı break ile sonlandırılmaktadır.
Switch-case if-else if yapısının sunduğu esnekliğe sahip
değildir. Daha çok menü olarak sunulacak işlerde kullanılır.
Örneğin unix’ in ünlü listeleme komutu ls içerisinde verilen
parametrelerin
kontrolü
switch
case
kullanılarak
sağlanmıştır. Open solaris, Free BSD veya Linux kodlarını
incelerseniz bunun gibi yüzlerce örnek bulabilirsiniz.
Artırma (Increment) ve azaltma (decrement) işlemleri
Daha önce ki bölümlerde aritmetik işlemlerden bahsetmiştik.
Bunların dışında yapabileceğimiz şeylerden biri artırma ve azaltma
işlemleridir.
Eğer i adında bir değişkenin değerini bir artırmak isterseniz, i=i+1
olarak yazarsınız. Veya 1 azaltmak isterseniz benzer şekilde i=i-1 de
yazabilirsiniz. Artırma ve azaltma işlemleri bu olayı daha basit bir
forma sokmaktadır. İ=i+1 yerine i++ veya i=i-1 yerine i—
yazabilirsiniz.
Artırma ve azaltma işlemleri temelde iki çeşittir. Birinci
yöntemde yukarıda yazdığımız gibi artırma /azaltma
sonradan yapılır. İkinci yöntemdeyse artırma/azaltma ilk
başta yapılır. Şimdi aşağıdaki örneklere bakalım:
/*
Bu programda artırma ve azaltma
işlemleri önce yapılacaktır.
*/
#include < stdio.h>
int main (void)
{
int i =10, j=60;
printf(“i=%d ve j=%d\n”, ++i, --j);
return 0
}
Yukarıda programı yazar ve çalıştırırsanız elde edeceğiniz
çıktı şu şekilde görünecektir:
i = 11 ve j= 59
Çünkü artırma ve azaltma işlemleri ekrana bastırmadan
önce yapılmış ve i ve j’ nin değerleri değiştirilmiştir. Şimdi
programı değiştirip öyle yazalım:
/*
Bu programda artırma ve azaltma
işlemleri sonra yapılacaktır.
*/
#include < stdio.h>
int main (void)
{
int i =10, j=60;
printf(“i=%d ve j=%d\n”, ++i, --j);
return 0
}
Bu defa da programın çıktısı şöyle olacaktır:
i = 10 ve j = 60
Burada hiçbir değişiklik yapılmamış gibi duruyor. Aslında
değişiklik yapıldı ve program sonlanmadan önce i 10
olurken, j 59 oldu. Ama artırma ve azaltma işlemleri
printf komutu çalıştırıldıktan sonra yapıldığı için, bir
değişiklik göremedik.
Kısacası önce artırma (pre-increment) veya önce azaltma
(pre-decrement) kullandığınızda ilgili komut satırında
çalışacak ilk şey bu komutlar olur. Ancak sonra artırma
(post increment) veya sonra azaltma kullaırsanız o zaman
bu işlemlerin etkileri ilgili komut satırından sonra geçerli
olacaktır. Aşağıdaki özel tabloyu inceleyelim:
Form Tip
i++
postfix
++i
i--
prefix
postfix
--i
prefix
İsim
postincrement
pre-increment
postdecrement
predecrement
Açıklama
İşlem sonrası artırma
İşlem öncesi artırma
İşlem
sonrası
azaltma
İşlem öncesi azaltma
Gelişmiş atama (Advanced Assignment) yöntemleri
C’ de yazım kolaylığı amacıyla sunulmuş bir başka
konu da gelişmiş aşama yöntemleridir. Biraz daha uzun
yazacağınız kodu kısaltmanıza yaramaktadır.
degisken_1= degisken_1 (operator)degisken_2
şeklinde yazacağınız ifadeleri daha kısa yazabilmeniz için
degisken_1 (operator) = degisken_2 şeklinde ifade
edebilirsiniz.
Gelişmiş atamalarda sunulan genel formlar şu şekildedir:
+-, -= , *= , /= , %=
Sanırım aşağıdaki örneklere bakarsanız, konuyu çok daha net
anlayacaksınız:
1-) j= j*(3+x)  j* =( 3+ x)
2-) a = a/ (5 – z)  a/ = (5 –z)
3-) x = x -5  x -= 5
Conditional Operatörler (?)
Koşullu operatörlerdir. Bu operatör if-else ile aynı
yapıdadır. Hiçbir farkı yoktur. Tek farkı koda bakıldığında
anlaşılmasının biraz daha zor oluşudur. Bir de if-else gibi
yazıyla ifade edilmez. Onun yerine soru işareti (?) ve iki
nokta üst üste ( : ) kullanarak yazarız.
Aşağıdaki tabloda if-else yapısıyla karşılaştırılmalı olarak
conditional operatör verilmiştir:
İf-else yapısı
if (koşul ) {
if_komut(lar)
}
else {
else_komut(lar)
}
Conditional operatör yapısı
Koşul?if_komut(lar):else_komutlar
Conditional operatör (?) akış diyagramı
Şimdi aynı programı, hem if-else, hem de conditional operatör
kullanarak yazalım:
/*
girilen tam sayının
10’ dan büyük olup
olmadığını gösteren
program
*/
#include<stdio.h>
int main ( void )
{
int sayi;
printf(“lütfen bir sayı giriniz>”);
scanf( “%d”, &sayi);
if ( sayi > 10 )
printf(“sayı 10’dan büyüktür\n”);
else
printf (“sayı 10’ dan küçüktür veya 10’a eşittir\n”);
return 0;
}
Aynı programı conditional operatör kullanarak
yazalım:
Görüldüğü üzere program biraz daha kısaldı.
/*
girilen tam sayının
10’ dan büyük olup
olmadığını gösteren
program
*/
#include<stdio.h>
int main ( void )
{
int sayi;
printf(“lütfen bir sayı giriniz>”);
scanf( “%d”, &sayi);
( sayi > 10 )? printf(“sayı 10’dan büyüktür\n”):
printf (“sayı 10’ dan küçüktür veya 10’a
eşittir\n”);
return 0;
}
Döngü Kavramı
Programlama konusunda –hangi dil olursa olsun- en
kritik yapılardan biri döngülerdir. Döngüler bir işi
belirlediğiniz
sayıda
yapan
kod
blokları
olarak
düşünülebilir. Ekrana 10 kere “Merhaba Dünya” yazan
programda “Merhaba dünya” yazdıran kodu aslında
tek bir defa yazarsınız, döngü burada devreye girip
sizin için bu kodu istediğiniz sayıda tekrarlar.
Döngüleri bu kadar kritik yapan unsur; iyi yazılıp optimize
edilmediği taktirde bilgisayarınızın işlem gücünü gereksiz
yere tüketmesi ve harcanan zamanı artırmasıdır. Benzer
şekilde
iyi
çalıştıracaktır.
yazılmış
bir
döngü
programınızı
hızlı
Bütün döngüler temelde iki aşamayla özetlenebilir.
Aşamalardan biri döngünün devam edip etmeyeceğine
karar verilen mantıksal sorgu kısmıdır. Örneğin ekrana 10
kere “Merhaba dünya” yazdıracaksanız kaçıncı seferde
olduğunu koşul kısmında kontrol edersiniz. Diğer aşama
döngünün ne yapacağını yazdığınız kısımdır. Yani ekrana
“Merhaba Dünya” yazılması döngünün yapacağı iştir.
Döngünün devam edip etmeyeceğine karar verilen
aşamada hatalı bir mantık sınaması koyarsanız, ya
programınız hiç çalışmaz ya da sonsuza kadar
çalışabilir.
C programlama diline ait bazı döngüler; while,
do while, for yapılarıdır. Bunlar dışında goto döngü
elemanı olmasına rağmen kullanılması pek tavsiye
edilmemektedir.
While döngüsü
While döngüsü en temel döngü tipimizdir. Bir kontrol
ifadesiyle döngünün devam edilip edilmeyeceği kontrol
edilirken, scope içinde (yani ayraç işaretleri arasında)
kalan bütün alan işleme sokulur. İşleme sokulan kod kısmı
döngü yapılacak adet kadar tekrar eder.
While döngüsünün genel yapısını ve akış şemasını
aşağıda görebilirsiniz:
While
while( koşul ) {
Komut(lar)
}
While akış diyagramı
Yukarıda 10 kere ekrana “Merhaba dünya” yazan
programdan bahsettik. Gelin bir anlaşma yapalım ve
döngülerle alakalı bütün ilk örnekler de bu programın nasıl
yazılacağını göstersin.
While
döngüsü
kullanarak,
ekrana
10
“Merhaba dünya” yazan program aşağıdaki gibidir:
kere
/*
Ekrana 10 kere “Merhaba Dünya”
Yazan program
*/
#include<stdio.h>
int main (void)
{
//i değişkenine bir başlangıç değeri atıyoruz.
//i’ ye ilk değer atanmazsa döngümüz yanlış çalışır.
int i= 0;
//i’ nin değeri kontrol işleminden
//sonra 1 artar.
while( i++ < 10){
// 2d bir tam sayının yazdırılacağı
//ancak bu sayı tek rakamdan oluşsa da
//2 rakamlık yer ayrılmasını belirtir.
printf( “ %2d: Merhaba Dünya\n”,i);
}
Return 0;
}
Yukarıdaki program aslında son derece basittir. İ değişkenine ilk
değer olarak 0 atıyoruz. Daha sonra, while döngüsüne başlıyoruz.
İfadenin doğruluğu (yani i’ nin 10’ dan küçük olup olmadığı) kontrol
ediliyor. Eğer doğruysa, döngü içindeki kodların çalışması
başlatılıyor. Elbette kodların başlamasından bir önce ki adımda i
değişkeni artırılıyor. (Önceki kısımda anlatmış olduğumuz postincrement işlemini hatırlayın. Bu yapı toplamda 10 kere tekrar
ediyor ve en sonunda i’nin değeri 10’ a eşit olunca döngü
sonlandırılıyor.
işlemi basit bir toplama ifadesidir. Bu ifadede
n değerini kullanıcıdan alacağımızı düşünerek bir program
yazalım. Bu program, alacağı n değerine göre kendisine
kadar olan sayıların karelerinin toplamını gösterecektir. Bu
programı yazarsak;
#include<stdio.h>
int main ( void )
{
int i= 0, toplam_deger=0;
int n;
printf(“lütfen n değerini giriniz>”);
scanf(“&d”,&n);
while ( i<=n) {
toplam_deger += i*i;
i++;
}
printf(“sonuç:&d\n”,toplam_deger);
return 0;
}
do while döngüsü
Göreceğimiz
ikinci
döngü
çeşidi,
do
while
döngüsüdür. Yaptığı iş while ile hemen hemen aynıdır.
Verilen işi döngü koşulu bozulana kadar sürdürür. Ancak
while’ a göre önemli bir farkı vardır.
While döngülerinde döngü içerisinde işlem yapmadan önce
sunulan koşul kontrol edilir. Şayet koşul sağlanmıyorsa o while
döngüsünün hiç çalışmama ihtimali de vardır. Do while
döngülerindeyse durum böyle değildir. İlk çalışmada koşul
kontrolü yapılmaz. Dolayısıyla her ne şartta olursa olsun
döngünüz en azından bir kere çalışacaktır.
Bazı durumlarda döngü bloğu içerisindeki kodların en
azından bir kere çalışması gerektiğinden do while yapısı kullanılır.
Do while ile ilgili genel yapıyı ve akış şemasını aşağıda
bulabilirsiniz:
Do while yapısı
do {
komut(lar)
} while ( koşul );
Do while akış diyagramı
#include<stdio.h>
int main ( void )
{
int i= 0;
do {
// önce i’ nin değeri artırılıyor
//sonra ekrana Merhaba Dünya yazdırılıyor.
printf( “%2d: Merhaba Dünya\”, ++i);
} while ( i < 10 );
}
Gördüğümüz gibi bir önceki örneğimize oldukça benzer bir
yapıda yazıldı. Tek fark i’ nin değeri 0’da olsa 1000 de olsa
en azından bir kez Merhaba Dünya nın yazılacak olmasıdır.
Ancak while de kontrol önce yapıldığı için hiçbir şey
ekrana yazılmaz.
Şimdi do while kullanılmasının daha mantıklı olacağı
bir program yapalım. Kullanıcıdan iki sayı alınsın. Bu iki
sayı toplandıktan sonra sonucu ekrana yazdırılsın.
Yazdırma sonunda “devam ettirmek istiyor musunuz”
sorusu sorulsun ve klavyeden “E” veya “e”
karakterlerinden birisi girilirse programa devam
edilsin. Yok farklı bir şey girilirse, program
sonlandırılsın.
Örnek
programımızı
aşağıda
bulabilirsiniz:
#include<stdio.h>
int main ( void )
{
int sayi_1, sayi_2;
char devam_mi;
do {
printf(“Birinci sayıyı giriniz>”);
scanf(“%d”,&sayi_1);
printf(“İkinci sayıyı giriniz>”);
scanf(“&d”,&sayi_2);
printf(“%d+%d = d\n”, sayi_1, sayi_2, sayi_1 + sayi_2);
printf(“Devam etmek ister misiniz?”);
//C’ de tek karakter okuma işlemi biraz sıkıntılı
//olduğundan, burada da bir do while kullandık.
do {
scanf (“%c”,&devam_mi);
} while ( devam_mi == ‘\n’ );
printf (“\n”);
} while ( devam_mi == ‘E’ I I devam_mi == ‘e’ );
return 0;
}
Program, kullanıcıdan iki sayı alıp, toplamını ekrana
bastıktan
sonra,
yeniden
işlem
yapıp
yapmak
istemediğimiz sormaktadır. Bu programı while ile de
yazabilirdik. Ancak while ile yazabilmek için, devam_mi
değişkenine
önceden
‘E’
değerini
atamamız
gerekmekteydi. Do while döngüsündeyse bu zorunluluğa
gerek kalmamıştır.
Not: Yukarıdaki programda fark etmiş olduğunuz gibi
karakter okumayı biraz farklı yaptık. Normalde scanf
fonksiyonunu kullanmak yeterliyken burada işin içine bir
de do while girdi. Açıklayacak olursak C’ de karakter
okumaları biraz sıkıntılıdır. Eğer giriş tampon belleğinde
(Buffer) veri bulunuyorsa bu direk karaktere atanır.
Bundan kurtulmak için birçok yöntem olduğu gibi
uygulanabilecek bir yöntem de yukarıda yazılmış olan
döngü şeklinde değer almaktır.
Çünkü siz daha bir şey girmeden ilk değer ‘\n’
geleceğinden döngünün ikinci çalışmasında doğru değer
atanacaktır. İleri ki konularda daha detaylı ele alacağımız
bir problem olarak şimdilik önemsemeyelim. Sadece
karakter okuyacağımız zaman problem çıkarsa yukarıdaki
gibi bir yöntem uygulanabileceğini bilmeniz şimdilik
yeterlidir.
for döngüsü
while ve do while dışında üçüncü bir döngü tipi olarak
for yapısı bulunmaktadır. Diğer iki döngüden farklı olarak
for yapısı yenilemeli tekrarlamalı (İngilizce iterative)
yapılarda kullanıma daha uygundur. Bu performans
anlamında değildir. Söylenmek istenen yazım tekniği
olarak for döngüsünün daha kullanışlı olmasıdır.
Örneğin birbirini sürekli tekrar eden işlemlerin yapıldığı
nümerik analiz gibi alanlar for döngüsü için iyi bir örnek
olabilir. Ancak bu söylenenler yanıltıcı olmamalıdır; for
döngüsü sadece soyut alanlarda çalışsın diye yaratılmış
bir şey değildir.
Programlarda diğer iki döngüden çok daha fazla for
kullanırsınız. Çünkü for sadece matematiksel hesaplama
işlemlerinde değil diziler gibi konularda sürekli kullanılan
bir yapıdır. Yazımı diğerlerine nazaran daha sade
olduğundan iteratif işlemlerde kullanılması daha uygun
olacaktır.
Aşağıda for döngüsünün genel yazımını ve akış
diyagramını göreceksiniz:
for yapısı
for
(ilk_deger_atama;
arttırma/azaltma) {
komutlar(lar)
}
koşul
;
for akış diyagramı
Şimdi ekrana 10 kere “merhaba dünya” yazdıralım.
#include<stdio.h>
int main( void )
{
int i;
for ( i = 0; i< 10; i++ ) {
printf (“%2d: merhaba dünya\n”, (i+1));
}
return 0;
}
Gördüğünüz gibi çok daha sade ve açık gözükür bir kod
oldu. For altında tek satır komut olduğundan, küme
parantezleri koymamız opsiyoneldi ama ne yaptığınızı
karıştırmamak
önerilmektedir.
için,
her
zaman
koymamız
For döngüleriyle ilgili bazı özel durumlarda vardır. For
döngüsü içerisine yazdığınız ilk değer atama, kontrol ve
artırma işlemlerini tanımlama esnasında yapmanız
gerekmez. Aşağıda verilen kod, yukarıdakiyle tamamen
aynı işi yapar. Farkı, i’ ni daha önce tanımlanmış olması
ve arttırma/azaltma işinin döngü içinde yağılmasıdır.
#include<stdio.h>
int main( void )
{
int i;
for ( i = 0; i< 10; ) {
printf (“%2d: Merhaba Dünya\n”, (i+1));
i= i + 1;
}
return 0;
}
break Komutu
Bazı durumlarda, döngüyü aniden sonlandırmak
isteriz. Bunun için ‘break’ komutunu kullanırız. Döngüyü
aniden sonlandırmak veya döngüyü kırmak işlemini,
zaten daha önce switch case’ lerde kullanmıştık ve bu
her döngü içerisinde kullanılabilir.
/*
0 ile 99 arasında tesadüfi sayılar üreten
Bir programın, kaçıncı seferde 61 sayısını
Bulacağını yazan program aşağıdadır.
*/
#include<stdio.h>
int main( void )
{
int i; tesadüfi_sayi;
int deneme_sayisi= 0;
//while içinde 1 olduğundan sonsuza kadar döngü çalışır.
While ( 1 ) {
//tesadüfi_sayi değişkenine, 0 ile 99 arasında
//her seferinde farklı bir sayı atanır.
//rand ( )fonksiyonu tesadüfi sayı atamaya yarar.
// mod 100 işlemiyse atanacak sayının 0 ile 99
// arasında olmasını garantiler.
tesadüfi_sayi= rand ( ) % 100;
//Döngünün kaç defa çalıştığını deneme_sayisi
//değişkeniyle buluruz.
deneme_sayisi++;
//Eğer tesadüfi sayı 61’ e eşit olursa,
//döngü kırılıp sonlandırılır.
İf ( tesadüfi_sayi == 61) break;
}
printf( “ Toplam deneme sayısı: %d\n”, deneme_sayisi);
return 0;
}
Program için koyulmuş açıklamalar (comment) zaten
n’ yi açıklamaktadır. Kısaca bir şeyler eklemek
gerekirse bitişinin nerede olacağını bilmediğimiz bir
döngüyü ancak break komutuyla sonlandırabiliriz.
Şartlar sağlandığında break komutu devreye girer ve
döngü sonlandırılır.
7 mayıs
continue komutu
break
olduğundan
komutunun
döngüyü
bahsetmiştik.
Bunun
kırmak
dışında
için
işlem
yapmadan döngüyü devam ettirmek gibi durumlara da
ihtiyacımız vardır. Bunun içinde continue (Türkçe:devam)
komutunu kullanırız.
/*
Sadece tek sayıları yazdıran bir
Program
*/
#include <stdio.h>
for( i = 0; i< 10; i++) {
// i değişkeninin 2’ ye göre modu
// 0 sonucunu veriyorsa, bu onun
// bir çift sayı olduğunu gösterir.
//Bu durumda ekrana yazdırılmaması
// için döngü bir sonra ki adıma geçer.
if( i%2 == 0) continue;
printf(“%2d\n”, i);
}
return 0;
}
0 ile 10 arasındaki tek sayıları gösteren program örneğini
yukarıda görebilirsiniz. Elbette ki bu işi daha farklı ve
daha iyi yapan bir program yazabilirdik. Ama şimdilik
continue komutunun nasıl kullanıldığını inceleyelim.
Program bir for döngüsü çalıştırmaktadır. Her defasında i
değişkenin 2’ ye göre modu alınır. Eğer sonuç 0’ sa bu
sayının çift olduğunu gösterir. Dolayısıyla, bu ekrana
yazdırılmaması gerekir. Bu yüzden döngü içerisindeki
işlemleri sürdürmek yerine altta kalan kodları atlarız.
Burada continue komutu kullanılır ve kullanıldığı
noktadan itibaren olan işlemler yapılmaz. Döngü başa
döner, aynı işlemleri yapar. Bu sefer i tek sayı
olacağından continue komutu çalışmaz ve sayıyı ekrana
bastırmış oluruz.
Goto Yapısı
C programlama dilinde bulunan bir başka yapı,
goto
deyimidir.
programın
bir
Koyacağınız
noktasından
etiketler
bir
başka
sayesinde,
noktasına
atlamanızı sağlar. Goto, bir döngü değildir ancak döngü
olarak kullanılabilir.
“goto” , çalışabilmek için etiketlere ihtiyaç duyar. Etiketler,
vereceğiniz herhangi bir isme sahip olabilir. Etiket
oluşturmak için bütün yapmanız gereken; etiket adını
belirleyip, sonuna iki nokta üst üste eklemek ( : ) ve
programın herhangi bir yerine bunu yazmaktır. Goto
deyimi kullanarak bu etiketleri çağırırsanız, etiketin
altında bulunan kodlardan devam edilir. Goto ve
etiketlere dair genel yapıyı, akış diyagramıyla birlikte
aşağıda bulabilirsiniz:
Goto yapısı
Label_name;
.
.
.
İf( kosul) {
Goto label_name
}
.
.
.
NOT: “goto” deyimi tek başına da kullanılabilir. Fakat mantıksal
bir sınama olmadan goto yapısını kullanmanızkullanmanız,
sonsuz döngüye neden olacaktır.
Şimdi goto ifadesiyle basit bir döngü örneği oluşturalım. Önceki seferlerde
olduğu gibi ekrana 10 defa “Merhaba Dünya” yazdıralım:
#include<stdio.h>
int main( void )
{
int i = 0;
// baslangıc_noktasi adında bir etiket koyuyoruz.
//i degiskeni 10 degerine ulasmadigi surece,
//program buraya donecektir.
Baslangic_noktasi
printf (“Merhaba Dünya\n”);
// i degerini arttiriyoruz.
İ++;
// i degeri kontrol ediliyor. Sayet 10’ dan kucukse,
// en basa donuyor.
if ( i< 10) goto baslangıc_noktasi;
return 0;
}
İstediğiniz
sayıda
etiket
programın
herhangi
bir
koyup,
goto
noktasına
kullanarak,
ulaşabilirsiniz.
Programınız, etiket altında kalan kısımdan itibaren
çalışır. Goto yapısıyla gelen esneklik ilk bakışta oldukça
güzel görünüyor. Ancak goto için birçok kaynak, “ya hiç
kullanmayın yada olabildiğince az kullanın” demektedir.
Okunup, anlaşılması zor ve üzerinde çalışılması güç bir
koddan, herkesin uzak durması gerekir. İngilizce’ de
karmaşık/komplex bir koda, “spagetti kod” denmektedir.
Goto deyimi, kodunuzun spagetti koda dönüşmesine
neden olur. Çünkü program akışının takibini zorlaştırıp,
kodun okunabilirliğini azaltır. İsterseniz goto deyimi
kullanabilirsiniz. Ama zorunlu olmadıkça kaçınmak en
iyisidir.

similar documents