Hosgeldiniz...
13 Eylül 2012 Perşembe
C++ Ders Notları
C++ ile Programlama Ders
Notları
1.Hafta (21.02.2012)
C++’ın Programlama Dilleri Arasındaki Yeri
Bilgisayar dünyası 1960’lardan bu yana pek çok dille
tanıştı. Başlangıçta herşey 1’lerden ve 0’lardan meydana geliyordu. O zamanlar
“komut” kavramı bile gelişmemişti. Bilgisayara komut vermek için daha önceden
belirlenmiş sayılar kullanılıyordu. O zamandan bu zamana temel programlama
mantığında çok fazla bir değişim olmadı. Değişen ve gelişen programlama dilleri
oldu. Bu programlama dilleri yakın bir zamana kadar teknolojiden bağımsızken
günümüzde tek başlarına pek bir anlam ifade etmiyorlar. Yeni çıkan bir
programlama dili genellikle başka bir dilden hareketle yazılmış oluyor. “Makine
Dili” hariç bütün diller başka bir dil temel alınarak yazılmıştır ve hepsinin
temeli “Makine Dili”ne dayanır. Peki C++ bu dillerin içinde nerede ve eğer ana
programlama dilimiz makine diliyse, neden yabancı bir dile ihtiyaç duyuyoruz?
Şimdi bu sorulara yanıt arayalım...
Makine dili en hızlı, bilgisayar kaynaklarına doğrudan erişimi
sağlayan ancak o oranda da ilkel bir dildir. Bu cümledeki zıtlığı yaratan
“ilkel” kavramıdır. Ancak burada kullanılan ilkel kelimesi hiçbir şekilde
makine dilinin tercih edilmemesi gerektiğini ifade etmez. Hatta mümkün
olduğunca makine dili kullanmak çok daha “kaliteli” sonuç verecektir. Ne yazık
ki makine dili kullanımı birçok proje için çok zor, zaman zaman işkencedir.
Değişken sayısının çok az oluşu, matematik işlemlerinin yetersizliği,
komutların kısa ve karmaşık isimlendirilmesi, bazı komutların bazı alanlarca
sınırlandırılmaları, ilkelliği oluşturan temel nedenlerdir.
Makine dili kullanılarak, önceleri daha kullanışlı makine
dili editörleri programlandı. Bunlarda artık sadece sayılardan oluşan adresler
yerine yavaş yavaş “label” yani “etiket” diye isimlendirdiğimiz harflerden
oluşan tanımlama satırları eklendi. Zamanla makine dilinden programlanan bazı
program parçalarını, tek bir komut halinde kullanan, ileri düzey diller
geliştirildi. Şu anda dünyada 100’lerce programlama dili var. Özel amaçlı ve
genel amaçlı 10’larca dil büyük kitlelerce kullanılıyor. Bunların hepsinin bir
tek ortak özelliği var: yazılan programı makine
diline çevirir ya da doğrudan makine dilinden komut komut çalıştırır. Bu işi
rakipsiz denebilecek kadar iyi yapan tek dil ise C++. C’ye rakip diller ya yine
C kullanarak yazılmıştır, ya da C’nin türevlerinden biridir. Kısaca özetlemek
gerekirse, C++ hem ileri düzey kullanım rahatlığına sahip hem de oldukça hızlı
bir dildir.
DEĞIŞKENLER
1)İngiliz alfabesindeki
2-) Rakamlar başa gelmez
3-) Derleyici büyük ve küçük harf arasında ayırım yapar
Sayı, SAYI à bu iki tanımlanan değişken aynı değildir
4-) İki alt çizgi veya bir alt çizgi ve sonra gelen büyük
harfle başlayan isimler derleyici tarafından özel amaçlar için kullanılır.
5-) Tek bir alt çizgi karakteri ile başlayan isimler
uygulamalarda genel belirleyiciler olarak kullanılmak üzere ayrılırlar.
6-) İsimler, istenilen uzunlukta olabilir fakat isimdeki kaç
karakterin değerlendirileceği derleyiciye bağlıdır.
7-) Ayrılmış kelimeler belirleyici olarak kullanılamaz.
Ayrılmış kelimelerin yerine anahtar kelimeler sözü de kullanılmaktadır.
C++ Programlama
Dilinin Genel Yapısı
3.1. Basit Bir C++ Programı
C++’ın temelleri 1960’ların sonları ve 1970’lerin başlarına dayansa da
bu dilin C++ adını alması çok daha sonra gerçekleşmiştir. 1970’lerin ve
1980’lerin favori programlama dili C birçok bakımdan ‘kusursuz’ denilebilecek
kadar iyi bir dil idi. Ancak insanoğlu doğası gereğince hep daha fazlasını
isteyerek sonunda C++’a ulaştı. BASIC gibi düşük seviyeli dillerde bir ‘x’
değişkeninin değerini bir arttırmak için ‘x = x + 1’ yazmak yerine C++’da ‘x++’
yazmamız yeterlidir. C’nin yapısı gereği ‘x += 1’ demek de x’i bir
arttırmaktır. Ancak sayıları birer birer saydırmak programcılıkta çok sık karşılaşılan
bir durum olduğu için bu ‘++’ ifadesi kullanılmıştır. ‘++’ bir sonraki anlamına
geldiği için de C’nin bir üst versiyonu C++ ismini almıştır. Şimdi bir C
programının genel yapısını inceleyelim.
1) İçerikler (include)
2) Tanımlamalar (define)
3) Fonksiyonların Tanımlamaları (function prototypes)
Global Değişkenler (global
variables)
4) Ana Fonksiyon (main function)
Diğer Fonksiyonlar (functions)
Burada 1. ve 2. kısımlar C++ komutları değildir. Bunlar compiler’a (C++
derleyicisine) gönderilen komutlardır. Bu komutların başına ‘#’ işareti
konulur. Bu işaret çok önemlidir çünkü ‘if’, ‘else’ gibi hem C++ hem de
compiler komutu olan bazı ortak komutlar mevcuttur. Bu komutların kullanım
biçimi şu şekildedir:
#include <dosya ismi>
#define tanım kalıp
‘#include’ komutu C++’ın içinde gelen birtakım kütüphanelerin (library)
başlık (header) dosyalarını programa ekleyerek bu kütüphanelerde yer alan
bilgileri kullanmamızı sağlar. Bu header dosyaları .h uzantısına sahiptir. ‘stdio.h’,
‘conio.h’, ‘math.h’ gibi C++’ın içerisinde gelen birtakım hazır kütüphane
başlık dosyaları mevcuttur. Bunun yanısıra C programcısı kendi kütüphanesini
kendisi de yaratabilir ya da büyük projelerde programın uzunluğundan dolayı
tanımlamalar için başlık dosyalarını kullanmayı tercih edebilir. Dosya isminin
iki yanına < ve > işaretleri koyarsak derleyici yalnızca kendi ‘include’
klasöründeki başlık dosyalarını arayacaktır. Eğer <.....> yerine tırnak
işareti kullanacak olursak, derleyici öncelikle o anda bulunduğumuz projemize
ait klasörün içinde belirttiğimiz dosyayı arayacak, bulamazsa o zaman kendi
‘include’ klasörüne bakacaktır. Kısaca “.....” şeklindeki kullanımı kendi
yarattığımız header filelar için kullanıyoruz. Örnek:
#include <stdio.h>
#include <conio.h>
#include “tanimlar.h”
C ve C++ arasındaki farklardan biri de C++’ın içerisinde standart C’de gelenden daha fazla kütüphane fonksiyonu
gelmesidir. Örneğin bundan önceki konudaki örnek programda kullandığımız
‘stdio’ kütüphanesi bir C kütüphanesidir. C++, C’nin tüm kütüphanelerini bulundururken, aynı zamanda onların
bazılarına alternatif kütüphaneler de içerir. “Merhaba Dünya!!!” örneğini ‘stdio.h’ yerine bir C++ kütüphanesi olan ‘iostream.h’ kullanarak da yazmamız mümkün. Bu sefer ‘printf’ yerine ‘iostream’in komutu olan cout’u kullanacağız. ‘cout’ ‘printf’e göre daha basit bir kullanım biçimine
sahiptir.
cout << “text” << değişken << özel tanımlamalar
‘#define’ ise programın içerisinde defalarca kullandığımız kalıpları
kısaltmamıza ve programda bazı terimleri daha anlaşılır biçimde kullanmamıza
imkan tanır. Örneğin trigonometrik fonksiyonlarla dolu bir program
yazıyorsunuz. Burada π sayısı
defalarca tekrarlanacaktır. Her seferinde 3.1415926535 yazmak hem sizi
uğraştıracaktır hem de programı daha karışık bir hale sokacaktır. Bunu
engellemek için şu şekilde bir tanımlama yapabiliriz:
#define PI 3.1415926535
C++’da ki dosyalar, kaynak dosyalar(.cpp), projeler(.cproj)
veya (.cbproj) benzeri uzantıya sahiptir. En kısa program örneği olarak;
int main()
{}
|
C++’da ki main fonksiyonu, programlama dilinde kullanılan
program anahtar kelimesinin yerini alır.
#include <iostream.h>
void main()
{
cout
<< "Merhaba Dunya!!!";
}
|
İo stream başlık dosyası diğer programlama dillerinde ekrana
yazdırma ve ekrandan okuma işlemleri için, read, readln, write, writeln
prosedürleri vardır. C++ programlama dilinde ise giriş çıkış işlemlerini
doğrudan gerçekleştiren özel ifadeler yoktur. Bu yüzden, ister klavye, ekran
dosya arasında olsun giriş çıkış işlemleri akış(stream) olarak adlandırılan
sınıfların(class) nesneleri(object) aracılığıyla gerçekleştirilir. Örneğin, en
basit giriş çıkış işlemleri olan ekrandan okuma ve ekrandan yazdırma
işlemleri(console) işlemleri iostream sınıfının cout ve cin isimli nesneleri
aracılığıyla gerçekleştirilir. İostream sınıfı iostream isimli başlık
dosyasında kayıtlıdır. Bu olmadan derleyici
a- çıkış
için kullanılan cout nesnesini ve << ekleme
b- giriş
için kullanılan cin nesnesini ve >> çıkarma işlemcisini tanımaz.
Bu yüzden, iostream isimli başlık dosyasının programının
başına eklenmesi gerekir. #include ön işlemci bildirisi derleyiciye bu
dosyaları derlemeden önce bu dosyalara iostream isimli başlık dosyasını
eklemesini söyler. İostream gibi bir çok başlık dosyası vardır. Akış(stream),
sınıf(class) ve nesne(object) kavramları başlık dosyası olarak kullanılabilir.
main Fonksiyonu
int main()
{
İfadeler
Return 0;
}
1- int
main() fonksiyon başlığıdır. Bu fonksiyonun { ile gövdesi oluşturulur. Bu
ifadelerin her birinin sonunda noktalı virgül(;) işareti bulunur. Main
fonksiyonundan önce gelen int kelimesi fonksiyon çağırıldığında çağıran
programa dönen sonucun tam sayı tipinde olması gerektiğini belirtir. İnt
main(void) şeklinde yazıldığında void kelimesi fonksiyonun argümanının
olmadığını gösterir.
2- Cout
<< “Merhaba Dünya!!! \ n”;
Satırı ekrana Merhaba Dünya!!! Yazar.
Cout teriminden sonra gelen
<< işareti işlemcisi ekrana yaz anlamındadır.
Cin >> a; ifadesi de a isimli değişkenin değerini
ekrandan okutur. Cin’den sonra gelen >> işlemcisi çıkarma işlemcisidir.
Ekrandan oku anlamına gelir.
\n kursörün bir alt satırın başına geçmesini sağlar.
Return 0; ifadesi de fonksiyonun
çağıran programa döndüreceği değerin 0 olduğunu gösterir. Dönüş değerinin 0
olması fonksiyonun derlenmesinin, başarılı olduğunu işletim sistemine
bildirmesini ifade eder. 0’dan farklı dönüş değeri, hata anlamına gelir.
Örnek 2 ;
#include <iostream>
using namespace std;
int main()
{ cout << "
Hosgeldiniz!\n";
int a; cin >> a;
return 0;
}
|
Örnek 3 ;
#include<iostream.h>
int main()
{
cout << "A
E I" << endl;
cout << "B
D F" << endl;
return 0;
}
ÖDEV 1: Ekrana
aşağıdaki çıktıyı veren programı yazınız
*** ***
*** ***
*** ***
***
***
***
ÖDEV 2: Ekrana
aşağıdaki çıktıyı veren programı yazınız
*** ANKARA ***
*** İSTANBUL ***
Fonksiyonlar
Fonksiyonlar, en önemli bloklardan biridir. Fonksiyonun
tanımlandığı bloğa fonksiyon bloğu denir. Fonksiyon bloğunda,
1- Fonksiyonun
adı (main)
2- Fonksiyonun
adından sonra gelen () lerinin içine yerleştirilen argüman listesi
3- Fonksiyonun
adından önce gelen bir dönüş veri tipi (int)
4- Fonksiyonun
gövdesi olarak adlandırılan küme parantezleri arasında yer alan kısım
5- Fonksiyon
gövdesinden sonra noktalı virgül yazılmaz.
. Programa açıklama satırı yazmanın iki yolu vardır.
1) İki tane düz slaş karakteri (//) kullandığımız taktirde bunların sağ
tarafında kalan alan compiler tarafından atlanır. Bu yalnızca bulunduğu satır
için geçerlidir.
2) Düz slaştan sonra çarpı kullanırsak (/*) compiler çarpıdan sonra düz slaş (*/) görünceye kadar bloğun tamamını atlar. Bu tek satır için değil bütün program alanı için geçerlidir.
2) Düz slaştan sonra çarpı kullanırsak (/*) compiler çarpıdan sonra düz slaş (*/) görünceye kadar bloğun tamamını atlar. Bu tek satır için değil bütün program alanı için geçerlidir.
Fonksiyonlar içinde kullanılan ifadeler, basit ifadeler ve basit olmayan ifadeler
olarak ikiye ayrılır.
1-Basit İfadeler:
int a;
a=12; è atama ifadesi
yıldız yaz (); è fonksiyon çağırma
ifadesi
go to son; è go to ifadesi
2-Basit Olmayan İfadeler:
Birleşik ifadeler
int x;
x=x+10;
Seçme İfadeleri
1- İki
durumdan birini seçme
if (x>0) y=sqrt(x);
2- İki
şeyden birini seçme
if(x>y)
y=sqrt(x-y);
else y=sqrt(y-x);
3-
Çok şey
arasından birini seçme
Notu=65;
Switch(nout)
{ case 45 : cout
<< “45” ;
break;
case 60 : cout
<< “60” ;
break;
case 85 : cout
<< “85” ;
break;
default : cout << “??”; break;
}
SAYI SİSTEMLERİ ve BELLEK YAPISI
Bu bölümde bilgisayarın bellek yapısını inceleyeceğiz. Bu
yapıyı kavrayabilmek için öncelikle bazı sayı sistemleri hakkında bilgi
edinmemiz gerekiyor.
Daha önce de söylendiği gibi bilgisayar için en uygun sayı
sistemi sadece iki rakamı (0 ve 1) olan ikili sayı sistemidir. Aslında
bilgisayar 1 ve 0’ın ne olduğunu “bilmez”. En eski yarı mekanik hesap
makinelerinden günümüzdeki mikroçip teknolojisinin en üst düzeyde kullanıldığı
elektronik bilgisayarlara kadar bütün bilgisayarlar olup bitenleri tek bir
sorgulamayla anlar. “Devre açık mı, kapalı mı?” yani “Elektrik akımı geçiyor
mu, geçmiyor mu?”. “Devre açık” yani “akım geçmiyor” durumunu “0” ; “devre kapalı” yani “akım
geçiyor” durumunu da “1”
ile temsil ederiz. Burada “0”
bilgi yok, “1”
ise bilgi var anlamındadır. O halde, örneğin 137 sayısını 1 ve 0’ları
kullanarak nasıl ifade edeceğiz.
Sayı Sistemleri
İkili Sayı Sistemi,
BIT ve BYTE Kavramları
İ. Bizim kullandığımız sayı sistemi on tabanında yani onlu
sayı sistemidir.
ikili tabanda bir örnek çözelim ve sonra bu tabanın
özelliklerini inceleyelim.
(101011)2 = (1 * 20) + (1 * 21)
+ (0 * 22) + (1 * 23) + (0 * 24) + (1 * 25)
(101011)2 = (1 * 1) + (1 * 2) + (0 * 4) + (1 *
8) + (0 * 16) + (1 * 32)
(101011)2 = 1 + 2 + 8 + 32
(101011)2 = 43
İkili sayı sisteminde 0 ve 1 harici bir rakam
kullanılamayacağı için pratikte işlemlerin ilk iki aşamasını atlamak mümkün.
İkili düzende verilen sayının basamaklarını sağdan sola doğru 1’den başlamak
suretiyle 2’nin üsleri şeklinde sayıp 0 olanlarını atlar, 1 olanları toplarsak
sayıyı onlu olarak elde ederiz.
“Bütün pozitif tamsayılar 2’nin pozitif tamsayı üstlerinin
toplamından elde edilebilir.”
Daha önce de belirtildiği gibi bellek byte’lardan
oluşmuştur. Ancak byte’ların sayısı arttıkça hesap kolaylığı için üst birimler
tanımlanmıştır. Tıpkı gram, kilogram gibi byte da başına kilo (bin), mega
(milyon), giga (milyar), tera (trilyon) gibi ekler alır. Ancak byte’lar ikili
sistem üzerine kurulduğu için gramda olduğu gibi 1000’er 1000’er değil, bunun
yerine 2’nin 1000’e en yakın üssü olan 210 = 1024’er 1024’er
artarlar.
1 TeraByte =
1024 GigaByte
1 GigaByte =
1024 MegaByte
1 MegaByte =
1024 KiloByte
1 KiloByte =
1024 Byte
Ara dönüşümler
de klasik yöntemle hesaplanabilir.
1 MegaByte =
1024 x 1024 Byte = 1048576 Byte
1 TeraByte =
1024 x 1024 x 1024 KiloByte = 1073741824 KiloByte
Bellek
birimleri de ağırılık, uzunluk birimleri gibi kısaltmalara sahiptirler.
TeraByte = TB
GigaByte = GB
MegaByte = MB
KiloByte = KB
Byte
genellikle B diye kısaltılmaz ve “byte” şeklinde kullanılır.
TEMEL VERİ TİPLERİ
1-
Tam Sayı
Veri Tipleri : C++’da; bool, char, short, int ve long gibi tam sayı veri tipleri bulunur. Basit veri tipli değişkenler sadece
bir değer taşıyabilirler.
int a;
a=4321;
bu tam sayı 4 byte’lık bellek alanına yerleştirilmiştir.
İşaretsiz tam sayılarda, başına unsigned deyimi getirilir.
Böylece unsigned char, unsigned short, unsigned int ve
unsigned long veri tipleri elde edilir.
Tablo 1 Tam sayı ve
Ondalık sayı veri tipleri
Veri Tipi
|
Alt Sınıf
|
Üst Sınıf
|
Duyarlı Basamak
Sayısı
|
Bellek Alanı (byte)
|
Bool
|
False
|
True
|
yok
|
1
|
Char
|
-128
|
127
|
Yok
|
1
|
Short
|
-32768
|
32767
|
Yok
|
2
|
İnt
|
-2147483648
|
2147483647
|
Yok
|
4
|
Long
|
-2147483648
|
2147483647
|
yok
|
4
|
|
|
|
|
|
Float
|
3,4x10^-38
|
3,4x10^38
|
7
|
4
|
Double
|
1,7x10^-308
|
1,7x10^308
|
15
|
8
|
Long double
|
3,4x10^-4932
|
3,4x10^4932
|
19
|
10
|
Tablo 2 İşaretsiz Tam
Sayı Veri Tipleri
Veri Tipi
|
Alt Sınıf
|
Üst Sınır
|
Bellek Alanı (byte)
|
Unsigned char
|
0
|
255
|
1
|
Wchar_t
|
0
|
32767
|
2
|
Unsigned short
|
0
|
65535
|
2
|
Unsigned int
|
0
|
4294967295
|
4
|
Unsigned long
|
0
|
4294967295
|
4
|
Yazacağımız programda, sayıların tiplerini doğru kullanırsak
programımız daha hızlı çalışır ve aynı zamanda bellekte bizim kullanmamız için
daha çok yer kalır. Yazacağımız syı ondalık sayı ise program yavaş çalışır.
SAYILAR
a) Kayan Noktalı Sayılar (Floating Point Numbers)
a1- long (Uzun kayan
noktalı sayılar)
a2- double (Çift
Duyarlı kayan noktalı sayı)
b) Tam Sayılar (Integers)
b1- int (Normal Tam sayı)
b2- short( Kısa Tam sayı)
b3- long ( Uzun Tam sayı
)
b4- char (Karakter)
b5- İşaretsizler (Unsigned)
b5.1- unsigned int (
İşaretsiz tamsayı)
b5.2- unsigned short
(İşaretsiz kısa tamsayı)
b5.3- unsigned long (
İşaretsiz uzun tamsayı)
Örnek: 5000000000
( Beş milyar )
Bu sayı, unsigned int veya long olarak verilir. Bu sayının büyüklüğü, 4milyar basamağındadır.
( 4 294 467 295)… Yani 5 milyar sayısını tam sayı olarak ifade edemeyiz.
Ondalık sayı veri tipi olarak kullanılarak çözülür.
Örneğin, 2.23 à 2,23e+0
1230000 à 1,23e+6
0.00000123 à 1,23e-6
Örnek:
float deg2;
deg2= 1.6e-19;
Bu sayı 4 byte’lık bellek bölgesine yerleştirilir.
|
Karakter veri tipi
ve küçük tamsayılar
Karakter veri tipi, char,
harf ve rakamları saklamak için kullanılır. ASCII karakter kodları ve benzer
kodlama sistemleri geliştirilmiştir. ASCII kod sisteminde “a” karakteri 97
sayısıyla temsil edilir.
Örnek: char
tipindeki karakter değişkeninin bellekteki yerleşimi
Kar = “a”
İfadesindeki “a” karakterinin ASCII karakteri kodu 97’dir.
|
Örnek 1: 700 tam
sayısını ekrana yazan bir C++ programı yazınız..
#include<iostream.h>
int main()
{
int a;
a=700;
cout<<a;
return 0;
}
|
Örnek 2: Ekrana 3*6=18 yazdıran programı yazdırınız..
#include<iostream.h>
int main()
{
cout <<"3*6=";
cout <<3*6;
return 0;
}
|
|
#include<iostream.h>
int main()
{
int a;
int b;
a=3;
b=6;
cout<<"3*6=";
cout<<a*b;
return 0;
}
|
Örnek 3: a
harfini ASCII kodunu yazan C++ programını yazınız
#include<iostream.h>
int main()
{
int
ch;
ch='a';
cout<<"a'nin
ASCII kodu ";
cout<<
ch;
cout<<"
dir";
return
0;
}
|
Örnek 4: Tek
duyarlı kayan noktalı (float) tipi sayılarla ilgili bir örnek program yazınız.
Örneğin, a=8.909 olan…
Örnek 5: char
veri tipli bir büyüklüğün int veri tipli
bir değişkene atanması, int verip tipli bir büyüklüğün karakter veri tipli bir
değişkene atanması örneği
#include<iostream.h>
int
main()
{
char ch1= 'A';
cout << " ch1= " << ch1 <<
"\n\n";
char ch2= '\t';
cout << "Tab karakterinin etkisine dikkat!"
" A nin yazildigi yere bak!\n"
<<"\n"<< ch2;
int i = ch1;
cout << ch1 << " nin ASCII karakter kodu :
" << i;
i= ch1;
cout << "\n\n Bir karakter gir : "; cin
>> ch1;
i=ch1;
cout << " \n Karakterin ASCII kodu : "
<< i;
cout << " \n\n Kucuk bir tam sayi gir : ";
cin >> i;
char ch3 = i;
cout << "\n\n Tam sayinin ASCII karakteri : "
<<ch3;
cin >> ch1;
return 0;
}
|
1-)B değişkenine 1000 değerini atayıp,bu sayıyı ekranda
görünteleyiniz.
2-)Bir üçgenin taban kenarı 12.8 yüksekliği 2.01 cm’dir,alanını hesaplayınız.
3-)Ekrana ANKARA yazdıran programı yazın(char türü değişken
kullanarak)
4-)x=298 olarak verildiğine göre x/60 ve x%60 işlemlerini
yapan programı yazınız.
5-) Ekrana ATA yazdıran program yazın(ASCII kodlarını
kullanarak).
2.Hafta
İşaretli ve İşaretsiz Tam Sayılar
Tamsayı işaretli olarak
tanımlanmışsa, derleyici sayının en yüksek değerli bitini işaret biti olarak
kabul eder. İşaret biti 0 ise sayı artı, 1 ise eksi olarak işlem görür.
İşaretsiz kısa tam sayı, bellekte 16 bitlik yer kaplar. 16 bit, onluk sayı
sisteminde 65535 sayısal değerine karşılık gelir. 65535 değeri bellekte 16 bitlik
bir sayının en büyük değeri olması için en soldaki biti 0, diğer tüm bitlerin 1
olması gerekir. Bu durumda, sayının alacağı en büyük değer 32767 ‘dir.
|
0 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 à +32767
işaretli tamsayı
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 à -32767
(signed int)
|
“char” (karakter
veri tipi)
Tek bir karakter saklanmak istendiğinde, değişken türü char
olarak bildirilir. Karakter veri türü, bellekte 1 byte’lık yer işgal eder.
#include <iostream.h>
int main()
{
char
ch;
ch='B';
cout
<<"ch'nin degeri "<<ch;
return
0;
}
|
Amerikan Ulusal Standartlar Enstitüsü tarafından her bir
karakter standart olarak sayısal bir kodla gösterilir ve bu koda ASCII kodu
denilir.
ÖRNEK : Bir firma
gidiş dönüş otobüs bileti alındığında bilet fiyatı üzerinden %20 indirim
yapmaktadır. İndirim uygulanmamış bilet ücreti, 10,000,000 TL olduğuna gör e,
yapılan indirimin ve indirim yapılmış bilet ücretini bulunuz. (Çift duyarlı kayan noktalı sayılar “double”
sayılara örnek)
#include <iostream.h>
int main()
{
double
bilet,indirim,in_fiyat;
bilet=10000000;
indirim=(bilet*.2);
in_fiyat=bilet-indirim;
cout
<< "indirim ";
cout
<< indirim<<"Tl'dir";
cout
<<"\n indirilmis fiyat ";
cout
<< in_fiyat<<" Tl'dir";
return
0 ;
}
|
Değişkenlere değer
verilmesi
1-
int a;
a=10;
|
2-
char harf;
harf=’B’;
|
C++ programlama dilinde karakterlerin saklanması için özel
bir veri türü yoktur. Bunları saklamak için, karakter türü bir boyutlu dizi
oluşturulur. Dizi, aynı türdeki veri elemanlarının art arda gelmesinden oluşur.
Örneğin, “ANKARA” katarını, bellekte saklamak için maksimum 11 elemanlı bir
dizi oluşturulur.
dyer[0]=İ[0]=A
İ[1]=N
İ[2]=K
İ[3]=A
İ[4]=R
İ[5]=A
İ[6]=\0
... İ[10]
ÖRNEK: Doğum yeri
giriniz. Girilen doğum yerini ekrana yazan programı yazınız.
#include <iostream.h>
int main()
{
char dyer[10];
cout
<< "Dogum yerini giriniz \n"; cin>>dyer;
cout<<"
dogum yeriniz";
cout<<dyer;
return
0;
}
|
ÖRNEK: Doğum
yerinizin ilk harfini yazan programı yazınız.
#include <iostream.h>
int main()
{
char
dyer[10];
cout<<"Dogum
yerini giriniz\n";
cin>>dyer;
cout<<"
dogum yeriniz"<<dyer;
cout<<"\n
dogum yerinizin ilk harfi.."; cout<<dyer[0];
return
0;
}
|
ÖRNEK: “ANKARA”
katarını ekrana yazan bir program hazırlayınız
#include <iostream.h>
int main()
{
char
dyer[]="Ankara";
cout<<"
dogum yeriniz " <<dyer<<"dir";
return
0;
}
|
ÖRNEK: “strcpy”
dizi kopyalama komutunu kullanarak “ANKARA” katarını “dyer” değişkenine
kopyalayan programı yazınız.
#include <iostream.h>
#include <cstring>
int main()
{
char
dyer[10];
strcpy(dyer,"Ankara");
cout
<< dyer;
return
0;
}
|
ARİTMETİK
İŞLEMCİLER
X=10 ve Y=3 değerleri için X’i Y’ye bölmenin sonucun ve
artık bölme işleminin (mod) sonucunu veren programı yazınız. - Artık
bölme için “%” sembolü kullanılır. -
#include <iostream.h>
int main()
{
int
x, y;
x=10;
y=3;
cout
<< "Bolmenin sonucu" << x/y<<endl;
cout
<< " Artik bolme isleminin sonucu " << x%y ;
return
0;
}
|
ÖRNEK: Çift
duyarlı kayan noktalı sayı “double” ya da tek duyarlı kayan noktalı sayı (float) veri
türleri için, “fmod()”
fonksiyonunu kullanan bir örnek yazınız. x =18 y=4 için.
#include
<iostream.h>
#include
<math.h>
int
main()
{
double x,y;
double z;
x=18;
y=4;
z=fmod(x,y);
cout << "Artik bolme isleminin
sonucu bolmenin sonucu " <<z;
return 0;
}
|
Bit İlişkili
(Bitwise) İşlemciler
SİMGE
|
İŞLEMCİ
|
& (ampersand)
|
VE (AND)
|
|
|
VEYA (OR)
|
^
|
ÖZEL VEYA (XOR)
|
!
|
DEĞİL (NOT)
|
<<
|
Bir bit sola
kaydır.
|
>>
|
Bir bit sağa
kaydır.
|
Bunları içeren bir
örnek;
#include <iostream.h>
int main()
{
int
a=24, b=12;
int
c,d,e;
c=a&b;
d=a^b;
e=a|b;
cout
<<"a&b="<<c<<endl;
cout
<<"a^b="<<d<<endl;
cout
<<"a|b="<<e<<endl;
return
0;
}
|
0001 1000 à 24
0000 1100 à 12
0 1000 a&b=8 AND
1 0100 a^b=20 XOR
1 1100 a|b=28 OR
Sağa (>>) ve
Sola (<<) kaydırma işlemleri
a>>4 ç Kaymanın kaç basamak olduğunu gösterir
Örneğin, 1331 sayısını iki basamak sola kaydırma işlemini
yapan
8192
4096
|
2048
1024
512
256
|
128
64
32
16
|
8
4
2
1
|
=1331
|
0 0
0 0
|
0 1
0 1
|
0 0
1 1
|
0 0
1 1
|
0 0
|
0 0 0
1
|
0 1 0
0
|
1 1 0
0
|
1 1 0
0
|
=5324
|
|
4096
|
1024
|
128
64
|
8
4
|
|
İki basamak sol kaydırılmak istenildiğinde, tüm bitler iki
basamak sola ötelenecektir. Ve yeni sayıda ötelemeden dolayı ortaya çıkan
boşluk iki sıfır eklenerek doldurulacaktır. Böylece, bitlerin konumu
değişecektir. Örneğin, önce değerlikleri sırasıyla 1 ve 2 olan bir değerlikli
ilk 2 bitin değeri, yeni durumda 4 ve 8 olacaktır. Bu durum, tüm bitler için
geçerlidir. Yeni sayı önceki değerden büyük olacaktır. Sola kaydırma işlemi
sonucunda, kaydırılan sayının alacağı değer bulunurken 1 bitlik sola kaydırma
sayısının 2^1=2, iki bitlik sola kaydırma işleminin tekrar ikiyle çarpılması
ile bulunur 2^2=4. Burada ise 1331 * 4 =
5324 olarak bulunmuştur.
ÖRNEK: İki
basamak sağ ve sola kaydırma yapınca elde ettiğimiz sonucu yazan bir program.
#include <iostream.h>
int main()
{
int
x,y,z;
x=1331;
y=x<<2;
z=x>>2;
cout
<<"x in iki basamak sola kaydirilmisi"<<y<<endl;
cout<<"x
in iki basamak saga kaydirilmisi"<<z;
return
0;
}
|
İlişkisel
İşlemciler
= = eşit anlamındadır.
!= eşit değil anlamındadır.
Mantıksal
İşlemciler
&&
|
VE (AND)
|
||
|
VEYA (OR)
|
|
|
DEĞİL (not)
|
ÖRNEK : (a<b
|| x<y) ifadesini yazan programı yazınız.
#include <iostream.h>
int main()
{
int
a=10, b=2;
int
x=1, y=5;
if(a<b
|| x<y)
cout<<"Karsilastirma
dogru";
return
0;
}
|
ÖZEL İŞLEMCİLER: C++ birçok özel işlemciye sahiptir;artırım
ve eksiltim
,işaretçi (pointer),ilişkili işlemci,virgül,cast ve sizeof
dur.
Artırım ve Eksiltim : Artırım(++) ve eksiltim(--) işlemcilerine sahip
olmasıdır.Eksiltim işlemcisi değişkenin değerini bir azaltırken artırım
işlemcisi de değişkeninin değerini bir çoğaltır.
X++;
|
X=X+1;
|
X--;
|
X=X-1;
|
X++ deyiminde önce x değişkeni kullanılır sonra artırma
işlemi yapılır.++X deyiminde ise önce artırma işlemi yapılır,sonra X değişkeni
kullanılır.
Örnek
#include<iostream.h>
int main()
{
int a,b;
a=7,b=7;
cout<<"a="<<++a<<endl;
cout<<"b="<<b++;
return 0;
}
Sonuç
a=8:b=7
Virgül
İşlemcisi
Virgül işlemcisi virgül ile
ayrılan birden çok deyimin tek bir deyim gibi değerlendirilmesini
sağlar.Virgülün sol yanında kalan deyimler kendi başlarına ifade edilebilir.
Örnek
a=(x=15,x+5): bu ifadeyi çalıştıran programı yazınız.
#include<iostream.h>
int main()
{
int a,x;
a=(x=15,x+5);
cout<<"a
degiskenin degeri"<<a;
return
0;
}
a=20
Kalıp(Cast işlemcisi)
Değişkenlerin veri türlerini
kalıp(cast işlemcisi) ile değiştirebilirsiniz.İki türlü yapılır ;açık(explicit)
veya örtük (implicit).
Bir tamsayı değerini kayan
noktalı double(sayı) değerine çevirip,ekranda kayan noktalı değer sonucunu veren bir örtük kalıbına bir örnek yazınız.
ÇÖZÜM:örtük kalıba örnek
#include<iostream.h>
int main()
{
int a=6;
double
b=2.4;
float c;
c=a+b;
cout<<c;
return
0;
}
8.4
Açık kalıp işlemi
Genelde açık kalıp işlemi tercih edilir.Bu tür tanımlamada değişkenden önce
tür ismi yazılır.Bununla ilgili bir örnek yazınız.
Örnek;
#include<iostream.h>
int main()
{
double
a=2.5,b=5.2;
int c;
c=(int)a+int(b);
cout<<"c
isleminin sonucu"<<c;
return
0;
}
7
Sizeof()
işlemcisi :
Sizeof işlemcisi herhangi bir
değişken türünün bellekte kaç bayt yer kapladığını belirtir.
Kullanım biçimi
;
Sizeof(değişken adı) , sizeof(veritürü)
Örnek;
Sizeof(a) ifadesi ile a
değişken türü olan tamsayı(int) veri türünün sizeof(d) ile d değişken veri türü
olan uzun tamsayı(long) veri türünün bellekte kapladığı yer bulan programı
yazınız.
#include<iostream.h>
int main()
{
int a=4;
double b=6.0;
short c=2;
long d=6;
double e=7.0;
cout<<"tamsayinin(integer)
tuttugu yer"<<sizeof(a);
cout<<"\n kisa tamsayinin(short)
tuttugu yer"<<sizeof(c);
cout<<"\n uzun tamsayinin(long)
tuttugu yer"<<sizeof(d);
cout<<"\n cift duyarli kayan
noktanın sayinin tuttugu yer"<<sizeof(b);
cout<<"\n cift duyarli kayan
noktanın sayinin tuttugu yer"<<sizeof(e);
return 0;
}
4,2,4,8,8
Örnek;
#include<iostream.h>
int main()
{
signed long int a=25000;
int b=3;
int c;
c=(a*b)/5;
cout<<"sonuc"<<c;
return 0;
}
Örnek;
#include<iostream.h>
int main()
{
int a=9;
int b=0;
int c;
c=a/b;
cout<<”sonuc”<<c;
return 0;
}
Divide =
ERROR hatası verir.
Önişlemci Komutları
ANSI C’de bulunan önişlemci
komutları şunlardır:
#define #if #pragma
#endif
#ifdef #undef
#elif
#ifndef #else
#include #error #line
#define önişlemcisi
ÖRNEK;
#define KUP((a)*(a)*(a))
#define ON 10
#define PI 3.14
#define SABIT 0.55
Ödev;
1-) #define önişlemcisi kullanarak pi sayısını 3.14
olarak programın başında tanımlayarak dairenin alanı ve çevresini bulan
programı yazınız.(r=5)
2-)a=(x=10,x+15) işlemini
yaptıran programı yazınız.
3-)a=8 b=3 olarak
verildiğinde bu sayılarla ve(&) ,or(|) işlemini gerçekleştiren programı
yazınız.
4-)3840 sayısını önce iki
basamak sola sonra da iki basamak sağa kaydıran programı yazınız.
5-)a=5,b=4 ise
a<b,a<=b,a>b,a>=b,a==b,a!=b işlemlerini gerçekleştiren programı
yazınız.
#include ön işlemcisi
Derleyicinin, özel ek
dosyaları okumasını ister. Ek dosyalar, kaynak dosyaların bir parçasıdır. Genellikle
programın başındaki #define ön işlemcisini, #include dosyasından ayırmamız
gerekebilir. #include ile #define dosyasını ayırmamız gerekebilir.
#define
RT ( (1/r1) + (1/r2) )
#include
<iostream.h>
int
main()
{
float r1,r2,rtp;
cout<<"r1 direncini
girin";
cin>>r1;
cout<<"r2 direncini
girin";
cin>>r2;
rtp=1/RT;
cout<<"paralel es direnc
dir.\n"<<rtp;
return 0;
}
|
Not : Bu örnekte kullandığımız program üzerinde değişiklik yaparak bir başlık
(header “.h”) dosyası oluşturalım. Bunun için derleyicide NEW seçeneği seçilip
“#define RT ( (1/r1) + (1/r2) )” satırını
yazdıktan sonra sürücüye “.h” uzantısıyla kaydetmemiz gerekir. Eğer C
sürücüsünde çalışıyorsak c:\RT.h olarak satırı kaydederiz. Daha sonra yeni
programın içinde #include “C.RT.h”
yazmamız gerekir.
#include
<iostream.h>
#include
<C:\DOCUMENTS AND SETTINGS\OGR\RT.h>
int
main()
{
float r1,r2,rtp,rt;
cout<<"r1 direncini
girin";
cin>>r1;
cout<<"r2 direncini
girin";
cin>>r2;
rtp=1/RT;
cout<<"paralel es
direnc"<<rtp<<" 'dir";
return 0;
}
|
Temel Giriş ve Çıkış Fonksiyonları
Ara Bellek ( Buffer ) : Arabellek, giriş ve çıkış fonksiyonlarının etkinliğini
arttırmak için kullanılan tekniktir. Herhangi bir bilgisayar sisteminde program
işletilirken programın en yavaş çalışan kısmı okuma ve yazma bölümüdür.
Arabellek kullanılarak okuma ve yazma hızı arttırmaktadır. Basit olarak
arabellek, çıkış cihazı yazıma hazır olana kadar veya bilgisayar bilgi girişine
hazır olana kadar verilenin başka bir yerden geçici olarak saklanmasıdır.
Özellikle dosya işlemlerinde arabellek çok önemlidir. Şimdilik arabelleğin
sadece çıkış ve giriş işlemlerinde kullanıldığının bilinmesi yeterli olacaktır.
Bu bölümde kullanılan tüm fonksiyonlarda arabellek kullanılmıştır.
Formatlı Giriş ve Çıkış İşlemleri
Biçim Tanımlayıcıları
Biçim
Tanımlayıcı
|
Anlamı
|
|
%d
|
Onlu (decimal) tam sayı
|
|
%c
|
Tek karakter
|
|
%s
|
Karakter katarı
|
|
%f
|
Ondalıklı sayı
|
|
%e
|
Ondalıklı sayı (üslü gösterimi ile)
|
|
%g
|
%e veya %f hangisi kısa ise
|
|
%u
|
İşaretsiz onlu tamsayı
|
|
%o
|
İşaretsiz sekizli tamsayı
|
|
%x
|
İşaretsiz on altılı tamsayı
|
|
Örnek :
#include
<iostream.h>
int
main()
{
char il[15];
cout<<"il ismini girin
\n";
cin>>il;
cout<<".....Cikis.....\n";
cout<<"il: "<<il;
return 0;
}
|
Soru : Üç
takımın adını ve puanlarını klavyeden girip, girdiğimiz bu bilgileri
görüntüleyen bir program yazınız.
Programda kullanılan
değişkenler
tak 1 I.
Takımın Adı --- p1 I .Takımın Puanı
tak 2 II.
Takımın Adı ---- p2 II .Takımın Puanı
tak 3 III.
Takımın Adı ---- p3 III .Takımın Puanı
#include
<iostream.h>
int
main()
{
char tak1[20];
char tak2[20];
char tak3[20];
int p1,p2,p3;
cout<<"Birinci takim adini
ve puanini giriniz";
cin>>tak1>>p1;
cout<<"Ikinci takim adini ve
puanini giriniz";
cin>>tak2>>p2;
cout<<"Ucuncu takim adini ve
puanini giriniz";
cin>>tak3>>p3;
cout<<"TAKIM PUAN \n";
cout<<"------ ------
\n";
cout<<tak1<<"\t\t"<<p1<<endl;
cout<<tak2<<"\t\t"<<p2<<endl;
cout<<tak3<<"\t\t"<<p3<<endl;
return 0;
}
|
TAKIM PUAN
---------- ---------
GS
78
FB 78
BT 78
IF ve SWITCH İFADELERİNİN YAPISI
İki çeşit denetim yapısı
vardır.
1-
Karşılaştırmalı
2-
Tekrarlı ( Döngü)
Karşılaştırmalı denetim Deyimlerinin Türleri
if
(denetim ifadesi)
deyim ;
|
1 – “if” ifadesinden sonra
parantez içerisinde yazılan ifadeyle karşılaştırma yapılmaktadır.
2 – “if” ifadesinden sonra
“;” karakteri yoktur, “;” karakteri sadece deyimin sonunda vardır.
3 – Denetim ifadesi doğru iken
(sıfır değilken), denetim ifadesindeki deyim işletilmektedir.
Örnek : Bir
öğrencinin notu ekrandan girilmektedir. Notu 50’den büyük eşit ise ekrana
başarılı yazan programı yazınız.
#include
<iostream.h>
int
main()
{
int not;
cout<<"Ogrencinin notu nedir";
cin>>not;
if (not>=50)
{
cout<<"Basarili\n";
cout<<"Ogrencinin
aldigi not"<<not;
}
return 0;
}
|
If – Else İfadeleri ( İki yollu Kontrol )
Bazı programlarda “if”
ifadesindeki koşula bağlı olarak, koşul doğru ise bir deyimin, yanlış ise bir
diğer deyimin işletilmesi yapılır.
Örnek : Bir
öğrencinin notu ekrandan girilmektedir. Notu 50’den büyük eşit ise ekrana
“başarılı”, hayır ise, “başarısız” yazan
programı yazınız.
#include
<iostream.h>
int
main()
{
int not;
cout<<"Ogrencinin notu nedir";
cin>>not;
if (not>=50)
{
cout<<"Basarili\n";
cout<<"Ogrencinin
aldigi not"<<not;
}
else
{
cout<<"Basarisiz
\n";
cout<<"Daha cok
calismaniz gerekmektedir"; }
return 0;
}
|
Örnek :
Klavyeden girilen iki sayının, azalan ya da artan sıralama olduğunu bulan
programı hazırlyınız.
#include
<iostream.h>
int
main()
{
int say1,say2;
cout<< "Iki sayi
giriniz";
cin>>say1>>say2;
if (say1>say2)
cout<<"Azalan
siralama \n"<<say1
<<"\t"<<say2;
else
cout<<"Artan siralama
\n"<<say1
<<"\t"<<say2;
return 0;
}
|
Örnek :
Klavyeden girilen iki sayıyı küçükten büyüğe doğru sıralayan programı
hazırlayınız.
#include
<iostream.h>
int
main()
{
int say1,say2,tut;
cout<< "Iki sayi
giriniz";
cin>>say1>>say2;
if (say1>say2)
{
tut=say1;
say1=say2;
say2=tut;
}
cout<<"Artan
siralama \n"<<say1
<<"\t"<<say2;
return 0;
}
|
ÖDEV 1 : Bir
banka 100 TL’ye kadar yapılacak havale işlemlerinde %1 komisyon, 100 TL
üzerindeki havale işlemlerine %2 komisyon almaktadır. Buna göre havale bedelini
girerek ödenmesi gerekli komisyon miktarını bulan programı yazınız.
SORU:Bir sınıftaki
örgencilerin girilen notunu harfe çeviren programı hazırlayınız
notu<60 F
notu<74 C
notu<84 B
….A
#include <iostream.h>
using namespace std;
//========================================
int main()
{
int notu;
char Kar = 'a';
cout << "ders kayidi? (e/h) : "; cin
>> Kar;
if (Kar == 'h')
{
cout << "dersi secmeliydin!";
goto son;
};
cout << "notu gir :"; cin >>notu;
if (notu<60)
{
cout<< "F";
goto son;
}
else if (notu <74)
{
cout << "C";
goto son;
}
else if (notu< 84)
{
cout<< "B";
goto son;
}
else
cout <<"A";
son:
cin >> notu;
return 0;
}
Soru: + toplama, -çıkarma,*
çarpma, /bölme yapan programı hazırlayınız
#include<iostream.h>
int main()
{
int a=10,b=5;
char ara;
cout<<"İslemciyi girin";
cin>>ara;
if(ara=='+')
cout<<a<<"+"<<b<<"="<<a+b;
else if(ara=='-')
cout<<a<<"-"<<b<<"="<<a-b;
else if(ara=='*')
cout<<a<<"*"<<b<<"="<<a*b;
else if(ara=='/')
cout<<a<<"/"<<b<<"="<<a/b;
return 0;
}
Switch İfadeleri:
İkiden çok durum arasında
birini seçmek gerektiği zaman switch ifadesi kullanılır. Bu ifade;
Switch(Tam sayı veya karakter
tipli değişken)
{
Case 1: ifade;…;ifade;break;
Case 2: ifade;…;ifade;break;
Default: ifade;…;ifade;
}
SORU: Klavyeden üç sayı
giriniz. Switch yapısı kullanarak 1 girdiğimizde birinci sayının karesini 2
girdiğimizde ikinci sayının karesini 3 girdiğimizde üçüncü sayının karesini
bulan programı yazınız.
#include<iostream.h>
void main()
{
int a,b,c,d,x;
cout<<"birinci sayiyi gir";
cin>>a;
cout<<"ikinci sayiyi gir";
cin>>b;
cout<<"ücüncü sayiyi gir";
cin>>c;
cout<<"Tercihinizi giriniz(1/2/3)";
cin>>x;
switch(x)
{
case 1: d=a*a;
cout<<"Birinci sayinin
karesi"<<d;
break;
case 2: d=b*b;
cout<<"ikinci sayinin
karesi"<<d;
break;
case 3: d=c*c;
cout<<"ucuncu sayinin
karesi"<<d;
break;
default:
cout<<"Bilinmeyen islemci\n";
}
}
SORU: Ekrandan aldığı derslerin harf karşılığı girildiğinde sayısal
karşılığını veren programı yazın.
#include<iostream.h>
//============================================
int main()
{
int notu;
char Kar, harf;
cout<<"Ders kayidi? (e/h) : "; cin>>
Kar;
if (Kar == 'h')
{
cout<<"Dersi secmeliydin!";
goto son;
}
cout<<"\nHarfi gir : ";cin>> harf;
cout<<"\n\n Girilen notun tahmin araligi :
";
switch(harf)
{
case 'F' : cout<<"0...59 arasi."; break;
case 'C' : cout<<"60...74 arasi.";break;
case 'B' : cout<<"75...84 arasi.";break;
case 'A' : cout<<"85...100 arasi.";break;
default : cout<<"\Hatali Giris!"; break;
}
son:
cin>>notu;
return 0;
}
Break deyimi ile switch blogundan cıkıs sağlanır.
DÖNGÜLER:
1-) for Döngüsü: for döngüsü
kullanımı en kolay döngüdür. For ile başlar ardından (birbirinden “;” ile
ayrılan) üç deyim gelir.
For(j=0;j<10;j++)
ÖRNEK:j nin değerini birer
boşluk ara ile satıra yazdıran dongu
#include<iostream.h>
int main()
{
int j;
for(j=0;j<10;j++)
cout<<j<<endl;
for(j=0;j<10;j++)
cout<<j<<' ';
cin>>j;
return 0;
}
ÖRNEK:
#include<iostream.h>
int main()
{
static char blg[]="sube";
int syc;
for(syc=1;syc<=6;syc++)
cout<<blg<<syc<<"\n";
return 0;
}
NOT: Değişkenler mümkün
olduğunca küçük bellek alanı kaplamalıdır. Fonksiyonlarda ana programa değer
aktarması yaparken extern anahtar sözcüğü kullanarak dışsal tanımlamalar tercih
edilir. Dört tane saklama sınıfı vardır.
Saklama sınıf
|
Anahtar sözcük
|
Süreklilik
|
Alan
|
Otomatik
|
auto
|
geçici
|
Yerel
|
Dışsal
|
extern
|
kalıcı
|
Genel
|
Statik
|
static
|
kalıcı
|
Genel
|
Yazmaç
|
register
|
geçici
|
Yerel
|
Static char blg[6]=”sube”;
Faktöriyel Hesaplaması:
#include<iostream.h>
int main()
{
int faktoriyel=1,i,n;
cout<<"Bir tamsayi girin";
cin>>n;
for(i=1;i<=n;i++)
faktoriyel=faktoriyel*i;
cout<<"\n"<<n<<"!="<<faktoriyel;
return 0;
}
#include<iostream.h>
int main()
{ unsigned int sayi;
unsigned long faktoriyel=1;
int faktoriyel=1,i,n;
cout<<"Bir tamsayi girin";
cin>>n;
for(int j=n;j>0;j--)
faktoriyel=faktoriyel*j;
cout<<"\n"<<n<<"!="<<faktoriyel;
cin>>n:
return 0;
}
get :Klavyeden tek karekter okuyarak ilgili degiskene
aktarir
cin.get(degisken);
getline:Klavyeden
belirtilen uzunluga kadar karekter dizisi okur/
cin.getline(degisken,uzunluk);
getline(cin,degisken);
#include <iostream.h>
char a[50] , b[50];
int main()
{
cout<<"1.cumle:";
cin.getline(a,50);
cout<< "2. cumle:";
cin.getline(b,5);
cout<< "\n getline ile alinan:" << a <<endl;
cout<< "\n getline ile alinan:" << b <<endl;
return 0;
}
WHILE DÖNGÜSÜ
Kullanım şekli böyledir
while (denetim ifadesi)
{
Deyim-1;
Deyim-2;
.
.
Deyim-n;
}
|
Bir işin kaç kere
tekrarlanacağını, döngüye girene kadar bilmiyorsak while döngüsü kullanılır. While döngüsünün tercih edilmesinin
sebebi, bu döngüde kontrolün döngünün başında yapılmasıdır. While döngüsünün,
döngü şartı sağlanmazsa gövdenin hiç işlemeyeceğini ifade eder. Denetim ifadesi
doğru ise, deyim işletilir. Bu işlem denetim ifadesi yanlış olana kadar devam
eder. Denetim ifadesi yanlış olduğunda program deyimden sonraki satıra gider.
Diğer denetim ifadelerinde olduğu gibi birden çok deyim var ise bu deyimler aç,
kapa ve küme parantezi arasına alınır.
Örnek: n=0
olana kadar çalışan bir program
#include
<iostream.h>
int
main()
{
int n;
cout<<"sifirdan farkli bir sayi
gir:";
cin>>n;
while(n!=0)
cin >>n;
return 0;
}
|
Örnek:
x>1 şartı sağlanana kadar çalışan programı yazınız
#include
<iostream.h>
int
main()
{
int
x;
x=5;
while(x>1)
{
x=x-1;
cout<<"x in degeri
"<<x<<"\n";
}
cout<<"dongu burada
bitti";
return 0;
}
|
4-3-2-1
DO WHILE DÖNGÜSÜ
do
Deyim
while(kontrol ifadesi);
|
Bir grup deyimi işlettikten
sonra, denetim ifadesini kontrol eder. Denetim ifadesi doğru ise deyim grubu
tekrar işletilir. Eğer yanlış ise, program döngüden çıkar. Do while döngüsünün while
döngüsünden farklı yanı, denetim ifadesinin döngünün sonunda olmasıdır.
“””
#include
<iostream.h>
int
main()
{
int x;
x=5;
do
{
x=x-1;
cout<<"x in
degeri" << x << "\n";
}
while(x>1);
cout<<"dongu burada
bitti";
return 0;
}
|
Örnek :
#include
<iostream.h>
int
main()
{
int sayac=0;
float say,ort,top;
top=0.0;
cout<<"lutfen ortalamasi
bulunacak sayilari giriniz \n"; cout<<"programi
bitirmek icin sifir giriniz \n";
do
{
cin>>say;
top=top+say;
sayac++;
}
while(say!=0.0);
ort=top/(sayac-1);
cout<<"ortalama"<<ort;
return 0;
}
|
Denetim ve artırım ifadeleri for döngüsünde yazılmazsa, sonsuz
döngüye girilir.
Örnek : z=2*sqrt(x-2)/y
#include
<math.h>
int
main()
{
char Kar;
int x,y;
double z;
bas:
cout << "\n Bir tam sayi gir
: " ; cin >> x;
cout << "\n Bir tam sayi gir
: " ; cin >> y;
if ( x>=2 && y !=0)
{
z=2*sqrt(x-2)/y;
cout << "\n z =
" << z;
}
else
cout <<" \n Sayilar
uygun degilé";
cout <<" \n\n Devam mi?
(e/h) : ";
cin >> Kar;
if ( Kar == 'e' && z > 100 )
{
goto bas;
}
return 0 ;
}
|
BİR BOYUTLU DİZİLER
Bir boyutlu dizi oluşturmak
için
1-
Dizinin
elemanlarında saklanan veri tipi
2-
Dizinin ismi
3-
Dizideki
elemanların sayısı ( [] parantezlerinin içinde ) belirtilmelidir.
Dizinin eleman sayısı ,10
gibi bir tam sayı sabiti veya bir const değer veya 3 * sizeof(int) gibi, büyüklüğü derleme sırasında bilinen sabit bir
ifade olabilir,fakat değişken olamaz.
Örneğin, 4 elemanlı bir sayı dizisi oluşturunuz.
#include
<iostream.h>
#include
<conio.h>
int
main()
{
int sayi[5];
for(int j=1;j<5;j++)
{
cin>>sayi[j];
cout<<"\n sayi["
<< j << "] = " << sayi[j];
}
return 0;
}
|
Dizinin 2.elemanını ekranda görüntüleyiniz
#include
<iostream.h>
#include
<conio.h>
int
main()
{
int sayi[5];
for(int j=1;j<5;j++)
{
cin>>sayi[j];
cout<<"\n sayi["
<< j << "] = " << sayi[j];
}
cout<<"\n
sayi[" << 2 << "] = " << sayi[2];
return 0;
}
|
Bir dizinin elemanlarına ilk değerlerinin atanmasını
sağlayan örnek ;
#include <iostream.h>
int main()
{
int ay,gun,gunTop;
int
AyGunSay[12]={31,28,31,30,31,30,31,31,30,31,30,31};
cout<<"\n 1 ile 12
arasında ayi gir:";
cin>>ay;
cout<<"\n 1 ile 31
arasında gun u gir:";
cin>>gun;
gunTop=gun;
for(int j=0;j<ay - 1;j++)
gunTop=gunTop+AyGunSay[j];
cout<<"Gun
sayisi:"<<gunTop; cin>>ay;
return 0;
}
İki Boyutlu Diziler
İki boyutlu bir dizi
oluşturmak için;
1-)Dizinin elemanlarında
saklanan verinin tipi,
2-)Dizinin ismi
3-)Dizideki satır ve
sütunların sayıları [ ] [ ]
Double dizi [i] [j] ;
İki boyutlu bir dizinin
ekranda okutulması ve ekranda yazdırılması ;
#include<iostream.h>
const int D=4;
const int M=3;
int main()
{
int d,m;
double dizi[D] [M];
for(d=0;d<D;d++)
for(m=0;m<M;m++)
{
cout<<d+1<<".satir";
cout<<m+1<<".sutun icin
sayi gir:";
cin>>dizi[d] [m];
}
cout<<"\n\n";
cout<<"sutunlar: 1 2 3\n";
for(d=0;d<D;d++)
{
cout<<"\n "
<<d+1<<".satir \t";
for(m=0;m<M;m++)
cout<<dizi[d] [m] ;
}
cin>>d;
return 0;
}
#include<iostream.h>
const int D=3;
const int M=3;
int main()
{
int d,m;
double dizi[D] [M];
for(d=0;d<D;d++)
for(m=0;m<M;m++)
{
cout<<d+1<<".satir";
cout<<m+1<<".sutun icin
sayi gir:";
cin>>dizi[d] [m];
if
(d==m) dizi[d] [m] = 1 ;
else dizi[d] [m] =0;
}
cout<<"\n\n";
cout<<"sutunlar: 1 2 3\n";
for(d=0;d<D;d++)
{
cout<<"\n "
<<d+1<<".satir \t";
for(m=0;m<M;m++)
cout<<dizi[d] [m] ;
}
cin>>d;
return 0;
}
3 kişinin boy,yaş, ağırlığını programı yazınız.(tek
boyutlu)
#include <iostream.h>
const int I = 3;
struct bilgi
{
int boyu,yasi;
float agirligi;
};
int main()
{
bilgi bil[I];
for(int n=0;n<I;n++)
{
cout<<"\n Boyu
gir:";cin>>bil[n].boyu;
cout<<"\nYasi
gir:";cin>>bil[n].yasi;
cout<<"\n Agirligi gir:";
cin>>bil[n].agirligi;
}
for(int m=0;m<I;m++)
{
cout<<"\n\n
Boyu:"<<bil[m].boyu;
cout<<"\n
Yasi:"<<bil[m].yasi;
cout<<"\n
Agirligi:"<<bil[m].agirligi;
}
int i; cin>>i;
return 0;
}
ÖDEV
1-)Tam sayı veri tipli ve 10
elemanlı bir dizi tanımlayınız ve bu dizinin elemanlarına başlangıç değeri
olarak 0 atayınız.Bu dizinin sadece ilk elemanına başlangıç değeri olarak 1
atarsanız kalan elemanların başlangıç değerleri ne olur?
2-)1’den 20’ye kadar olan tam
sayıların toplamını ;
a)for b)while ve c)do while
yapısını kullanarak bir diziye atayan ve bu dizinin elemanlarını ekrana
yazdıran C++ programlarını yazınız.
3-)3 satır 3 sütünlu bir M
matrisi oluşturunuz.
a-) Her satırın toplamını
b-)Her sütunun toplamını
c-)Köşegenlerinin toplamını
hesaplayan programı
hazırlayınız.
STRING VE KARAKTER TİPLİ DİZİLER
String
Bellekteki ardışık byte lara
kaydedilen karakterlerden oluşan bir dizidir.İki tiptir
1-)C- stili string.
2-)String sınıfının bir nesnesi
olarak tanımlanan string.
Bellekteki ardışık byte lara
karakterlerlerin kaydedilmesi şeklinde oluşan dizi kavramı,bizi; string’in char
tipli bir dizi olduğu sonucuna götürür.
C-stili string’in kendine has
bir özelliği her string’in son karakterinin ‘\0’ şeklinde yazılan null
karakteri olmasıdır. Örnek;
Char
kar1[5]={‘a’,’b’,’e’,’d’,’z’); // C-stili string değil !
Char kar2[5]= {‘c’,’f’,’g’,’u’,’\0’); // String
Bu dizilerin her ikisi de
char tipli,fakat sadece ikincisi C-stili string’dir.C-stili string’de null
karakteri önemli bir rol oynar.
Soru
Karakter katarı sabitleri.İlk değer atanmış karakteri
katarı örneği.
#include<iostream.h>
int main()
{
char st[]="Bugun hava cok sicak degil.";
cout<<st<<endl;
int i;cin>>i;
return 0;
}
#include<iostream.h>
#include<conio.h>
int main()
{
const int M=5;
char st[M];
cout<<"\n Bir cumle gir:"; cin.get(st,M);
cout<<"Girdiginiz
cumle:"<<st<<endl;
int i;cin>>i;
return 0;
}
İki boyutlu karakter dizisi
#include<iostream.h>
#include<conio.h>
int main()
{
const int G=4;
const int K=4;
char dizi [G][K]
={"Sal","Car","Prs","Cum"};
for (int j=0;j<G;j++)
cout<<dizi[j]<<endl;getch();
return 0;
}
YAPI ve NUMARALAMA VERİ TİPLERİ
Yapı veri tipi bir değişken,
tipleri farklı olabilen birden çok veriyi saklar. Bir yapının içinde tanımlanan
değişiklikler de olabilir. Bunların bazıları int veri tipinde, bazıları float
veri tipinde ya da diğer tiplerden birinde olabilir. Bu bakımdan yapılar, tek
tip verileri saklayabilen dizilerden farklıdır.
Yapı Veri Tipi Tanımları
1.struct anahtar kelimesi olması gerekir (blok başlatan bildiri
deyimi)
2.bilgi, yapı veri tipinin adı ya da etiketi
3.{…..}, Küme Parantezleri
4.; işareti (noktalı virgül)
Örneğimizde, adı , boyu, yaşı
ve ağırlığı yapı veri tipinin elemanları olan değişken isimleridir. Küme
parantez kapandıktan sonra gelen noktalı virgül işareti yapı veri tanımının
sonunu gösterir. Bilgi isimli yapı veri tanımında değişkenlerin tanımlanmasında
sadece bir taslak görevi görür. Yapı değişkeni tanımlanmış olmaz yani bu
tanımlama bellekte yer ayırmaz. Bu basit bir değişkenin tanımından farklıdır.
Basit bir değişken tanımlandığında bu değişken için bellekte yer de ayrılmış
olur.
Örnek: Yapı
ve struct (record=kayıt) veri tipi program
#include <iostream.h>
#include <conio.h>
const int M = 80;
struct bilgi
{
char adi[M];
int boyu, yasi;
float agirligi;
};
int main()
{
bilgi bil;
cout<< "\n Adini gir : ";
cin>> bil.adi;
cout<< "\n Boyunu gir : ";
cin>> bil.boyu;
cout<< "\n Yasini gir : ";
cin>> bil.yasi;
cout<< "\n Agirligini gir : ";
cin>> bil.agirligi;
cout<< "\n Adi : " << bil.adi;
cout<< " \n Boyu : " << bil.boyu
<< " cm";
cout<< ", Yasi : " << bil.yasi;
cout<< " , Agirligi : " <<
bil.agirligi << " kg";
return 0;
}
Yapı Veri Tipi Değişken Tanımlama
bilgi bil ;
Bilgi tipinde bil adında bir
değişken tanımlar. Bu tanım bellekte bil
için yer ayırır. Yani, adı (80 byte), boyu (4 byte), yasi(4 byte) ve
ağırlığı için 4 byte değişkenlerini saklamaya yetecek kadar. Toplam olarak 92
byte bellekte yer ayırır.
Yapının Üyelerine (Elemanlarına) Erişme
Yapı veri tipi bir değişken
tanımlandığı andan itibaren, bu değişkenini üyelerinin elamanlarına ( . ) nokta işlemcisi kullanılarak
erişilebilir. Bir üyeye değer verme işlemi şöyle olabilir.
bil.boyu= 172;
Bu ifade 3 parçadan oluşur
1. Yapı değişkeninin ismi
(örnekte bil)
2. Nokta işlemcisi
(Yukarıdaki örnekte : . )
3. Üyenin elemanının ismi (
örnekte : boyu)
Nokta işlemcisinin asıl ismi
üyeye erişme işlemcisidir.
Yapı üyelerine ilk değer atanması
#include <iostream.h>
#include <conio.h>
const int M = 80;
struct bilgi
{
char adi[M];
int boyu, yasi;
float agirligi;
};
int main()
{
bilgi bil = { "Mustafa" , 168, 20, 72.44F};
cout<< "\n Adi : " << bil.adi;
cout << "\n Boyu : " << bil.boyu
<< "cm";
cout<< " , Yasi : " << bil.yasi;
cout <<" , Agirligi : " <<
bil.agirligi << " kg " ;
bilgi bil2;
bil2=bil;
cout<< " \n Adi : " << bil2.adi;
cout << "\n\nBoyu : " << bil2.boyu
<< "cm";
cout<< " Yasi : " <<
bil2.yasi ;
cout << " Agirligi : " <<
bil2.agirligi << " kg " ;
return 0;
}
Yapı üyelerine atanacak
değerle küme parantezlerinin içine yazılı ve birbirlerinden virgül ile ayrılır.
Listedeki ilk değer birinciye ve ikinci ise ikinciye atanır ve böylece devam
eder.
YAPI İÇİNDE YAPI
Bir yapı veri tipini de yeni
bir yapı veri tanımında kullanmak mümkündür. Aşağıdaki örneğimizde Oda isimli yapı veri tipinin tanımında uzunluk isimli yapı veri tipi
kullanılmaktadır.
#include <iostream.h>
#include <conio.h>
struct Uzunluk
{
int fit;
float inc;
};
struct Oda
{
Uzunluk en ;
Uzunluk boy;
};
int main()
{
Oda yemekOd;
yemekOd.en.fit= 13;
yemekOd.en.inc = 6.5;
yemekOd.boy.fit = 10;
yemekOd.boy.inc = 0.0 ;
float E = yemekOd.en.fit + yemekOd.en.inc / 12;
float B = yemekOd.boy.fit + yemekOd.boy.inc / 12;
cout << " Yemek odasinin alani = " <<
E * B << " fit kare .
\n";
return 0;
}
Kümelenmiş yapıların üyelerine erişme
Yapılar kümelendiğinde,
üyelere erişmek için nokta iki kez kullanılır.
yemekOd.en.fit = 13;
1.
yemek.Od,Oda
tipli değişkenin adıdır.
2.
en, Oda
tipli dış yapının Uzunluk yapı tipli
bir üyesidir.
3.
fit ise Uzunluk tipli iç yapının int tipli bir üyesidir.
Dolayısıyla fit’e erişebilmek için önce en dıştaki değişkene (yemekOd), sonra bunun içindekine (en), daha sonra ise onun içindeki (fit)’e erişmek gerekir.
Yani, yemekOd
isimli yapı değişkeninden yola çıkıp Oda
yapı tipinde, sonra Oda yapı
tipinin en isimli elemanına, daha sonra en elemanının tipi olan Uzunluk tanımında bulun fit isimli alan
değişkenine ulaşılır.
AnaDeğişken à AnaTip, Anatip à AlanDeğişkeni, AlanDeğişkeni à İçTip, İçTip à İçDeğişken, vs sırası izlenir
Yemek à Oda, Oda à en, en à Uzunluk , Uzunluk à fit vs. sonuçta
yemekOd.en.fit sırası ortaya
çıkar.
Kümelenmiş Yapılara İlk Değer Atama
OdayemekOd = { {13,6.5}, {10,0.0}};
Uzunluk’a {13,6.5}, ikinci
Uzunluk’a {10,0.0 } değerleri atanmış daha sonra Oda tipli yemekOd değişkenine
atanır.
Kümelenme Derinliği
#include <iostream.h>
#include <conio.h>
const int sinek = 0 ;
const int karo = 1 ;
const int kupa = 2 ;
const int maca = 3 ;
const int vale = 11 ;
const int kiz = 12;
const int papaz = 13 ;
const int as= 14;
struct kart
{
int rakam;
int seri;
};
int main()
{
kart yedek, secilen, tutulan;
int sira;
kart kart1 = { 7, sinek };
cout << " 1.kart sinek 7 li \n";
kart kart2 = { vale, kupa };
cout << " 2.kart kupa vale \n";
kart kart3 = { as, maca };
cout << " 3.kart maca as \n";
tutulan = kart3;
cout<< " 1.kart ile 3.karti degistiriyorum
\n";
yedek = kart3;
kart3 = kart1;
kart1= yedek;
cout<< " 2.kart ile 3.karti degistiriyorum
\n";
yedek = kart3;
kart3 = kart2;
kart2=yedek;
cout<< " 1.kart ile 2.karti
degistiriyorum\n";
yedek=kart2;
kart2=kart1;
kart1=yedek;
cout<< "Uc kagittan birini sec (1, 2, 3) : ";
cin>> sira;
switch(sira)
{
case 1 : secilen = kart1;break;
case 2 : secilen = kart2;break;
case 3 : secilen = kart3;break;
}
cout<< "Sectigin karti ac.maca as i mi?";
if(secilen.rakam == tutulan.rakam &&
secilen.seri == tutulan.seri)
cout<< "Evet! Kazandiniz!\n";
else
cout<< "Uzgunum! Kaybettiniz \n";
return 0;
}
NUMARALAMA VERİ TİPLERİ
Yapı struct kullanıcı tarafından
çok elemanlı veri tipi tanımlama yollarından biridir. Numaralandırma yani
enumeration isimlendiriyoruz
Numaralanma veri tipi bu veri
tipinin alabileceği sınırlı değerlerin listesini önceden bildiğimiz durumlarda
işimize yarar
enum olarak
tanımlanır
Soru: Haftanın günlerini
temsil eden enum veri tipinde bir
örnek yazınız.
#include <iostream.h>
#include<conio.h>
enum HaftaGun {Pz, Pzt, Sa,
Ca, Pe, Cu , Ct};
int main()
{
HaftaGun gun1,gun2;
gun1 = Sa;
gun2 = Cu;
int fark = gun2 - gun1;
cout<<"Fark =
"<<fark<<endl;
if (gun1<gun2)
cout<<"1. gun,
once gelir. \n";
else
cout<<"1. gun,
sonra gelir. \n";
getch();
return 0;
}
Numaralandırma derleyici
tarafından tam sayı olarak ele alınır.
Listedeki ilk elemanın degeri
0 dır0,1,2 diye devam eder.
#include <iostream.h>
#include<conio.h>
enum cevap {hayir,evet};
int main()
{
cevap cev = hayir;
char ch = 'a';
int KelimeSayisi = 0;
cout<<"Bir cumle yaziniz: \n";
do
{
ch = getche();
if (ch == ' ' || ch == '\r')
{ if (cev
== evet)
{KelimeSayisi++;cev = hayir;}
}
else
if (cev == hayir) cev = evet;
}
while (ch!= '\r');
cout<<"\n Kelime Sayisi:
"<<KelimeSayisi<<"---- \n";
getche();
return 0;
}
FONKSİYONLAR
C++ programında bir şey yaptırılacağı
zaman, o işi yapacak olan bir fonksiyon çağırılır. Fonksiyon birkaç tane
program ifadesini tek bir blok içinde toplar ve buna bir isim verir. Bu blok
daha sonra programın diğer blokları tarafından kullanılmak üzere çağırılır. Bir
fonksiyon, deklare edilmeden önce çağırılmaz.
Argümansız (Basit) Fonksiyonlar
Bir fonksiyonu bir program
içinde kullanabilmek için gerekli 3 işlem vardır.
1.
Fonksiyonun
deklarasyonu (the function declaration)
2.
Fonksiyona
yapılan çağrılar (the calls to the function)
3.
Fonksiyonun
tanımı (the function definition)
Fonksiyonu Deklare Etmek
Bir fonksiyonu derleyiciye
bildirmeden kullanamayız. Bunun için farklı 2 yol vardır.
1.
Fonksiyonu
çağırmadan önce deklare etme
2.
Fonksiyonu
çağırmadan önce tanımlama
Örneğin p1.cpp programında,
YildizYaz() fonksiyonu
void YildizYaz();
şeklinde deklare edilmiştir.
Bu deklarasyon, derleyiciye daha sonraki bir noktada YildizYaz adında bir
fonksiyon kullanacağımızı ve bunun şekli hakkında bize hatırlatma yapmak için
söylenir. void anahtar kelimesi, fonksiyonun geri döndüreceği bir değerin
olmadığını gösterir. İçi boş parantezler [ () ] fonksiyonun argümanlarının
olmadığını gösterir. Ve noktalı virgülle sona erdirilir. Bir fonksiyonu program
içinde istediğimiz sayıda çağırabiliriz. Fonksiyonun tanımını yaparken
1.
void YildizYaz();
fonksiyon başlığı ile,
2.
{…} küme
parantezleri arasında yer alan fonksiyon gövdesinde oluşur.
Fonksiyon başlığı,
fonksiyonun deklarasyonu ile uyuşmak zorundadır. Yani fonksiyon ismini
kullanmalı, ve döndürdüğü değer aynı olmalıdır.
Programda kullanılan
fonksiyonun ve fonksiyonun denklarasyonu ve tanımı, #include <conio.h>
isimli başlık dosyasındadır. getche() fonksiyonunun tanımı ise, derlenip makine
diline çevrilmiş olarak programımız çalıştığında programımıza kendiliğinden bağlanan
bir kütüphane dosyasının içindedir.
YildizYaz() fonksiyonunu
tanımlayan bir program.
#include <iostream.h>
#include<conio.h>
#include <iomanip.h>
void YildizYaz();
int main()
{
YildizYaz();
cout<<setw(10)<<"Adi: ";
cout<<setw(24)<<"Ege UNIVERSITESI \n";
YildizYaz();
cout<<setw(30)<<"ISTATISTIK
"<<endl;
YildizYaz();
getch();
return 0;
}
void YildizYaz()
{
for (int j=0;j<50;j++)
cout<<'*';
cout<<endl;
}
Fonksiyonun Tanımı:
void YildizYaz()
{
for (int j=0;j<50;j++)
cout<<'*';
cout<<endl;
}
<iomanip.h>
à
Bazı biçimleyicileri kullanmak için kullanılan başlık dosyasıdır.
|
C++’da bazı kütüphaneler
#include<kutuphane adı>
İostream : Temel işlemler ve
ekran komutları
Windows : Windows
uygulamaları fonksiyon ve makro
Vectors : dizi işlemleri ile
ilgili fonksiyonlar
Limits : sayısal sınıflar
New : dinamik bellek
kullanımı ve işlemleri
Complex : karmaşık sayı
sistemleri
Algorithms : özellikle eleman
dizili fonksiyonlar
SINAVA HAZIRLIK SORULARI
1-
Klavyeden
girilen 5 elemanlı bir A dizisindeki pozitif elemanları B dizisine, negatif
elemanları da C dizisine yerleştiren programı yazınız.
#include
<iostream.h>
int
main()
{
int i;
int x=0,y=0;
int A[5],B[5],C[5];
cout<<"\n A Dizisinin:
\n";
for(i=0;i<5;i++)
{
cout<< i+1 <<". elemani=";
cin>> A[i];
}
for(i=0;i<5;i++)
{
if(A[i]>0) {x++;B[x-1]=A[i];}
if(A[i]<0) {y++;C[y-1]=A[i];}
}
cout<<"\n B dizisi: \n";
for(i=0;i<x;i++)
cout<<B[i]<<"\t";
cout<<"\n C dizisi:\n";
for(i=0;i<y;i++)
cout<<C[i]<<"\t";
return 0;
}
|
2-
Klavyeden girilen 3 adet nokta çiftinden, kaç
tanesinin
(x-a)^2+(y-b)^2=r^2 dairesinin içinde kaç tanesinin dışında
ve kaç tanesinin üzerinde olduğunu bulan
programı yazınız.
#include <iostream.h>
using namespace std;
int i, a, b, r, isay=0, usay=0, dsay=0;
float F;
int main()
{
cout<<"Daire
merkezinin koordinatlari ve yaricapi: \n";
cout<<
" x koordinati => ";
cin>>a;
cout<<"
y koordinati =>";
cin>>b;
cout<<"Yaricapi=>";
cin>>r;
int
X[3],Y[3];
cout<<"\n";
for(i=0;i<3;i++)
{
F=(X[i]-a)*(X[i]-a)+(Y[i]-b)*(Y[i]-b);
if(F<(r*r))
isay++;
else
if(F>(r*r)) dsay++;
else usay++;
}
cout<<
"\n Dairenin => \n";
cout
<<" Icindekilerin sayisi => "
<<isay<<"\n";
cout <<" Uzerindekilerin sayisi => "
<<usay<<"\n";
cout <<"
Disindailerin sayisi => " <<dsay<<"\n";
return
0;
}
X=2
Y=3
r=5
nokta sayısı 3
|
3- Klavyeden
girilen 3 elemanlı A dizisinin aritmetik, geometrik ve harmonik ortalamasını
hesaplayan programı yazınız.
#include
<iostream.h>
#include
<math.h>
int
i;
float
T=0,C=1,HT=0,AO,GO,HO;
int
main()
{
float A[3];
cout << "\n";
for(i=0;i<3;i++)
{
cout
<<"A("<<i<<")=";
cin>>A[i];
}
for(i=0;i<3;i++)
{
T+=A[i];
C*=A[i];
HT+=1/A[i];
}
AO=T/3;
GO=pow(C,(1.0/3));
HO=3/HT;
cout <<"\n Dizinin aritmetik
ortalamasi = "<< AO << endl; cout
<< "Dizinin geometrik ortalamasi = "<< GO <<
endl;
cout <<" Dizinin harmonik
ortalamasi = "<< HO << endl;
return 0;
}
|
4- Sayısal
analizde belirli integral hesaplamak için diğer popüler yöntem de yamuklar
yöntemidir. Dikdörtgenler yönteminde; fonksiyon ile eksen arasında kalan alan,
dikdörtgenlere bölünürken yamuklar yönteminde ise yamuklara bölünmektedir ve
sonuç yamuk alanlarının toplamı şeklinde oluşmaktadır. belirli integrali
hesaplanırken [a,b] aralığı n tane parçaya bölünür ve yüksekliği h= (b-a)/n
olan yamuklara tamamlanır.
Buna göre klavyeden parça(oluşturacak
yamuk) sayısı girilen f(x)=3x^2+2x fonksiyonunun belirli integralini verilen [a
b] aralığında hesaplayan program.
BUNU FİNALDE YAPACAKMIŞIZ
5-
Fibonacci
Serisini oluşturan programı yazınız.
#include <iostream.h>
using namespace std;
unsigned N,T1,T2,T3;
int main()
{
cout<<
"Fibonacci Serisi" << endl;
cout
<< " Terim sayisi: " ;
cin>>
N;
T1=1;
T2=1;
cout
<< "\n " << T1 << " \t" << T2
<< "\t";
for(int
i=1;i<=N-2;i++)
{
T3=T1+T2;
cout
<< T3 << "|\t";
T1=T2;
T2=T3;
}
return
0 ;
}
|
6-
Cos(x)
fonksiyonu, Maclaurin serisine aşağıdaki gibi açılmaktadır. Buna göre klavyeden
girilen x değerinin cosinus’unu belirtilen terim sayısına kadar seriye açarak
hesaplayan program.
Cos(x)= 1-(x^2/2!)+ (x^4/4!)+ (x^6/6!)+…..=
Şeklinde ortaya çıkar.
#include
<iostream.h>
#include
<math.h>
int
aci,N,is;
float
X,F,T=1;
const
float PI=3.14;
int
main()
{
cout<<" Aci degeri: " ;
cin>> aci;
cout << " Terim sayisi: " ;
cin>> N;
X=aci * PI/180;
is=1;
for(int i=1;i<N;i++)
{
F=1;
for(int j=1;j<2*i;j++) F*=j;
is*=(-1);
T+=is*pow(X,2*i)/F;
}
cout << " \n Seri acilimi ile
hesaplanan deger: " << T<< endl;
cout << " Komutla hesaplanan
deger: " << cos(X) << endl;
return 0;
}
|
7-
Klavyeden
katsayıları girilen ikinci dereceden fonksiyonun
köklerini
bulan programı hazırlayınız?
#include
<iostream.h>
#include
<math.h>
float
a,b,c,d,x1,x2;
int
main()
{
cout<< "A=";
cin>>a;
cout<<"B=";
cin>>b;
cout<<"C=";
cin>>c;
d=b*b-4*a*c;
cout<<"\n";
if(d>0)
{
cout<<"Gercel
koklervardir: "<<endl;
x1=(-b-sqrt(d))/(2*a);
x2=(-b+sqrt(d))/(2*a);
cout<<"Kokler:"
<<x1<<"\t"<<x2<<endl;
}
else if(d==0)
{
cout<< "Katli kok
vardir : " << endl;
x1=-b/(2*a);
cout<<"Katli kok:
" <<x1<<endl;
}
else cout <<"Sanal kokler
vardir. " << endl;
return 0;
}
|
8- Klavyeden girilen bir sayının
tamsayı olup olmadığını test eden programı hazırlayınız.
#include
<iostream.h>
int
main()
{
float s;
cout<< "Bir sayi giriniz:
" ;
cin>>s;
if(s-(int) s ==0) cout << "
Tamsayi";
else cout << " Tamsayi degil
" ;
return 0 ;
}
|
9 - Bir ve
kendisinden başka tamsayıya bölünmeyen sayılara asal sayı denir. Buna göre
klavyeden girilen üst sınıra kadar olan asal sayıları yazdıran programı
yazınız.
#include
<iostream.h>
int
N,s;
int
main()
{
cout << " Belirtilen
araliktaki ASAL sayilar \n";
cout << " \n Ust sinir =>
" ;
cin >> N;
cout << " \n+++ ASAL SAYILAR
+++\n " << endl;
for(int i=2;i<=N;i++)
{
s=0;
for(int j=1;j<=i;j++)
if(i%j==0) s++;
if(s==2) cout
<< i << "\t";
}
return 0 ;
}
|
10-
1 ile 5
arasında girilen notlara göre başarıyı yazan program.
#include
<iostream.h>
int
a;
int
main()
{
cout << " Notunuzu
giriniz< (1-5) => ";
cin>>a;
switch(a)
{
case 1: { cout << " Cok
zayif " << endl ; break; }
case
2: { cout << " Zayif " << endl ; break; }
case 3: { cout << " Orta
" << endl ; break; }
case 4: { cout << " Iyi
" << endl ; break; }
case 5: { cout << " Cok iyi
" << endl ; break; }
default: { cout << "
Gecersiz not " << endl; break; }
}
return 0 ;
}
|
11-
NxN tipinde 2
matrisinin elemanlarını ekrana yazdırınız
#include <iostream.h>
int A[100][100];
int main()
{
int A[3][3];
cout << " \n A Matrisi : \n";
for (int i=0;i<3;i++)
{ for(int j=0;j<3;j++)
{
cout <<
"A("<<i<<","<<j<<")=";
cin>> A[i][j];
}
}
{
cout << " A matrisi : \n ";
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
cout << A[i][j] << "
\t";
cout << " \n";
}
return 0 ;
}
1-
Bir struct
yapılardan soru
2-
Tek boyutlu
diziler
3-
İki boyutlu
diziler
4-
Ardı ardına döngü
ile soru
5-
While case
kullanımı switch
6-
Enum ile ilgili
kullanım
Fonksiyon tanımını kutuphane fonksiyonu
ile karşılaştırma
Kütaphane
fonksiyonlarının deklerasyonunun ve
tanımını örneğin getche() fonksiyonu deklerSYONU
#İNCLUDE<CONİO.H>
Başlık
dosyasındadır.
Program
derlenip çalıştığında fonksiyonun tanımı derlenip makına diline çevrilmiş
olarak kendiliğinden baglanan kutuphane dosyasının içindedir.
Fonksiyonların Deklerasyonundan kurtulma
Fonksiyonun deklerasyonunu yazmadan
fonksiyona yapılacak ilk cagrıdan once fonksiyonun tanımını programın
listesının ıcıne yerleştırmek gerekır.
Void YıldızYaz();
Argumanlı Fonksiyonlar
Fonksıyonları tanımlarken ( ) içi daha
once bostu bunlar argumansız fonksıyonlardı. Arguman cagıran program tarafından
bir fonksiyona gonderılen verıdır.
Ornegın Yıldızyaz() fonksıyonunda
herhangi bir karekteri herhangı bır sayıda yazan bir fonksıyon olarak
tanımlayabılırız.
#include
<iostream.h>
#include
<iomanip.h>
using
namespace std;
#include
<conio.h>
int
main()
{
KarakterYaz('+',60);
cout<< setw(10) <<"Adi
:";
cout<< setw(24) <<"Prof.
Dr. Mustafa Dkici\n";
KarakterYaz('+',65);
cout<< setw(30)
<<"IslemTamam!" <<endl;
KarakterYaz('+',70);
getch();
return 0;
}
Not: Bu fonksiyonun deklarasyonu void karakter (char,int); şeklindedir.
Buradaki, parantez içindeki char ve int, KarakterYaz() fonksiyonuna çağıran
program tarafından gönderilecek argümanların veri tipleridir. Örnekte,
KarakterYaz(‘+’,60) fonksiyon içinde uygun yerlere yerleştirilmiştir. Ekrana 60
tane ‘+’ işareti yazması gerekir.
Fonksiyonu
çağıran program, fonksiyona gerekli argümanları sağlar. Fonksiyonun içinde bu
argümanları saklamak için kullanılan değişkenlere parametre denir.
KarakterYaz() fonksiyonunun tanımında bu parametreler, ‘k’ ve ‘n’ ile
gösterilir. void KarakterYaz(char k, int n); fonksiyon başlığı argümanların
veri tiplerini bu parametrelere atamıştır.
Fonksiyonlara
değişkenleri gönderme örneğinde,
#include
<iostream.h>
int
main()
{
char kar;
int tam;
cout << "Bir karakter gir:
"; cin >> kar;
cout << "Tekrar sayisini gir:
"; cin >> tam;
cout << endl;
YildizYaz(kar,tam); cin >> tam;
return 0;
}
Not: Bu programdaki, main fonksiyonunda tanımlanan ‘kar’ ve ‘tam’ isimli
değişkenler YıldızYaz() fonksiyonuna gönderilen argümanlar olarak kullanılır.
‘kar’ ve ‘tam’ argümanlarının değerleri ekrandan okutulduktan sonra bu değerler
YıldızYaz(kar,tam) fonksiyon çağırma ifadesi tarafından gereği yapılmak üzere,
YıldızYaz() fonksiyonuna gönderilmektedir.
Argümanların
bu şekilde gönderilmesini, yani fonksiyonun kendisine gelen argümanların
kopyalarını çıkardığı bu gönderme şekline ‘değer olarak gönderme’ denir. Bu
sayede, çağıran programda fonksiyon çağırılırken kullanılan ‘kar’ ve ‘tam’
değişkenlerini sakladığı değerler korunmuş olur.
Fonksiyona
yapı tipli argümanı değer olarak göndermek için daha önceki bilgi yapı tipli b1
değişkeni BilYaz() fonksiyonuna değer argümanı olarak gönderilmiştir. Fonsiyona
değer olarak gönderilen argümanlar geri değer döndürmezler.
#include <iostream.h>
#include <conio.h>
struct bilgi
{
int boyu, yasi;
float agirligi;
};
int main()
{
bilgi b1;
cout << "\nBoyu : " ; cin>> b1.boyu;
cout<< " \nYasi : "; cin >> b1.yasi;
cout <<" \nAgirligi : "; cin >>
b1.agirligi;
cout << “\n\nFonksiyonun icinde : \n\n”;
BilYaz(b1);
cout
<<”\n\nCagiran programin icinde : \n”;
cout <<” Boyu : “ << b1.boyu << “ cm/n”;
cout
<< “Yasi : “ << b1.yasi << “\n”;
cout << “Agirligi : “ << b1.agirligi<< “
kg”;
getch();
return
0;
}
Fonksiyona dizi tipli
argümanı değer olarak göndermek için, fonksiyon çağırma ifadesinde dizi
fonksiyona gönderilen dizinin ilk elemanının adresini int
toplam=dizitopla(dizi,D); fonksiyonunda ‘D’ fonksiyona gönderilen dizinin
boyutunu gösterir. Bu büyülükler dizitopla() fonksiyonuna değer argümanı olarak
gönderilmiştir.
int dizitopla(int diz[], int
n);
Burada diz[] dizisinin boyutu
verilmemiştir. Ayrıca dizitopla
fonksiyonunun dönüş tipi ‘int’ olduğundan ‘return’ deyimi
kullanılmamıştır. Programdaki ‘return’ deyimisadece ’topla()’ fonksiyonunu
döndürür.
#include <iostream.h>
int DiziTopla(int Diz[], int
n);
const int D = 8;
//================
int main()
{
int Diz[D] = {0, 1, 2, 3, 4, 5, 6, 7 };
cout<< "\nDizi nin adresi : "<< Diz
<< endl;
int Toplam = DiziTopla(Diz,D);
cout << "\n\nDondukten sonraki dizi: \n";
cout <<
"\nDizi nin adresi : " << Diz << endl;
for(int i= 0; i<D; i++)
cout << Diz[i] <<' ';
cout << "\nDizi elemanlarinin toplami : "
<< Toplam;
cin >> Toplam;
return 0;
}
//================
int DiziTopla(int Diz[], int
n)
{
int Topla = 0;
for (int i=0; i<n; i++)
Topla = Topla + Diz[i];
cout << "\nFonksiyon icinde: \n";
cout << "\nDiz in adresi : " << Diz
<< endl;
for(i=0; i<n; i++)
{
Diz[i] = 2 * i;
cout << Diz[i] << ' ';
}
return Topla;
}
Fonksiyondan Değer Döndürme
Bir fonksiyon çalışmasını
tamamladıktan sonra, kendisini çağıran programa değer döndürebilir. Genellikle
döndürülen bu değer, fonksiyonun çözdüğü problemin sonucudur. Çağıran program
bir fonksiyona ‘()’ parantezlerinin içinde birçok argüman gönderebilir. Fakat
fonksiyon, çağıran programa ‘return’ deyimi aracılığı ile sadece bir değer
döndürür.
1-Fonksiyondan yapı tipli bir
argümanı döndürme
2-Fonksiyona argümanları
referans olarak gönderme ve fonksiyondan argümanları referans olarak döndürme
3-Fonksiyon argümanları
olarak pointerları kullanma
Fonksiyondan dizi tipli bir
argüman döndürme şeklinde yöntemlerle bir fonksiyondan birden çok değer
döndürme amacıyla bu işlemler yapılır.
Eğer fonksiyon bir değer
döndürmüyorsa, ‘void’ anahtar kelimesi kullanılır. Programdaki gereksiz
değişkenlerden kurtulmak için, ‘return’ ifadesi farklı tipte yazılır.
Örnek:
#include <iostream.h>
const int D=7;
void DiziArtir(int*, int);
int main()
{
int Dizi[D] = {1, 2, 3, 4, 5, 6, 7 };
int* dg = &Dizi[0];
cout << "\nDizinin ilk elemani: "<< *dg
<< endl;
cout << "\n\nFonksiyonda: \n";
DiziArtir(dg, D);
cout << "\nCagiran programda: ";
cout << "\nYeni dizinin elemanlari: \n";
for(int i=0;i<D;i++)
cout << i << " -> " <<
*(dg++) <<endl;
cin >> i;
return 0;
}
void DiziArtir(int* Diz, int
n)
{
for(int i=0;i<n;i++)
{
Diz[i] = 10 + *(Diz + i);
cout << "\n = " << i <<
" -> Diz[" << i << "] = " << Diz[i]
<< endl;
}
}
FONKSİYONLARDA ARGÜMANLARI REFERANS OLARAK DÖNDÜRME
Referans, bir değişkene takma
isim, yani farklı bir isim vermeye denir.
Referans veri tipinin ismi
ile değişken isminin arasına & karakteri yazılarak tanımlanan ve basit
olmayan veri tipidir. Basit olmayan bir veri tipi, bir başka veri tipi
yardımıyla tanımlanır. Örnek:
Float& OndSay; // OndSay değişkeni referans olarak tanımlanmış.
Referans olarak tanımlanan
bir değişkene başlangıç değeri verilmelidir.
int intDeg = 1024;
int &RefDeg = intDeg;
int &RefDeg1; //Yanlış,
çünkü başlangıç değeri verilmemiş.
int &RefDeg2=10 //Yanlış,
çünkü başlangıç değeri bir sayı verilemez. Başlangıç değeri bir değişken
olmalıdır.
Referans bir değişkene verilen
takma isim olduğu için ve esas değişkenin her ikisi de aynı değere sahiptir ve
bunların her ikisi aynı bellek alanını kullanır.
Örneğin;
RefDeg += 2;
Bu değişkenin referans olduğu
tam sayı tipi ve intDeg isimli değişkene RefDeg+2 değerini atar. Bu değişken,
intDeg değişkenine doğrudan eriştiği gibi, RefDeg değişkeni aracılığıyla da
erişebilir.
RefDeg = 5;
İfadesinde intDeg’e de 5
atanmıştır.
~Örnekler~
int il = 1024,
i2 = 2048;
int &r1 = il, r2 = i2;
int i3 = 1024, &ri = i3;Y
int &r3 = i3, &r4 =
i2;Y
const int intDeg = 1024;
const int &RefDeg =
intDeg; // Referans ve değişkenin her ikisi de sabit
int &Ref2 = intDeg;
//Hatalı, bir sabit, değişkene referans olamaz.
NOT: const olmayan
referanslara başlangıç değeri verilemez.
double dDeg = 3.14;
const int &ri = dDeg;
ifadeleri yazılırsa,
derleyici bunları
int deg = dDeg;
const int &ri = deg; //deg’i ri’ye bağlar.
Referansları fonksiyonlara
argüman olarak gönderebiliriz. Fonksiyon çağırma ifadesindeki argümanların veri
tipleri ile çağrılan fonksiyonun argümanlarının veri tipleri aynı; fakat
fonksiyonların çağırma ifadesindeki parametre isimleriyle çağrılan
fonksiyonların parametrelerinin isimleri farklıdır. Bu yüzden fonksiyon
kendisini çağıran programdaki orijinal değişkenlere ulaşamaz. Bu, fonksiyonun
kendisini çağıran programdaki değişkene zarar vermesini önler. Bu durum
Pascal’daki procedure ve function tanımlarında parametre tanımından önce
yazılan var anahtar kelimesinin yaptığı iş ile aynıdır.
Yukarıda yaptığımız Topla()
fonksiyonuna tam sayı tipli bir büyüklük referans olarak gönderilmekte ve
fonksiyondan dönen büyüklük ekrana yazdırılmaktadır. Topla() fonksiyonun
deklarasyonu
void Topla(int n, int&
top)
#include <iostream>
using namespace std;
#include <conio.h>
int main()
{
void Topla(int, int&);
int tam1, tam2 = 10;
char kar;
do
{
cout<<"\n \t \t Cagiran programda :
\n";
cout<<"\n \t \t Tam sayi gir:
";cin>>tam1;
Topla(tam1,tam2);
cout<<"\n \n \t \t Cagiran programda:
\n";
cout<<"\n \t \t Girilen sayi =
"<<tam1;
cout<<"\n \n \t \t Donen sayi
="<<tam2;
cout<<"\n \n \t \t Devam mi
(e/h)?";cin>>kar;
}
while (kar == 'e');
return 0;
}
void Topla(int n, int&
top)
{
cout<<"\n \n Fonksiyonun icinde: ";
cout<<"\n \n n = "<<n<<endl;
cout<<"top = "<<top<<endl;
top+= n;
cout<<"\n \n n + top =
"<<top<<endl;
char a; cin>>a;
}
NOT: 10 MAYIS à QUIZ/8.mayıs quiz
17 MAYIS à ÖDEV SUNUMLARI/15.mayıs
ÖDEV KONULARI:
1-
search
algoritması ve uygulamaları
2-
find algoritması
ve uygulamaları
3-
sort algoritması
ve uygulamaları
4-
transform algoritması
ve uygulamaları
5-
count algoritması
ve uygulamaları
6-
istatistiksel
rastgele sayı simulasyonları, zar atma simulasyonu
7-
Monte Carlo
yöntemlerinin C++ üzerinde örneklenmesi
Örnek: Ondalık bir sayının
tam ve ondalık kısımlarının ayrılması işlemini Ayir() isimli bir fonksiyonla
gerçekleştiren tam sayı ve ondalık sayı olarak ayrılan bu değerler, çağıran
program olan main() fonksiyonuna döndüren programı referans argümanlar
kullanarak hazırlayan programı hazırlayınız.
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
void Ayir(float, float&, float&);
float sayi, tam, kesir;
do
{
cout<<"\n \t \t Cagiran programda :
\n";
cout<<"\n \t \t Ondalik sayi
gir:";
cin>>sayi;
Ayir(sayi, tam, kesir);
cout<<"\n \n \t \t Cagiran programda:
\n";
cout<<"\n \t \t Tam kismi =
"<<tam;
cout<<"\n \t \t Kesir kismi
="<<kesir;
cin>>sayi;
}
while (sayi != 0.0);
getch();
return 0;
}
void Ayir(float f, float&
t, float& k)
{
int yedek = static_cast<int>(f);
cout<<"\n \n Fonksiyonun icinde :";
cout<<"\n \n Yedek =
"<<yedek<<endl;
t = static_cast<float>(yedek);
cout<<"Tam = "<<t<<endl;
k=f-t;
cout<<"Kesir = "<<k<<endl;
}
Programda fonksiyon çağırma
ifadesinde & referans işlemcisinin yer almadığını görüyoruz.
Soru: Sırala fonksiyonuna gönderilen
n1 ve n2 Sirala() fonksiyonunda & referans olarak tanimlanan say1 ve say2
parametrelerine atayan ve Sirala() fonksiyonunda referans olarak tanımlanan
say1 ve say2 parametrelerinde meydana gelen değişiklikleri aynen çağıran bir
program örneği yazınız.
#include <iostream>
using namespace std;
int main()
{
void Sirala(int&, int&);
int n1=99, n2 = 11, n3=222, n4=88;
Sirala(n1, n2);
cout<<"n1= "<<n1<<endl;
cout<<"n2= "<<n2<<endl;
Sirala(n3, n4);
cout<<"n3= "<<n3<<endl;
cout<<"n4= "<<n4<<endl; cin>>n1;
return 0;
}
void Sirala(int& sayi1,
int& sayi2)
{
if (sayi1>sayi2)
{
int yedek = sayi1;
sayi1=sayi2;
sayi2=yedek;
}
}
Örnek: Yapı tipli verileri
referans olarak gönderen bir program örneği hazırlayınız.
#include <iostream>
#include <conio.h>
using namespace std;
struct Uzunluk
{
int fit;
float inc;
};
void Degistir( Uzunluk&,
float );
void Yaz( Uzunluk );
int main()
{
Uzunluk u1={12, 6.5};
cout<<"\n u1= "; Yaz(u1);
Degistir(u1, 0.5);
cout<<"\n u1= "; Yaz(u1);
Uzunluk u2 = {10, 5.5};
cout<<"\n \n u2= "; Yaz(u2);
Degistir(u2, 0.25);
cout<<"\n u2= "; Yaz(u2); getch();
return 0;
}
void Degistir( Uzunluk&
uu, float carpan)
{
float inc = (uu.fit * 12 + uu.inc) * carpan;
uu.fit = static_cast<int>(inc / 12);
uu.inc = inc - uu.fit * 12;
}
void Yaz(Uzunluk uu)
{
cout<<uu.fit<<" fit, "
<<uu.inc<< " inc";
}
Fonksiyonların kendi kendini çagırması
Örnek…
#include<iostream>
using namespace std;
unsigned long fakt(unsigned
long);
int main()
{
int n;
unsigned long faktoryel;
cout<<”\n bir tamsayı
gir:”;cin>>n;
faktoryel=fakt(n);
cout<<n<<”nin
faktoryeli=”<<faktoryel;
cin>>n;
return 0;
}
unsigned long fakt(unsigned
long m)
{
if (m>1)
return m * fakt(m-1);
else
return 0;
}
Yerel ve genel degıskenler
Yerel(local) genel(global) degıskenler
#include <iostream>
#include <conio.h>
using namespace std;
void KarakterYaz( char = '*',
int = 45);
int main()
{
KarakterYaz();
KarakterYaz( '=');
KarakterYaz('+', 30);
getch();
return 0;
}
void KarakterYaz(char k, int
n)
{
for (int j=0; j<n; j++) cout<<k;
cout<<endl;
}
Soru: Aşağıdaki
çerçeveyi oluşturan bir program örneği yazınız.
Sol alt
köşe à 192
Sol üst köşe à 218
Sağ üst köşe à191
Sağ alt köşe à217
Düz çizgi à 240
#include <iostream>
#include <conio.h>
using namespace std;
void KarakterYaz( int = 218,
int = 1);
void KarakterOku( int = 192,
int = 1);
int main()
{
KarakterYaz();
KarakterYaz( 45, 20);
KarakterYaz( 191,1);
KarakterOku(192,1);
getch();
return 0;
}
void KarakterYaz(int k, int
n)
{
char ch = k;
for (int j=0; j<n; j++) cout<<ch;
}
void KarakterOku(int l, int
m)
{
char ch = l;
for(int x=m; x<0; x--) cout<<ch;
}
Bu programı tamamlayınız.
Sınıf ve Veri Tipi ve Nesne – Yapısal Programlamaya
Geçiş
Değişik tipteki verileri bir
bütünlük içinde, bir arada tutmak için struct veri tipi geliştirilmiştir. C++
programlama dili günlük hayatta gerçekten var olan sistemleri temsil etmek
üzere bilgisayar modelleri kurmaya yarayan doğal bir imkan sağlar. Sınıf
(class) bu işin esasını oluşturur. Bir otomobil sınıfı, otomobilin
argümanlarını ve bu veriler üzerinde yapılacak işlemleri çok genel bir tarzda,
bir arada ifade eder. Bir sınıftan kalıtım yoluyla yeni sınıflar üretilir. Yani
otomobil tanımından spor otomobili, yarış otomobili, jeep, hatta kamyonet
oluşturulabilir.
Grafik bir örnek oluşturmak
için genellikle ekran üzerindeki fiziksel pikselleri modellemek üzere düzlem
geometride nokta tanımı kullanılır. Ekran üzerinde bir noktanın yerini
göstermek üzere o noktanın x ve y koordinatları veri elemanı olarak alınıp,
struct nokta
{int x, y;};
Burada “nokta” isimli bir
yapı veri tanımlanır x ve y büyüklüklerinin ekran üzerindeki bir noktayı
gösterdiğini düşünürsek, o zaman kavramı değiştirmemiz gerekir. Bunun için
ekran üzerindeki yeri belirten bir noktayı ışıklı bir nokta haline getirmek
isteyelim, budurumda belirlenen noktayı göstermek üzere x ve y koordinatlarına
bu noktanın görülebilir olması özelliğini göstermek üzere bool veri tipli parlak elemanına ihtiyaç duyarız. Bu
özelliğe sahip nokta isimli yeni bir yapı veri tipi iki şekilde tanımlanır;
1-
struct Nokta
{ int X, Y;
bool Parlak;
};
2-
struct Yer
{ int X, Y;};
struct Nokta
{ YerKonum;
bool Parlak;
};
Nokta tanımının dışında
veriler üzerinde gerekli işlemleri yapacak fonksiyonlar belirlenebilir. Bu
durumda veri ve işlem ayrı ayrı ele alınır ya da veriler üzerinde yapılacak
işlemleri gösteren fonksiyonlar, üye fonksiyonlar olarak Nokta isimli yapı veri
tanımının içine katılabilir.
Yapı ve sınıf veri tipleri
arasındaki biçimsel tek fark;
1-
bir yapının
içindeki üyelerin varsayılan durumda public,
2-
bir sınıfın
içindeki üyelerin varsayılan durumda private
olmasıdır.
C++ programlama dilinde
veriler ve bu veriler üzerinde yapılacak işlemlerin bir bütünlük oluşturacak
şekilde bir arada tanımlandığı veri tipi sınıf (class) olarak tanımlanır. Genel
kullanımı;
class sınıfın ismi
{
private:
Üye verilerin deklarasyonu
public:
Üye fonksiyonların prototipleri
}
Bir nesne ile sınıf arasında
ilişki tıpkı bir değişkenle veri tipi arasındaki ilişki gibidir.
ÖRNEK:
#include <iostream>
using namespace std;
class Ornek
{ private:
int veri;
public:
void VeriyeAta(int d)
{veri =d;}
void VeriyiYaz()
{cout<<"Veri:"<<veri<<endl;}
};
int main()
{ Ornek o1, o2;
o1.VeriyeAta(55);
o2.VeriyeAta(666);
o1.VeriyiYaz();
o2.VeriyiYaz();
int i; cin>>i;
return 0;
}
Class Ornek isimli sınıfın
tanımı:
1-
class ayrılmış
kelimesi
2-
sınıfın adı
(Ornek)
3-
{ … }
4-
“;”
Den oluşur.
Class ayrılmış kelimesi
sınıfın adı; sınıfın başlığını gösterir. { … }, sınıfın gövdesidir. Üye
verileri ve üye fonksiyonları burada yer alır. Yapı ve sınıf veri tiplerinin
tanımları “;” ile biter. Nesnelerle programlamanın en iyi özelliği, bir veriyi
izlemektir. Yani veriye kendi sınıfının dışında, başka fonksiyonlar tarafından
istem dışı erişilmesini önlemektir. Veriyi gizlemenin en başta gelen yöntemi, “private” olarak tanımlamaktır. Private olarak
tanımlanan veri ya da fonksiyonlara sadece kendi sınıfları içinden
erişilebilir. Public olan veri yada fonksiyonlara ise kendi sınıflarının
dışından da erişebilmek mümkündür. Amaç, bir sınıfın verisini diğer sınıflardan
gizlemek ve programcıları hatalardan korumaktır. Ornek adındaki sınıfta veri
adında ve int tipli veri elemanı vardır. Herhangi bir yapıda (struct) istenen
sayıda veri elemanı olabildiği gibi, bir sınıfta da istendiği kadar veri
elemanı bulunabilir. Üye fonksiyonlar bir sınıfın içinde yer alan
fonksiyonlardır. VeriyeAta() ve VeriyiYaz() üye fonksiyonları vardır.
Nesnelerin tanımlanmasında main() fonksiyonunda ilk ifade Ornek isimli bir
sınıfın o1 ve o2 nesneleri tanımlanmaktadır. Bir sınıfın üye verilerine ulaşma
ve üye fonksiyonları çağırma işlemleri, yapı veri tipli değişkenlerde olduğu
gibi, “.” Kullanılarak gerçekleştirilir. VeriyeAta() üye fonksiyonunda
o1.VeriyeAta(55);
o2.VeriyeAta(666);
ifadeleriyle ulaşılır ya da
VeriyeAta() üye fonksiyonu kullanılır. Bir üye fonksiyon, her zaman bir
nesnenin üzerinde işlem yapmak için çağırılır. Burada Ornek sınıfının o1
nesnesinin VeriyeAta() üye fonksiyonu tarafından çağrıldığını ifade eder. o1
nesnesindeki veri değişkenine 55 değerini verir.
Örnek:
#include <iostream>
using namespace std;
#include <string>
class Kimlik
{ private:
string adi;
char cinsiyeti;
int yasi;
float boyu;
public:
void KimlikAta(string a, char k, int y,
float b)
{
adi = a;
cinsiyeti = k;
yasi = y;
boyu
= b;
}
void Yaz()
{ cout<<"Adi:
"<<adi<<", Cinsiyeti: "<<cinsiyeti<<
",
Yasi:"<<yasi<<", Boyu:"<<boyu<<" m
\n";
}
};
int main()
{
Kimlik kim;
kim.KimlikAta("Alev Gurtunca", 'b', 50, 1.58F );
kim.Yaz(); int i; cin>>i;
return 0;
}
Bu programda kim.KimlikAta(
.. ) fonksiyon çağırma ifadesi, kimlik sınıfının kim nesnesine KimlikAta() üye
fonksiyonu aracılığıyla adı, cinsiyeti, yaşı ve boyu veri üyelerini atar.
Örnek:
#include <sekilh.h>
class Daire
{
protected:
int x, y, ycap;
renk dolgurengi;
dolgu dolgusitili;
public:
void ata(int xx, int yy, int r, renk dr, dolgu ds)
{x=xx;
y=yy;
ycap = r;
dolgurengi=dr;
dolgusitili=ds;
}
void ciz()
{ renk_sec(dolgurengi);
dolgu_sec(dolgusitili);
daire_ciz(x, y, ycap);
}
};
int main()
{
init_graphics();
Daire d1, d2, d3;
d1.ata(15, 7, 5, cMavi, X);
d2.ata(41, 12, 7, cKirmizi, 0);
d3.ata(65, 18, 4, cYesil, Ortam);
d1.ciz(); d2.ciz(); d3.ciz();
goto xy(1, 25);
getch();
return 0;
}
#include <iostream>
using namespace std;
#include <conio.h>
class Uzunluk
{ private:
int fit;
float inc;
public:
void Ata(int ft, float in)
{ fit = ft; inc = in; }
void Oku()
{ cout<<"\n fit i gir: "; cin>>fit;
cout<<"inc i gir: "; cin>>inc;
}
void Yaz()
{ cout<<fit<<"fit,
"<<inc<<" inc";}
};
int main()
{
Uzunluk u1, u2;
u1.Ata(11, 6.25);
u2.Oku();
cout<<"\n u1 = "; u1.Yaz();
cout<<"\n u2 = "; u2.Yaz();
getch();
return 0;
}
“İNDİS”
İşlemcisi
Dizinin elemanlarına erişmek
için kullanılan indis işlemcisi, “[ ]” aşırı yüklendiğinde güvenli bir dizi oluşturmak
için, diziye erişmek için kullandığımız indis numaralarını otomatik olarak
kontrol eden bir dizi oluşturabiliriz. Böylece indisin dizi sınırları dışına
çıkması önlenmiş olur. Bunun için, dizi sınırlarının yani indis işlemcisinin
referans olarak dönmesi gerekir. Güvenli bir dizi oluşturmak için, 3 tane
yöntem vardır.
1- get() ve put()
fonksiyonları
putel(), diziye bir eleman
eklemek için; getel(), bir dizi elemanının değerini bulmak için kullanılır. Her
iki fonksiyon da, dizi sınırlarının dışına çıkılmamasını garanti etmek için
indis numaralarının değerini kontrol eder.
Örnek:
#include <iostream>
#include <process.h>
#include <conio.h>
using namespace std;
const int L = 12;
class GuvenliDizi
{
private:
int
diz[L];
public:
void
putel(int n, int el)
{
if
(n<0 || n>=L)
{
cout<<"\n
indis siniri asti!";
exit(1);
}
diz[n]
= el;
}
int getel(
int n) const
{
if(
n<0 || n>= L)
{
cout<<"\n
indis siniri asti!";
exit(1);
}
return
diz[n];
}
};
int main()
{
GuvenliDizi
d1;
for (int j = 0; j<L; j++)
d1.putel(j,
j * 10);
for
(j = 0; j<L; j++)
{
int
yedek = d1.getel(j);
cout<<j<<".
eleman: "<<yedek<<endl;
}
getch();
return
0;
}
2- Referans olarak
dönen bir tek access() fonksiyonu
Bir diziye güvenle hem veri
eklemek, hem de diziden veri okumak için aynı üye fonksiyonu kullanabiliriz.
Bunun için fonksiyondan referans yoluyla değer döndürme işlemi yapılır. Bu, şu
anlama gelir: fonksiyonu = işaretinin sol tarafına yerleştirilebilir, böylece
sağ taraftaki değer fonksiyonun döndürdüğü değişkene atanır.
Örnek:
#include <iostream>
#include <process.h>
#include <conio.h>
using namespace std;
const int L = 20;
class GuvenliDizi
{
private:
int
diz[L];
public:
int&
access(int n)
{
if
(n<0 || n>= L)
{
cout<<"\n
indis siniri asti!";
exit(1);
}
return
diz[n];
}
};
int main()
{
GuvenliDizi
d1;
for (int
j=0;j<L;j++)
d1.access(j)
= j*10;
for (j=0;
j<L; j++)
{
int
yedek = d1.access(j);
cout<<j<<".
eleman: "<<yedek<<endl;
}
getch();
return 0;
}
3. Referans olarak dönen
aşırı yüklenmiş [ ] indis işlemcisi
Güvenli bir diziye erişmek
için indis işlemcisine GuvenliDizi sınıfı içerisinde yeni bir görev yüklenir,
ancak bu işlemci genellikle = işaretinin sol tarafında kullanıldığı için aşırı
yüklenmiş işlemci, referans yoluyla değer döndürmelidir.
Örnek:
#include <iostream>
#include <process.h>
#include <conio.h>
using namespace std;
const int L = 20;
class GuvenliDizi
{
private:
int
diz[L];
public:
int&
operator [] (int n)
{
if(n<0
|| n>= L)
{
cout<<"\n
indis siniri asti!";
exit(1);
}
return
diz[n];
}
};
int main()
{
GuvenliDizi
d1;
for (int
j=0; j<L; j++)
d1[j]
= j*10;
for (j =
0; j<L; j++)
{
int
yedek = d1[j];
cout<<j<<".
eleman: "<<yedek<<endl;
}
getch();
return 0;
}
Veri Tipi Dönüşümü
Bir değişkenin sahip olduğu
değeri başka bir değişkene atamak için “=” atama işlemcisi kullanılıyordu.
Örneğin;
int a = int b;
u3 = u1 + u2;
Örneğin Uzunluk sınıfı
tipinde olan toplamanın sonucu u3 nesnesine atanır. Bir nesnenin değeri, aynı tipte
bir başka nesneye atandığında üye veri elemanlarının tümünün değerleri, yeni
nesneye kopyalanır. = atama işlemcisinin her iki tarafındaki değişkenler farklı
tiplere sahipse;
1-
Önce derleyicinin
temel veri tiplerini kendiliğinden nasıl dönüştürdüğüne,
2-
Daha sonra
derleyicinin kendiliğinden yapmadığı ve derleyiciye ne yapması gerektiğini
söylememiz gereken durumları
inceleyeceğiz.
Temel Veri Tipleri Arasındaki Dönüşümler
Örneğin:
intDeg = floatDeg;
Buradaki örnekte intDeg’in
tamsayı tipinde, floatDeg’in de ondalık sayı tipinde olduğunu düşünürsek,
derleyici floatDeg değişkenini tamsayı değişkenine dönüştürmek için özel bir
fonksiyon çağırması gerekir. Böylece floatDeg’de saklanılması gereken değer,
intDeg değişkenine aktarılabilir. Bunun için derleyicide float’tan double’a,
char’dan float’a döndüren hazır fonksiyonlar vardır. Bu tür dönüşümler
kapalıdır, program listesinde açıkça görülmezler. Bu tip dönüşüm yapması için
(cast) işlemcisini kullanırız. Örneğin float tipinden int tipine dönüşüm için;
intDeg =
static_cast<int>(floatDeg);
yazarız. Bu ifade, floatDeg
isimli değişkenin tipini float veri tipinden int veri tipine dönüştürür.
Nesneler ve Temel Veri Tipleri Arasındaki Dönüşümler
Örnek:
#include <iostream>
#include <conio.h>
using namespace std;
class Uzunluk
{
private:
const
float metFit;
int fit;
float
inc;
public:
Uzunluk():fit(0),inc(0.0),metFit(3.280833F )
{ }
Uzunluk(float
metre) : metFit(3.280833F )
{
float
fltfit = metFit * metre;
fit
= int(fltfit);
inc
= 12 * (fltfit - fit);
}
Uzunluk(int
ft, float in) : fit(ft), inc(in), metFit(3.280833F )
{ }
void
Oku()
{
cout<<"\n
fit i gir: "; cin>>fit;
cout<<"\n
inc i gir: "; cin>>inc;
}
void
Yaz() const
{
cout<<fit<<"
fit, "<<inc<<"inctir"; }
operator
float() const
{
float
OndalikFit = inc/12;
OndalikFit
+= static_cast<float>(fit);
return
OndalikFit/metFit;
}
};
int main()
{
float
met;
Uzunluk
u1 = 2.35F ;
cout<<"\n
u1 = "; u1.Yaz();
met = static_cast<float>(u1);
cout<<"\n
u1 = "<<met<<" metredir. \n";
Uzunluk
u2(5, 10.25);
met =
u2;
cout<<"\n
u2 = "<<met<<" metredir. \n";
getch();
return
0;
}
SORULAR (QUIZ VE SINAV İÇİN)
1- C++ programlama dilinde;
yapı (struct) veri tipi ile sınıf (class) veri tipi arasındaki temel farkı
belirtiniz.
2- Yapı veri tipi varken, sınıf
veri tipine neden gerek duyulur?
3- Gerçek dünya ile sınıf
(nesne) arasında nasıl bir ilişki var?
4- Üye veri ve üye fonksiyona
hangi durumlarda ulaşılabilir?
5- Bir sınıfın üye
fonksiyonunun sınıfın içinde veya dışında tanımlanması sırasında ne gibi değişiklikler
yapılır?
6- Farklı sınıfların içinde
aynı isimli üye fonksiyonların tanımlanmış olması karışıklığa sebep olur mu? Bu
üye fonksiyonlar nasıl çağırılmalıdır?
7- const Uzunluk saha(300,100); // saha nesnesi
...
void Yaz() const
{
cout<<( (isaret == poz) ? "(+)" :
"(-)" );
Uzunluk::Yaz(); //ft ve i.
}
...
//Topla2() fonksiyonunun
deklarasyonu:
Uzunluk Topla2( const
Uzunluk& ) const;
Yukarıdaki ifadede const
deyiminin ne anlama geldiğini açıklayınız.
8- Sınıftaki
öğrencilerin kimlik bilgilerini, seçtiği üç dersi ve bu derslerin arasınav,
bitirme ve başarı notlarını kaydeden ve geçme notu ile genel not ortalamasını
hesaplamakta kullanılan sınıf (veya sınıfların) tanımlarını yapınız.
9- Yukarıdaki soru için
tanımladığınız sınıfların nesnelerini tanımlayınız.
a. İlgili fonksiyon çağırma
ifadelerini yazınız.
b. Tanımladığımız sınıfların
saklanacağı bir başlık dosyası oluşturunuz.
10- Yukarıda sıralanan
işlemleri değişik problemlere uygulamayı deneyiniz.
6. FONKSİYONLAR (özet)
Şu ana kadar verilen örneklerde çeşitli fonksiyonlar kullanıldı ve
3.Bölümde fonksiyonlardan kısaca bahsedildi. Bu bölümde ise fonksiyonlar başlı
başına bir konu olarak ele alınacaktır.
6.1. Fonksiyon Nedir?
Fonksiyon, aldığı değerler üzerinden işlem yapabilen, değer geri döndürebilen,
programın bir alt parçasıdır. Bütün C++ programları en azından bir fonksiyona
sahiptirler. Bu fonksiyon main()
fonksiyonudur. Bu fonksiyon otomatik olarak en başta çağırılır. Bu main() fonksiyonundan diğer fonksiyonlar ve onların içinden diğerleri çağırılabilir.
Yani istenildiği kadar iç içe fonksiyon kullanmak mümkündür.
Bütün fonksiyonların bir ismi vardır. Bu ismin yazıldığı yerde program
fonksiyona gider ve fonksiyonun bitiminde bir değer döndürerek çağırıldığı
yerin bir satır altından program çalışmaya devam eder.
İki tip fonksiyon vardır. Birincisi kullanıcı tarafından tanımlanmış
‘user defined’ fonksiyonlar, diğeri ise derleyicinin içerisinde hazır olarak
gelen ‘built in’ fonksiyonlardır.
6.2. Fonksiyon Tanımlanması
C++ programlarında fonskiyonları kullanabilmek için onları tanımlamak
gerekir. Bu tanımlama fonksiyonlar hakkında üç bilgiyi derleyiciye tanıtır:
fonksiyonun ismi, fonksiyonun tipi ve fonksiyonun parametreleri. Fonksiyon
tanımlaması fonksiyonun ne şekilde çalışacağını gösterir. Tanımlanmadan önce
bir fonksiyon çağırılamaz.
6.2.1. Fonksiyonun Tanımlanışı
Fonksiyonları tanımlamak için iki yöntem vardır. Birincisi başka bir
fonksiyon tarafından çağırılmadan önce, yani programın başlarında yazılması
durumunda fonksiyon çağırılabilir. Eğer ‘x’ fonksiyonuna gelmeden önce bir ‘y’
fonksiyonu ‘x’ fonksiyonunu çağıracak ise önceden ‘x’ fonksiyonunun bir
prototipinin bulunması gerekir. Prototip en güzel ve tercih edilmesi gereken
çözümdür. Bunun üç nedeni vardır:
1) Fonksiyonları prototip
kullanmadan programın içine sıralı bir şekilde dizmek her zaman güzel bir çözüm
değildir. Programa yeni eklemeler yapıldıkça sorunlarla karşılaşılabilir.
2) Her fonksiyon tek işlevli değildir.
Dolayısıyla bir ‘x’ fonksiyonu içerisinden bir ‘y’ fonksiyonu çağırılırken,
aynı anda bu ‘y’ fonksiyonu da farklı bir amaçla ‘x’ fonksiyonunu çağırıyor
olabilir. Dolayısıyla prototip kullanmaksızın programda hangi fonksiyon önce
yazılırsa yazılsın çalışmayacaktır.
3) Prototip kullanıldığı taktirde derleyici programı çalıştırmadan da fonksiyon tipinde ya da parametrelerinde hata olduğu taktirde bunu farkedebilir.
3) Prototip kullanıldığı taktirde derleyici programı çalıştırmadan da fonksiyon tipinde ya da parametrelerinde hata olduğu taktirde bunu farkedebilir.
6.2.2. Fonksiyonun Prototipi
Derleyicinin fonksiyonlar hakkında bilmesi gereken üç temel bilgi
vardır. Fonksiyonun tipi, adı ve parametreleri. Prototip fonksiyon yazılmadan
önce sadece bu üç özelliği tanımlamak amacı ile kullanılır ve bir tanımlama
biçiminde yazılarak sonuna (;) işareti konulur.
int hacimHesapla(int, int, int);
Burada derleyiciye fonksiyonun ‘int’ tipinden olduğu, isminin
‘hacimHesapla’ olduğu ve üç tane ‘int’ tipi parametresi olduğu veriliyor. Ancak
parametreleri bu şekilde kullanmak çok akıllıca değildir. Çünkü kaçıncı
parametrenin neyi ifade ettiği bir süre sonra unutulabilir. Bunun için tiplerin
yanına sembolik değişken isimleri girmek daha kullanışlı olacaktır.
int hacimHesapla(int en, int boy, int yukseklik);
Burada kullanılan değişken isimlerinin hiçbir önemi yoktur. Yalnızca
hangi parametrenin ne olduğunu hatırlatma amaçlıdır.
Fonksiyon prototipinin kullanımına bir örnek verelim:odec c++ cevırın..
#include <stdio.h>
#include <conio.h>
int hacimHesapla(int en,
int boy, int yukseklik);
void main()
{
int e, b, y, hacim;
char kareKarakteri = 253;
printf("prizmanin eni: ");
scanf("%d", &e);
printf("prizmanin boyu: ");
scanf("%d", &b);
printf("prizmanin yuksekligi: ");
scanf("%d", &y);
hacim = hacimHesapla(e, b, y);
printf("\nprizmanin hacmi = %d br%c\n", hacim,
kareKarakteri);
printf("\ndevam etmek icin bir tusa basiniz...");
getch();
}
int hacimHesapla(int x, int
y, int z)
{
return x * y * z;
}
Bu örnekte dikkat edilmesi gereken nokta prototiple fonksiyonun
parametrelerinde farklı isimler kullanılmış olmasıdır. Genellikle prototipte ve
fonksiyonda aynı isimleri kullanmak adettir. Ancak buna mecbur değiliz. Hatta
prototipte isim kullanmama hakkına da sahibiz.
Bu programda ana fonksiyondan önce hacimHesapla() fonksiyonunun prototipi tanımlanıyor. Daha sonra ana fonksiyonda ekran
siliniyor ve ‘e’, ‘b’, ‘y’ ve ‘hacim’ isimli dört adet tamsayı değişkeni
tanımlanıyor. Bunların hemen altında ise Tablo 4.12’de verilen ASCII
karakterlerinden ‘²’ karakteri bir karakter değişkenine atanıyor.
Program çalıştırıldığı zaman bizden üç adet bilgi istiyor, ‘en’, ‘boy’,
‘yükseklik’. Klavyeden bu bilgiler girildiği anda ‘e’, ‘b’ ve ‘y’ değişkenleri hacimHesapla()
fonksiyonuna parametre olarak veriliyorlar.
Program hacimHesapla() fonksiyonuna atladığı anda ‘x’ ‘e’nin, ‘y’ ‘b’nin ve ‘z’ ise ‘y’nin
değerini alıyor. Burada ‘x’, ‘y’ ve ‘z’ çarpılarak değerleri geri döndürülüyor.
Program geri döndüğü zaman ‘hacim’ bu dönen değeri alıyor ve daha sonra
bu değer ekrana yazılarak program sona eriyor.
6.3. Fonksiyonların Çalışma Prensibi
Fonksiyonlar çağırıldıkları anda ‘{‘ parantezini gördükleri yerden ‘}’
parantezinin kapandığı yere kadar olan program parçasını çalıştırırlar.
Fonksiyonlar diğer fonksiyonları çağırabildikleri gibi ‘if’ kullanılarak
kendilerini de çağırabilirler. Dizi elemanlarını hesaplamada bu tür kendini
çağıran (recursive) fonksiyonlar sık sık kullanılır.
#include <stdio.h>
#include <conio.h>
void hesapla(int x, long int y);
void main()
{
int x;
long int
y;
clrscr();
printf("Genel
Formul:\nf(x) = [f(x + 1) + 3] / 2\n\n");
printf("f(x)
= y\nx = ");
scanf("%d",
&x);
printf("y
= ");
scanf("%ld",
&y);
printf("f(%d)
= %ld\n", x, y);
hesapla(x,
y);
getch();
}
void hesapla(int x, long int y)
{
long int
hesap;
if(x
> 1)
{
hesap
= 2 * y - 3;
printf("f(%d)
= %ld\n", x - 1, hesap);
hesapla(x
- 1, hesap);
}
}
Bu program f(x) = [f(x – 1) + 3] / 2 şeklinde tanımlanmış bir dizinin
1.elemanını bulmaya yarar.
Program öncelikle dizinin kaçıncı elemanının hangi değere eşit olduğunun
girilmesini istiyor. Girilen elemanın 1’den büyük olması gerekiyor (programda
bu kontrol edilmiyor). Girilen eleman ve değeri hesapla() fonksiyonuna gidiyor. Burada dizi elemanlarının büyük değerler
alabileceği göz önüne alınarak ‘long int’ tanımlama yapılıyor.
‘x’ yani eleman numarası 1’den büyük olduğu sürece fonksiyon bir önceki
elemanı başta verilen genel formüle bağlı olarak hesaplayıp ekrana yazarak
yeniden kendisini çağırıyor. Ancak bu sefer bir önceki eleman ve değeri
parametre olarak veriliyor.
‘if’ kontrolü yapılmadığı taktirde kendisini çağıran bir fonksiyon
genellikle sonsuza dek tekrar eder. Ancak burada dizinin 1. elemanına gelindiğinde
‘if’ koşulu gereği hesapla() yeniden çağırılmayarak fonksiyon sona eriyor ve bir tuşa basılana kadar
bekledikten sonra program sona eriyor.
Bu örnekte de görüldüğü gibi iterasyon içeren hesaplamalarda kendini
çağıran fonksiyonlar kullanmak çok pratik olabilir. Ancak bu kullanımın
‘infinite loop’ yani ‘sonsuz döngü’ gibi programı kilitleyici sonuçlara da yol
açabileceği göz önünde bulundurularak dikkatli olmak gerekir.
6.4. Lokal Değişkenler
Bir değişken bir fonksiyonun içerisinde tanımlandığı durumda bu
değişkene yalnızca bu fonksiyonun içerisinden ulaşılabilir. Diğer
fonksiyonlarda bu değişken herhangi bir değere sahip olmadığı gibi
tanımlanmadığı sürece kullanılamaz da. Farklı fonksiyonlar içerisinde aynı
isimde lokal değişkenler kullanmak mümkündür.
Bir fonksiyon geri döndüğü andan itibaren o fonksiyonun içerisinde
tanımlanmış tüm lokal değişkenler iptal olur. Bunun yanısıra geri döndüğü
fonksiyonda bu değişkenlerden birinin adaşı varsa bu değişkenin değerinde,
tanımlanışında hiçbir değişim olmaz.
#include <stdio.h>
#include <conio.h>
void sub();
void main()
{
clrscr();
int x =
10;
sub();
printf(“x
= %d\n”, x);
getch();
}
void sub()
{
int x =
5;
}
Bu örnekte ana fonksiyonda ‘x’ ana fonksiyona ait bir lokal değişken
olarak tanımlanıyor ve 10’a eşitleniyor.
Daha sonra çağırılan sub() fonksiyonunun içerisinde ana fonksiyonda daha önce tanımlamış olduğumuz
lokal değişkenle aynı isimde bir lokal değişken tanımlanıyor ve bu sefer ‘x’
5’e eşitleniyor.
Ana fonksiyona geri dönüldüğü gibi ‘x’in değeri ekrana yazdırılıyor ve
bir tuşa basılana kadar beklenerek programdan çıkılıyor.
Bu örneğin sonucunda ekrana ‘x = 10’ yazılacaktır. Aslında sırayla inceleyecek
olursak, ‘x’ 10’a eşitlendikten sonra 5’e eşitlenerek değerini değiştiriyor ve
ekrana 5 yazılması gerekirdi. Ancak ‘x’ global bir değişken değil, fonksiyonuna
özgü lokal bir değişken olarak tanımlandı. Bu yüzden sub’da tanımlanan ‘x’ ana
fonksiyondakinden bağımsız ve fonksiyon sona erdiği gibi de yok edildi. Bunun
yanısıra ana fonksiyonda tanımlanan ‘x’ de aynı şekilde sub’a gidildiği anda
geçerliliğini yitirdi ve geri döndüğünde yeniden aktif oldu.
Bellek yapısı ve değişken isimleri anlatılırken bahsedildiği gibi
değişkenlerin isimleri yalnızca programcı için vardır. Bilgisayar için
değişkenin ismi değil, değişkenin hafızadaki yeri ve değeri önemlidir. Burada
tanımlanan ‘x’leri biz aynı değişken gibi görsek de bilgisayar onları farklı
hafıza adreslerinde tuttuğu için başka bir fonksiyonda tanımlanan adaş değişken
öncekini silmez.
Eğer başka fonksiyonlarda kullanılmayan ya da kullanılsa da fonksiyona
parametre şeklinde aktarılan bir değişken tanımlanması yapılacak olduğunda
lokal tanımlama tercih edilmelidir. Ancak program içerisindeki birçok fonksiyon
aynı değişkeni kullanıyorsa ya da fonksiyon yüzlerce, binlerce ya da daha fazla
çağırılan bir fonksiyonsa global değişken tanımlamak tercih edilebilir. Çok
tekrar eden fonksiyonlarda her seferinde tanımlama yapılıp, daha sonra
fonksiyonun çıkışında bu değişken iptal edileceğine, bir kez başta global
tanımlamak, programın çalışmasını hızlandıracak güzel bir optimizasyondur.
6.5. Global Değişkenler
Fonksiyonların dışında tanımlanan herhangi bir değişken global
değişkendir ve ana fonksiyon dahil tüm fonksiyonlarda tekrar tekrar
tanımlamadan kullanılabilir. Global değişkenlerin değerleri fonksiyondan
fonksiyona değişmez, her zaman en son verilmiş olan değer üzerinden işlem
yapılır.
#include <stdio.h>
#include <conio.h>
int x;
void sub();
void main()
{
clrscr();
x = 10;
sub();
printf("x
= %d\n", x);
getch();
}
void sub()
{
x = 5;
}
Lokal değişkenler ile ilgili olarak verilen örneğin hemen hemen aynısı
olan bu örnekte, sonuç 10 değil 5 olarak ekrana yazılacaktır. Çünkü ‘x’,
fonksiyonların içerisinde değil en başta global olarak tanımlanıyor. Ana
fonksiyonda 10 değerini aldıktan sonra sub’a gelindiğinde ana fonksiyonda değer
verilen bellek adresiyle aynı adrese değer verilerek ‘x’in değeri 5 oluyor.
Yeniden ana fonksiyona dönüldüğünde ‘x’in son değeri 5 olarak ekrana
yazdırılıyor.
Lokal ve global
değişkenler hakkında geriye tek bir soru işareti kaldı. Global tanımlanmış bir
değişkenle adaş bir lokal değişken olabilir mi? Evet olabilir. Bu durumda
global değişken fonksiyon sona erinceye kadar pasif duruma düşerek lokal
değişken kullanılır ve fonksiyon bitiminde yeniden global değişken aktif olur.
#include <stdio.h>
#include <conio.h>
int x;
void sub();
void main()
{
clrscr();
x = 10;
sub();
printf("x
= %d\n", x);
getch();
}
void sub()
{
int x =
5;
}
Bu örnekte tek değişen yer sub() fonksiyonunda ‘x’in başına gelen ‘int’ tanımlaması. ‘x’i burada yeniden
tanımlamak demek ‘x’i lokal bir değişken olarak kullanmak demektir. Bu
fonksiyon sona erdiğinde ana fonksiyonda ‘x’ tanımlanmadığı için yeniden global
değişken devreye girecek ve ekrana ‘x = 10’ yazılacaktır.
Global değişkenler, genellikle tüm program boyunca sıkça kullanılacak ya
da farklı fonksiyonlar tarafından ortak kullanılacak ise tanımlanırlar. Örneğin
ekranın çözünürlüğü en başta “int ekranX = 640,
ekranY = 480” şeklinde global tanımlanabilir. Ekran çözünürlüğü değişene kadar bütün
fonksiyonlar ekrana basılacak objelerin koordinatlarını bu çözünürlüğe göre
hesaplarlar. Eğer ‘#define’ kullanarak bu tür bir tanımlama yapmaya kalkarsak
çözünürlük program sona erene kadar değiştirilemez. Halbuki günümüzde pekçok
oyun’da çözünürlük programın içerisinden değiştirilebilmektedir.
6.6. Fonksiyon İçerisindeki Lokal Alanlar
Lokal değişkenlerin daha ileri düzeyde kullanımı fonksiyon içerisinde
açılan bloklarla sağlanır. Bir fonksiyon açar kapar gibi küme parantezleri
fonksiyonun içerisinde açılıp kapandığı taktirde fonksiyon içerisinde bir alt
bölge yaratmak ve orada da lokal değişkenler kullanmak mümkündür.
#include <stdio.h>
#include <conio.h>
void sub();
void main()
{
clrscr();
int x =
10;
printf("main'in
basinda x = %d\n", x);
sub();
printf("main'in
sonunda x = %d\n", x);
getch();
}
void sub()
{
int x =
5;
printf("sub'in
basinda x = %d\n", x);
{
printf("sub'in
icindeki blogun basinda x = %d\n", x);
int
x = 1;
printf("sub'in
icindeki blogun sonunda x = %d\n", x);
}
printf("sub'in
sonunda x = %d\n", x);
}
Bu örnek çalıştırıldığı zaman kendi kendisini açıklayacaktır. Ana
fonksiyonda tanımlanan ve 10’a eşitlenen ‘x’, fonksiyonun başında ve sonunda 10
değerini ekrana yazdıracaktır. Arada sub() fonksiyonuna gelen program burada ikinci bir ‘x’ lokal değişkeni
tanımlayıp bu değişkeni 5’e eşitler. Bu fonksiyonun başında ve sonunda da yine
ekrana başta verilen 5 değeri yazdırılır.
Aradaki bloğa gelindiğinde ise bir tanımlama yapılana kadar hala sub()’daki ‘x’
değişkenini kullanmak mümkündür. Ancak ‘x’ burada tanımlandığı andan itibaren
yalnızca bu bloğa ait bir lokal değişken olarak kullanılır. Bloğun başında ‘x’
5 olarak ekrana yazdırıldıktan sonra lokal bir ‘x’ daha tanımlanıp 1’e
eşitlenir ve bu değer bloğun sonunda ekrana yazdırılır. Blok kapandığı anda sub()’ın başında tanımlanan ‘x’ yeniden aktif olur.
6.7. Global Değişkenler Hakkında Uyarı
Global değişkenler gerekli yerlerde düzgün bir biçimde kullanıldıkları
taktirde kullanışlı olabildikleri gibi birçok durumda kullanılmaları aslında
tehlikelidir. Global değişkenlerde tutulan veriler tüm fonksiyonlar tarafından
paylaşıldığından, bir fonksiyon diğer fonksiyondan bağımsız şekilde değişkenin
değerini değiştirerek sorunlar çıkmasına neden olabilir. Oluşacak bu tür
hataların en kötü yanı, fark edilmesi zor hatalar olmalarıdır. Büyük bir proje
söz konusu olduğunda onbinlerce satır arasında değişkenin birinin değerini
bozan yeri bulmak saatler alabilir. Aşağıda bunun çok basit bir örneği yer
almaktadır.
#include <stdio.h>
#include <conio.h>
int i;
int carp(int a, int b);
void main()
{
clrscr();
for(i =
0; i < 10; i++)
printf("%d
* %d = %d\n", i, i, carp(i, i));
getch();
}
int carp(int a, int b)
{
i = a *
b;
return
i;
}
Bu örnekte 0’dan 9’a kadar olan rakamların kendileriyle çarpımlarını
ekrana yazdırmak istiyoruz. Ancak sonuçta 0, 1, 4 ve 25’in kendisiyle çarpımı
listeleniyor. Buradaki hata ‘carp’ fonksiyonunda global tanımlı ‘i’ değişkenini
kullanmamızdan ileri geliyor. Burada ‘i’nin değeri değiştiği için ‘for’ döngüsü
0’dan 9’a kadar sıralı sayma işlemini gerçekleştiremiyor.
Sorunu çözmek için ya ‘i’leri lokal kullanmak, ya da iki fonksyonda
farklı değişkenler kullanmak gerekir.
6.8. Inline Fonksiyonlar
Normalde bir fonksiyon tanımlandığında derleyici bellekte bu
fonksiyondan bir tane oluşturur ve fonksiyon her tekrarlanışında bu bölge
çağırılır. Daha sonra da program kaldığı yerden devam etmek üzere geri
döndürülür. Bu işlem çok zaman kaybettiren bir işlem değildir ancak programın
içerisinde zaman zaman yüzbinlerce, milyonlarca kez çağırılan fonksiyonlar
bulunur. Örneğin 1280x1024 çözünürlükte ekranı kaplayan bir resmi basmak için
pixel basma fonksiyonu 1,310,720 kez çağırılır. Bu tür durumlarda fonksiyonu
tanımlarken başına ‘inline’ yazarak tanımlayacak olursak programda fonksiyonun
her tekrar ettiği yere fonksiyonun içeriği yazılarak işlemlerin hızlandırılması
sağlanır. Ancak herşeyin bir bedeli vardır: ‘inline’ fonksiyon kullanmak
programın uzunluğunu arttırır.
#include <stdio.h>
#include <conio.h>
inline int carp(int a, int b);
void main()
{
int
sayi1 = 11, sayi2 = 24, sonuc;
sonuc
= carp(sayi1, sayi2);
sonuc
= carp(sonuc, sayi1 + sayi2);
printf("sonuc
= %d\n", sonuc);
getch();
}
int carp(int a, int b)
{
return
a * b;
}
Sonuç olarak ‘inline’ kullansak da kullanmasak da görünen şey aynı
olacaktır. Ancak ‘inline’ kullandığımız fonksiyonlarda mantık olarak farklılık
vardır.
“sonuc = carp(sayi1, sayi2);” satırı normalde carp() fonksiyonuna gider, gerekli işlemleri yapar ve geri döner. Burada
‘inline’ kullandığımız için carp() fonksiyonu görülen yere fonksiyonun içeriği yazılarak, satır “sonuc = sayi1 * sayi2;” haline getirilir. Alttaki satır da aynı şekilde “sonuc = sonuc * (sayi1 + sayi2);” şeklinde çalışacaktır. Ayrı parametreler halinde verildiğinden parantez
otomatik olarak formüle eklenir yani işlem sırası karışmaz.
‘inline’ mutlaka gerçekleşecek bir komut değildir, yalnızca derleyiciye
yapılan bir tavsiyedir. Derleyiciler programın yapısına göre çeşitli
optimizasyonlar yaparlar. Bu arada ‘inline’ olmadığı halde varmış gibi, olduğu
halde yokmuş gibi davranabilirler. Ancak bu tür bir harekette bulunuyorlarsa bu
daha iyi bir sonuç almak içindir.
7. SINIFLAR ve YAPILAR
Belirli bir konu üzerine, sınırlı
kavramlar kullanarak, küçük bir uygulama yazılacağı zaman genellikle sınıf veya
yapı (class, structre) kullanılmasına gerek yoktur. Ancak projeler büyüdükçe,
kavramlar çoğaldıkça, aynı kriterlere sahip objeler ortaya çıktıkça,
kullanılacak kavramları sınıflandırmak gerekir. Sınıflandırma, gerçek yaşamda
karşılaşılan kavramları program diline dökmek konusunda programcıya üst düzeyde
yardım sağlar.
Bu bölümde sınıflar ve nesnelerin ne
olduklarını, nasıl tanımlandıklarını, ne amaçla kullanıldıklarını ve bunlara
bağlı üye fonksiyonları göreceğiz.
7.1. Sınıf Nedir? Neden Sınıflandırmaya İhtiyaç Duyulur?
Sınıf, içerisinde bir konuda kriter
teşkil eden değişkenler barındıran, tip belirlemek amacıyla kullanılan,
içerisindeki değişkenlere ancak o sınıf tipinde tanımlanmış bir nesnenin
üyeleriyle ulaşılabilen bir tanımlamadır. Diğer bir değişle sınıf değişkenler
koleksiyonudur. Bu değişkenler tanımlanışları dışında direkt olarak değer
almazken, o sınıf tipinde tanımlanmış bir nesnenin özellikleri şeklinde, nesnenin
üyeleri biçiminde değerler alabilirler.
Doğa sınıflandırma konusundaki en
iyi örnektir. Doğadaki her varlık eşsizdir ancak benzer kriterlere sahip
olanlar aynı kategoriye, aynı sınıfa girerler. İnsanlar, hayvanlar, çiçekler ve
böcekler birer sınıftır. Güller ise çiçeklerin bir alt sınıfıdır. Eğer daha
fazla detaya ihtiyaç duyulmuyorsa gülleri bir sınıf olarak kabul ettikten sonra
bu sınıfın üyeleri olarak renk, boyut ve ülke tanımlanabilir. Geniş yapraklı
siyah İngiliz gülü ile küçük kahverengi Türk gülünün ortak özellikleri arandığı
zaman, ikisinin de çiçek olması ve ikisinin de aynı tür çiçek yani gül olması
ilk olarak göze çarpan belirgin özellikleri. Gül sınıfının üyelerine bakacak
olursak renk, boyut ve ülke kriterleri sırasıyla ilkinde ‘siyah’, ‘geniş
yapraklı’, ‘İngiliz’, diğerinde ise ‘kahverengi’, ‘küçük’ ve ‘Türk’. Bu şekilde
bir sınıf oluşturmuş olduk.
Örneğin bir bilardo oyunu yapmaya
karar verdiğimizi düşünelim. Ekranda 10’u aşkın bilardo topu mevcut olsun. Her
biri x, y konumu, ivme vektörü, ivme vektör bileşenleri, spini, top numarası ve
top tipi özellikleri ile tanımlanmış olsun. Sınıflandırma kullanmazsak şu
şekilde değişkenler tanımlamamız gerekir.
int beyazTopX, beyazTopY, beyazTopNo, beyazTopTip;
float beyazTopA, beyazTopAX, beyazTopAY, beyazTopSpin;
float beyazTopA, beyazTopAX, beyazTopAY, beyazTopSpin;
int birinciTopX, birinciTopY,
birinciTopNo, birinciTopTip;
float birinciTopA, birinciTopAX, birinciTopAY, birinciTopSpin;
float birinciTopA, birinciTopAX, birinciTopAY, birinciTopSpin;
int ikinciTopX, ikinciTopY, ikinciTopNo,
ikinciTopTip;
float ikinciTopA, ikinciTopAX, ikinciTopAY, ikinciTopSpin;
float ikinciTopA, ikinciTopAX, ikinciTopAY, ikinciTopSpin;
...
...
int siyahTopX, siyahTopY, siyahTopNo, siyahTopTip;
float siyahTopA, siyahTopAX, siyahTopAY, siyahTopSpin;
...
int siyahTopX, siyahTopY, siyahTopNo, siyahTopTip;
float siyahTopA, siyahTopAX, siyahTopAY, siyahTopSpin;
Topların çarpışıp çarpışmadığını
kontrol etmek istediğimizde karşımıza büyük bir sorun çıkar. Ekranda 10 adet
top olduğunu varsayarsak (n² - n) / 2 formülünden (100 - 10) / 2 = 45 adet
çarpışma kontrolü yapmamız gerekir. Sınıflandırma kullansak da kullanmasak da
bu 45 çarpışma ihtimalinin test edilmesi şarttır. Bu durumda sınıflandırmanın
bir faydası yoktur, fakat sınıflandırma bize iki nesne arasında test fonksiyonu
yazmak için büyük kolaylıklar sağlar. Göstergeler (pointer) ve kaynakların
(reference) da kullanılmasıyla sınıf ve yapılar bu tür problemlerin basite
indirgenmesine yardımcı olurlar.
7.2.
Sınıflar ve Üyeler
Bir sınıf tanımlamak demek, yeni bir
tip yaratmak demektir. Sınıflar çeşitli değişkenler ve onlara bağlı olan
fonksiyonlardan ibarettir. Bir konu üzerinde birden fazla yönde kriter
belirlenebilir. Örneğin bir arabanın rengi, markası, modeli bir kriter
oluşturabileceği gibi hızı, hareket yönü, ivmesi de bir kriter oluşturabilir.
Sınıflandırma bütün bu özellikleri tek bir koleksiyonda toplamaya yarar. Bu
şekilde oluşturulan değişken koleksiyonlarına nesne (obje) denir.
Sınıflandırma sayesinde veriye
ulaşmak, veriyi işlemek ve kopyalamak daha basit bir hale gelir. Programın içerisinde sınıfla
ilgili işlem yapan program parçaları verinin ne olduğuna aldırmadan kolaylıkla
işlem gerçekleştirebilir.
Kriter olarak bir sınıfın içerisinde
tanımlanan her bir değişkene ‘üye değişken’ ya da ‘üye veri’ denir. Arabanın
lastiklerinin arabanın bir parçası olduğu gibi, üyeler de sınıfın birer
parçasıdır.
Bir sınıf içerisinde başka bir sınıf
da kullanılabilir. Örneğin ‘arabanın lastiği’ bir sınıf olarak tanımlanabilir.
Yol tutuşu, çapı, genişliği, dayanıklılığı gibi kriterlerden bir lastik sınıfı
oluşturulabilir. Daha sonra, araba sınıfını tanımlarken, lastik tipi arabanın
bir alt sınıfı olarak tanımlanabilir. Bu şekilde istenildiği kadar iç içe sınıf
tanımlaması yapılabilir.
Sınıfların içerisinde üye
değişkenler tanımlanabildiği gibi üye fonksiyonlar da tanımlamak mümkündür. Bu
fonksiyonlar, tanımlanmış olan sınıfla ilişkili olan fonksiyonlardır. Araba
için gaz(), fren(), savrulma(), yakıtAzalt() gibi fonksiyonlar araba sınıfının birer üye fonksiyonudur.
Üye fonksiyonlara metotlar da denir. Metotlar, sınıfın nesnelerinin ne
yapabileceğini belirlerler.
7.2.1. Sınıf Tanımlama
Sınıf tanımlarken kullanılan komut, sınıfın ingilizcesinden gelen
‘class’ komutudur. Komutun ardından sınıfın ismi yazılmak suretiyle bu isimde
bir sınıf yaratılmış olur. Sınıfın üye değişkenleri ve üye fonksiyonları da
sınıfın isminin ardından açılıp kapanan küme parantezleri arasında kalan alanda
tanımlanırlar. Küme parantezi kapatıldıktan sonra, ‘enum’ komutunda olduğu gibi
(;) konularak tanımlama sona erer.
class Insan
{
unsigned int yas;
unsigned int kilo;
Yaslan();
KiloAl();
KiloVer();
};
Bu örnekte ‘insan’ isminde bir sınıf
tanımlanıyor. Yaş ve kilo değişkenleri tanımlandıktan sonra yaşlanmayı sağlayacak
olan Yaslan() ve kilo alıp kaybetmeye yarayacak olan KiloAl(), KiloVer()
fonksiyonları tanımlanıyor.
7.2.2. Sınıfların
İsimlendirilmesi
Bölüm 4.5’de değişken
isimlendirmeleriyle ilgili bilgi verilmişti. Sınıflar da isimlendirilirken aynı
kurallar geçerlidir. Ancak sınıflar bir ‘tip’ teşkil ettiğinden ayırt edici
olması amacıyla ya ilk harfi ya da tamamen büyük harf kullanılarak
isimlendirilirler. ‘insan’ yerine ‘Insan’ ya da ‘INSAN’ gibi. Birçok
programcının kullandığı bir diğer isimlendirme yöntemi de sınıf isminin başına
‘class’ kelimesini temsilen bir ‘c’ harfi koymaktır. ‘cInsan’, ‘cAraba’,
‘cKedi’ gibi. İlerleyen örneklerde yalnızca ilk harf büyük yazılarak sınıf
tanımlaması yapılacaktır. Fakat diğer sınıf isimlendirmelerinin de bilinmesi farklı
programcıların yazdığı programları incelerken faydalı olacaktır.
Metotlar yani üye fonksiyonlar
isimlendirilirken de bütün kelimelerin ilk harflerini büyük harf olarak yazmak
kullanışlı bir yöntemdir. GazPedalinaBas(), FrenYap() gibi.
7.2.3. Nesne
(Obje) Tanımlama
Sınıf tanımlama örneği olarak
gördüğümüz ‘Insan’ sınıfı, bu sınıfı kullanarak bir nesne tanımlamadığımız
sürece programın içerisinde yalnızca yer kaplayacaktır. Sınıflar program
içerisinde ‘int’, ‘float’ gibi yalnızca bir tip olarak yer alırlar. Onları işe
yarar hale getirmek için bir tanımlama yapmak gerekir.
int x;
float m;
Insan Ali;
Bu program parçası ‘x’ isimli bir
tamsayı, ‘m’ isimli bir ondalıklı sayı ve ‘Ali’ isimli bir insan tanımlar.
7.2.4. Sınıflarla Nesnelerin Karşılaştırılması
Gerçek yaşamda arabanın tanımı
alınmaz, arabanın kendisi alınır ve kullanılır. Arabanın tanımının benzini
bitmez, kullanılmakta olan arabanın benzini biter. Aynı şekilde C++’da da bir
‘Araba’ sınıfı yaratılırken arabaların genel özellikleri ve başlarına
gelebilecek olaylar düşünülerek bir sınıf oluşturulur. Ancak asla bu ‘Araba’
sınıfı kullanılmaz, ‘Araba’ sınıfıyla tanımlanan özel bir araba nesnesi
kullanılır ve olaylar bu nesnenin üzerinde gelişir.
7.3.
Sınıf Üyelerine Erişim
Yukarıda teorik olarak gösterdiğimiz
eşitliği C++ diline çevirelim.
class
Insan
{
unsigned int yas;
unsigned int kilo;
Yaslan();
KiloAl();
KiloVer();
};
Insan
Ali;
Ali.yas = 19;
Görüldüğü gibi sınıfların üyelerine
erişmek için nesneleri kullanmak zorundayız. Nesne’nin tanımlandığı sınıfa ait
bir üye değişken ya da üye fonksiyona ulaşmak için nesne tanımlandıktan
sonra nesneye verilen ismin arkasına nokta konularak değişken ya da
fonksiyonun adı yazılır.
class Insan
{
unsigned int yas;
unsigned int kilo;
Yaslan();
RejimYap();
KiloAl();
KiloVer();
};
Insan Ali;
Ali.yas = 20;
Ali.kilo = 70;
Ali.Yaslan();
Ali.KiloAl();
Ali.RejimYap();
Ali.KiloVer();
Bu örnekte Ali’nin yaşlandıkça kilo
aldığı ve aldığı kiloları rejim yaparak verdiği varsayılmış ve fonksiyonlar
buna göre tanımlanmıştır. Sınıfları kullanarak C++’da bu tür gerçek yaşam
kompozisyonları yazmak mümkündür. Sınıfların sağladığı en büyük yararlardan
biri programın okunabilirlik seviyesini arttırmasıdır. Bu örnekteki gibi düzgün
sınıf, değişken ve fonksiyon isimleri seçildiği taktirde programı incelemek
kitap okumak kadar kolay bir hal alır.
7.3.1. Sınıflara Değil, Nesnelere Değer Girmek
Bir insanın yaşı ve ağırlığı ne kadardır? Bu soruya gerçek hayatta cevap
aranırsa kesin bir yanıt bulunamaz. Ancak değer aralıkları ve ihtimallerle
karşılaşılır. Aynı şekilde C++’da da ‘Insan’ sınıfı kullanılarak bu sınıfın üye
değişkenlerine değerler atanamaz. Ancak bu sınıfla tanımlanan bir nesneye,
örneğin ‘Ali’ye bağlı olarak bir yaş ve kilo değeri belirlenebilir.
İnsan’ın yaşı = 20 (Yanlış)
Ali’nin yaşı = 20 (Doğru)
Bu eşitlikleri C++’a çevirecek
olursak.
Insan.yas = 20; // Yanlış
Ali.yas = 20; // Doğru
‘Insan.yas’ı bir değere eşitlemeye çalışmak ‘int’i bir değere eşitlemeye çalışmaktan çok daha mantıklı değildir.
Sırasıyla önce nesne tanımlanmalı, daha sonra bu nesne kullanılarak bir değer
verilmelidir.
Insan Ali;
Ali.yas = 20;
7.3.2. Tanımlanmayan Özelliklerin Sınıfa
Dahil Olmaması
Sınıf içerisinde tanımlanmayan bir
özelliğin sınıfa dahil olmaması pek de şaşırılacak bir durum değildir. Ancak
özellikle eski derleyicilerde sınıfların üye değişken ve fonksiyonlarını
listeleme özelliği bulunmadığı için gerek yazım hatası, gerek dikkatsizlik
sonucu tanımlanmayan bazı sınıf üyeleri kullanılmaya çalışılabilir ve sonucunda
program hata verir.
Şimdi, aşağıdaki örneği inceleyelim:
class
Kopek
{
int
saldirganlikDerecesi;
int boy;
int
agirlik;
Havla();
Isir();
OyunOyna();
};
Kopek Arsiz;
Arsiz.saldirganlikDerecesi = 3;
Arsiz.yas = 4; // Yanlış
Arsiz.Havla();
Arsiz.Konus(); // Yanlış
Burada, ‘Kopek’ isimli bir sınıf yapısı içerisinde, köpekler çeşitli
özellikleri ile tanımlanmış, ancak köpekler konuşamaz. Bu durumda Arsız’ı
konuşturmaya çalıştığımız anda program hata verecektir. Ancak bundan önce yapılan
bir başka hata Arsız’ın yaşını belirlemeye çalışmaktır. Köpekler konuşamaz
ancak köpeklerin de yaşı vardır. Yine de sınıfın içerisinde bir yaş özelliği
tanımlanmamışsa, bu şekilde Arsız’a herhangi bir yaş değeri verilemez.
7.4. Kullanıma Kapalı ve Açık Üyeler
Bu bölüm içerisinde şu ana kadar verilen program parçalarının her biri
temsilidir ve çalışmaz haldedirler. Çünkü aksi söylenmediği sürece sınıf
üyeleri kullanıma kapalıdır ve ancak sınıf fonksiyonları tarafından
erişilebilirler.
class Kedi()
{
unsigned
short int yas;
Miyavla();
};
Kedi.yas = 2; // Yanlış
Kedi.Miyavla(); // Yanlış
Üyelerin erişilebilir veya
erişilemez olmasını belirleyen komutlar ‘public’ ve ‘private’dır yani ‘açık’ ve
‘özel’. Eğer hiçbir tanımlama yapılmazsa sınıfın üyeleri otomatik olarak
‘private’ kabul edilir. Bu yüzden üyelere erişmek için ‘public’ tanımlaması
yapılması gerekir. ‘public’ ve ‘private’ birer label gibi tanımlanırlar yani
sonlarına ‘:’ işareti konulur.
class SinifIsmi()
{
public:
...
...
...
private:
...
...
...
};
7.11. Sınıfın Bir Üyesini Başka Bir Sınıfla Tanımlamak
Daha önce de bahsedildiği gibi bir sınıfın üye değişkeni başka bir
sınıfla tanımlanmış olabilir. Örneğin bir çember noktalardan oluşmuştur. İki
boyutlu bir düzlemde her bir noktanın x ve y gibi iki koordinatı vardır. Bu
durumda bir ‘Nokta’ sınıfı tanımlanacak olursa, bu sınıfa ait iki değişken de
‘x’ ve ‘y’ değişkenleri olacaktır. Çember için bir ‘Cember’ sınıfı tanımlanması
gerekir. Bu sınıfın da yarıçap ve koordinat değişkenlerine ihtiyacı olacaktır.
Bu değişkenlerden yarıçap tamsayı olarak tanımlanırken koordinat daha önce
tanımlanmış olan ‘nokta’ sınıfıyla tanımlanır.
Şimdi yukarıda anlatılanları programa dökerek bir çember çizdirelim:
#include <stdio.h>
#include <conio.h>
#include <math.h>
#define PI 3.1415926535
class Nokta
{
public:
int x;
int y;
};
class Cember
{
public:
Cember(int
yc);
~Cember();
void
CemberCiz();
private:
Nokta
Koordinat;
int
yariCap;
};
Cember::Cember(int yc)
{
yariCap
= yc;
}
Cember::~Cember()
{
}
void Cember::CemberCiz()
{
for(int
i = 0; i < 360; i++)
{
Koordinat.x
= 40 + (2 * yariCap * cos((float)i / 180 * PI));
Koordinat.y
= 13 + yariCap * sin((float)i / 180 * PI);
gotoxy(Koordinat.x,
Koordinat.y);
printf("xx");
}
}
void main()
{
clrscr();
Cember
Tekerlek(10);
Tekerlek.CemberCiz();
getch();
}
Daha önce bir elips çizdirme örneği yapılmış olduğundan (bkz. Bölüm
5.4.3) bu örnek için açıklama yapılmayacaktır. Ancak bu örnekte dikkat edilmesi
gereken konu ‘Cember’ sınıfında tanımlanan ‘Koordinat’ değişkeninin ‘Nokta’
sınıfıyla tanımlanması ve daha sonra bu ‘Koordinat’ın CemberCiz()
fonksiyonunda ‘Koordinat.x’ ve ‘Koordinat.y’ şeklinde sınıf üye değişkenleriyle
sınıf içi sınıf şeklinde kullanılmasıdır.
Sınıf içi sınıf kavramının daha iyi anlaşılması için biraz daha teorik
ancak açıklayıcı bir örneği inceleyelim:
#include <stdio.h>
#include <conio.h>
class A
{
public:
int x;
};
class B
{
public:
A y;
};
void main()
{
clrscr();
B Nesne;
Nesne.y.x
= 3;
printf("Nesnenin
ilk degeri = %d\n", Nesne.y.x);
Nesne.y.x++;
printf("Nesnenin
ikinci degeri = %d\n", Nesne.y.x);
getch();
}
Bu örnekte A sınıfında bir ‘x’ tamsayı değişkeni tanımlandıktan sonra B
sınıfında bir ‘y’ A tipi değişken tanımlanıyor. Daha sonra ana fonksiyonda B
tipi bir nesne tanımlanıyor ve bu nesnenin üye değişkeni olan ‘y’ye değer
girilmek isteniyor. Ancak ‘y’ bir tamsayı değişken değil, A tipinden bir
değişken. A sınıfında tamsayı olan ‘x’ tipi bir değişken tanımlı. Bu durumda A
tipiyle tanımlanmış olan ‘y’nin üye değişkeni olan ‘x’e ulaşmak üzere ‘y.x’
yazmak gerekiyor. Sonuçta ‘Nesne’ye bir tamsayı değer vermek gerektiğinde
‘Nesne.y.x’ şeklinde sınıf içi sınıf kullanılmış oluyor.
Bu örnek her ne kadar teorik olması açısından karmaşık görünse de, başka
programcılar tarafından yazılmış bu tür anlamsız program parçalarını inceleyip
anlamak yönünden iyi bir pratik olacaktır.
7.12. Struct Komutu ile Class Komutu Arasındaki İlişki
Bu bölüme ‘Sınıflar ve Yapılar’ başlığı atıldı. Ancak şu ana kadar hep
sınıflardan bahsedildi. Çünkü sınıf ve yapı hemen hemen aynı şeydir. Biri
‘class’ diğeri ise ‘struct’ komutu ile tanımlanır. Aralarındaki asıl fark ise
yapı (structure) ‘private’ bölümünü içermez, yalnızca ‘public’den ibarettir.
Ayrıca yapılarda ‘public:’ şeklinde bir tanımlamaya da ihtiyaç duyulmaz ve
doğrudan küme parantezinden sonra ilgili üyeler girilir.
Yapıların sınıflara göre eksikliği sadece metotlar tarafından
erişilebilen gizli üye değişkenler yaratılamamasıdır. Bütün üye
değişkenlere nesne üzerinden direkt erişim mümkündür. Bunun yanında, bu tür
gizli üye değişkenler kullanılmayacağı taktirde sınıflarda mecburen yaptığımız
‘public:’ tanımlamasını yapmadan yapıları kullanabiliriz.
Geçtiğimiz bölümde verilen çember çizme örneğini mümkün olan yerlerde yapı
kullanarak yeniden düzenleyelim:
#include <stdio.h>
#include <conio.h>
#include <math.h>
#define PI 3.1415926535
struct Nokta
{
int x;
int y;
};
class Cember
{
public:
Cember(int
yc);
~Cember();
void
CemberCiz();
private:
Nokta
Koordinat;
int
yariCap;
};
Cember::Cember(int yc)
{
yariCap
= yc;
}
Cember::~Cember()
{
}
void Cember::CemberCiz()
{
for(int
i = 0; i < 360; i++)
{
Koordinat.x
= 40 + (2 * yariCap * cos((float)i / 180 * PI));
Koordinat.y
= 13 + yariCap * sin((float)i / 180 * PI);
gotoxy(Koordinat.x,
Koordinat.y);
printf("xx");
}
}
void main()
{
clrscr();
Cember
Tekerlek(10);
Tekerlek.CemberCiz();
getch();
}
Bu örneğin daha önceki örnekten tek
farkı ‘Nokta’nın sınıf olarak değil yapı olarak tanımlanmış olmasıdır. Bu
yapının başında ‘public:’ tanımlamasına da gerek olmadığından program bir satır
kısalmıştır.
‘Cember’ sınıfı da yapı olarak
tanımlanabilirdi ancak bu durumda ‘Koordinat’ ve ‘yariCap’ gizliliklerini
yitirir ve direkt erişim iznine sahip olurlardı. Programın temel yapısını
bozmamak amacıyla ‘Cember’ sınıf olarak bırakıldı. Bunun yanında ‘Nokta’
‘private’ içermeyen bir sınıf olduğu için ‘struct’ yani yapı olarak
tanımlanabildi.
Kaydol:
Kayıtlar (Atom)