C++ Preprocessor (Ön işleyici)

    Pre-processor derleyicinin önemli bir parçasıdır. Ben pre-processorün  bize yazdığınız kodu derlemeye başladığınızda şunu dediğini düşünüyorum:  evet sen bu kodu yazdın ama bu kodu hem performans açısından hem de verimlilik açısından bir kontrol edelim, gerekli değişiklikleri yapalım, işe yaramaz kısımları atalım, bu arada bana makrolarla bildirdiğin direktifleri de yerine getireceğim. Yaptığı iş tam olarak budur, ancak işin kötü tarafı neler yaptığını neleri düzenlediğini bizimle paylaşmıyor maalesef,  paylaşıyor olsaydı daha güzel bir programlama dünyasına sahip olabilirdik :)
    Peki bu bahsettiği makro direktifleri nelerdir? Yeni bir satırda # hash, sharp diez ne derseniz artık işaretiyle başlarlar.

    #define ZERO 0 

    define bunlardan biridir, preprocessor bu direktifle kodunuz içerisinde ZERO deyimini arar ve bulduğu heryerde 0 ile değiştirir. Değişken tanımlar gibi eşittir kullanmadığımıza ve satır sonunda noktalı virgül kullanmadığımıza dikkat edin. kullanırsak onu da kopyalayacağından şüpheniz olmasın :)

    #include <iostream>

   include içerisinde yazdığınız dosyayı açar, tüm içeriğini kopyalar ve tam olarak include direktifini kullandığınız yere yapıştırır.

int kosul = 1;
#if kosul == true
//koşul sağlanıyorsa yapılacaklar
#else
//koşul sağlanmıyorsa yapılacaklar
#endif

Şimdi burada dikkat etmenizi istediğim birkaç şey var, öncelikle koşulun sağlanıp sağlanmadığını renklerden ayırt edebilmeniz, aktif olduğu belli olan kısım else kısmı, yani VS bize burada söz konusu koşulun sağlanmadığını ve hangi kod bloğunun yürütüleceğini gösteriyor. İkincisi bir satır yukarda int kosul diye bişey tanımlamışız ve 1 demişiz öyleyse koşul true gibi duruyor neden sağlanmamış olabilir? Pre-processor de işler biraz daha farklı yürüyor, buradaki koşul runtime da kullanılan bir değişkenden çok pre-precessing time içerisinde tanımlanan ifadelere göre işlem yapıyor yani değişken değil #define kullanmak gerekiyor. Yani şöyle olsaydı :

#define kosul 1;
#if kosul == true
//koşul sağlanıyorsa yapılacaklar
#else
//koşul sağlanmıyorsa yapılacaklar
#endif

kosul diye bişeyi hiç tanımlamasaydık nasıl davranırdı? false olarak kabul eder ve else bloğunu işlerdi, copy-paste olayı burda da geçerlidir. Pre-processor hangi koşul geçerliyse oradaki kod bloğunu alır (tüm if bloğunun tamamnın yazıldığı yere yapıştırır.) Yukardaki durum için #if ile başlayıp #endif ile biten tüm satırlar silinip yerine //koşul sağlanıyorsa yapılacaklar kısmı yapıştırılıyor olacak, tabi yorum yerine bir kod yazmış olsaydık. Dikkatinizi çekmekte fayda görüyorum: yalın kullanılan if ile karıştırmayın #if.

    Bir de benim de sıklıkla cross-platform kütüphaneler yazdığımda severek kullandığım iyi ki var dediğim bir diğer tanımlama da #ifdef tanımlamasıdır :

int main() 
{
#ifdef WIN32
	std::cout << "Merhaba Dünya" << std::endl;
#endif
#ifdef ARDUINO
	Serial.println("Merhaba Dünya");
#endif
}

Bu kodu win32 sistemde çalıştırdığınızda std::cout kullanır, arduino ile kullandığınızda Serial.println kullanır.

Sonraki Konu : 


Fonksiyon Prototiplerinin ve Bildirimlerinin Görünürlüğü

    C++ 'da fonksiyon kullanılmadan önce bildirilmeli ya da tanımlanmalıdır. Ana kodumuzun üzerinde tüm fonksiyonlarımızı yazarak sayfa içerisinde kalabalığa sebep oluruz, bunu engellemek için fonksiyon bildirimlerinin (function prototypes) kullanıldığından bahsetmiştik. Bunlar da yeterince fazlalaşınca da header dosyalarına geçiş yapıyoruz. 
    Eğer ki fonksiyonun çağırılması bu bildirim ya da tanımlamadan önce yapılırsa compile time hatası dediğimiz hata tipiyle karşılaşırız:

