Zamanınız sınırlı, başkalarının hayatını yaşayarak bunu ziyan etmeyin.

9 Eylül 2014 Salı

Program Organizasyonu


    C programlama dili ile yazılmış programların bir çoğu çok sayıda dosyaya bölünerek yazılmıştır.
    Bu yöntemin en çok kullanıldığı yer birden fazla yazılımcının olduğu projelerdir.
    Her programcı kendine verilen işi yapan bir program parçası oluşturur.
    Projenin sonunda ise bu dosyalar birbirine entegre edilerek proje tamamlanır.Bu konuyla ilgili bilmemiz gereken önemli iki nokta vardır.Bunlar :
    A)Arayüz ( İnterface ) :
    Kütüphane dosyalarında olan makroların,fonksiyon imzalarının ve sabitlerin oluşturduğu bir bütündür.
    Bir yazılım ekibi , başkaları tarafından tasarlanılan modülü kullanırlarken arka planda ne iş yaptığı ile ilgilenmezler.
    İşte bu modüllerin birleştirilmesiyle ortaya program çıkar.
    B)Implementasyon :
    Örneğin bir projede siz kullanıcıda tarafından girilen sayının faktöriyelini bulmakla yükümlüsünüz.
    Bunu önceki kodlarımızda gördüğünüz gibi iki şekilde yaptık.Yinelemeli ve iteratif bir şekilde.
    Örneğin bir yinelemeli yöntem ile fonksiyonumuzu oluşturduk.Karşı taraf bunu iteratif bir hale dönüştürse bile bizim kodumuzu değiştirmemize gerek kalmaz.
    Bu paradigmaya program to interface (arayüzler kullanılarak programlama) denir.
    Bu paradigmayı kullanan sistemlere gevşek sistem denir ve bir sistem ne kadar gevşekse o kadar modülerdir.
    Arayüz Ve İmplementasyon Farkı :
 
    Arayüz içinde fonksiyonları ve verileri bulundurur.
    Implementasyon ise o fonksiyonların arka planda ne iş yaptığına bakılmasıdır.
    Yukarıdaki saati kullanan kişi için önemli olan şey saatin arayüzü yani saattir.
    Kullanıcı dişlilerin nasıl çalıştığını yada gücünü nereden aldığınu önemsemez.
    .h Uzantılı Kütüphane Dosyalarının Yapısı :
    Bu dosyalar .c uzantılı kaynak dosyaları arasında ortak bir bilginin tek bir noktada tanımlanmasını sağlar.Bunlara örnek olarak şunları verebiliriz:
    Program sabitleri,
    Makro tanımları,
    Fonksiyon imzaları.
    Dikkat etmeniz gerek en önemli şeylerden birisi arayüzler fonksiyonlara tanımlama yapılmamasıdır.Fonksiyonun sadece imzasını belirtmeniz gerekir.Bu arada aynı şey .c uzantılı dosyaların başka dosyalara dahil edilmemesinde de geçerlidir.
    .c Uzantılı Kaynak Dosyalarının Yapısı :
    Bu dosyalar kütüphane dosyalarının içerdiği bütün özelliklere sahiptir.Bu dosyalar genellikle implementasyon,kütüphane dosyaları ise arayüz dosyaları olarak adlandırılırlar.
    Birden Fazla Dosyadan Oluşan C Programları :
    Daha öncede bahsettiğim gibi büyük programlar ekip çalışması sonucu ortaya çıkarlar.Görev dağılımı yapılır ve her yazılımcı kendine verilen modülü oluşturur.Bunlar birleştirilere günümüz programları ortaya çıkar.
    Büyük yazılımları tek bir dosya içerisinde yürütmek mümkün olsa bile bu verimli bir yöntem değildir.
    Birden Fazla Dosyadan Oluşan C Programlarının Derlenmesi :
    A)Komut Satırı Kullanarak Derleme :
    Kullandığımız işletim sistemine göre komutlarla dosyanın projemizin bulunduğu dizine gideriz.
    Aşağıdaki kod yardımıyla klasördeki .c uzantılı dosyaların derlenip .o uzantılı nesne dosyaları oluşturmasını sağlarız.
    gcc –c *.c
    Aşağıdaki kod yardımıyla oluşan nesne dosyalarını birbirine bağlayıp bir program içinde çalıştırırız.
    Gcc – faktöriyel.exe *.0 –lm
    Yukarıdaki 3 2 komut verildikten sonra faktoriyel.exe komutu ile programımızı çalıştırabiliriz.
    B)Make Aracını Kullanarak Derleme :
    Basit projeler komut satırı kullanılması sıkıntı oluşturabilir.100 dosyadan oluşan bir projemiz var ise bunların birbiriyle bağlantısı biraz zor olduğundan make aracını kullanmak daha mantıklıdır.
    Makefile Kavramı :
    Make aracı arkaplanda oluşturduğu makefile adı verilen konfigürasyon dosyası ile modüllerin birbirine bağlanmasını , derlenmesini gerçekleştirir.
    Şimdi görsellerle olayı aydınlatmaya çalışacağım.2.resim makefile dosyasına aittir.



    Hedef ( Target ) :
    Hedefler make komutunun birbirinden bağımsız olarak çalıştırabileceği komut gruplarını listeler.
    Yukarıdaki makefile dosyasında 4 hedef bulunmaktadır.
    Örneğin yukarıdaki clean hedefini make clean komutu ile çalıştırırsak bütün .o uzantılı dosyaların silinmesini emreder.
    Kural ( Rule ) :
    Belli bir hedef çalıştırıldığında hangi dosyalara ihtiyaç duyulduğu belirtilen alana kural denir.Eğer dosyaya ihtiyaç yoksa kural alanı boş bırakılabilir.
    Komut ( Command ) :
    Kural bölümünde dosyalar belirlendikten sonra o dosyalara neler yapılacağının ya da dosya tanımlamazsa arka planda hangi işlerin gerçekleşeceğinin belirtildiği alandır.
    Bunlara ek olarak ise bazı sabitlerde yukarıda görülmektedir.CC=gcc gibi.Bu derlemenin nasıl yapacağının bizim seçmemiz için yapılmıştır.Örneğin gcc değilde bcc olsaydı programımız Borland C Compiler ile derlenecekti.
    Make Komutunun Kullanımı :
    Şimdi hangisini hedef alacaksam o komutu vereceğim.Ben terminalde make Makeornek komutunu verdim.
    Şimdi aşağıdaki resimle konuyu kavramaya çalışalım.

