C Dili Temel Bilgiler
C Dili Temel Bilgiler
C++ bilindigi gibi programlama dünyasinda en çok ilgi gören C dilinden türemistir. C++'i klasik C dilinden farkli yapan yani; Nesne Yönelimli Programlamayi da ( Object Oriented Programming) C'nin sözdizimi kurallariyla birlikte desteklemesidir. Normalde C ile sadece yapisal programlama yaparken C++ dili ile hem yapisal hem de nesne yönelimli programlar yazabilirisiniz. C++ diline baslarken önce dilin C'den gelen ve temel olan özelliklerini ögrenmek gerekir. Örnegin, degisken tanimlama, atama ve diger basit aritmektik islemler, kontrol yapilari ve döngüler gibi.
Teknolojinin ulastigi son noktadaki programlama dillerinden olan C ve C++, bir çok yeni ve güçlü özellikleri içerir. Derslerimiz devam ettikçe bunlarin teker teker içine girecegiz. C dilinin özelliklerinin %80 i C++'da da mevcuttur (bu karsilastirma sahsi görüsümdür). Zaten C++, C'nin üst gurubudur. Bunu söyle siralayabiliriz. C, C++ ve C# dir.
C dilinin avantajlari, az komut kümesinden olusmasi ve bu komutlarin diger yüksek seviyeli dillere nazaran daha hizli çalismasidir. Ayrica C deki kütüphaneler sayesinde fonksiyon tanimlamaniza gerek kalmadan islemlerinizi yapmak mümkün olacaktir. Bu konuda çok detaya inmeden, programlamaya geçmek istiyorum. Çünkü, programlamaya basladigimizda her örnekten sonra o an kullandigimiz programin içinde geçen fonksiyon, hata, degisken, belirleyiciler, kisitlamalar, notasyonlar v.s gibi bilgilerden ara ara bahsedecegim. Yalniz çok önemli olan bir konuya burada deginmek istiyorum. C nin avantajlarini programlamayla birlikte görmek güzel ama C nin dezavantajlarini programlamadan önce bilmeliyiz ki bunlardan sakinalim. Öncelikle Tanimlayicilardan bahsetmek istiyorum. Her derleyici ve assmbley için degiskenleri, sabitleri, etiketleri ve fonksiyon adlarini tanimlama kurallari vardir. Bu notasyonlara, tanimlayici denir. C++ da tüm tanimlayicilar a, . . . , z - A, . . . , Z harfleri ile ya da alt çizgi "_" ile baslar. Bundan sonra rakam, harf, ya da alt çizgi kullanilabilir. ANCI C uyumlu derleyiciler 31 karaktere kadar tanimlayici kabul ederler fakat tanimlayicinin ilk sekiz karakterini kullanmayi kendimize aliskanlik etmeliyiz. Dikkat etmemiz gereken özelliklerden biri de kullandigimiz ifadelerdeki büyük küçük harflerdir. C ve C++ büyük ve küçük harf duyarliligina sahiptir. Kullandigimiz ifadeleri birbirinden farkli ve ayni ifade olarak kullaniyorsak programimiz hata verecektir. Bunu bir örnekle anlatayim:
Program
program
PROGRAM
Bu sekilde tanimlarsak hepsi birbirinden farkli ifadeler olarak C++ da okunacaktir. Biz Sunu aliskanlik edinmeliyiz; tanimlayicilarimizin bas harfi büyük olacak. Büyük ve küçük harf kombinasyonlarinin kullanilmasi ile önceden yapilan tanimlamalar bazen isi zorlastirabilir. Eger bu degiskenlerden birini kullanmak isterseniz, bu zamana kadar nasil tanimladiginizi bilmeniz gerekir. Örnegin printf()`in PRINTF() olarak çagrilmasi durumunda " bilinmeyen tanimlayici " (Unknown identifier) hata mesaji vererek sizi uyarir. Buna benzer olarak %f ve %F kullanimi hata verdirecektir. Programlamayi yaparken bunlara dikkat etmemiz gerekecek. Çünkü bir degiskeni veya tanimlayiciyi basta nasil kullandiysaniz üç, dört sayfa kod yazdiktan sonrada ayni sekliyle kullanmak zorundasinizdir. Iste burada en büyük handikap yasanacaktir. Çünkü C/C++ derleyicileri her zaman hatanin nerde oldugunu göstermez. Bunu programci kendisi satir satir takip ederek bulacaktir. Bundan dolayi bu söylediklerime bastan dikkat etmemiz gerekiyor.
1. c dili programı ve acıklaması
|
"//" isaretini açiklama satirlarinda kullaniyoruz. C++ derleyicisi bu notasyonla baslayan satiri okumaz. Bununla birlikte daha uzun cümlelerimiz olursa bunlari da " /* */ " notasyonunun içinde yazicagiz. Bu özellik de C den bize kalma. Demistik zaten C `nin tüm özelliklerini C++ içerir. Fakat biz genelde " // " yi kullanacagiz.
#include : Bu bizim C++ da bulunan kütüphane dosyamizi çagirmaya yariyor. Ben size söyle tarif edeyim. iostream.h kütüphanesindeki hazir olan " cout " fonksiyonunu çagiriyor. Yani buda bizim fazla kod yazmamiza engel oluyor. .h ile biten dosyalar kütüphane dosyalaridir. Bunu suna da benzetebiliriz. Farz edelim ki elimizde bir alet çantasi var içinden tornavidayi çagirdigimizda vida sikacagizdir. Bu da ona benziyor. C++ da ki hazir kütüphanelerde bir çok hazir fonksiyonlar vardir. Ilerde Bu hazir fonksiyonlar isimizi görmemeye baslayinca kendi kütüphanemizi yapmaya baslayacagiz. Tabi bu seviyeye geldigimizde olayi hemen hemen kavramis olacagiz, tabi neden olmasin öyle degil mi?
Daha sonraki satir her C++ programinda mutlaka bulunmasi gereken bir satirdir. Her C++ programinda main() fonksiyonu olmak zorundadir; bu fonksiyonumuzun önünde ise o fonksiyonun dönderdigi degiskenin veri tipi olmalidir. Tabi ki C++ fonksiyonlar ve onlarin dönderdikleri degerler konusunu da ileride isleyecegiz.
Bir sonraki satirda ise; C++ fonksiyonlar ve kod bloklari " { } " parantezleri arasinda bulunmalidir. main de bir fonksiyon ise onun içindeki kodlar dogal olarak { } parantezleri arasindadir.
Program derlenip çalistirildiginda ise ( Turbo C++ 3.1 kullaniyorsaniz ctrl+f9 kisa yoluyla programi çalistirabilirsiniz (Run) ) karsimiza "Bu benim ilk programim" yazisi çikacaktir. Iste bu yaziyi ekrana veren komut da iostream.h kütüphanesindeki cout fonksiyonudur.
Önemli bir nokta ise C++ dilinde her satir ifadenin sonuna " ; " koymak zorundayiz. Bundan farkli olarak #include satirlarinin ve bir kaç farkli satirin arkasina " ; " gelmez. Bunlari ileride görecegiz.
Return 0 : programimizin (ayni zamanda main fonksiyonumuzun) çikis noktasidir. Eger return ile 0 degeri dönderirsek programimizin güvenle çiktigini isletim sistemine bildirmis oluruz. Bu sayede güvenle programimizin çalistigini görecegiz
En cok kullanılan prinf kullanmamızın sebebi stdio.h olması 1. örnek kafanızı karıştırmasın
|
Değişkenler
|
Burada bundan önce yaptigimiz programlardan farkli olarak int i kullandik, yani degisken tanimladik.
Degisken Nasil Tanimlanir?
Degiskenleri tanimlamak için asagidaki sema kullanilir.
[Veri Tipi] [Degisken Adi];
Örnegin
int sayi;
Simdi degisken.cpp örnegindeki int i; kismini anlamissinizdir. Burada degiskenlere deginmek istiyorum. Biz yukarda Içinde sayi tutan bir degiskeni tanimladik. Benzer olarak asagidaki tanimlamalar da vardir.
char c;
int i;
float f;
double d;
unsigned int ui;
Veri Tipleri
Integer = Tamsayi
Tamsayilari içerir. Bellekte 2 Byte tutar. DOS'ta ve Win3.1'de 16 bit uzunlugunda ama Windows9x, WinNT, Win200 ve WinXP 32 bit uzunlugundadir.
Deger araliklari Short ve long için degisir.
Örnek: 5, -20, 1 gibi.
2) Sort tipi
Tam sayilari içerir. 16 bit uzunlugundadir.
signed: -32768 ile +32767 arasinda deger alir, unsigned: 0 ile 65535 arasinda deger alir.
3) Long tipi
Tam sayilar içerir. 32 bit uzunlugundadir.
signed: -2147483648 ile +2177483647 arasinda deger alir, unsigned: 0 ile 65535 arasinda deger alir.
4) Gerçel Tipler (Float, Double, Long double)
Gerçel sayilari içerirler.
float : Bellekte 4 Byte yer tutar. 3.4E-38 ile 3.4E+38 araliginda deger alir. Hassasiyet 7-8 basamaktir.
double : Bellekte 8 Byte ter tutar. 1.7E-308 ile 1.7E308 araliginda deger alir. Hassasiyet 15-16 basamaktir.
long double : doublenin tipinin daha genisidir.1.2E-4932 ile 1.2E-4932 araliginda deger alir. Hassasiyet 19-20 basamak.
5) Char Tipi
Char : Karakter
Alfanumerik karakterleri içerir. Ve ya 8 bit uzunlugunda tamsayi.
signed: -128 ile 127 arasinda deger alir, unsigned: 0 ile 255 arasinda deger alir.
Örnegin: ' 0,1,2,3,4,5,6,7,... ' , ' *,-,+,... ' , 'a,b,c,....,A,B,C,D,,,,, '
6) Bool tipi
true(dogru) = 1 veya false(yanlis) = 0 degerini alir. Eski derleyiciler bu türü desteklemeyebilir. Yeni ANSI C++ standardinda eklenmistir. Bu soyut matematik gördüyseniz. "p V q" ya benzer :) ( matematikçiyiz, konusturalim azicik). Deger araligi ise ya 1 dir (dogru) yada 0 dir (yanlis).
7) Enum tipi
enum siralanmis degerleri tutar. Short int ile ayni degeri tasir.
Bu temel bilgileri aldiktan sonra programlamaya geçebiliriz. Derleyici Olarak ben Turbo C++ 3.1 i tavsiye ederim. Su an bununla baslar iseniz isiniz daha kolay olacaktir (bence). Ilerde Borland a geçecegiz.
Degisken tanimlama konusunda bir konuya daha deginmek istiyorum. Degiskenlere deger atama ve ayni anda bir çok degisken tanimlamamiz C++ da mümkündür.
char c = 'c';
int i = 5;
Daha sonradan deger atama:
char c;
int i;
c = 'c ';
i = 5;
Bir de ayni anda bir çok degisken tanimlayalim.
Örnegin:
int x , y , z;
x = y = z = 5;
x,y,z' nin degeri 5 oldu
İlişkisel işleçler Operatörler
işleç anlamı
> büyük
>= büyük - eşit
== eşit
< küçük
<= küçük - eşit
!= eşit değil
x=8, y=5 için
x > y Doğru
x < y Yanlış
x !=y Doğru
Mantıksal işleçler : İki mantıksal ifade arasındaki ilişki üzerindeki ilişkide kullanılır.
! DEĞİL (NOT)
&& VE (AND)
|| VEYA (OR)
(X>0) && (X>Y)
(X>0) || (Y>0)
İfadelerde işleçlerin yürütülme sırası
işleç Önceliği
( ) en yüksek (ilk yürütülür)
!
*, /, %
+, -
<, <=, >=, >
==, !=
&&, ||
= en düşük (son yürütülür)
= işleci sağdan sola, diğerleri soldan sağa doğru yürütülür.
Görüldüğü gibi ifadelerde matematiksel ve mantıksal işlemler bittikten sonra ilişki test edilir.
X=50, Y=80, Z=45 için
( ( X / 4 + Y / 4 + Z / 2 ) >= 50 ) && ( Z >= 50 )
For Döngüsü
ifade;
ifade2 doğru ( veya farklı 0) olduğu sürece ifade yürütülür (bitiş koşulu).
Döngünün ilk adımından önce ifade1 yürütülür ( başlangıç adımı).
Döngünün her adımında ifade3 yürütülür (artış miktarı).
for (i = 1; i < 5; i++)
printf("%d ",i);
ifade1, ifade2 ve ifade3 seçimliktir. ifade2 belirtilmez ise herzaman
doğru olduğu ( == 1 ) kabul edilir. Yani sonsuz döngü oluşur.
|
Diziler
Diziler, "indisleri olan degiskenler" olarak adlandirilirlar. Diger bir deyisle, birden fazla tek düze veri tipi içeren degiskenlerdir. Diziler birbirine bitisik bellek gözleri kullanilarak olusturulurlar. Bunu biraz daha açarsak: farz edelim ki elimizde üç tane kutu var, birinde yesil kalemler, birinde kirmizi kalemler ve birinde de mavi kalemler olsun. Bu kutucuklari 1,2,3 diye adlandirdigimizi düsünelim. Biz diziler ile numarasini bildigimiz kutucugun içindeki malzemeyi alabilecegiz. Daha dogrusu numarasini vermis oldugumuz kutunun içindeki bilgiyi bilgisayar okuyacaktir.
Not: For döngüsü dizi elemanlarina ulasmak için en çok kullanilan yöntemdir.
Dizilerin indislerden olustugunu söylemistik. Diger yüksek seviyeli dillerle karsilastirildiginda arasindaki fark ilk elemanin indisi daima sifir (0) olmasidir.
for(int i=0; i
Bir dizi tanimlayicisi -adi-, dizinin ilk elemaninin adresini tanimlayan adrestir. Bunu söyle izah edelim; elimizde bir dizi var ve ilk elemani karakter ise biz "char DiziAdi[boyut]" seklinde tanimlariz. Tam sayi ise "int DiziAdi[boyut]" seklinde olur.
Dizilerin TanımlanmasıDizi tanımlamalarının genel biçimi:
Yukaridaki gösterimde köşeli parantez eleman sayısının seçimlik olduğunu değil, eleman sayısı bilgisinin köşeli parantez içine yazılması gerektiğini göstermektedir.
tür : Dizi elemanlarının türünü gösteren anahtar sözcüktür.
dizi ismi : İsimlendirme kurallarına uygun olarak verilecek herhangi bir isimdir.
eleman sayısı : Dizinin kaç elemana sahip olduğunu gösterir.
Dizilere Deger atama:
Bu yöntemleri madde madde verelim,
1. Duragan ve global (erisilen) dizilerde yaratildiklari anda içerik otomatik olarak belirlenebilir. Programin taniminda erisilen tüm degiskenler, otomatik olarak sifir yapilir.
2. Duyuru sirasinda sabit degerler belirtilerek belirlenebilir.
3. Programin çalismasi sirasinda indisler kullanilarak her elemana tek tek veri kopyalanabilir.
1. maddenin örnegi #include
const int boyut=5;
int GlobalDizi[boyut];
main() {
//"satatic" yerel degiskende tanimlanmasina ragmen tüm program boyunca
//geçerlidir. Ancak sadece tanimlandigi fonksiyon tarafindan erisilebilir.
static int DuraganDizi[boyut];
for(int i=0; i
}
Programin çiktisinada göreceginiz gibi, dizi aratilirken indislere ait eleman bloklari temizlenmis ve sifir degerlerini almistir.
Burada bir konuya daha dikkat çekmek istiyorum. Çok yaptigimiz hatalardan biri olarak da, dizi duyurusunu yaparken belirttigimiz degerden fazla sayida deger girmemizdir.
int DiziAdi[5]={1,8,9,5,4,6};Görmüs oldugunuz gibi bes tane dedik ama alti tane yazdik. !!! hata !!!. Bu tür hatalar için elimizde kullanabilecegimiz bir kalip var.
char DiskOkunmuyor[ ] = "Disk okunmuyor";
char DosyaYok[ ]= "Dosya Yok";
Putchar Fonksiyonu
putchar standart bir C fonksiyonudur. Bütün sistemlerde bulunması zorunludur. Parametresi olan karakteri ekranda imlecin bulunduğu yere yazar. Örneğin:
#include
main()
{
char ch;
ch = getchar();
putchar (ch);
return 0;
}
Burada putchar fonksiyonunun yaptığı işi printf fonksiyonuna da yaptırabilirdik;
printf("%c", ch);
putchar(ch) ile tamamen aynı işleve sahiptir.
putchar fonksiyonu ile '\n' karakterini yazdırdığımızda printf fonksiyonunda olduğu gibi imleç sonraki satırın başına geçer. putchar fonksiyonu ekrana yazılan karakterin ASCII karşılığı ile geri dönmektedir.
putchar fonksiyonu derleyicilerin çoğunda stdio.h dosyası içinde bir makro olarak tanımlanmıştır. Makrolar konusunu ileriki derslerde detaylı olarak öğreneceğiz.
Fonksiyonlar
y=F(x) fonksiyonu; Bu matematiksel fonksiyon parametre olarak aldinan deger üzerinde bir islem gerçeklestirip, bir sonuç degerini döndürür. Mesela F(x)=x^3+5 seklinde bir fonksiyonumuz olsun, x=2 için F(x)=13 olur. Burada x fonksiyonun parametresi, 13 ise fonksiyonun geri döndürdügü degerdir. Simdi de bu matematiksel ifadeyi kodlarimizla yorumlayalim.
Int x;
x=F(2,5)
//buradan da "
int f(2,5)
" gibi görebiliriz...Dikkat edersek ikinci satirda, daha önce islemedigimiz bir kod var. Int x
, F(2,5) degerine esitlenmistir. Simdi bir fonksiyonun nasil yazildiginin kalibini çikartabiliriz.
<Döndürdügü deger> <Fonksiyonun adi> ( <parametre listesi> ) { |
Buradaki parantezlere ve küme isaretlerine dikkat ediniz. Simdi yukarda yazdigimiz kalibi biraz açalim.
<Döndürdügü deger> : Fonksiyon her hangi bir tipte deger döndürebilir. Bu bilesen fonksiyonun döndürecegi degerin tipini ifade eder. (örnegin, int, dounle, float v.s v.s )
<Fonksiyonun adi> : Yapmak istedigimiz islemin adidir. Örnegin bir asal sayi fonksiyonu yazacagiz. Burada yazacagimiz fonksiyonun adini belirtiyoruz. Benim size tavsiyem AsalSayi veya asal_sayi seklinde kullanmanizdir. Okunabilirlik açisindan size avantaj saglayacaktir.
<parametre listesi> : Fonksiyonun kullanacaga parametrelerin tipleri ile siralanir. Örnegin, FonksiyonAdi(int x, double y)
gibi.
<ifadeler> : Fonksiyonun kullanacagi tanimlamalar ve kodlardan olusan kisimdir. Nasil biz main() { kodlar }
seklinde kullaniyorsak. Bunu da ona benzetebiliriz. Ama main() i bunlarla karistirmayiniz.
Simdi bu fonksiyon kalibina uygun bir kod yazalim. Örnegin, Faktoriyel bulma islemini ele alalim. Biz bir sayinin Faktörüyelini nasil bulurduk?
n!=n(n-1)(n-2)...1 Yani, 1 den n e kadar olan sayilarin çarpimidir.
long Faktoriyel(int n) { |
Evet, burada fonksiyonumuzu tanimladik. Sanirim yukaridaki blokla karsilastirinca, ne kadar kolay oldugunu sizde görmüssünüzdür. Simdi bu Faktoriyel fonksiyonumuzu nasil bir programda kullanacagiz? Hemen devamini yazayim.
long Faktoriyel(int n) { |
Iste gördügünüz gibi ne kadar basit degil mi? J Fonksiyonumuzu tanimladik. Sonra programimizda n`e 5 degerini verdik. Faktoriyel fonksiyonu hesaplayip bize söyledi.
Biraz da yaygin yapilan hatalardan ve dikkat etmemiz gereken noktalardan bahsedelim. Kodlama yaparken fonksiyon adini belirttigim sekilde yazarsaniz 30-40 sayfalik kodlarda hata bulmaniz ve de fonksiyonlarin yerini belirlemeniz açisindan büyük kolaylik olucaktir. Yukarida verdigimiz x=F(2,5) fonksiyonununu göz önünde tutalim. Görüldügü gibi F(2,5) degeri x e atanmistir. Hiç bir zaman Fonksiyonun aldigi deger sola yazilmaz. Ayrica bir Fonksiyon çagrisi, baska bir fonksiyonun çagrisi olabilir. Örnegin, x=F(a,F(a,5) gibi. Burada F Fonksiyonun iki parametresi vardir a ve F(a,5) dir. Bu durumda öncelikle parametreler hesaplananacagi için F(a,5) in degeri ile a nin degeri F te parametreler olarak kullanilir.
Örnek Program 5
Girdi : Ay ve yıl
Çıktı : Aydaki gün sayısı
int aydakigun(int ay, int yil)
{
int i;
switch (ay) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12 : i = 31;break;
case 2 :
if (yil % 4 == 0)
i = 29;
else
i = 28;
break;
default : i = 30;
}
return i;
}
Örnek Program 6
Girdi: Bu yıl kutlanılan tarih
Çıktı : Sonraki tarih
#include
int aydakigun(int, int);
main()
{
int gun,ay, yil;
int i, j ;
clrscr();
printf("Bu yılki tarihi giriniz (G A Y) : ");
scanf("%d %d %d",&gun, &ay, &yil);
yil = yil + 1;
gun = gun - 11;
if (gun < 1 ) {
ay = ay - 1;
if (ay < 1 ) {
ay = 12;
yil = yil - 1 ;
}
gun = gun + aydakigun(ay, yil);
}
printf("\nGelecek bayram = %d/%d/%d\n",gun,ay,yil);
}
Örnek Program 4
#include
long okek(long, long);
main()
{
long i, j;
clrscr();
printf("İki tamsayı giriniz :");
scanf("%ld%ld", &i, &j);
printf("sayıların okeki = %ld \n" okek(i, j));
}
long okek(long p, long q)
/* p < q olmali. Degil ise yerlerini değiştir. */
{
long i, k;
if (p>q) {
i=p;
p=q;
q=i;
}
/* p nin öyle bir katını bul ki q sayısına tam bölünsün
2 sayısından itibaren taranmaya başlanabilir fakat
p/q yeterli
*/
i = q / p;
do {
k = p*i;
i = i+1;
} while ( k % q != 0);
return
Örnek Program 3
main()
{
int tahmin; /* tahminimiz */
int min; /* Tahminin alt siniri */
int max; /* Tahminin ust siniri */
char cevap; /* Kullanicinin cevabi */
min = 0; max = 100;
do {
tahmin = (max - min) / 2 + min;
printf("Tahminim %d\n",tahmin);
printf("Buyuk / Kucuk / Esit ");
scanf("%c",&cevap);
if (cevap == 'B')
max = tahmin - 1;
else
if (cevap == 'K')
min = tahmin + 1;
} while (cevap != 'E');
}
Kücük Örnekler
1'den 100'e kadar olan sayıların toplamı
j =0;
for (i=1; i<=100; i=i+1)
j =j+i;
printf("Toplam %d",j);
-------------------------------------------
Girilen sayının faktöriyelini
fact =1;
for (j=1; j<=i; j++)
fact =fact*j;
printf("Faktöriyel =%f",fact);
}
-------------------------------------------
Çarpım tablosu. (içi içe döngüler)
main()
{
int i,j;
for (i=1; i<=10; i++) {
for (j =1; j<=10; j++)
printf("%4.0d",i*j);
printf("\n");
}
}
--------------------------------------------
Bir tamsayının kübünü veren işlev
#include
main()
{
int sayi;
int kub(int); /* işlevin prototipi */
printf("sayıyı gir ");
scanf("%d", &sayi);
printf("Kübü = %d\n", kub(sayi));
}
int kub(int i)
{ return i*i*i; }
Örnek Program 2
/* Nufus Tablosu */
#include
main()
{
int i; /* sayac */
int yil; /* yillar */
float nufus; /* nufus miktari */
float artis; /* artis orani */
artis = 0.023;
yil = 1993;
nufus = 60000000;
printf("%d - %10.0f\n",yil,nufus);
i = 1;
while (i < 11)
{
nufus = nufus * (1 + artis);
printf("%d - %10.0f\n",yil + i,nufus);
i = i + 1;
}
}
Girilen tarihteki günün adını veren program
#include
main ( )
{
int gun, ay, yıl ;
long gt ;
printf(“Tarihi gir”) ; scanf ( “%d %d %d “,&gun)
/* oncekı yıllardakı gun sayısını hesapla */
gt=( yıl*1)*365 + yıl/4;
/* bu yildaki aylardaki gunleri ekle */
if (ay==2)
gt = gt + 31 ;
else if (ay ==3)
gt = gt + 31 + 28 ;
else if (ay ==4)
gt = gt + 31 + 28 +31;
else if (ay ==5)
gt = gt + 31 + 28 +31+ 30 ;
else if (ay ==6)
gt = gt + 31 + 28 +31+ 30 +31;
else if (ay ==7)
gt = gt + 31 + 28 +31+ 30 +31+ 30 ;
else if (ay ==8)
gt = gt + 31 + 28 +31+ 30 +31+ 30 + 31 ;
else if (ay ==9)
gt = gt + 31 + 28 +31+ 30 +31+ 30 + 31+30 ;
else if (ay ==10)
gt = gt + 31 + 28 +31+ 30 +31+ 30 + 31+30 + 31;
else if (ay ==11)
gt = gt + 31 + 28 +31+ 30 +31+ 30 + 31+30 + 31+ 30 ;
else if (ay ==12)
gt = gt + 31 + 28 +31+ 30 +31+ 30 + 31+30 + 31+ 30 +31;
/*Bu ayı ekle */
gt = gt+ gun;
if(yıl%4==0 && ay>2),
gt =gt+1;
gt=gt %7,
if(gt==1)
printf(“Pazar”);
else if(gt==2)
printf(“Pazartesi”);
else if(gt==3)
printf(“Salı”);
else if(gt==4)
printf(“Carsamba”);
else if(gt==5)
printf(“Persembe”);
else if(gt==6)
printf(“Cuma”);
else if(gt==7)
printf(“Cumartesi”);
}
Pointer
Bir veri bloğunun bellekte bulunduğu adresi içeren (gösteren) veri tipidir. Tanımlama biçimi:
veri tipi *p;
p değişkeni
int *iptr;
float *fptr;
Bu kadar tanımla sonucunda bellekte p değişkeni mevcuttur. Ancak işaret ettiği veri bloğu yoktur. Bunun için iki yol vardır. Birincisi kullanılan herhangi bir değişkeni işaret etmek, ikincisi ise veri bloğunu boş belleği kullanarak oluşturmak.
İşaretçi değişkenin var olan bir değişkenin bulunduğu adresi göstermesi.
Bu işlemi yapabilmek için var olan değişkenin adresinin bilinmesi gerekmektedir.
& işleci : Bir değişkenin adresinin belirlenmesi için kullanılır. Kullanım biçimi:
&değişken
&i : i değişkenin adresini verir.
main()
{
int i;
int *iptr;
i = 5;
iptr = &i;
clrscr();
printf("i değişkeninin adresi %p\n", &i);
printf("iptr değişkeninin değeri %p\n", iptr);
}
Bellek modeline göre SSSS:OOOO veya OOOO biçiminde adres yazar.
8FF8:1000
Veri bloğunu boş belleği kullanarak oluşturmak.
Bu yolla veriler için dinamik yer ayırılır. Bunun için malloc işlevi kullanılır
void *malloc(n) : Boş bellekten n byte yer ayırıp başlangıç adresini döndürür.
iptr = (*int) malloc(2);
!!!!!!!!! Daha sonra dönüş yapılacak. sizeof, cast işleci (*tip) ...
Veriye işaretçi değişken yoluyla erişim
Bir işaretçinin gösterdiği adresteki veriye erişmek için işaretçi değişkeninin önüne * karakteri konur.
main()
{
int i;
int *iptr;
iptr = &i;
*iptr = 8;
printf("i değişkeninin değeri %d\n", i);
printf("iptr adresinin içeriği %d\n", *iptr);
}
Ekranda çıktı :
i değişkeninin değeri 8
iptr adresinin içeriği 8
!!! İşaretçi değişkenin gösterdiği adresin içeriği değişken ilklendirmeden kullanılmamalıdır
İşaretçi Aritmetiği
İşaretçi değişkenler üzerinde toplama ve çıkartma işlemleri (++, --) geçerlidir. Ancak eklenecek değer tamsayı olmalıdır.
İşaretçi değişkenin değeri 1 arttırıldığı zaman değişken bir sonraki veri bloğunu işsaret eder. Değişkenin alacağı yeni değer işaretçi değişkenin ne tip bir veri bloğunu işaret ettiğine bağlıdır.
int *iptr, i;
...
iptr = &i; i değişkenin adresinin 1000 olduğunu varsayalım. iptr nin değeri 1000 dir.
iptr++; iptr nin değeri 1002 olur. ( int değeri işaret ettiği için)
aynı örneği double için yaparsak
double *iptr, i;
...
iptr = &i; i değişkenin adresinin 1000 olduğunu varsayalım. iptr nin değeri 1000 dir.
iptr++; iptr nin değeri 1008 olur. ( double değeri işaret ettiği için)
int *iptr, i, j;
...
iptr = &i; i değişkenin adresinin 1000 olduğunu varsayalım. iptr nin değeri 1000 dir.
*(iptr+4)=2; 1008 adresinin içeriğini 2 yapar.
!!! Arttırma işaret edilen veri bloğuna göre yapılır Yani bir sonraki veri bloğunun gösterilmesi sağlanır.
iptr++ ; bir sonraki veri bloğunu göster
(*iptr)++; iptr değişkeninin gösterdiği adresteki değeri 1 arttır
İşaretçiler ve Diziler
İşarteçiler üzerinde geçerli aritmetik yardımıyla dizilere işaretçi değişkenler ile erişmek mümkündür.
#include
main()
{
int i[10], j;
int *iptr;
for (j=0; j<10; j++)
i[j]=j;
/* Dizinin başlangıç adresine erişmek için ilk elemanın adresi kullanılabilir &i[0] veya doğrudan */
iptr = i;
clrscr();
for (j=0; j<10; j++) {
printf("%d ", *iptr);
iptr++;
}
printf("\n");
/* iptr artık dizinin başını göstermez */
iptr = i;
for (j=0; j<10; j++)
printf("%d ", *(iptr+j));
printf("\n");
/* iptr hala dizinin başını gösterir */
getch();
}
Örnek: İşaretçi ve dizgi kullanımı.
#include
main()
{
char *a="1234567890";
char b[11];
char *p1, *p2;
printf("%s\n", a);
p1 = a;
p2 = b;
while (*p1 != '\0') {
*p2 = *p1;
p1++;
p2++;
}
printf("%s\n", b);
}
İşlevleri Referans Yoluyla Çağırma
Şu ana yazdığımız işlevlerde gönderilen parametrelerin (diziler hariç) değerlerinin değiştirilmesi mümkün değil idi. İşlev çağırıldığı zaman parametrelerin bir kopyası çıkartılıp işleve gönderiliyordu. Bir işlevin birden fazla değer gönderebilmesi için işaretçilere gereksinimiz vardır.
void arttir(int);
main()
{
int i;
i = 5;
printf("öncesi %d\n", i);
arttir(i);
printf("sonrası %d\n", i);
getch();
}
void arttir(int k)
{
k++;
}
Çıktı :
öncesi 5
sonrası 5
Gönderilen parametrenin kopyası işleve gönderildiği için işlev içerisinde yapılan değişiklikler işlevin çağırıldığı yeri etkilemez. Eğer parametredeki değişikliklerin işlevin çağırıldığı yerde de geçerli olmasını istiyorsak işleve parametrenin adresini göndermek gerekir.
void arttir(int*);
main()
{
int i;
i = 5;
printf("öncesi %d\n", i);
arttir(&i);
printf("sonrası %d\n", i);
getch();
}
void arttir(int *k)
{
(*k)++;
}
öncesi 5
sonrası 6
Örnek : Sayısal dizgiyi tamsayıya dönüştüren işlevde iyileştirme. Geçersiz karakterin konumu da verilsin.
int deger(char *s, int *konum)
konum = -1 ise tüm karakterler rakam
>=0 ise geçersiz karakterin konumu
Örnek : Sıraya dizme. Yer değişikliği işlevde ve parametrelere referans yolu ile erişim.
#include
#include
#define N 20
void degistir (int *, int *);
main()
{
int s[N];
int i, k;
clrscr();
for (i=0; i
printf("%4d",s[i]);
}
printf("\n");
k=1;
do {
k=0;
for (i=0; i
degistir (&s[i], &s[i+1]);
k = 1;
}
} while (k);
for (i=0; i
printf("\n");
getch();
}
void degistir (int *a, int *b)
{
int gec;
gec = *a;
*a = *b;
*b = gec;
}
!!! Dizilerde işaretçi olduğu için a değişkeni bir dizi(veya işaretçi ise)
a[i] ile *(a+i) ifadeleri aynı anlamı taşır.
Örnek : İşleve gönderilen dizinin işlev içerisinde işaretçi olarak kullanımı.
#include
#include
#define N 5
float ort (int *);
main()
{
int s[N];
int i, k;
clrscr();
for (i=0; i
printf("%4d",s[i]);
}
printf("\n");
getch();
}
float ort (int *a)
{
int i;
float t = 0;
for (i=0; i
return t/N;
}
Örnek : işleve gönderilen işaretçinin işlev içerisinde dizi olarak kullanımı .
void malloc(n): En az n byte uzunluğunda bellekten yer ayırır. İşlevin değeri
>0 ise bloğun bellekteki yeri, NULL yer yok demektir.
int *i;
i = (int *) malloc(2000) ; 2000 byte yer ayırıp bloğun başlangıç adresini i 'ye atar
( 1000 elemanlı int dizisi )
double *x;
x = (double *) malloc(8*2000); 2000 elemanlı double dizi
sizeof(n) : n ifadesinin/tipinin byte olarak uzunluğunu verir.
i = (int *) malloc(1000*sizeof(int)) ; 1000 tane int değer içerecek bellek uzunluğu
x = (double *) malloc(2000*sizeof(double)); 2000 elemanlı double dizi
void free (void *block) : mallock işlevivi tersi. Block değişkenin tuttuğu yeri boş belleğe gönderir
Strlen Strcpy Strcmp Strcat Strcmp Atoi
Bu fonksiyon bir karakter dizisinin uzunlugunu verir ve "string.h" kitapliginda tanimlidir. Strlen() fonksiyonu, sözcükler (strings) bölümünde bahsettigimiz string ifadeleri okumak için kullanilir. Fakat sondaki "nul terminator" diger sekliyle ''\0'' degerini okumaz. Örnegimizde de oldugu gibi "Deneme" ve ''d'' ''e'' ''n'' ''e'' ''m'' ''e'' sözcükler kisminda ki biz buna 7 karakter demistik, "null" ile birliktedir ama strlen() bunu bize 6 diye okuyacaktir.
int boy = strlen(h);
for (int i = 0; i<=boy; i++)
y[i] = h[i] ;
strcpy()
Bu fonksiyonda sözcük kopyalamaya yarar ve "string.h" kitapligindadir.
#include
#include
#define OTUZ 30
void main(void)
{
char Dosya1[OTUZ]="C:\\belgelerim\\deneme.txt",
Dosya2[OTUZ];
strcpy(Dosya2, Dosya1);
cout<
cout<<"\n ikinci dosyayi gir: ";
cin>>Dosya1;
strcpy(Dosya2, Dosya1);
cout<<"\n"<
strcat()
strcat() fonksiyonu iki karakter katarini bir birine ekler.
strcmp()
Iki sözcügün (iki karakter katarinin) ayni olup olmadigini kontrol etmek için kullanilir. Bu fonksiyon büyük/küçük harf duyarli degildir.
atoi()
Bazen sayilari karakter dizisi olarak okumamiz gerekebilir. Ancak esas, bu sayilarin sayi degerlerine gereksinmemiz vardir. Atoi fonksiyon, bir karakter dizisini alir ve onu sayiya çevirir.
Örnegin; "123456" dizisini alir 123456 sayisina döndürür.
Örnek Dizi Bildirimleri
double a[20]; /* a, 20 elemanlı ve elemanları double türden olan bir dizidir*/
float ave[10]; /* ave 10 elemanlı ve her elemanı float türden olan bir dizidir. */
unsigned long total[100]; /* total 100 elemanlı ve her elemanı unsigned long türden olan bir dizidir */
char path[80]; /* path 80 elemanlı ve her elemanı char türden olan bir dizidir. */
Tanımlamada yer alan eleman sayısının mutlaka tamsayı türlerinden birinden sabit ifadesi olması zorunludur. (Sabit ifadesi [constant expression] tanımını hatırlayalım; değişken ve fonksiyon çağırımı içermeyen, yani yalnızca sabitlerden oluşan ifadelere, sabit ifadesi denir.)
int dizi[x]; /* x dizisinin bildirimi derleme zamanında hata olusturur .*/
int dizi[5.]; /* gerçek sayı türünden sabit ifadesi olduğu için derleme zamanında hata olusturur . */
int sample[10 * 20] /* sample dizisinin bildirimi geçerlidir. Eleman sayısını gösteren ifade sabit ifadesidir. */
Dizi bildirimlerinde eleman sayısı yerine sıklıkla sembolik sabitler kullanılır:
#define MAXSIZE 100
...
int dizi[MAXSIZE]; /* geçerli bir bildirimdir */
...
Diğer değişken bildirimlerinde olduğu gibi, virgül ayıracıyla ayrılarak, birden fazla dizi tek bir tür belirten anahtar sözcükle tanımlanabilir.
int x[100], y[50], z[10];
x, y ve z elemanları int türden olan dizilerdir.
Dizi tanımlamaları diğer değişken tanımlamaları ile kombine edilebilir.
int a[10], b, c;
a int türden 10 elemanlı bir dizi, b ve c int türden nesnelerdir.
Dizi elemanlarının her biri ayrı birer nesnedir. Dizi elemanlarına index operatörüyle [] ulaşılabilir. Index operatörü bir gösterici operatörüdür. Göstericiler konusunda ayrıntılı bir şekilde ele alınacaktır.
İndex operatörünün operandı dizi ismidir. (Aslında bu bir adres bilgisidir, çünkü dizi isimleri adres bilgisi belirtirler.) Köşeli parantez içinde dizinin kaçıncı indisli elemanına ulaşacağımızı gösteren bir tamsayı ifadesi olmalıdır.
C dilinde dizilerin ilk elemanı sıfırıncı indisli elemandır.
a[n] gibi bir dizinin ilk elemanı a[0] son elemanı ise a[n - 1] dur.
Örnekler:
dizi[20] /* a dizisinin 20. indisli yani 21. sıradaki elemanı. */
ave[0] /* ave dizisinin 0. indisli yani birinci sıradaki elemanı */
total[j] /* total dizisinin j indisli elemanı */
Görüldüğü gibi bir dizinin n. elemanı ve bir dizinin n indisli elemanı terimleri dizinin farklı elemanlarına işaret eder. Bir dizinin n indisli elemanı o dizinin n + 1 . elemanıdır.
Bir dizi tanımlaması ile karşılaşan derleyici, tanımlanan dizi için bellekte yer tahsis edecektir..Ayrılacak yer şüphesiz dizinin eleman sayısı * bir elemanın bellekte kapladığı yer kadar byte olacaktır.
Do-While Döngüsü
do
Deyim
while (
Mantıksal ifade doğru olduğu sürece döngü tekrar edilir. Yanlış olduğunda while sözcüğünden
sonraki deyim yürütülür.
5 sayısı girilene kadar oku
do
scanf("%d",&i);
while (i!=5);
i =1;
do {
printf("%d",i*i);
i =i+1;
} while (i<=10);
Break ve Exit Komutu
Break komutunu, swtich komutundan çikmak için önceki derslerimizde görmüstük. Komutun kendine özgü bir kullanimi daha vardir. Break komutu bir döngünün içinde çalistirilirsa o an o döngü biter. Bir goto gibi islem gördügünü de söyleyebiliriz. Break kullaninca program döngüyü bitirir ve döngünün sonundaki satirdan çalismaya devam eder. Bir örnek verelim.
|
Iste örnegimizde gördügünüz gibi. X 7''ye esit olunca break; döngüyü bitiriyor ve döngüden sonraki satiri çalistirmaya basliyor.
Exit
Hayati hata durumlarini ele almak için exit() fonksiyonundan yararlanilir. Bu hatalar main() fonksiyonunu return ile normal olarak sonlandirilmadan önce olusabilir. Exit() fonksiyonu, durum degerini bir tam sayi parametre olarak döndürür.
Exit() ile özel bir degerin gönderilmesi bazi islemler yapmasi için kullanilabilir. Örnegin program komut satirinda kullaniliyorsa ve durum degeri bazi hatalari gösteriyorsa, isletim sistemi bunlari mesaj olarak yazabilir. Exit() fonksiyonu programi sonlandirmanin yaninda, tüm bekleyen yazma islemlerini tamamlar ve açik tüm dosyalari kapatir.
Exit() fonksiyonunu kullanirken kullanmamiz gerek kütüphaneler ise process.h ve stdlib.h tir.
While Döngüsü
while ( ifade )
{
komut;
komut;
komut;
.
.
.
}
Burada bir seye dikkat etmenizi istiyorum. Çoklu komutlar kullandigimizda " { } "parantezleri gereklidir.
// while1.cpp |
Burada önce x ve y yi tanimladik. y=0 degerini verdik. Sonra klavyeden girilen degerin x oldugunu yazdik. while (x< 101) iste burada ifademiz x< 101. Simdi bu kosul saglanincaya kadar döngümüz devam edecek. While'' den sonraki bloga geçtigimizde ise. y` ye x i ekliyoruz ve x in degerini her seferinde 1 arttiriyoruz. Sanirim bu basit örnekte döngünün basit yapisini ve mantigini anlamis oldunuz.
Döngünün verilen ifade veya kosula göre saglanmasi döngülerin en önemli konusudur. Eger bir döngüden çikilmazsa o döngü sonsuza gider. Buna da "sonsuz döngü" denir. Döngüler konusunda en çok rastlayacagimiz hata da budur.Simdi buna bir örnek verelim. Fakat, simdiden uyariyorum, sonsuz döngü yapildiginda bilgisayariniz kilitlenebilir.
//sonsuz.cpp |
Burada neden sonsuz bir döngü oldu? Evet iste x ifadesini kosula baglamadik. Sayet while(x<10)
demis olsaydik. 1,2,3,4,5,6,7,8,9 a kadar x sayisi siralanacakti.
//klavye.cpp |
Bu programda da klavyeden girilen sayilarin toplami 20'' den büyük olunca program Toplam olarak söylüyor. Sanirim basit While yapisini anladiniz. Simdi birazda karmasik programciklar yapalim:).
1. Örnek: Girilen alti not''un ortalamasini aliyor.
//ortalama.cpp |
Bu örnegimizde yine toplam, sayac, not, ortalama gibi degiskenleri tanimladik. ( toplam =0 ; ve sayac = 1; )
de degiskenlere ilk degerlerini atadik. While döngüsünün içinde sayac degiskenimizi alti defa islemesini söyledik. Sonra alttaki toplam ve sayac bölümlerinde ise toplam a not'' u ekliyoruz, her seferinde de sayac degerini bir arttiriyoruz ve sayac degeri 6'' ya gelince while döngümüz duruyor. Program sonra toplami alip altiya böler bu sayede ortalamayi alir, sonrada çiktisini gerçeklestirir.
2. Örnek:
//faktoriyel.cpp |
Burda faktoriyel *= sayi--;
evet burda da daha önce gördügümüz gibi esitleme operatörü olan ( *= ) i kullandik. Yani faktoriyel''e faktoriyel*sayi-- nin degeri atanir. Matematigini düsünürseniz; 7 sayisinin faktöriyeli 7 *= 7-- gibi. yani 7 ye devamli 7-- oda 6 demektir. 6 ile carpimi eklenir, bu 6-- ile devam eder. En basit anlatimi bu:) Sonrada tüm while döngüsü bittikten sonrada faktoriyel'' in sonucu çikti olarak ekrana gelir. Bu örnekte negatif sayilarin faktöriyelini de 1''e esit tutuyor. Dikkat ediniz. Negatif sayilarin faktöriyeli alinmaz sartini koymadik. Sayet siz koymak isterseniz bir if else blogu yerlestirmelisiniz if(sayi>=0) faktoriyel al yoksa faktoriyel alma gibi.
3. Örnek:
// maas.cpp |
Switch Case Yapısı
|
Seçicinin aldığı değere eşit seçeneğin olup olmadığına bakar. Var ise o noktadan sonraki deyimler yürütülür. switch deyiminin sonuna gelindiğinde veya break deyimi ile karşılaşıldığında yürütme işlemi durur ve programın akışı switch deyimini izleyen deyim ile devam eder.
|
Sorunu ortadan kaldırma için her durum için break deyimi eklenmeli.
. Seçici Ordinal tiplerden biri olmalıdır (Ordinal tip: tüm değerleri listelenebilinen veri tipleri - integer, char).
. Seçici ile seçenekler aynı tipte olmalıdır.
. default kısmı seçimliktir. Seçeneklerin hiçbiri uygun değil ise yürütülür.
|