Severity Code Description Project File Line Suppression State

Error (active) E0304 no instance of overloaded function "topla" matches the argument list Project1 E:\!Blog\C++ Dersleri\Project1\merhabadunya.cpp 14

#include <iostream>
 
//int topla(int a,int b = 17);
//int topla(int, int, int);
 
int main() 
{
	int toplam = topla(5);
	// int toplam = 22;
}
 
int topla(int a, int b) // fonksiyon parametrelerine ulaşmak için isim veriyoruz
{
	int sonuc = a + b; // sonuc adıyla int tipinde bir değişken tanımlayıp
					   // a + b ye eşitliyoruz.
	return sonuc;	   // geri dönüş değerimizi belirliyoruz.
}
 
int topla(int a, int b, int c)
{
	return a + b + c;
}
 
 
yukarıdaki kod için topla fonksiyonlarının her ikisi de yazılmasına rağmen bu hataya sebebiyet vermiştir. Bildirim satırlarının "comment-out" yapıldığına dikkat edin. Bu hatayı engellemenin yolu en azından fonksiyon bildiriminin fonksiyon çağrısından önce yapılmasıdır. Yorum satırı haline getirilmiş iki bildirim satırı yorum satırı durumundan çıkıp kod haline getirildiğinde hata da giderilmiş olacaktır. Mutlaka bildirim yapmak zorunda da değiliz, şu da geçerli bir durumdur ancak dediğim gibi yukarı kısımda "kod kalabalığına" sebebiyet verir :

int topla(int a, int b) // fonksiyon parametrelerine ulaşmak için isim veriyoruz
{
	int sonuc = a + b; // sonuc adıyla int tipinde bir değişken tanımlayıp
					   // a + b ye eşitliyoruz.
	return sonuc;	   // geri dönüş değerimizi belirliyoruz.
}
int main() 
{
	int toplam = topla(5, 17);
	// int toplam = 22;
}
fonksiyonun çağırılmadan önce tanımlandığına dikkat edin.
    Prototip yazılırken fonksiyonun geri dönüş tipi int ve aldığı parametrelerin tipi (int,int) (adını yazma zorunluluğu yoktur) yazılmak zorundadır.
    Header dosyası kullanımı içinse yapılması gereken yeni bir header file oluşturup tüm fonksiyon bildirimlerini içine yazmak ve ana kodumuz içerisinde #include "oluştuğumuz header dosyasının adı.h" yazarak ana kodumuza dahil edilmesini istememizdir.

örnek olarak matematik.h dosyamızı oluşturalım ve içine fonksiyon bildirimlerimizi yazalım:

int topla(int a,int b = 17);
int topla(int, int, int);
ana dosyamız şu şekle gelebilir :

#include <iostream>
#include "matematik.h"
 
int main() 
{
	int toplam = topla(5, 17);
	// int toplam = 22;
}
int topla(int a, int b) // fonksiyon parametrelerine ulaşmak için isim veriyoruz
{
	int sonuc = a + b; // sonuc adıyla int tipinde bir değişken tanımlayıp
					   // a + b ye eşitliyoruz.
	return sonuc;	   // geri dönüş değerimizi belirliyoruz.
}
int topla(int a, int b, int c)
{
	return a + b + c;
}

bu durumda ilk derlemede matematik.o dosyası oluşturulup main.o içerisinde kullanılıyor olarak ilişkilendirilmiş olacaktır. Eğer ki fonksiyon bildirimlerini yazıp fonksiyonun içeriğini herhangi bir yerde yazmamışsak bu bize : unresolved external symbol hatası olarak döner. Bu, bana bir fonksiyon yazacağını söyledin ben herşeyi derlememe rağmen bu fonksiyona ulaşamadım demektir.