2 Eylül 2014 Salı

Ön İşlemci Direktifleri (Preprocessor Directives)

·         Ön İşlemci :
·         Derleme işleminin ilk adımı C ön işlemcisi tarafından gerçekleştirilir.Bir C ön işlemcisi şu görevleri yapar:
·         .c uzantılı kaynak dosyasını inceler ve bu dosyadan yorumları kaldırır.
·         # işareti ile başlayan ön işlemci direktiflerini ve makroları yorumlayıp bunları kaynak dosyaya ekler.
·         #include ile başla kütüphane dosyalarını kodlara entegre eder.
·         Ön İşlemci Direktifleri
·         Genellikle # işareti ile başlayan komutlara ön işlemci direktifleri(komutları) denir.C ön işlemcisi bu komutları yorumlayarak .c uzantılı kaynak dosyaya entegre eder.
·         #define Komutu :
·         Bu komut iki görev gerçekleştirir:
·         A)Program Sabiti Tanımlamak :

·         Şimdi bir örnek üzerinde konuyu kavramaya çalışalım.


·         const ve #define Arasındaki Farklar :
·         const ve #define benzer amaçlar için kullanılırlar.Aralarındaki farklar ise şunlardır :
·         const bir kod iken #define bir ön işlemci direktifidir.
·         #define kullanıldıktan sonra noktalı virgül kullanılmazken const kullanıldıktan sonra noktalı virgül kullanılır.
·         #define bütün program bloklarında geçerliyken const sadece tanımlandığı blok içerisinde işlevini yapabilir.
·         Şimdi bir örnekle konuyu kavramaya çalışalım


·         B)Makro Tanımlamak :
·         Makrolar fonksiyona benzeyen özel ifadelerdir.Şimdi konuyu bir örneğimizle kavramaya çalışalım.


·         Programdaki en önemli özellik ön işlemci komutlarının tip kontrolü yapmadığıdır.Gördüğünüz gibi makro hem int hemde float tipinden değer döndürmüştür.
·         Bir önemli noktada kod içerisinde makroyu çağırdıktan sonra noktalı virgül kullanılmasıdır.
·         Makro Tanımlamalarında Parantezlerin Önemi :
·         Arkadaşlar direkt olarak örnek üzerinden anlatacağım.Çok iyi bir şekilde anlayacağınızı umuyorum.


