C Programlama Örnekleri Pointer - İşaretçiler 07
C Programlama Dinamik olarak ayrılan bir hafıza bölgesine 1 ile 100 arasında rastgele oluşturulan 10 tane tam sayıyı yazan program
Devamı...C Programlama Örnekleri Özyineleme - Rekürsif 06
C Programlama Faktöriyel Hesaplama (Rekürsif fonksiyon)
Devamı...C Programlama Örnekleri String İşlemleri 05
C programlama ile Her Harfin Tekrar Sayısını Bulma
Devamı...C Programlama Örnekleri
Konu Başlıkları
00 - Intro (Giriş)
- Anahtar Kelimeler ve Tanımlamalar
- Değişkenler ve Sabitler
- C Veri Tipleri
- C Giriş / Çıkış
- C Operatörleri
01 - Basic (Basit)
- Matematiksel İşlemler
02 - Flow (Akış)
- if…else
- switch case
- break and continue
- While/For Döngüleri
03 - Arr (Arrays- Diziler)
- Çok Boyutlu Dizi (Matris)
- Diziler ve İşlevler
04 - Func (Function - Fonksiyon)
- Fonksiyon Tipleri
05 - String (Karakter Dizileri)
06 - Recursive (Özyinelemeli Fonksiyon)
07 - Pointer (İşaretçiler)
08 - Data (Data Structures - Veri Yapıları)
- Listeler
- Stack (Yığın)
- Queue (Kuyruk)
- Trees (Ağaçlar)
09 - File (Dosya)
C Programlama Örnekleri Fonksiyonlar 04
C Programlama ile Şans Oyunu
Devamı...C Programlama Örnekleri Diziler 03
Dizideki Elemanların Ortalaması
Devamı...C Programlama Örnekleri Karşılaştırmalar Döngüler 02
Tek Sayıların Toplamı
Devamı...C Programlama Örnekleri Girdi/Çıktı Değişken ve İşlemler 00
Giriş
Devamı...C++ Alıştırmalar
Bu sayfada C++ ile ilgili alıştırmalar ve uygulamalar verilmiştir. Her birini eksiksiz çözmeniz sizin için güzel bir çalışma olacaktır.
Aşağıdaki kaynak koddaki her bir sentaks hatasını
- C dilinin kurallarına göre
- C++ dilinin kurallarına
belirleyiniz. Her bir sentaks hatasının nedenini açıklayınız:
Devamı...C++ Vektörler
Konteynerlerin içinde genel amaçlı kullanımda ileri çıkan vektördür. Vektör sınıfı, ihtiyaç duyulduğunda boyutları artan dinamik dizileri destekler. C++’da bir dizinin boyutu derleme zamanında sabit hale getirilir. Bu uygulama, dizileri kullanmanın en verimli yolu olsa da, çalışma zamanında dizinin boyutu, değişen ihtiyaca göre ayarlanamadığından, esneklik konusunda yeterli değildir. Bir vektör, ihtiyaç duyulan belleği ayırarak bu sorunu çözer.
Vektörler, boyutları değişebilen dizileri temsil eden sıralı konteynerlerdir.Tıpkı diziler gibi, vektörler de elemanları için bitişik depolama konumlarını kullanır. Ancak dizilerden farklı olarak, depolama alanları konteyner tarafından otomatik olarak işleme tutulduğundan, boyutları dinamik olarak değişebilir.
Vektörler, boyutu değiştirebilen sıralı konteynerlerdir. Konteyner, aynı türdeki verileri tutan nesnelerdir. Sıra konteynerleri, öğeleri kesinlikle doğrusal sırayla depolar.
Vektörler tıpkı diziler gibi tek bir veri türü ile tanımlanabilir.
Bir vektör için şablon bildiriminin genel yapısı aşağıda gösterilmektedir:
Devamı...C++ Map
Map sınıfı, benzersiz anahtarların belirli değerlerle eşleşdiği bir ilişkisel konteynerdir. Map, içinde anahtar/değer ikililerinden oluşan bir liste yer alır. Anahtar bir ismi ifade eder ve bu isim karşılığında bir değer yer alır. Anahtar adını kullanarak kaydettiğimiz bir değeri, yine anahtar adını kullanarak okuyabiliriz.
Map içinde yer alan anahtar/değer ikililerindeki değeri, anahtar adını kullanarak okuyabilmemiz için, tüm anahtar ifadeleri benzersiz olmalıdır.
Bir map sınıfı için şablon bildiriminin genel yapısı aşağıda gösterilmektedir:
template <class Key, class T, class Comp = less<Key>, class Allocator = allocator<pair<const key, T>> class map
Key: Anahtarların veri türüdür.
T: Map’e kaydedilen veri türünü gösterir.
Comp: İki anahtar karşılaştıran fonksiyonu gösterir.
allocator: Tahsis ediciyi ifade eder.
Map konteynerleri aşağıdaki constructor fonksiyonlarını içerir:
Devamı...C++ Listeler
List sınıfı, çift yönlü ve doğrusal bir liste sağlar. Bir listedeki elemanlara sadece sıralı olarak erişim sağlanabilir. Elemanlara rastgele erişim yapılamaz. Çift yönlü olduğu için baştan sona veya sondan başa doğru erişim sağlanabilir.
Bir list sınıfı için şablon bildiriminin genel yapısı aşağıda gösterilmektedir:
template <class T, class Allocator = allocator<T>> class list
T: Listeye kaydedilen veri türünü gösterir.
allocator: Tahsis ediciyi ifade eder.
List konteynerleri aşağıdaki constructor fonksiyonlarını içerir:
Devamı...C++ Fonksiyon nesneleri
Fonksiyonları nesneleri, fonksiyon çağırma işlemcisi olan () işlemcisine çoklu görev tanımlama (overloading) işlemi uygulanarak, bir sınıftan oluşturulan nesnelerin bir fonksiyon gibi çağrılmasını sağlanmasıyla oluşturulur.
Tekli fonksiyon nesnesi tek bir parametre, ikili fonksiyon nesnesi ise iki parametre gerektirir.
Yerleşik fonksiyon nesneleri
Tekli fonksiyon nesnesi tek bir parametre, ikili fonksiyon nesnesi ise iki parametre gerektirir.
STL içinde yer alan fonksiyon nesneleri aşağıdaki tabloda gösterilmektedir:
Fonksiyon nesneleri
| divides | equal_to | greater | greater_equal | less |
| less_equal | logical_and | logical_not * | logical_or | minus |
| modulus | multiplies | negate * | not_equal_to | plus |
Yanında * işareti bulunanlar tek parametrelidir.
Fonksiyon nesneleri isimleri ile belirtilen işlemleri gerçekleştirir.
Yerleşik fonksiyon nesneleri, () işlemcisine çoklu görev tanımlama işlemi uygulayan, şablon sınıfları olup seçilen veri türü için belirtilen işlemin sonucunu geri döndürür. Örneğin, float verisi için plus() fonksiyon nesnesini çağırmak için aşağıdaki yapıyı kullanabiliriz:
plus<float>()
Yerleşik fonksiyon nesneleri <functional> başlık dosyasını kullanır.
Şimdi, tek parametre alan bir fonksiyon nesnesinin kullanımını bir örnek üzerinde incelemeye çalışalım:
Örnek
Devamı...C++ Algoritmalar
Algoritmalar konteynerler üzerinde işlem yaparlar. Her konteyner kendi temel işlemleri için gerekli fonksiyonları sağlar. Standart algoritmalar ise daha genişletilmiş veya karmaşık işlemler için aynı anda iki farklı tipte konteyner ile çalışmaya olanak sağlar.
STL içindeki algoritmaları kullanmak için, programlarımıza <algorithm> başlık dosyasını eklememiz gerekir.
Herhangi bir konteyner ile kullanılabilen ve tümünün bildirimi şablon olarak yapılmış olan STL algoritmalarının bir kısmı aşağıdaki tabloda yer almaktadır:
Devamı...C++ Şablonlar (Templates)
Şablonlar, C++’ın en gelişmiş ve en güçlü özelliklerinden biridir. Şablonları kullanarak genel amaçlı olarak kullanılan fonksiyonlar, sınıflar ve değişkenler oluşturabiliriz. Genel amaçlı olarak kullanılan bir fonksiyon veya sınıfta, fonksiyonun veya sınıfın üzerinde çalıştığı veri türü bir parametre olarak belirtilir. Böylece, her veri türü için farklı kod yazmak yerine, birkaç farklı veri türüyle bir fonksiyon veya sınıfı kullanabiliriz.
C++’da halen kullanılmakta olan üç çeşit şablon vardır:
- Fonksiyon şablonları
- Sınıf şablonları
- Değişken şablonları (C++14)
C++ Standart şablon kütüphanesi (STL)
Standart şablon kütüphanesi (Standart Templates Library - STL), hazır sınıf ve fonksiyon şablonları içerir. Bu şablonlar kullandıkları vektör, liste, kuyruk ve yığın gibi yaygın algoritma ve veri yapılarına erişim için fonksiyonlar tanımlar. STL şablon sınıflarından oluşturulduğundan, algoritmalar ve veri yapıları neredeyse her tür veriye uygulanabilir.
STL, birbiriyle bağlantılı olarak çalışan dört temel unsurdan oluşur:
- Konteynerler (Containers)
- Algoritmalar
- Tekrarlayıcılar (Iterators)
- Fonksiyonlar
Konteynerler (Containers)
Konteynerler kütüphanesi, kuyruklar, listeler ve yığınlar gibi ortak veri yapılarının kolayca kullanılmasını sağlayan, genel bir sınıf şablonları ve algoritmalardan oluşur. Her biri farklı bir işlem grubu sağlamak üzere tasarlanmış üç konteyner sınıfı vardır:
- Sıralı konteynerler (Sequence containers)
- İlişkisel konteynerler (Associative containers)
- Sırasız İlişkisel konteynerler (Unordered associative containers)
Konteyner, elemanları için ayrılan depolama alanını yönetir ve doğrudan veya tekrarlayıcılar (iterators) yolulya elemanlarına erişim sağlamak için üye fonksiyonlar içerir.
Verilerin depolanmasında kullanılan konteynerlerin listesi aşağıdaki tabloda gösterilmektedir:
| Konteyner | Açıklama |
|---|---|
| bitset | Bir seri bit değeridir. |
| deque | Çift uçlu bir kuyruktur. |
| list | Linear bir listedir. |
| map | Her bir anahtarın tek bir değer ile eşleştiği anahtar/değer ikililerini depolar. |
| multimap | Her bir anahtarın iki veya daha fazla değer ile eşleştiği anahtar/değer ikililerini depolar. |
| multiset | Her bir elemanın benzersiz olması gerekmeyen bir set tanımlar. |
| priority_queue | Öncelikli bir kuyruğu ifade eder. |
| queue | Bir kuyruğu ifade eder. |
| set | İçindeki her bir elemanın benzersiz olduğu bir gruptur. |
| stack | Bir yığını ifade eder. |
| vector | Dinamik bir dizidir. |
Algoritmalar
Algoritmalar konteynerler içeriğinde yer alan verilere ilk değer verme, sıralama ve arama gibi işlemler yapabilirler.
Tekrarlayıcılar (Iterators)
Tekrarlayıcılar, aşağı yukarı işaretçiler gibi davranan nesnelerdir. Bir konteyner içinde yer alan verilere sırasıyla erişim için tekrarlayıcıları kullanabiliriz. Tekrarlayıcıların beş farklı türü vardır:
| Tekrarlayıcı | Erişim yetkisi |
|---|---|
| Rastgele erişim | Değerleri depolar ve okur. Elemanlara rastgele erişilebilir. |
| Çift yönlü | Değerleri depolar ve okur. İleri ve geri hareket eder. |
| İleri | Değerleri depolar ve okur. Sadece ileri hareket eder. |
| Giriş | Değerleri okur fakat depolamaz. Sadece ileri hareket eder. |
| Çıkış | Değerleri depolar fakat okumaz. Sadece ileri hareket eder. |
İşaretçiler gibi kullanılan tekrarlayıcıları, artırabilir, azaltabilir ve * işlemcisi ile kullanabiliriz. Yineleyiciler, çeşitli konteynerler tarafından tanımlanan yineleyici türü kullanılarak bildirilir. Tekrarlayıcıların bildirimi farklı konteynerler tarafından iterator ifadesi kullanılarak yapılır.
STL ile, ters tekrarlayıcıları da kullanabiliriz. destekler. Ters tekrarlayıcılar, bir dizi boyunca ters yönde hareket eden çift yönlü veya rastgele erişimli tekrarlayıcılardır. Bu nedenle, bir ters tekrarlayıcı bir dizinin sonunu gösterirse, bu tekrarlayıcının artırılması dizinin sondan bir önceki elemanını göstermesini sağlar.
Fonksiyonlar
Konteynerler, algoritmalar ve tekrarlayıcıların yanı sıra karşılaştırma fonksiyonları ve fonksiyon nesneleri yer almaktadır.
<functional> başlık dosyası içindeki şablonlar, operator() tanımlayan nesneleri oluşturmamıza yardımcı olur. Bunlar fonksiyon nesneleri olarak adlandırılır ve birçok yerde fonksiyon işaretçileri yerine kullanılabilirler. <functional> başlık dosyasında içinde bildirilmiş önceden tanımlanmış birkaç fonksiyon nesnesi aşağıda gösterilmektedir:
En yaygın kullanılan fonksiyon nesnesi olan less, bir nesnenin diğerinden daha küçük olduğunu belirler. Fonksiyon nesneleri, STL algoritmalarında gerçek fonksiyon işaretçilerinin yerine kullanılabilir. Fonksiyon işaretçileri yerine fonksiyon nesnelerini kullanmak, STL’nin daha verimli kod üretmesini sağlar.
C++ Sınıf şablonları
Şablon sınıflar oluşturmak için, bir sınıf içinde kullanılan değişkenlerin en az bir tanesini veri türü değişken parametre olarak tanımlamak gerekir. Veri türü değişken parametreleri sınıf içindeki fonksiyonlarda aynı kodlarla kullanabilir.
Şablon sınıftan bir nesne oluşturulurken, sınıfa parametre olarak geçirilecek değişkenlerin veri türü belirlenir.
Bir sınıf şablonları, farklı veri türlerine aynı kodlarla işlem yapılmasına olanak sağladığından, büyük kolaylık sağlar.
Bir sınıf şablonu da fonksiyon şablonu gibi template ve typename anahtar kelimeleri ile oluşturulur. Sınıf şablonu bildirimi için kullanılan genel yapı aşağıda gösterilmektedir:
Devamı...C++ Run-Time Type ID
C++’da, nesneye yönelik programlama çerçevesinde çalışma zamanında çok biçimlilik özelliğini desteklemek için Çalışma zamanı veri türü tanımlama (run-time type identification - RTTI) ve dört adet geçici veri türü değiştirme (casting) işlemcisi kullanılır. Çalışma zamanı veri türü tanımlama özelliği, bir programın çalışması esnasında bir nesnenin veri türünü belirlemek için kullanılır. Geçici veri türü değiştirme işlemcileri ise, daha kontrollü işlem yapma olanağı sağlar.
C++’da, bir sınıf türetilen sınıflar sisteminde ana sınıf işaretçileri ve sanal fonksiyonları kullanarak çok biçimlilik kuralına uygun uygulamalar geliştirilebilir. Ana sınıf işaretçileri, ana sınıftan oluşturulan veya ana sınıftan türetilen sınıflardan oluşturulan herhangi bir nesneyi gösterebileceğinden, herhangi bir anda bir ana sınıf işaretçisinin hangi nesneyi göstereceği önceden bilinmeyebilir. Bu belirsizliği ortadan kaldırmak için, çalışma zamanı veri türü tanımlama özelliği kullanılır.
Bir nesnenin veri türünü elde etmek için, aşağıda iki farklı genel yapısı verilen ve <typeinfo> başlık dosyasında yer alan typeid işlemcisini kullanabiliriz.
typeid(değişken-adı)
typeid(veri-türü-adı)
değişken-adı: Veri türü elde edilecek olan değişken veya nesne adını gösterir.
veri-türü-adı: Veri türü elde edilecek olan veri türü adını gösterir.
typeid, değişkenin veri türünü gösteren type_info veri türünden bir referans geri döndürür.
type_info sınıfı içinde yer alan public fonksiyonlar aşağıdadır:
bool operator==(const type_info &ti)
bool operator!=(const type_info &ti)
bool before(const type_info &ti)
const char* name()
- == ve != işlemcileri veri türlerinin karşılaştırılması için kullanılır.
- Eğer çağrılan değişken parametre olarak kullanılan değişkenden önce geliyorsa, before() fonksiyonu doğru bir değer döndürür.
- name() fonksiyonu veri türünün adını gösteren bir işaretçi geri döndürür.
typeid işlemcisinin değişken adı ile kullanılması
Şimdi, typeid işlemcisinin kullanılmasını bir örnek üzerinde incelemeye çalışalım:
Örnek
Devamı...C++ Referanslar
C++’da, referans değişken adı verilen bir değişken tanımlayarak oluşturduğumuz değişenlere farklı bir isim ile erişim sağlayabiliriz.
Referans bildirimi aşağıdaki şekilde yapılmaktadır:
veri-türü& referans-adı = değişken-adı;
int id; // Değişken bildirimi
int& rid = id; // Referans bildirimi
Yukarıdaki işlem satırları ile, önce bir adet id adlı int değişken, sonra bu değişkeni referans gösteren bir adet referans oluşturulur.
Referans oluşturulduğunda, bellekte herhangi bir değişiklik olmaz. Yani, rid referans değerini depolamak için bellek kullanılmaz. Referans rid aslında id değişkeni için ikinci bir isim olarak kullanılır. Bu durumda, referans değeri kullandığımızda değişken adını kullanmış gibi oluruz. id değerini değiştirmek rid değerini değiştirmek ve rid değerini değiştirmek id değerini değiştirmek anlamına gelir.
Referans değişkenlerinin bildirimi yapıldığında bir ilk değer verilmelidir. Ancak, bir sınıf içinde yer aldığında, bir fonksiyon parametresi veya bir fonksiyon geri dönüş değeri olarak kullanıldığında bu kural geçerli değildir.
Şimdi, referans kullanımını bir örnek üzerinde incelemeye çalışalım:
Örnek
Devamı...