C++ Fonksiyonlar

    Programlamada çok tekrar ettiğimiz kod satırlarını ya da kod bloklarını lazım olduğu her yerde yeniden yazmak yerine, yahut kopyala yağıştır yapmak yerine, söz konusu bloğu bir fonksiyon olarak tanımlar ve gerektiği yerde fonksiyonu çağırarak bunu bir rutin haline getirebiliriz.
    C++ 'da fonksiyonlar parametrik olarak tanımlanabilirler, yani, bir fonksiyona değer gönderebiliriz. Fonksiyonun tanımlandığı tipe göre bir dönüşü olmak zorundadır, tipsiz dediğimiz void tanımlaması için bu durum istisnadır.
    Programlama dillerindeki fonksiyon kullanımı matematiksel fonksiyonları andırmaktadır ve aynı zamanda matematiksel fonksiyonlar programlama dillerindeki fonksiyonların esin kaynağıdır. C++ için fonksiyon tanımının tam karşılığı (procedure) prosedür kelimesi olsa gerek. Bu manada tam olarak matematiksel fonksiyonlarla eşleştirmek doğru olmayabilir.
    Fonksiyonlar genellikle belirli bir işlevi yerine getirmek içindir ve bir programın herhangi bir yerinden çağırılabilirler, bunun için azami şart fonksiyonun varlığının bildirilmesi(declaration) ve tanımlanmasıdır (definition). C++ için bu fonksiyon bildirimleri, -bildirim denmesinin sebebi fonksiyonun sadece prototipinin yazılıp içeriğinin, yani yaptığı/yapacağı işlemlerin kodlanmadığı kısım olmasıdır- hem ana kod içerisinde kalabalık etmemesi açısından hem de programın farklı kaynak kodu sayfalarında çağırılabilip kullanılabilmesinin kolaylaştırılması açısından .h uzantılı header files dediğimiz dosyalar içerisinde yapılır. Bir programı yazmak kadar o programlama dilinin kod yazma disiplinine hakim olmak ve o disiplini uygulamak da önemlidir.

    Fonksiyon Bildirimleri ( Function Declarations )

    Bir fonksiyon bildirimi, derleyiciye bu fonksiyonun var olduğunu, fonksiyonun bir prototipini yazarak bildirilmesine denir. Söz dizimi aşağıdaki gibidir:

int topla(int a, int b);

satır sonunda noktalı virgül olduğuna dikkat edin. Bu satırla derleyiciye benim int tipinde geri dönüşü olan parametre olarak iki tane integer tipinde sayı alan ve adı topla olan bir fonksiyonum var ileride ya da kodun başka bir yerinde bu fonksiyonu yazacağım demiş oluyoruz. burada a ve b tiplerini fonksiyonun gövdesi dediğimiz kısımda kullanacağız. Fonksiyon bildirimi yapılırken değişken isimlerini yazmak zorunda da değiliz:

int topla(int, int);

iki örnek için de bir geri dönüş tipi belirledik bu fonksiyonlar geriye bir dönüş yapmak zorundadır, fonksiyonumuz sadece bir iş yapacak ve geriye hiçbir değer döndürmesine gerek yoksa void tipinde tanımlanabilirler :

void ekranaYaz(const char* metin);

içerisine parametre olarak verdiğimizi metini ekrana yazması için bir fonksiyon yazıyorsak bize bir değer döndürmesine ihtiyaç duymayız.

    Fonksiyonun Çağırılması (function call)

    Bir fonksiyonun bildirimi yapıldıktan sonra çağırılabilir. Bir fonksiyonu satır sayısı bakımından yukarıda çağırıp alt satırlarda bildirim yapamazsınız.

#include <iostream>
 
int topla(int, int);
 
int main() 
{
	/*
	 Burada sadece fonksiyon bildirimi yaptık
	 fonksiyonun kendisi bu sayfa içerisinde yazılmamış olsa da
	 çağırılması legaldir, zira fonksiyon başka bir object
	 dosyasında tanılanıyor olabilir, hiç tanımlanmamışsa 
	 hata alıyor oluruz. Yani Linker derki bana bu fonksiyonu
	 tanımlayacağını söyledin ama tanımlamadın.
	*/
	topla(5,17);
}

burada fonksiyonun değerlerini de ilk parametre için 5 ikinci parametre için 17 olarak göndermiş olduk.

    Fonksiyonun Tanımlanması (Definition)

    Fonksiyonun tanımlanması bildirilmesi gibi başlar ancak artık değişken isimlerini vermeli ve fonksiyonun yerine getirmesini istediğimiz kodları süslü parantez içerisine yazmamız gerekir.

int topla(int a, int b) // fonksiyon parametrelerine ulaşmak için isim veriyoruz
{
	int sonuc = a + b; // sonuc adıyla int tipinde bir değişken tanımlayıp
					   // a + b ye eşitliyoruz.
	return sonuc;	   // geri dönüş değerimizi belirliyoruz.
}

burada mutlaka bir değişken tanımlayıp onu döndürmek zorunda değiliz return a + b; 'de aynı işi yapacaktır. return ile döndürülen değer fonksiyonun çağırıldığı yere yazdırılır, bu tam olarak şu demektir:

int toplam = topla(5,17);
// int toplam = 22;

topla(5,17) yerine 22 yazıldığını düşünebilirsiniz.

    Fonksiyon Aşırı Yükleme (Function Overloading)

    Bunu bu şekilde Türkçeye çevirmeyi hiç sevmiyorum ama yerine de uygun bir şey bulamadım. Bu tam olarak aynı isimde fakat farklı parametreler alan bir fonksiyon kullanmak için kullanılır. Yukarıdaki örnekte iki sayıyı topladık, üç ayrı sayıyı toplamamız gereken bir fonksiyona ihtiyac duyuyor olduğumuzda farklı isim vermek zorunda değiliz, aynı isimle farklı parametreler alan ve tamamen farklı işlemler yapan fonksiyonlar yazabiliriz :

int topla(int, int);
int topla(int, int, int);

bu durumda her iki fonksiyon için de ayrı ayrı tanımlama yazmanız gerekiyor:

nt topla(int a, int b) // fonksiyon parametrelerine ulaşmak için isim veriyoruz
{
	int sonuc = a + b; // sonuc adıyla int tipinde bir değişken tanımlayıp
					   // a + b ye eşitliyoruz.
	return sonuc;	   // geri dönüş değerimizi belirliyoruz.
}
 
int topla(int a, int b, int c)
{
	return a + b + c;
}

