1 Mart 2009 9031150 - Temel Bilgisayar Bilimleri Ders Notu #2 Referans: Bugün: 1. Ders Notları. C Programlamaya Giriş C dilinde genel olarak kullanılan komutlar ve ifadeler 1. Tekrar Geçen ders printf, scanf ve putchar komutlarını gördük. Basit Bir C Programı C dili hakkında önemli birçok özelliği gösteren basit bir program ile başlayalım. Bu program ekranda bir satırlık metin görüntüler. C Dilinde Basit Bir Toplama Programı /* Toplama programi */ # include <stdio.h> main() int tamsayi1, tamsayi2, top; /* bildirim */ printf( Ilk tamsayiyi girin\n ); /* uyari */ scanf( %d,&tamsayi1); /* bir tamsayi oku */ printf( Ikinci tamsayiyi girin\n );/* uyari */ scanf( %d,&tamsayi2); /* bir tamsayi oku */ top = tamsayi1 + tamsayi2; /* top atamasi */ printf( Toplam %d\n, top);; /* top goruntule */ return 0; 2. putchar Kullanıcıdan bir tek karakter almak amacıyla kullanılır. ch değişkeninin daha önceden char ch; olarak tanımlandığını varsayarsak ch = getchar(); 3. printf ortalama değişkeninin 3.5758 olduğunu varsayarsak printf ( %f,ortalama); ifadesinin ekran çıktısı 3.5758
2 olacaktır. printf ( %.3f,ortalama); ifadesinin çıktısı ile ondalık değerlerden ilk üç tanesini görüntüleyerek 3.575 olacaktır. Aynı mantıkla, printf ( %.0f,ortalama); ifadesi ekrana tamsayı özelliğinde bir sayı görüntüleyecektir. Değişkenlerin tipleri ve tanımlanması unsigned char: C dilinde tanımlanan en küçük değişken tipidir. İşaretsiz sayıları tanımlar. 0 ile 255 arasındaki tüm sayılar yazılabilir. char: Bellekte 1 baytlık alan kaplar. Negatif sayıları da tanımlar. 1/0 Birinci alanda 1 varsa sayı negatif, 0 varsa sayı pozitiftir. Char ile yazılabilecek en küçük sayı -128 ve en büyük sayı 127 dir. unsigned short int: Hafızada 2 bayt lık (16 bit lik) alan kaplar. Yazılabilecek en küçük sayı 0, en büyük sayı 65535 dir. short int: En soldaki bit i işaret biti olmak üzere 2 bayt lık (16 bit lik) alan kaplar. Yazılabilecek en küçük sayı -32768, en büyük sayı 32767 dir. unsigned int: Hafızada 4 bayt lık (32 bit lik) alan kaplar. int: Hafızada 4 bayt lık (32 bit lik) alan kaplar. Yazılabilecek en küçük sayı -2 milyar, en büyük sayı 2 milyardır. float: Hafızada 4 baytlık (32 bit lik) alan kaplar. Hepsi işaretlidir. Unsigned şekilde bulunmaz. double: 8 bayt lık (64 bit lik) alan kaplar. long double: 10 bayt lık (80 bit lik) alan kaplar. Örneğin bir programda tamsayı top ve n değişkenleri kullanılacak olsun. Bu değişkenlerin main fonksiyonundan önce deklare edilmesi gerektiğini öğrenmiştir. Öyleyse: int sum; int n; ya da int sum, n; şeklinde bir bildirim yapabiliriz.
3 Daha sonra bu ifadelerin oranını almak istediğimizde bolum adlı bir değişkene bu iki sayının birbirine oranını aşağıdaki şekilde atayabiliriz: (Bildirime float bolum; eklendiğini varsayarsak) bolum = toplam/n; HATIRLATMA: Atama işlemi sağdan sola doğru işlem görür. Yukarıdaki ifade doğru sonucu vermeyecektir. Çünkü bir çok aritmetik işlemde geçerli olduğu gibi, bölme işlemi de C dilinde float sonuç döndürür. Bu nedenle yukarıdaki bölme işleminin sonucunu doğru olarak bulabilmek amacıyla iki farklı yöntem uygulanabilir: Kısaca int = float dönüşümleri bilgisayarda depolanamaz. 1. Bildirimde değişiklik yapılması float sum; float n; ya da float sum, n; şeklinde bir bildirim yapabiliriz. Daha sonra: (Bildirime float bolum; eklendiğini varsayarsak) bolum = toplam/n; ifadesi doğru sonucu görüntüleyecektir. 2. Aritmetik işlemde tanımlama yapmak: int sum; int n; ya da int sum, n; şeklindeki bildirim aynı kalmak şartıyla: (Bildirime float bolum; eklendiğini varsayarsak) bolum = (float)toplam/n; ifadesi doğru sonucu görüntüleyecektir. ( ) terimine cast adı verilir. Her zaman parantez içerisinde gösterilir. Herhangi iki sayının bellekteki yerlerini değiştiren program yapısı nasıl olur? #include <stdio.h> main() int a, b, c; a=7, b=8; c=a; a=b; b=c; printf( %d %d, a, b); a 7 8 c 7 b 8 7 return 0;
4 Herhangi iki sayının bellekteki değerlerini, 3. bir değişken kullanmadan değiştiren program nasıldır? #include <stdio.h> main( ) int a, b; a=7, b=8; a = a + b; b = a b; a = a b; printf( %d %d, a, b); return 0; a 7 15 8 b 8 7 4. Mantıksal Operatörler VE (AND) && VEYA (OR) DEĞİL (NOT)! VE ifadesinde doğru sonuç olması için de her iki ifadenin de doğru olması gereklidir. Buna rağmen VEYA mantıksal operatöründe yalnızca bir adet ifadenin doğruluğu doğru sonucu döndürür (Bakınız Tablo 1 Tablo 2). 5. Atama İşlemcisi (=) Tablo 1 VE işlemcisinin sonuçları VE D Y D D Y Y Y Y Tablo 2 VEYA işlemcisinin sonuçları VEYA D Y D D D Y D Y Daha önceki dersten bildiğimiz gibi, atama işlemcisi sağdan sola işlem görür. Örneğin tamsayi1 değişkenine 2 değeri atamak istiyorsak: tamsayi1 = 2; İfadesi kullanılır. İlk olarak eşitliğin sağ tarafı işlem görür. 6. Artırma/Azaltma İşlemcileri
5 int i olarak bildirim yapıldığını varsayarsak i++; ifadesi her çevrimde i değişkenini 1 artıracaktır. i = i + 1; İfadesi de yukarıdaki ifade ile aynı işlemi yapar. i=10 varsayalım. printf( %d, ++i); ekrana 11 sayısını basar. (prefix) i=10 varsayalım. printf( %d, i++); ekrana 10 sayısını basar ve sayıyı 1 artırarak 11 değerine atar. (postfix) If kontrol ifadesi Kullanımı if (boolean ifadesi) blok ifadeler şeklindedir. if (a<b) a b den küçük ise if (x==10) x=10 ise if (n!= 0) n 0 a eşit değil ise if(a<b && a!=4) a b den küçük VE a 4 e eşit değil ise 0 yanlışı (FALSE) temsilen kullanılır. 1 doğruyu (TRUE) temsilen kullanılmaz. 0 dışında herhangi bir şey doğruyu temsilen kullanılır. x değişkeninin 10 olduğunu varsayarsak printf( %d, x); if(x==10) DOĞRU bir ifadedir. Blok ifadeler yalnızca if ifadeleri doğru ise işlem görmelidir. If bloğu yazılırken hizalamaya dikkat edilmelidir. If (boolean ifade) tek bir cumle; YANLIŞ If (boolean ifade) tek bir cumle; DOĞRU
6 Birden fazla cümle var ise: If (boolean ifade) ifade; ifade; ifade; Doğru formatlanmış bir if ifadesi aşağıdaki şekildedir: If (x<10) printf( x<10 ); scanf( %d,x); top = top + x; Yukarıdaki top = top + x; ifadesi kümülatif toplama yapar. Her döngüde top değişkenine x değişkeninin değerini atar. if(x%2 == 0) printf( x cift bir sayidir ); x+ = 2; printf( x degiskeni artirildi ); Neden küme parantezleri yazılmamış? Çünkü x+ = 2; İfadesinden itibaren if ifadesi doğru olsun ya da olmasın işlem görecektir. If Else ifadeleri Kullanım şekli: if (boolean ifadesi) ifade/blok; else ifade/blok; If ifadesi doğru ise bir şey yap, değil ise başka bir şey yap.
7 D If Y i bas i bas top if (i<10) printf( %d,i); else printf( %d,10); top = top + x; Bu küme parantez kullanımı doğrudur. if (i<10) printf( %d,i); else printf( %d,10); top = top + x; Bu küme parantezi kullanımı da kabul edilir. Küme parantezlerinin sırası if ifadelerinin yürütümünde büyük önem taşır. if (x==y) if (a>b) b *=2; else y=0; Yukarıdaki örnekte else ifadesi ilk if ifadesine aittir.
8 Aşağıdaki ifade bir önceki örnekle aynı değildir. if (x==y && a>b) b *=2; else y=0; if (boolean ifade1) blok1; else if (boolean ifade2) blok2; else if (boolean ifade3) blok3; else blok4; Eğer blok1 DOĞRU ise (TRUE) birinci blok yürütülür. Aksi taktirde tüm blok atlanır ve bir sonraki kontrol döngüsü kontrol edilir. blok4 her şart altında yürütülür. if (hiz > 100) ceza = 500; printf( Tutukla ); else if (hiz > 75) ceza = 200; printf( Uyari ); else if (hiz>55) ceza = 50; printf( Rusvet ver bana ); else printf( Yoldan cekil ); NOT: Kalın gösterilen küme işaretleri tercihe bağlıdır. Olmamaları halinde de program çalışacaktır. NOT 2: Yukarıdaki örnekte else ifadesi olmazsa ne olurdu? a, b ve c tam sayılarından en büyük olanını a değişkenine, en küçük olanı c değişkenine ve ortancayı b değişkenine atayan program nasıl olur? #include <stdio.h>
9 main () int a, b, c, d; a = 5 ; b = 11; c = 8; if (a<b) d = a; a = b; b = d; if (a<c) d = a; a = c; c = d; if (b<c) d = b; b = c; c = d; printf ( a = %d, b = %d, c = %d, a, b, c); return 0; Seçme kontrol teknikleri 1. switch Kullanımı: switch(degisken) olay değeri/etiket : s1; s2; s3; olay etiketi default s5; s6; :s1; :s4; default (varsayılan) olayın sonuna break konmasına genelde gerek yoktur. Fakat, iyi programcılık gereği daha sonra altına başka olayların eklenebilme olasılığına karşı küme parantezi iyi tercih edilen uygulamadır. switch komutu da if else gibi davranış gösterecektir. Fakat if-else ifadeleri her zaman switch ile değiştiremezsiniz. Çünkü switch komutu spesifik değerler kullanımını gerektirir. switch (shape) case t : case T : s1; s2; s3; case C : case c : s4; s5;
10 NOT: switch ifadesinde kullanılan değişken ordinal değişken olmalıdır. Diğer bir deyişle değişken karakter ya da tamsayı olmalıdır. Float (gerçek sayı) tipindeki değişkenler switch ifadesinde kullanılmaz. switch (not) /* notun icerigini kontrol et */ case 'A': case 'a': ort = 4.0; /* A = 4 puan */ case 'B': /* B = 3 puan */ case 'b': ort = 3.0; case 'C': /* C = 2 puan */ case 'c': ort = 2.0; case 'D': /* D = 1 puan */ case 'd': ort = 1.0; case 'F': /* F = 0 puan */ case 'f': ort = 0.0; default : gecerli_girdi = FALSE; /* degerlerde not yoksa not gecersizdir. */ /* switch ifadesini sonlandir */ Bu bloğun ait olduğu main fonksiyonu aşağıdaki gibidir: int main(void) /* main fonksiyonuna basla */ char not; /* harf not: A, B, C, D vs */ int gecerli_girdi = TRUE; /* boolean flag veya yanlis veri */ float ort; /* nota karsilik gelen sayi */ printf("ders notunu girin --> "); /* not girisi icin uyari */ not = getchar(); /* standart girdiden notu oku */ switch (not) /* notun icerigini control et */ case 'A': case 'a': ort = 4.0; /* A = 4 puan */ case 'B': /* B = 3 puan */ case 'b': ort = 3.0; case 'C': /* C = 2 puan */ case 'c': ort = 2.0; case 'D': /* D = 1 puan */ case 'd': ort = 1.0; case 'F': /* F = 0 puan */ case 'f': ort = 0.0;
11 default : gecerli_girdi = FALSE; /* degerlerde not yoksa not gecersizdir. */ /* switch ifadesini sonlandir */ Başlangıçta default değeri TRUE (DOĞRU) olarak tanımladığımızdan dolayı switch ifadesinde belirtilen değerlerden herhangi birisi doğru olduğu taktirde bloğun devamındaki ifadeler yürütülecektir. Aksi taktirde giriş yapılan değer geçersiz sayılacak ve programın yürütümü durdurulacaktır. if (gecerli deger) if ifadesinde eğer DOĞRU ise kullanılmaz. Tanım gereği yukarıdaki ifade gecerli deger ise demektir. Her zaman girdinin doğruluğu kontrol edilmez. Bazı durumlarda YANLIŞ girdinin kontrol edilmesi daha uygundur ( YANLIŞ girdinin sayısının daha az olduğu durumlarda) YANLIŞ ı test etmek için: if (! Gecerli girdi) if (x!= 2) Dosya sonuna (EOF end of file) ulaşılıp ulaşılmadığını test etmek için: c = getchar(); while (c!= EOF) printf( %c, toupper(c)); c = getchar(); EOF = Ctrl c ^c toupper(c) ctype kütüphanesinde yer alır ve girilen karakteri büyük harfe çevirir. Bu nedenle ifadeyi kullanmak için main fonksiyonundan önce programa #include <ctype.h> eklenmesi gereklidir. Aşağıdaki örnek yardımıyla bu uygulama döngünün daha kısa olabilir. while (c=getchar())!= EOF) printf( %c, toupper(c)); Bu ifadede atama daha önce meydana gelmelidir. Programlama Ödevi: Araba satıcılığı örneğine bir varsayımla başlayacağız: satacağımız araba tek tiptir ve bir binek arabası olacaktır (sedan). Bu arabanın çeşitli seçenekleri olacaktır: 2 ya da 4 kapılı, güneşlikli ya da güneşliksiz (sunroof), renk seçeneği, otomatik pencereler ve kilitler ya
12 da normal (manuel) pencere ve kilitler. Bu nedenle kullanıcıya toplam dört seçenek sunmalıyız. Satış elemanının potansiyel alıcıya sorabileceği soruları düşün. Yazacağınız program soruları soran satış elemanı olacaktır. Satın alıcı, müşteri ise klavyeden cevapları giren kimse olacaktır. Son seçimin yapılması için bazı temel kurallar vardır: 1. Sedan kırmızı, mavi ya da yeşil renkte üretilmektedir. 2. Yalnızca mavi ve kırmızı arabalarda güneşlik seçeneği vardır. Güneşlik yeşil renkteki sedanlarda mevcut değildir. 3. Yeşil ve kırmızı aralar hem 2-kapılı hem de 4-kapılı olabilir. Mavi arabalarda yalnızca 4- kapılı seçeneği vardır. 4. Tüm renklerde otomatik pencere ve kilit seçeneği vardır. Yazacağınız program kullanıcıya öncelikle ne renk araba istediğini sormalıdır. Rengin ilk harfini kullanın ( K, M, ya da Y). Bu seçimde kullanıcının büyük ya da küçük harfle yanıt girmesine olanak tanıyın. Bunu yapmanın en kolay yolu derste gördüğümüz toupper(c)makrosunu kullanmaktır. Bu makro harfi büyük harfe çevirecektir. Harf halihazırda büyük harfse işlem yapmayacaktır. Makroyu aşağıdaki şekilde kullanın: printf(kullaniciyi girdi icin uyarin...); /* musteriye uyari goruntule */ scanf("%c\n",&renk); /* musterinin secimini oku */ renk = toupper(renk); /* buyuk harfe cevir */ Daha sonra (müşterinin geçerli bir renk girdiğini varsayarsak) güneşlik hakkında bilgi almanız gerekir. Müşteri yeşil renkte araba seçerse güneşlik için hemen 'H' değeri atayabilirsiniz (Hayır anlamında). Daha sonra üç numaralı adıma geçin. Aksi taktirde, yani müşteri mavi ya da kırmızı renkte bir araba seçmişse güneşlik için değişkeni okutup kullanıcın E ya da H girmesini sağlayın. Daha önceki gibi bu değerleri de büyük harfe çevirin. Üçüncü adım olarak (daha önceki girdilerin doğru olduğunu varsayacak olursak) kapı sayısı hakkındaki bilgiyi elde etmeniz gerekir. Kullanıcı mavi renkli bir araba seçmişse kapı sayısını otomatik olarak 4 e atayın ve dördüncü adıma geçin. Eğer seçim maviden farklı ise (yeşil ya da kırmızı) kullanıcıya kaç kapılı araba istediğini sorun. Bu değer yasmayı 2 veya 4 olmalıdır. Bu nedenle büyük/küçük harf ile ilgilenmeniz gerekmez. Kullanıcı 2 veya 4 kapıdan farklı sayıda seçim yaparsa (aynı şey renk ve güneşlik seçenekleri için de geçerlidir) programda uyarı mesajı görüntülenmeli ve daha sonraki işlemlere geçilmemelidir. Dördüncü adım (tüm girişlerin doğru olduğunu varsayarsak) kullanıcıya otomatik kilit ve pencere ya da manuel kilit ve pencere tercihinin sorulmasıdır. Tüm renklerde bu seçenek olduğundan dolayı seçilen arabanın renginden bağımsız olarak tüm seçenekler için bu soruyu sorabilirsiniz. Bu seçenek için Evet/Hayır anlamında E/H kullanın. Son olarak siparişi konfirme etmek amacıyla bir mesaj görüntülemeniz gerekir. Bu mesaj aşağıdaki örneğe benzemelidir: Mavi renkte manuel kilit ve pencereli, 4 kapili ve gunesligi olan bir araba siparis ettiniz. ya da Yesil renkte otomatik kilit ve pencereli, 2 kapili ve gunesligi olmayan bir araba siparis ettiniz. Uyarı mesajındaki tek farkın arabanın rengi, otomatik ya da manuel kelimesi, 2 veya 4, olan ya da olmayan kelimeleri olduğuna dikkat edin.
13 Herhangi bir tercihte kullanıcı yanlış ir seçim yaptığı taktirde program yürütümü durdurulmalı ve tekrar tercih sorulmalıdır. Kullanıcıya bir sonraki sorunun sorulmaması ve yapmış olduğu tercihi düzeltmesi amacıyla if-else ifadeleri kullanın ve ekrana Yanlis bir tercih girdiniz, lutfen tekrar girin (E(e)/H(h)) ya da (Y(y), M(m), K(k)) şeklinde uyarı görüntüleyin. Bunu aşağıdaki örnekteki gibi gerçekleştirebilirsiniz: printf(... kullaniciyi renk icin uyarin...); /* secenek goruntule */ scanf("%c\n",&renk); /* renk oku */ renk = toupper(renk); /* buyuk harfe cevir */ if (renk!= 'R' && renk!= 'B' && renk!= 'G') /* dogruluk kontrolu */ printf("gecersiz bir renk girdiniz.\n"); /* hataliysa hata mesaji */ hata = TRUE; /* hata bayragi */ else /* else hata yok, devam */... ikinci adima devam et... 'error' değişkeni bizim bayrak (flama) olarak adlandırdığımız ve özel bir durumu temsilen kullanılan bir değişkendir. Bu örnekte, error değişkeni kullanıcın doğru bir seçim yapıp yapmadığının kontrolünde kullanılmaktadır. Bu yolla, konfirmasyon mesajı görüntülenirken 2error2 değişkeni DOĞRU (TRUE) ise bu adımı atlayabilirsiniz. Tüm seçenekler güzel ve düzgün bir formatta görüntülenmelidir. Örneğin, kapı sayısı ile ilgili soru sorulurken, aşağıdaki gibi bir örnek düşünülebilir: Arabaniz 2 ya da 4 kapili olabilir. 2-kapili model icin 2 tusuna basin. 4-kapili model icin 4 tusuna basin. Seceneginizi girin ==>