Şimdi bir örnekle daha konuyu pekiştirmeye çalışalım.


·         #define Komutunun Diğer Kullanımları :
·         Arkadaşlar şimdi bir örnek ile konuyu kavramaya çalışalım.


·         #define Komutunun Aşırı Kullanılmamasının Nedenleri :
·         Bir c ön işlemcisi C programlama dilini bilmez.#define komutunun yaptığı iş bir metin dosyasında bazı ifadelere karşılık gelen yerleri tümüyle tanımlanan ifadelerle değiştirmektir.
·         Kendimize ait bir söz dizimiz olmasına rağmen bu ön işlemci seviyesinde olur.Derleyicilerin kod biçimleme avantajlarını kaybetmiş oluruz.
·         #ifdef #else #endif Komutları :
·         Arkadaşlar bu komutları bir örnek içerisinde açıklamalar yaparak anlatmaya çalışacağım.


·         #if defined() ve #if !defined() Komutları :
·         Bu komutları #ifdef ve #ifndef komutları ile hiçbir farkı yoktur.
·         #elif Komutu :
·         else if kodunun ön işlemcideki karşılığıdır.Test edilen birden fazla koşulda kullanılır.
·         Şimdi bir örnekle konuyu kavrama çalışalım.


·         #undef Komutu :
·         #define ile tanımlanan sabiti ya da makroyu kendisinden sonraki satırlar için geçer kılmayı sağlar.
·         Şimdi bir örneğimizle konuyu kavramaya çalışalım.


·         #pragma Komutu :
·         Bu komut derleyiciye özel ön işlemci komutlarının yürütülmesini sağlar.Bu derleyiciye özel ve ve ön işlemci direktiflerinin her derleyiciye özel olması sebebiyle araştırılma yapılması gereken bir konudur.
·         #include Komutu :
·         Bu komut kaynak dosyalarının derleyiciye tanıtır ve kaynak dosyaların içerisindeki makroları,sabitleri ve fonksiyonları kullanabiliriz.Nasıl kütüphane ekleneceğiniz artık biliyorsunuz.
·         Eğer kendi kaynak dosyamızı oluşturmak istersek #include “kendikaynakdosyamız.h” yazmamız yeterli olacaktır.

24 Temmuz 2014 Perşembe

Dinamik Bellek Yönetimi

·         Arkadaşlar konuyu anlatmaya başlamadan önce statik bellek,otomatik bellek ve dinamik bellek hakkında araştırma yapınız.Bunlar sözel kısımlar o yüzden buraya uzun uzun anlatmayacağım.
·         Direktmen Dinamik Bellek Yönetimi konusuna giriş yapacağım.
·         Bismillah diyerek başlayalım.
·         Şimdi size iki tane örnek sunacağım ve sizlerle dinamik bellek yönetiminin ne kadar önemli olduğunu anlayacaksınız.
·         1.örnek olarak 30 karakterlik bir metin dizisi tanımladığımızı düşünelim.Kullanıcıdan bir metin girilmesi istendiğinde kullanıcı 10 karakterlik bir metin girdi.Eee geri kalan 19 karakter ne olacak.Boşa alan kaybı.Bu arada NULL karakterini unutmayın.Peki kullanıcı ya 30’dan fazla karakter girerse?İşte o zaman da programımız hata verecektir.
·         Dinamik bellek yönetiminde kullanabileceğimiz 3 tane çok özel fonksiyonlar vardır.Bunlar : malloc,free,sizeof.
·         malloc() Fonksiyonu :
·         Bu fonksiyonun bizim bellekten ödünç alan almamızı sağlar ve bu alanın başlangıç adresini tutan bir işaretçi döndürür.
·         free() Fonksiyonu :
·         Bu fonksiyon malloc ile aldığımız ödünç alanı belleğe geri iade etmemizi sağlar.

·         Şimdi bir örneğimizle konuyu kavramaya çalışalım.


·         İşaretçi Değişkenlerinin Birbirine Atanması :
·         Arkadaşlar örnek üzerinde açıklama yapacağım.


·         Bellek Alanlarının Farklı İşaretçilerle Yönetilmesi :
·         Arkadaşlar örnek üzerinde açıklama yapacağım.


·         Tek Boyutlu Dizilerde Dinamik Bellek Yönetimi :
·         Arkadaşlar daha önce dizilerle işlem yaparken sabit eleman sayısı tanımladık.Şimdi eleman sayısını kullanıcıdan alarak bellekten kazanç sağlayacağız.
·         Şimdi örneğimizle konuyu kavramaya çalışalım.