Visual Studio kullanıyorsanız, (tavsiyemdir bana güvenin şuanda en güçlü IDE VS'dir.) fonksiyonun adını yazıp üzerine gelirseniz tüm overload durumlarını görebilirsiniz:

C++ function overloading in Visual Studio

    Fonksiyon Varsayılan Parametre Değerleri (default parameter)

    Fonksiyon içerisine gönderilecek parametrelere varsayılan değerler verebiliriz, bu sayede o parametrenin kullanılması zorunluluğu da ortadan kalkmış olur, ancak bunu fonksiyon bildirimlerinde yapmamız ve değer vereceğimiz parametreleri en sona yazmamız gerekmekte:

#include <iostream>
 
int topla(int a, int b = 17);
int topla(int, int, int);
 
int main() 
{
	/*
	 Burada sadece tek bir int parametresi alan topla
	 fonksiyonu olmamasına rağmen, ikinci parametreye
	 varsayılan değer atadığımız için bu şekilde kullanabildik.
	*/
	
	int toplam = topla(5);
	// int toplam = 22;
}

bu durumda fonksiyona ikinci bir parametre girilmediği için onu 17 olarak aldı ve girilen ilk parametre olan 5 ile toplayıp aynı sonucu üretmiş oldu. Ancak

int topla(int a = 5, int b);

şeklinde kullanmamız mümkün değil, bu size "Severity Code Description Project File Line Suppression State

Error (active) E0306 default argument not at end of parameter list Project1 E:\!Blog\C++ Dersleri\Project1\merhabadunya.cpp 4

"gibi bir hata üretir. Varsayılan değer atanacak parametreler yallah en sona!


Önceki Konu : C++ Derleme Süreci




C++ Derleme Süreci

Bilgisayarda ya da C++ ile kodladığınız uygulama hangi platform üzerinde çalışıyorsa, C++ kodunun o platformun anlayacağı dile (assembly) çevirme işlemine derleme (compile) adı verilir. Bu süreci yöneten uygulama ise derleyicidir (compiler).
C++, C dili üzerinde yapılan geliştirmelerle ortaya çıkmıştır dolayısıyla derleme işleminin biçimi de C 'den miras olarak almıştır. Dört ana adımda bu sürece göz atmamız gerekirse:

  • Pre-Processing : ön işleme, ön işlemci tarafından kod içerisindeki makro yapıların işlemlerini gerçekleştirir. Bunlara örnek vermek gerekirse #include ile dosyamıza dahil ettiğimiz harici dosya içeriklerini kopyalayıp, dahil ettiğimiz yere yapıştırır, ya da #define direktifi ile tanımladığımız sembolik sabitleri değerleriyle değiştirir.
  • C++ ön işlemcisi tarafından genişletilen/daraltılan, hazır edilen kaynak kod dosyası, hedef platformun anlayacağı assembly diline derlenir.
  • Derlenen kod hedef platform için bir nesne koduna dönüştürülür ( .o uzantılı dosya )
  • Linker : Derlenen tüm object dosyaları birleştirilerek nihai hale getirilir. (bir önceki adımda bahsedilen işlem proje içerisindeki tüm kaynak kodlar ve kütüphaneler için gerçekleştirilir.)
Mevcut olan bir çok C/C++ derleyicisi vardır. Bazılarında bazı durumlar değişkenlik gösterse de genel yapı itibariyle yürütülen adımlar neredeyse tüm diğer derleyiciler için geçerlidir. 

C++ Derleme Süreci

Önceki Konu : C++ Yorum Satırları



C++ Yorum Satırları (comments)

 C++ ya da diğer hemen hemen tüm programlama dillerinde yorum satırları, kendinize ya da kodunuzu okuyacak olan diğer kişilere yazacağınız ve derleyicinin kodunuzu derlerken dikkate almayacağı açıklama satırlarıdır diyebiliriz.

C++ için iki tip açıklama satırından bahsetmek mümkündür.

Tek satırlı yorum 

İki tane bölü // işaretinin peşpeşe yazılmasından sonra yazılacak herşey yorum olarak kabul edilir.

#include <iostream>
 
int main() 
{
	// Tek satırda yorum yazma
	int a; // satır sonuna yorum yazabilirsiniz.
}

C Stili Blok halinde yorum satırları

Sıralı bölü ve yıldız  /* işaretlerinden sonra yorum yazmaya başlayabilir, yine sıralı yıldız ve bölü işareti */ ile yorum yazmayı istediğiniz yerde ve sütunda bitirebilirsiniz. Bu iki işaret içerisinde ne yazarsanız yazın buna C++ syntaxları da dahil, yorum olarak işlem görürler. C ve C++ için geçerlidir.

#include <iostream>
 
int main() 
{
	/*
	 Bu bir yorum bloğudur, 
	 derleyici tarafından dikkate alınmazlar
	 C++ a ait reserved words ya da söz dizimi olsa bile
	 int a = 5 sadece bir yorumdan ibarettir.
	*/
	
	int a; 
}

aşağıdaki gibi kullanımları da mümkündür:

void fonksiyonum( /*ilk parametre */ int a, /*ikinci parametre*/ int b)

Yorum Satırlarının Kullanım Amaçları ve Önemi

Her programlama dilinde geçerli olabilecek şekilde yorum satırlarının önemini kısaca şöyle sıralayabiliriz:

  • Kod okunurluğu ve bakımının kolayca yapılabilmesi için açıklamalar eklemiş oluruz, bu sayede ek olarak kod için döküman hazırlamanız gerekmez.
  • Yazılan bir fonksiyonun nasıl kullanıldığı hangi parametreleri aldığı ve bu parametrelerle neler yaptığı hangi sonucu ürettiği gibi bilgileri yazıp, kodu okuyan kişinin bu fonksiyonu kullanmasını basitleştirebiliriz. Emin olun zaman zaman bunu siz bile hatırlamıyor olabiliyorsunuz.
  • Kod geçmişi bilgilerini ve yapılan revizyonlardaki yeniliklerden bahsedebiliriz.
  • Kodu yazan kişinin bilgilerini iletişim bilgilerini ve varsa telif hakkıyla alakalı notlarımızı yazabiliriz.
Yukarıdaki disipline uymak zorunda değiliz ancak uyuyor olursak, kodda yaptığımız her değişikliği  değişiklik tarihini ve bu değişikliği yapan kişi bilgilerini revizyonlar kısmına eklemeliyiz, Bunun size ek olarak bir yük getireceğine dair bir çekinceniz yoksa kod satırları paylaşım dostu uygulamalardır, kodunuza daha resmi bir görünüm kazandırırlar. Ancak yine de yorum satırlarında aşırıya kaçılması kodun okunabilirliğini zora sokup rahatsız edici bir durum halini alabilir.

Benim de en çok kullanma sebebim olan son kullanma gereksinimi ise bir kod bloğunu yoruma çevirmektir. Kodun geliştirilmesi aşamasında bir işi yapmak için bir çok farklı yöntem deneyebilirsiniz. Bir yöntemi denediniz verim alamadınız, ancak belki o blokla alakalı spesifik bir şeyi atlamış olabileceğiniz fikri de kodu silmenize müsaade etmiyor olur, bu durumda kodu yorum bloğu haline getirip diğer yöntemi deneyebilirsiniz. Bazı durumların ekrana yazılması gerekmez ama o andaki değerini görmek için siz yazdırmış olabilirsiniz, kodun o kısmı bittiğinde bu yazdırma satırlarını da orijinal tabiriyle "comment-out" yapıp kurtulabilirsiniz. Merak etmeyin bu yolda ilerledikçe bahsettiğim şeyleri çok kullanıyor olacaksınız. :)


Önceki Konu : C++ Merhaba Dünya



C++ Merhaba Dünya

 Merhaba Dünya

Aşağıda görmüş olduğunuz kod yapısı en basit haliyle bir C++ uygulamasını göstermektedir. Komut satırı ekranına "Merhaba Dünya" yazar.

#include <iostream>
 
int main()
{
	std::cout << "Merhaba Dünya" << std::endl;
}

Kod Analizi

Yazdığımız kodu parça parça incelememiz gerekirse sırasıyla

  • #include <iostream preprocessor (önişleyici) 'e gönderilen ve C++ 'ın standart header dosyalarından biri olan iostream.h 'ı kodumuza dahil eden bir talimattır.

    iostream.h dosyası standart giriş çıkış akışlarının tanımlarını ve alan isimlerini (namespace)içerir.

    Standart giriş çıkış akışıyla kastettiğim şey harici bir sistemden bir bilgi almak ya da bilgi göndermektir. Mevcut durum için bu terminal/konsol diye adlandırabileceğimiz CMD ekranıdır.

  • int main(){...main adında yeni bir fonksyion tanımlar. Bu fonksiyon programımız çalıştırıldığı zaman ilk çağırılan özel bir fonksiyondur. Her C++ programı yalnızca bir main fonksiyonuna sahip olabilir, tipi int olmalıdır, geriye bir tamsayı (integer) döndürür. Bu değer programın çıkış kodu olarak adlandırılır. Eğer ki bu kod 0 ise program sorunsuz yürütülmüştür, 0 haricindeki her dönüş bir hatayı belirtir. Bu aynı zamanda özel bir tanımlama olan EXIT_SUCCESS 'tir. Eğer fonksiyon içerisine return ifadesi yazılmamışsa varsayılan olarak 0 döndürür.

  •  std::cout << "Merhaba Dünya<< std::endl; std bir namespace 'dir, :: operatörü o namespace 'e ait bir fonksiyona erişmek için kullanılır.  Yani cout konsola yazı yazan ve std namespace 'ine ait bir fonksiyondur. Bunlara ileride daha detaylı bakacağız şimdilik açıklamış olmak için yazıyorum, anlamıyorsanız önemsemeyin :)  << operatorü cout fonksiyonuna metin göndermek için kullanılır, stream nesnesine bir obje eklemek diyelim mi. Aynı operator peş peşe de kullanılabilir :

     std::cout << "Merhaba " << "Dünya<< std::endl;

    satırı da ekrana Merhaba Dünya yazacaktır.

  • "Merhaba Dünya" bir string ifadesidir. Çift tırnak içerisinde yazıldığına dikkat edin!

  • std::endl; ifadesi burada satırı bitirmek istediğimizi ve bundan sonra yazacaklarımızın bir alt satırda gösterilmesini sağlamak için yazılmıştır, bunun yerine string ifadesinin sonun \n ekleyerek de aynı durumu elde edebiliriz : "Merhaba Dünya\n"


Önceki Konu : C++ Nedir?
Sonraki Konu : C++ Yorum Satırları

C++ dersleri - Konu Başlıkları ~ İçerik


1 C++ 'a Başlarken
    1.1. C++ Nedir?  
    1.2. Merhaba Dünya
    1.3. C++ Yorum Satırları
    1.4. Derleme Süreci
    1.5. C++ Fonksiyonlar
    2.1 this keyword
    2.3 C++ true false
    2.4 nullptr


    6.3 Bit Toggle
    6.4 Bit Kontrol
    6.8 Bit Kopyalama


7 Bit Alanları - Gömülü Sistemler Bellek Organizasyonu

C++ Dersleri 1 Bölüm ~ C++ 'a başlarken

C++ Nedir?

C++ yüksek performanslı uygulamalar oluşturabileceğiniz değişik platformlarda (mobil, android, ios, gömülü sistemler : stm, avr, arm gibi) kullanılabilen popüler bir programlama dilidir. Programcısına sistem kaynaklarının etkili kullanılmasında özellikle de bellek üzerinde yüksek düzeyde kontrol imkanı sağlamaktadır. Bir çok programlama dilini öğrenmiş çeşitli projelerde çalışmış ve uygulamalar geliştirmiş biri olarak kendi tabirimle "C++ güçlü bir dildir" diyebilirim. C++ 'ın fazlaca kapsamlı bir yapısı olması sebebiyle bu konuda yazılacak çok fazla şey var, vakit buldukça burada paylaşıyor olacağım. Dilerim sizlere C++ deryasında yol almanızda ufak da olsa bir faydam dokunur.

İçerik : C++ Dersleri İçerik 
Sonraki konu : C++ Merhaba Dünya

                                            

Nesnelerin İnterneti IoT Esp8266 Webserver

NodeMCU kullanarak oluştuğumuz webserver ile, Esp8266 kart üzerindeki lede komutlar göndereceğiz.

Aşağıda yer alan kod üzerinde yer alan 

const char* ssid = ""; // Bağlanılacak Wifi Adı
const char* pwd = ""; // Bağlanılacak Wifi Şifresi

satırlarında bulunan bilgileri girmeniz gerekiyor, kartımızın bağlanacağı kablosuz ağa ait olan bilgiler kullandığınız wifi bağlantı noktasının ismi ve parolasıdır. Lütfen bu bilgileri çift tırnak içerisine yazdığınızdan emin olun.

Bu bilgileri girdikten sonra kodu kartımıza yükleyebiliriz. Yine Tools -> Board-> ESP8266 Boards menüsünden Generic ESP 8266 module seçili olduğundan ve  Port kısmından karta ait doğru portu seçtiğinizden emin olun. Yüklemeyi gerçekleştirdikten sonra Arduino IDE üzerinden Tools -> Serial Monitor (Araçlar -> Seri Ekran) 'ü açarak, wifi modeminizin kartımıza tanımladığı ip adresine ulaşabiliriz.

NodeMCU erişim IP adresi

http://192.168.1.39/

benzeri bi metinle karşılaşacaksınız. adres kısmını kopyalayıp, internet tarayıcınızın adres kızmına yapıştırıp adrese erişim sağlıyoruz, şöyle bir görüntüyle karşılaşıyoruz:


Gördüğünüz sayfanın gelmesini sağlayan kodlar aşağıdaki kod içerisinde 72 ~ 84. ü satırlar arasında bulunmakta. Arduino IDE Kod Satır Numaraları Nasıl Açılır, bilmiyorsan buraya tıklayıp öğrenebilirsin. Aynı metodla HTML bilginize bağlı olarak daha etkili bir sayfa tasarlayabilirsiniz. Tek yapmanız gereken HTML kodlarınızı
  client.println("");

fonksiyonula client nesnesine yazırmaktır. Basitçe yazdığımız bu HTML koduna bakacak olursak 3 tane buton eklemişiz ve butonlarımı da belirli adreslere a href ile yönlendirmişiz. Örnek olsun diye ilk satıra bakalım 
  client.println("</h1><a href='/LED-ACIK'><button>Ledi YAK</button></a>");

burada buton tıklandığında, dikkat: mevcut host dizini içinde LED-ACIK içeriğini talep ediliyor, bu aslında tam olarak şu adrestir: http://192.168.1.39/LED_ACIK ,bunun tamamını bu şekilde yazmak daha garanti bir yazım olacaktır, bu durumda o anda hangi web dizininde olursa olsun, net olarak gitmesini istediğimiz adresi yazmış oluruz. 
Peki bunu web serverimiz nasıl karşılar, yani webserverdan bu içerik talep edildiğinde ne yapacağını nasıl kodluyoruz. Bunun için bir request nesnemiz var. Bu nesne o anda web sitemizde dolaşanan kişinin "request" lerini tutuyor, ne demek bu; talep, yani kullanıcı bizden ne talep etmiş, LED-ACIK diye bir talebi var. Peki, bunu kontrol etmek için request nesnemizi kontrol etmemiz gerekiyor.
  if (request.indexOf("/LED-KAPALI") != -1) {
    digitalWrite(ledPin, LOW);
    led = 0;
  }

bu kodla kontrol ettiğimiz şey indexOf methodu gelen talebin içinde tırnak içine yazdığımız ifadenin olup olmadığıdır. -1 döndürmüşse bunun anlamı sorgumuz talepte yok demektir. -1 dışında gelen değer ise, talebin hangi karakterinde başladığı bilgisidir. Bu koşul için 0 dönecektir. Talebi karşıladığımıza göre süslü parantez içine bu talep geldiğinde nodeMcu 'ya ne yapması gerektiğini kodlayabiliriz. Ledi kapatacağız ledPin 'i low yapıyoruz. Bu kadar basit. Bir de ledin durumunu sayfada göstermek için led diye bir değişken tanımlamışız, sayfayı yazdığımız kod içerisinde de bunu 0 ya sönük 1 se yanıyor olarak bastırmışız. Kodun tamamı aşağıda yer alıyor :
/*
 *  ServerLEDControl.ino
 *  
 *  Led control over NodeMcu webserver
 *  
 *  Author Hakan ÖZMEN
 *  21.03.2021
 *  
 *  www.devrelerim.com
 *  www.youtube.com/HakkanR
 *  video of code : https://youtu.be/U-U49xkXW6o
 */
#include <ESP8266WiFi.h>
const char* ssid = ""; // Bağlanılacak Wifi Adı
const char* pwd = ""; // Bağlanılacak Wifi Şifresi

uint8_t ledPin = 4;
WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  delay(10);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);

  //Wifi bağlantısı
  Serial.println();
  Serial.print(ssid);
  Serial.println(" erişim noktasına bağlanılıyor.");
  WiFi.begin(ssid, pwd);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  server.begin();
  Serial.println("Sunucu başlatıldı.");
  Serial.println("NodeMCU erişim IP adresi");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");
}