·         İki Boyutlu Dizilerde Dinamik Bellek Yönetimi :
·         Arkadaşlar burada yapmamız gereken çok kolay bir şey var.Basit düşünmek!
·         Şimdi 2x3 lük bir matrisimiz var diye düşünelim.
·         Yapmamız gereken her satır için belirli tamsayı atamak.Yani 1.satır için 3 eleman atayacak kadar eleman istemek.
·         Aynısını 2.satır içinde yaparsak matrisimiz oluşur.
·         İşte programlamacı mantığı böyle olmalıdır arkadaşlar.

·         İşaretçilerin Bellek Adreslerini Tutan İşaretçiler :

·         Arkadaşlar bu konuyu örnek üzerinde açıklama yaparak anlatacağım.


·         İki Boyutlu Dizilerde Dinamik Bellek Yönetimi :
·         Bu konunun püf noktalarına bir önceki makalemde değinmiştim.
·         Şimdi sıra geldi bir örnek ile taçlandırmaya.


·         calloc() Fonksiyonu :
·         Bu fonksiyon malloc fonksiyonu ile aynı görevi yapar.malloc fonksiyonundan tek farkı ödünç olarak aldığımız bellek alanındaki değişkenlere 0 değerini atar.
·         realloc() Fonksiyonu :
·         Bu fonksiyon daha önceden ödünç aldığımız bellek alanını yeniden belirlememizi sağlar ve ayırdığı alanın başlangıç adresini döndürür.
·         Şimdi bu iki fonksiyonu bir örneğimizle kavramaya çalışalım.


·         string.h Kütüphanesi Bellek Yönetim Fonksiyonları :
·         memset() Fonksiyonu :
·         Bu fonksiyon malloc ve realloc ile ödünç aldığımız hafıza alanının tamamına 0 değerini atamamızı sağlayan bir fonksiyondur.
·         Bu fonksiyonun genel kullanış amacı ise hafıza alanını belirli bir bölümüne 0 değerini atamaktır.

·         Şimdi bir örneğimizle konuyu kavramaya çalışalım.


·         memcpy() Fonksiyonu :
·         Arkadaşlar bu fonksiyon strcpy fonksiyonu ile kısmen aynı görevi yapar.
·         Tek farkı parametre olarak kopyalanacak bellek alanını alır ve aktarımı yapar.
·         Böyle olmasının sebebi bu fonkiyonunun bütün bellek alanlarına uygulanabilmesidir.
·         Şimdi bir örnekle konuyu kavramaya çalışalım.
·         memmove() Fonksiyonu :
·         Bu fonksiyon memcpy fonksiyonu ile aynı görevi yapar.
·         Tek farkı çakışan bellek alanları olması durumunda bu fonksiyonun daha kullanışlı olmasıdır.
·         memcpy fonksiyonu çakışan alanlar üzerine uygulanırsa vereceği çıktı tahmin edilemez.
·         Şimdi bir örnekle konuyu kavramaya çalışalım.


·         Bellek Alanlarının Örtüşmesi Durumu :
·         Örnek üzerinden açıklamalar yaparak bu konuyu anlatacağım.


·         memchr() Fonksiyonu :
·         Arkadaşlar bu fonksiyon kendine parametre olarak gelen bellek alanında bizim belirttiğimiz kadar ilk n bayt içerisinde bir değeri aramamızı sağlar.
·         Eğer bellek alanında bu değer bulunamazsa NULL değeri döndürülür.
·         Eğer bellek alanında bu değer bulunursa değerin bulunduğu baytı gösteren bir işaretçi döndürür.
·         Şimdi bir örneğimizle konuyu kavramaya çalışalım.


·         memcmp() Fonksiyonu :
·         Bu fonksiyon bize parametre olarak gelen iki dizisinin ilk n baytlarını karşılaştırmamızı sağlar.
·         Eğer ilk n baytlar eşit ise 0 değeri döndürülür.
·         Eğer ilk dizinin[dizi1] ilk n baytı ikinci dizinin[dizi2] ilk n baytından küçükse değer olarak negatif bir değer döner.
·         Eğer ilk dizinin[dizi1] ilk n baytı ikinci dizinin[dizi2]ilk n baytından büyükse değer olarak pozitif bir değer döner.
·         Şimdi bir örneğimizle konuyu kavramaya çalışalım.