void loop() {
  WiFiClient client = server.available();
  if (!client) return;
  Serial.println("Bir kullanıcı sunucuya bağlandı.");
  while (!client.available()) delay(1);
  boolean led = 0;
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();

  if (request.indexOf("/LED-KAPALI") != -1) {
    digitalWrite(ledPin, LOW);
    led = 0;
  }
  if (request.indexOf("/LED-ACIK") != -1) {
    digitalWrite(ledPin, HIGH);
    led = 1;
  }
   if (request.indexOf("/LED-BLINK") != -1) {
    for (uint8_t a = 0; a<3; a++)
    {
      digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
      delay(500);
    }
    led = 0;
  }

  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html;charset=utf-8");
  client.println("<!DOCTYPE HTML>");
  client.println("");
  client.println("<html>");
  client.print("<h1>Led Şuanda ");
  if (led) client.println("YANIYOR");
  else client.println("YANMIYOR-SÖNÜK");
  client.println("</h1><a href='/LED-ACIK'><button>Ledi YAK</button></a>");
  client.println("<a href='/LED-KAPALI'><button>Ledi KAPAT</button></a>");
  client.println("<a href='/LED-BLINK'><button>Led BLINK</button></a>");
  client.println("</html>");
  delay(1);
  Serial.println("Kullanıcı bağlantısı kesildi.");
}


Merak ettiğiniz herhangi bir şeyi yorumlarda sormaktan lütfen çekinmeyin.
Konuyu Youtube Kanalımda detaylı anlattım dilerseniz bağlantıya tıklayarak izleyebilirsiniz:




Arduino IDE Kod Satır Numaraları Nasıl Açılır

 Arduino IDE editöründe yazdığınız kodların satır numaralarını görüntülemek için yapmanız gereken şey

File -> Preferences -> Settings sekmesinde Display line numbers kutucuğunu işaretlemek, ve ardından OK butonuna tıklayarak satır numaralrının gösterilmesini sağlayabilirsiniz.

Arduino IDE kod satır numaraları

Ben türkçe kullanıyorum, nasıl yapacağım? Size nacizane tavsiyem Elektronik ve Programlama alanlarında tüm uygulamalarınızı ingilizce kullanmanız, bu sayede daha fazla içeriğe ulaşabilirsiniz.  Bu yazılı olmayan kurallardan biridir, teknolojinin dili ingilizcedir. Türkçe gideceğin yol şu şekilde; Dosya -> Tercihler -> Ayarlar sekmesinde, Satır numaralarını göster olarak yer bulur kendisine.

Satır Numaraları Nedir Neye Yararlar ?

  • En basit haliyle kodunuz toplamda kaç satır olmuştur o bilgiye sahip olursunuz.
  • Birine kodunuzla alakalı bir tarif yapacağınız zaman satır numarasını söyleyerek kodun neresine bakması gerektiğini kolayca tarif edebilirsiniz.
  • Kodunuzda bir hata aldığınızda bunu size editörünüz satır numarasıyla bildirir, hatanın olduğu satıra gitmek için Edit -> Go to line ya da CTRL + L tuş kombinasyonuyla çıkan pencereye satır kodunuz yazarak hızlıca ulaşabilirsiniz. Bunun için mutlaka satır numaralarının görünür olması gerekmez.




Türksat Saat Kanalı ve IRIG-B Time Code

Türksat Saat Kanalından Saat Bilgisi Nasıl Alınır? Uyduda kanalları dolaşırken, şu Türksat Saat kanalı hep dikkatimi çekmiştir. Özellikle  S...