2 Mayıs 2015 Cumartesi

C Programlama Ders 4 - Temel Giriş/Çıkış Fonksiyonları (printf, scanf, puts, gets, getchar)

Bütün programlama dillerinde temel giriş/çıkış fonksiyonları bulunur. Bu fonksiyonlar en genel tabiriyle kullanıcının programdan veri okumasını veya programa veri girişi yapmasını sağlar.

C Standart Kütüphanesinde temel giriş/çıkış fonksiyonları "stdio.h" başlık dosyası içinde tanımlıdır. En çok kullanılan temel giriş/çıkış fonksiyonları şunlardır:

  • printf()
  • scanf()
  • puts()
  • gets()
  • getchar()
Faydalı Bilgi 4.1 - Fonksiyonları Programa Dahil Eden Bağlayıcı (Linker)

Temel giriş/çıkış fonksiyonları da tıpkı diğer standart fonksiyonlar gibi kütüphanede bulunurlar. Kütüphane fonksiyonları C programlama dilinin bir parçası değildir. Derleyici kaynak kodu makine diline çevirirken bir standart fonksiyon gördüğünde oraya işaret koyarak boş bırakır. Çünkü kütüphanenin yerini derleyici değil, bağlayıcı(linker) bilir. Derlemeden sonraki aşamada bağlayıcı bu boşlukları doldurur ve kaynak kod makine diline çevrilmiş olur. Bu son aşamadır artık çalıştırılabilir (executable) program hazırdır.

Fonksiyonların yanlış yazılması durumunda ise derleyici hatayı anlayamaz. Bunu bağlayıcı boşlukları doldururken fark eder ve bağlamayı sonlandırarak "undefined reference" (tanımsız referans) şeklinde hata mesajı gönderir.

printf() Fonksiyonu


İlk dersimizde printf fonksiyonuna kısaca değinmiştik ve bu derse kadar yaptığımız uygulamalarda da printf fonksiyonunu çeşitli şekillerde kullandık. Bu ders printf() fonksiyonunu baştan alıp daha teknik bilgilerle ileriye götürerek bütün kullanım şekillerini ve inceliklerini göreceğiz.

Fonksiyon Prototipi

int printf(const char *format, ...);

Bu prototip programcıya şunu söyler: "Bana göndereceğin ilk parametre char tipinde olsun, diğerlerinin sayısını ve tipini sen belirle."

Ek Bilgi

printf() fonksiyonunun başka bir özelliği de yazdırdığı metnin kaç karakter olduğunu geriye döndürmesidir. Bu nedenle prototipin başındaki geri dönüş tipi int olarak belirtilmiştir. Aşağıda bu özelliği kullanarak bir uygulama yapacağız. (Fonksiyonun geri döndürmesi derken ne kastettiğimi anlamayanlar o uygulamayla anlayacaktır.)

const ifadesi ise; fonksiyona gönderilen değerin, fonksiyon içersinde değiştirilemez, sadece okunabilir olduğunu belirtir.


Basit bir printf() uygulaması:
#include <stdio.h>
main()
{
 
 printf("Alt Developer\n");
 printf("Ders 4\nTemel Giris/Cikis Fonksiyonlari");

}

Çoğu zaman ekrana bir değişkenin değerini yazdırmamız gerekir. Bunun için tip belirteçlerini kullanırız. Yazdığımız metinde değişken değerinin gözükmesini istediğimiz yere tıpkı new-line (\n) karakterini eklediğimiz gibi bir belirteç ekler virgülden sonra ise değişkenin adını gireriz.

Bu noktada bilmemiz gereken, her veri tipi için farklı belirteç kullanıldığıdır. Belirteçler ve kullanıldıkları veri tipleri aşağıdaki tabloda verilmiştir:

Belirteç Veri Tipi Anlamı
 %c  char  tek bir karakter
 %s  char  karakter dizisi (string)
 %d  int  tamsayı
 %ld  long  uzun tamsayı
 %u  unsigned int  işaretsiz tamsayı
 %lu  unsigned long  işaretsiz uzun tamsayı
 %f  float  Gerçel sayı
 %lf  double  Çift duyarlı gerçel sayı

Bu bilgiler ışığında artık herhangi bir değişkenin değerini ekrana yazdırabiliriz.

Değişken değerini yazdırma:
#include <stdio.h>
main()
{
 
 int gun=29,yil=1453;
 char ay[5]="Mayis";
 
 printf("Istanbul %d yilinda %s ayinin %d'unda fethedilmistir.\n",yil,ay,gun);

}

Değişkenlerle matematiksel işlemler yapıp sonucu parametre olarak atayabiliriz:
#include <stdio.h>
main()
{
 
 int kurulusTarihi=1923;
 printf("%d tarihinde kurulan Cumhuriyetimiz %d yasinda.\n",kurulusTarihi, 2015-kurulusTarihi);
 
 int kapasite=2000, katilim=1979;
 printf("%d kisilik salonda sadece %d tane bos koltuk var.\n\n",kapasite,kapasite-katilim);

}

 "printf() fonksiyonu aynı zamanda geriye karakter sayısını döndürür." demiştik. Yukarıda yaptığımız örneklerde bu fonksiyonu sadece çalıştırdık. Onu herhangi bir değişkene atamadığımız için geriye döndürdüğü değeri göremedik. Şimdi aşağıdaki örneği inceleyelim ve fonksiyonun geriye döndürdüğü değer derken neyi kastettiğimizi anlayalım.

printf() fonksiyonuyla karakter sayısını bulma:
#include <stdio.h>
main()
{
 
 int karakterSayisi, sayi=321;
 
 karakterSayisi=printf("Deneme %d\n",sayi);
 printf("Yukaridaki metin %d karakter uzunlugundadir.\n\n",karakterSayisi); 
        // boşluk ve \n birer karakterdir.

}


scanf() Fonksiyonu


Şimdiye kadar yaptığımız programlarda değişkenlerin değerlerini kendimiz belirledik. Kullanıcının değer girmesine izin vermedik. Ancak hemen hemen her programda kullanıcının programa veri girişi yapması gereken durumlar vardır. Bu durumlar için scanf() fonksiyonu kullanılır.

Fonksiyon Prototipi

int scanf(const char *format, ...);

Ek Bilgi

scanf() fonksiyonuyla veri girişi yapıldıktan sonra fonksiyon geriye 1 veya 0 sayısını döndürür. Eğer girilen değer belirtilen veri tipine uygunsa veri girişi başarılı olur ve geriye 1 döndürür. Eğer girilen değer veri tipine uygun değilse giriş başarısız olur ve geriye 0 döndürür.

Yani veri tipine uygun olmayan giriş hata üretmez. Dolayısıyla bunun sınamasını programcı yapmalıdır. Aksi taktirde program yanlış sonuçlar üretebilir. Bunu ileride if-else yapısını anlatırken göstereceğiz.


Basit bir scanf() uygulaması:
#include <stdio.h>
main()
{
 
char ad[10];
 int numara;
 printf("Adinizi girin: ");
 scanf("%s",&ad);
 printf("Numaranizi girin: ");
 scanf("%d",&numara);
 
 printf("%s bey numaranizi %d olarak girdiniz.\n\n",ad,numara);

}

Değişken isminin başına eklediğimiz & işaretine adres operatörü denir. Bir değişkenin başına geldiğinde artık değişkenin değeri değil, bellekteki adresi temsil edilir. Daha detaylı bilgiyi pointer konusuna geldiğimizde vereceğiz. Şimdilik şunu bilmeniz yeterli; scanf() fonksiyonuna değişkenin değeri değil bellekteki adresi gönderilir.

scanf() fonksiyonunun ilk parametresine belirteçler dışında bir karakter girmeniz doğru değildir. Derleme esnasında hata üretmez ancak programın yanlış ve saçma sonuçlar üretmesine neden olur.

scanf() fonksiyonuyla klavyeden birden fazla sayı okunabilir. Bunun için yapmanız gereken belirteçler arasına birer boşluk bırakmak. Klavyeden giriş yaparken ise diğer sayıya geçmek için boşluk, tab veya enter tuşları kullanılabilir. Bu tuşların her biri sonlandırıcı karakter olarak adlandırılır.

Tek scanf() ile birden fazla sayı girilmesi:
#include <stdio.h>
main()
{
 
int not1,not2,not3;
 float ortalama;
 
 printf("Notlarinizi Giriniz: ");
 scanf("%d %d %d",&not1, &not2, &not3);

 ortalama= (float)(not1+not2+not3)/3;
 
 printf("Ortalamaniz: %f\n\n",ortalama);

}


puts() Fonksiyonu


Bu fonksiyon printf() gibi ekrana çıktı vermek için kullanılır ancak aralarında farklar vardır.

printf() Fonksiyonundan Farkı:

  1. Sadece metin yazdırılabilir. int, float, double gibi veri tipleri yazdırılamaz. (Metnin içinde rakam olabilir.)
  2. Tek parametre kabul eder. 
  3. Metni yazdırdıktan sonra alt satıra iner. (new-line karakteri (\n) kullanmaya gerek kalmaz.) 


Fonksiyon Prototipi

int puts(const char *s);

Prototipten anlayacağımız üzere fonksiyon, char tipinde tek bir parametre alıyor. Yani virgül koyup ikinci veya üçüncü parametrelere izin vermez. Bu yüzden printf() fonksiyonundaki gibi belirteç kullanımını tanımaz ve belirteci olduğu gibi yazdırır.

Not: Geriye değer olarak; eğer başarıyla gerçekleştiyse pozitif bir sayı, başarıyla gerçekleşmediyse EOF karakterini döndürür. EOF karakteri işletim sistemlerine göre değişmekle birlikte genelde -1'dir

puts() Kullanımı:
#include <stdio.h>
main()
{
 
 puts("Alt Developer C Programlama Dersleri");
 
 char metin[20]="Puts Kullanimi";
 puts(metin);

}


gets() Fonksiyonu


Bu fonksiyon da scanf() fonksiyonu gibi programa veri girmek için kullanılır ve aralarındaki fark puts-printf arasındaki ilişki gibidir.

scanf() Fonksiyonundan Farkı:

  1. Girilen değeri sadece char tipine atar. 
  2. Tek parametre kabul eder. 
  3. Önemli: scanf()'te boşluk, tap ve enter tuşları metine dahil edilmez ve girişi sonlandırır. gets()'te sadece enter girişi sonlandırır boşluk ve tab tuşlarına izin verir. 

Fonksiyon Prototipi

Fonksiyon Prototipi

char *gets(char *s);

Şimdiye kadar gördüğümüz fonksiyonlardan farklı olarak prototipin başında char var. Fakat geri dönüş tipi char değildir. gets'in başındaki * geri dönüş tipini pointer yapar. Yani geriye bellekten bir adres döndürür. Pointer kavramını ilerideki derslerde anlatacağız. Burada şunu bilmeniz yeterli; gets() fonksiyonunun geriye döndürdüğü değer, ona atadığımız verinin bellekteki adresidir.

gets() Kullanımı:
#include <stdio.h>
main()
{
 
        char cumle[50];
 
 printf("\nMetin girin: ");
 gets(cumle);
 
 printf("\nGirilen metin: %s\n\n",cumle);

}


getchar() Fonksiyonu 


Bu fonksiyon ile sadece karakter okunur. Bu karakteri hiçbir değişkene atamaz veya yazdırmaz. Programı istenen yerde durdurmak için kullanılır. Enter'a bastıktan sonra program bir alt satırdan devam eder.

Fonksiyon Prototipi

int getchar(void);

Prototipteki void ifadesi boş veri tipidir. Fonksiyona parametre girilmesine gerek yoktur.

getchar Kullanımı:
#include <stdio.h>
main()
{
 
        printf("1. Bunu yazdirdi ve durdu.");
 getchar();
 printf("2. Enter'a basinca bunu yazdirdi.");

}

Temel giriş/çıkış fonksiyonları bu kadarla sınırlı değildir. Çeşitli eylemleri gerçekleştirmek için bir çok giriş/çıkış fonksiyonu vardır. En çok kullanılanlar burada verdiklerimizdir.

Bu dersimizi burada bitiriyoruz. Bir sonraki dersimizde karşılaştırma veya sınama yapmamızı sağlayan if-else yapısı ve switch-case yapısını anlatacağız.

30 Nisan 2015 Perşembe

C Programlama Ders 3 - Aritmatiksel İşlemler ve Veri Dönüştürme

İlk bilgisayarların oda büyüklüğünde hesap makineleri olduğunu hatırlarsak, bilgisayarlar ve buna bağlı olarak programlar temelde işlem yapabilme yetenekleri üzerine kurulmuşlardır demek hiç de zor olmaz. C'de dört işlem yapma, temel seviyede bir matematik bilgisine sahip herkesin hiç zorlanmadan yapabileceği bir eylemdir. Kullanılan işaretler günlük hayatta matematik işlemlerinde kullandığımız işaretlerden farklı değildir. Matematik bilimindeki öncelik sırası, bire bir C programlama dili için de geçerlidir.

Bu dersteki örnekleri dikkatle incelediğinizde aritmetik işlemlere dair kafanızda bir soru işareti kalmayacaktır. Yapılan işlemlerin yanına yorum ekleyerek özel durumların gözünüzden kaçmaması için dikkatinizi çekmeye çalıştım.

İlk olarak bütün ders boyunca kullanacağımız tamsayı değişkenlerini tanımlayalım. (Dersin devamında sırası geldikçe bunlara değerler atayıp farklı işlemlerde kullanacağız.) Ardından tam1 ve tam2 değişkenine değer ataması yapalım:
int tam1,tam2,tam3,tam4;   

tam1= 1453;  
tam2= 16;

// Değerlerini değiştirmek için tekrar tanımlamaya gerek yoktur.

tam1= 19;   // tam1 artık 19'u temsil ediyor.
tam2= -67;  // tam2 artık -67'yi temsil ediyor.
//...
Şimdi tam1 ve tam2 sayılarını kullanarak matematiksel işlemler yapalım.
//...
tam1= 3+5;    // =8
tam2= 3+5*10; // =53  "Çarpma işlemi öncelikli.
++tam1;       // =9 "tam1'i 1 arttırır.
--tam2;       // =52 "tam2'yi bir azaltır.
tam1+=6;      // =15 "tam1'e 6 ekler.
tam2-=2;      // =50 "tam2'den 2 çıkarır.
//...
Peki eşitliğin her iki tarafında da aynı değişken olursa ne olur?
Bilinmelidir ki her zaman eşitliğin sağ tarafı önceliklidir. Sağ taraftaki işlem bittikten sonra sola aktarılır.
//...
// Önceki durum: tam1=15 - tam2=50
tam1=tam1+2;          // =17 "(15)+2=17
tam2=tam2-(tam1+10);  // =23 "(50)-(17+10)=23
//...

Önemli


C programlama dilinde aritmetik işlemlerde eşitliğin sağ tarafındaki sayılardan hiçbiri gerçel sayı(float veya double) değilse sonuç her zaman tam sayı çıkar. Bu durum kesme hatası (truncation error) olarak adlandırılır.

Örneğin 5/2=2.5 olması beklenir.
Fakat C'de bunun sonucu 5/2=2 şeklidedir.

C'nin tamsayılarla bölme mantığını şu algoritmayla daha iyi anlayabilirsiniz: (Bu algoritmanın bilinmesi gerekmez. Kafanızı karıştıracak gibiyse bu 3 adımı atlayın.)

Tam sayılarla 5/2 işlemi;
I.    5-2=3      bölüm=1 kalan=3      (Fark 0'dan büyük old. için kalana aktarıldı ve bölüm 1 arttı.)
II.   3-2=1      bölüm=2 kalan=1      ( I. Adımla aynı )
III.  1-2=-1                                          (Fark 0'dan küçük old. için bu adım atlandı ve işlem sonlandı.)

Böylelikle 5/2 işleminin sonucu 2 olur ve kalan 1'dir.

Mod Operatörü (%)


Bir bölme işleminden kalanı öğrenmek için ise mod operatörünü kullanırız. Mod alma işlemi bir sayının başka bir sayıya bölümünden kalan sayıyı döndürür. 5/2 işlemine mod uygularsak 1 döner. Mod operatörü %(yüzde) işareti ile uygulanır:

  • (bölünen) % (bölen)
Örnek:
15%6 işlemi 3'e eşittir.
"15 mod 6" veya "15'in 6'ya bölümünden kalan" diye okunabilir.

Tam sayılarla bölme işlemine ve mod operatörüne örnek olarak şu uygulamaya inceleyelim.
//...
tam3= 15/6;  // =2 " 2,5 değil !
tam4= 15%6;  // =3 " 15/6 'dan kalan=3
//...
Yani önemli başlığı altında verdiğim bilgi ve bu uygulama ışığında bölme işleminde işleme tabi tutulan sayıların hepsi tam sayı ise gerçek sonucun virgülden sonrası kesilir diyebiliriz.

Acaba eşitliğin sol tarafında integer değil de float tipinde bir değişken olsaydı sonuç olarak virgülden sonrası döner miydi? Eğer az önce belirtmeye çalıştığım durum anlaşıldıysa ve "eşitliğin sağ tarafındaki" ile "işleme tabi tutulan" kelimelerini neden kalın puntolarla yazdığımı farkettiyseniz bu soru size kolay gelmiştir.
Hadi deneyelim ve sonucu görelim.
Bir önceki işlemi gerçel sayılar için kullanılan float veri tipine uygulayalım.
//...
//Önceki durum: tam1=17- tam2=23 - tam3=2 - tam4=3

float ondalik1, ondalik2, ondalik3, ondalik4, ondalik5, ondalik6;

ondalik1=9/4;       // =2,00  " 9/4=2  -  2,25 değil !
ondalik2=tam1/tam4; // =5,00 " 17/3=5 -  5,67 değil !
//...
Not: Virgülden sonraki sıfırları gerçel sayı olduğunu belirtmek için yazdım. Çıktı aldığınızda da aksini belirtmediğiniz sürece 0'lar gözükecektir. Dersin sonundaki çıktıları inceleyebilirsiniz. 

Gördüğünüz gibi sonuca virgülden sonra 0'ların eklenmesinden başka birşey değişmedi.

Peki neden float bir değişkene atama yapmamıza rağmen virgülden sonrası dikkate alınmadı?
Bunun çok basit bir cevabı var.

Eşitliğin sağ tarafı, sol tarafa tam sayı bir değer gönderiyor. Dolayısıyla sol taraf ondalıklı bir sayı kabul etmesine rağmen tam sayıyla yetinmek zorunda kalıyor. O da kendine gelen tam sayıya virgülden sonra 0'lar ekleyerek gerçel sayı yapıyor. O zaman şunu sormamız gerekiyor.Ne yapmalıyız ki sağ taraftaki işlemin sonucu ondalık bir değer çıksın. Böylelikle sol tarafa virgüllü bir değer göndersin.

Bunun için işleme giren sayılardan sadece birini gerçel sayıya dönüştürmemiz yeterli. Bunu yaparsak C bizim gerçel sayılarla işlem yaptığımızı anlar ve diğer değişkenleri otomatik dönüştürür. Ve sonuç olarak kayıp vermeden bir gerçel sayı elde etmiş oluruz.
O halde tip dönüşümü nasıl yapılır gösterelim:

  • (hedef tip)değişkenIsmi 
Örnek:
(float)tamSayi1;     (Float tipine dönüştürür.)
(int)ondalik1;         (Tam sayı tipine dönüştürür.)

 Şimdi uygulamamıza bakalım.
//...
//Önceki durum: tam2=23 - tam3=2 - ondalik1=2,00 - ondalik2=5,00

ondalik3=(float)tam2/tam3;  // =11,5  " 23,00/2 (tam2 dönüştürüldü)
ondalik4=tam2/(float)tam3;  // =11.5  " 23/2,00 (tam3 dönüştürüldü)
ondalik5=5.00/2;            // =2,5  " 5 sayısı float tipte yazıldı
ondalik6=ondalik2/tam3;     // =2,5   " ondalik2 float old. için dönüştürmeye gerek yok.
//...
Dönüştürme örneklerinde dikkat ettiyseniz sadece bir değişkene dönüştürme uyguladık. İsterseniz ikisine de uygulayabilirsiniz, bir şey farketmediğini, aynı sonucu verdiğini göreceksiniz.

Son olarak sonuçları ekrana yazdıralım ve doğruluğunu kontrol edelim. Yaptığımız tüm işlemlere çıktı şu şekilde olmalı:

  • tam1=17
  • tam2=23
  • tam3=2
  • tam4=3
  • ondalik1=2,00
  • ondalik2=5,00
  • ondalik3=11,5
  • ondalik4=11,5
  • ondalik5=2,5
  • ondalik6=2,5
//...
printf("Degisken Adi - Degeri\n");
printf("tam1=          %d\n",tam1);
printf("tam2=          %d\n",tam2);
printf("tam3=          %d\n",tam3);
printf("tam4=          %d\n",tam4);
printf("ondalik1=      %f\n",ondalik1);
printf("ondalik2=      %f\n",ondalik2);
printf("ondalik3=      %f\n",ondalik3);
printf("ondalik4=      %f\n",ondalik4);
printf("ondalik5=      %f\n",ondalik5);
printf("ondalik6=      %f\n",ondalik6);
//...

Çıktıda float tiplerin sonundaki fazladan 0'lar dikkatinizi çekmiştir. Bunları yok etmek veya azaltmak gerekebilir. Belirteçler üzerinde yapacağımız ufak dokunuşlarla bu mümkün.

Aşağıdaki çıkış ifadesinde %f'lerin aralarına yazılan .0 ve .2 lere dikkat ediniz.
//...
printf("\nVirgulden Sonrasiz Float Yazdirmak\n");
printf("ondalik1=      %.0f\n",ondalik1);
printf("ondalik2=      %.0f\n",ondalik2);
printf("ondalik3=      %.0f\n",ondalik3);
printf("ondalik4=      %.0f\n",ondalik4);
printf("ondalik5=      %.0f\n",ondalik5);
printf("ondalik6=      %.0f\n",ondalik6);

printf("\nVirgulden Sonra 2 Rakamli Float Yazdirmak\n");
printf("ondalik1=      %.2f\n",ondalik1);
printf("ondalik2=      %.2f\n",ondalik2);
printf("ondalik3=      %.2f\n",ondalik3);
printf("ondalik4=      %.2f\n",ondalik4);
printf("ondalik5=      %.2f\n",ondalik5);
printf("ondalik6=      %.2f\n",ondalik6);

Bu dersimizi de burada sonlandıralım. Bir daha ki dersimizde kullanıcı tarafından programa veri girilmesini sağlayan scanf() fonksiyonunu anlatacağız. 

23 Nisan 2015 Perşembe

C Programlama Ders 2 - Veri Tipleri ve Değişkenler

Tıpkı matematik bilimindeki sembolik ifadeler gibi programlama dillerinde de sayı veya metin gibi verileri sembolik bir adlandırmayla tutarız. Bu sembolik adlandırmalara değişken denir. Her değişken bellekte işletim sistemine ve derleyiciye bağlı olarak 1 ile 16 bayt arasında belirli bir alan işgal eder ve işgal ettiği bu alanın adresi ile çağrılır ve kullanılır. Her bir değişken; metin, tamsayı, gerçel sayı gibi farklı veri tiplerinden sadece birini tutabilir. Bu yüzden değişkene değer atamadan önce onun veri tipini tanımlamak gerekir.

C programlama dili, veri tipi bakımından oldukça zengin bir dildir. Dört temel veri tipi bulunmaktadır. Bunlar;

  • char - Tek karakter veya küçük tamsayı
  • int - Tam sayı
  • float - Tek duyarlı gerçel sayı (7 basamak)
  • double - Çift duyarlı gerçel sayı (15 basamak)
Ek olarak bu veri tiplerinin önüne gelerek onların türevlerini oluşturan niteleyiciler vardır. Bunlar da;

  • short (kısa) 
  • long (uzun) 
  • unsigned (işaretsiz) 
Niteleyicilere ihtiyaç duyulmasının sebebi her veri tipinin sınırlarının olmasıdır. short bir veri tipinin sınırlarını daraltırken, long ise veri tipinin sınırlarını genişletir. Unsigned ise negatif tarafı yok edip bunu pozitif tarafa ekler. Dolayısıyla alt sınır 0 olurken pozitif sınır 2 katına çıkar. Burada dikkat etmemiz gereken nokta sınırlar genişledikçe bellekte kaplayacağı alanın da doğal olarak artıyor olmasıdır.

Farklı işletim sistemleri ve derleyicilerde veri tipinin kapladığı alan değişkenlik gösterir. Buna bağlı olarak veri tipinin sınırları da değişir. Bunun hesaplanmasında standart kütüphanedeki sizeof() fonksiyonundan yararlanılır. Bu fonksiyonu ayrı bir bölümde anlattık merak edenler fonksiyon isminin üzerine tıklayıp inceleyebilir fakat kullanımını anlayabilmek için bu dersi tamamlayıp, belirteçleri öğrenmiş olmak gerekli ve yeterlidir.

Değişken Tanımlama ve Değer Atama

C programlama dilinde değişkenlerin kullanabilmesi için önceden tanımlanması gerekir. Böylelikle değişkene bellekte bir adres tayin edilir ve o adres değişkenin kimliği olur. Değişken tanımlama(declare) şu şekilde yapılır:

  • degiskenTipi degiskenAdi;

Değişken adını belirlemede sınırlayıcı kurallar vardır. Bu kurallar;

  • Değişken adları İngilizce karakterler (A-Z) veya (a-z) yada rakamlar (0-9) ile yazılmalıdır. Türkçe karakterler, özel karakterler veya boşluk karakteri kullanılamaz. (Alt tire ( _ ) kullanılabilir.) 
  • Değişken adları rakamla başlayamaz. İlk karakter bir harf olmalıdır. Sonrasında rakam kullanılabilir.
  • C 'nin anahtar kelimeleri (Key Words) değişken ismi olarak kullanılamaz. Bu anahtar kelimeler;
autodoubleintstruct
breakelselongswitch
caseenumregistertypedef
charexternreturnunion
constfloatshortunsigned
continueforsignedvoid
defaultgotosizeofvolatile
doifstaticwhile

Aşağıdaki tanımlamaları inceleyiniz.
#include <stdio.h>

void main()
{
 //Bu kodlar belirttiğimiz hatalardan dolayı derlenmez.
 
 char karakter1,harf6;  // GEÇERLİ
 int tamSayi,tam2,sayi;  // GEÇERLİ
 float ondalik1;    // GEÇERLİ
 double ondalik2;   // GEÇERLİ
 int tam_sayi;    // GEÇERLİ (Alt tire (_) serbest)
 
 int ondalik1;  // HATA (ondalik1 önceden tanımlandı.) 
 int sayı;   // HATA (Türkçe karakter kullanılamaz.)
 int 1tamSayi;  // HATA (Rakamla başlayamaz.)
 int tam sayi;  // HATA (Boşluk kullanılamaz.)
 int tam-sayi;  // HATA (Özel karakter kullanılamaz.)
 int double;   // HATA (Anahtar kelimeler kullanılamaz.)
}

Tanımlanan değişkenlere, türüne uygun herhangi bir değer atayabiliriz. Şimdi bir uygulama yapalım.
#include <stdio.h>

void main()
{
 char krk1,krk2,krk3,krk4;
 int tam1,tam2,tam3,tam4,tam5,tam6;
 float float1;
 double double1; 

 krk1='Z';
 tam1=1453;
 float1=987.123;
 double1=1234.9876;
 
 tam2=310.95; // Geçerlidir Fakat virgülden sonrasını keser.
 tam3=tam4=409; // Geçerlidir iki değişken de 409'a eşitlenir.
 krk2='4';  // Geçerlidir değer olarak 4'ü tutar.
 krk3='MA';  // Geçerlidir Fakat değer olarak ilk harfi tutar.
 krk4=18;  // Geçerlidir Fakat değer olarak rakam tutmaz..
     // ..ACCII tabloda o rakama düşen karakteri tutar.
 
 printf("Degisken Adi  Degeri\n");
 printf("krk1          %c\n",krk1);
 printf("krk2          %c\n",krk2);
 printf("krk3          %c\n",krk3);
 printf("krk4          %c\n",krk4);
 printf("tam1          %d\n",tam1);
 printf("tam2          %d\n",tam2);
 printf("tam3          %d\n",tam3);
 printf("tam4          %d\n",tam4);
 printf("float1        %f\n",float1);
 printf("double1       %lf\n",double1);
}

Yukarıdaki örnekte printf fonksiyonlarını incelediğimiz zaman, derslerimizde daha önce karşılaşmadığımız bir takım işaretler görüyoruz. %c, %d, %f, %lf gibi. Bunlara belirteç adı veriliyor. Değişkenleri bu belirteçler yardımıyla okuyabiliyor ve sonraki dersimizde göstereceğim şekilde veri girişi yapabiliyoruz. Derleyici herhangi bir belirteç yakaladığı an orayı atlıyor ve sırası geldiğinde bu belirtecin olduğu yere ilgili değişkenin değerini gönderiyor. 1'den fazla belirteç olduğu durumlarda değişken isimlerini girerken sıraya dikkat etmek gerekir.

Veri tipleri için kullanılan belirteçleri aşağıdaki tablodan görebilirsiniz. Kutu içine aldıklarım temel veri tipleri, diğerleri ise bunların türevleridir.
C How To Program adlı kitaptan alınmıştır.

Belirteçlerin nerde ve nasıl kullanıldıklarını anlamak için bir önceki örneği tekrar dikkatli bir şekilde inceleyebilirsiniz. Sonraki derslerimizde bunları bolca kullanarak pekiştirmiş olacağız. Biz bu dersimizi burada noktalarken merak edenler, veri tiplerinin boyutlarını öğrenmek için kullanılan sizeof() fonksiyonunu üzerine tıklayarak inceleyebilir.

sizeof() Fonksiyonu

Her veri tipi bellekte 1 ile 16 byte arası bir alan kaplar. Kapladıkları bu alan işletim sistemine ve derleyiciye göre farklı boyutlarda olabilir. Bu nedenle C Standart Kütüphanesinde bunun hesabını yapan bir fonksiyon bulunur. Bu fonksiyon sizeof() fonksiyonudur.

Kullanımı:

  • sizeof(veriTipi)
Geriye değer olarak bir tamsayı döndürür. Dolayısıyla belirteç olarak tamsayıyı ifade eden %d kullanılır.

#include <stdio.h>

void main()
{
 printf( "Veri Tipi        Boyut  \n");
 printf( "========================\n");
   printf( "char           : %d bayt\n", sizeof(char));
   printf( "short          : %d bayt\n", sizeof(short));
   printf( "int            : %d bayt\n", sizeof(int));
   printf( "long           : %d bayt\n", sizeof(long));
   printf( "unsigned char  : %d bayt\n", sizeof(unsigned char));
   printf( "unsigned short : %d bayt\n", sizeof(unsigned short));
   printf( "unsigned int   : %d bayt\n", sizeof(unsigned int));
   printf( "unsigned long  : %d bayt\n", sizeof(unsigned long));
   printf( "float          : %d bayt\n", sizeof(float));
   printf( "double         : %d bayt\n", sizeof(double));
   printf( "long double    : %d bayt\n", sizeof(long double));
}


Eğer sizin de bilgisayarınız 64bit işletim sistemine sahipse ve derleyici olarak TDM-GCC kullanıyorsanız bu programı çalıştırdığınızda aynı çıktıyı üretecektir.


Uyarı: DevC++ bir derleyici değildir. Tümleşik geliştirme ortamı, yani IDE'dir (Integrated development environment). İçinde derleyici, yorumlayıcı, hata ayıklayıcı, kod yazım editörü ve programcıya kolaylık sağlayan çeşitli araçlar barındıran bileşik bir yazılımdır. 5 ve üstü sürümlerinde derleyici olarak TDM-GCC kullanmaktadır.

21 Nisan 2015 Salı

C Programlama Ders 1 - Printf Fonksiyonu ve Temel Bilgiler

      İlk dersimizde geleneği bozmayarak ekrana "Hello World" yazdıralım. Bunu yapabilmek için ihtiyacımız olan tek şey printf() fonksiyonu. Tabi öncesinde printf() fonksiyonunu barındıran <stdio.h> başlık dosyasını standart kütüphaneden çağırıp programımıza dahil etmeliyiz.
#include <stdio.h>

int main() 
{ 
 printf("Hello World");
 system("pause");
}

<stdio.h>

<stdio.h> başlık dosyası standart giriş/çıkış fonksiyonları(printf,scanf...) hakkında bilgiler içerir. Bu bilgiler sayesinde derleyici fonksiyonun doğru veya yanlış kullanıldığını test eder. Eğer yanlış kullanıldıysa derleyici bunu tespit edip işlemi yarıda keser ve programcıyı bu yanlışı düzeltmesi için uyarır. Fakat bu başlık dosyasını eklememiş olsaydık hata yapmış dahi olsak derleyici bunu tespit edemeyecekti. Çünkü fonksiyonun nasıl kullanılacağı hakkında bir bilgisi olmayacaktı. Bu hata programın çalışması esnasında karşımıza çıkacak ve başımızı çok fazla ağrıtabilecekti. (Bunun önemini bu programda anlamak mümkün değil.)

Tavsiye

Salı günü okula giderken çarşamba günün ders kitaplarını taşımak istemezsiniz öyle değil mi? O halde yazacağınız programın sırtına da ihtiyacından fazla kitap (başlık dosyası) yüklemeyin. Kullanacağınız standart fonksiyonların, kütüphanede hangi başlık dosyası altında bulunduğunu bilmek bunun için önemlidir. Biz, çoğu ders anlatımında ihmal edilen bu konuya özellikle değineceğiz.

system("pause")

Programa system("pause") komutunu dahil etmeseydik de program aynı işlemleri yapıp sonuç sağlayacaktı. Ancak ekrana "Hello World" yazdırdıktan sonra yapacak başka bir şeyi kalmadığı için program sonlanacaktı. Biz bu komutla programa "Kapanmak için benden işaret bekle!" demiş oluyoruz. Ve program kapanmak için bizim herhangi bir tuşa basmamızı bekliyor.

int main()

3. satırda bulunan int main() komutu bir fonksiyon belirtir. Ancak bu fonksiyon her programda olması gereken özel bir fonksiyondur. Derleyici kodları derlemeye bu fonksiyondan başlar. Eğer programda main() fonksiyonunu bulamazsa programı derleyemez. Çünkü nereden başlayacağını bilmez. Bunun önemini ilerde fonksiyon yazmaya başladığımız zaman daha iyi anlayacaksınız. Yine fonksiyonlara geçtiğimiz zaman başındaki int ifadesi ne işe yarıyor sorusunun cevabını da bulacaksınız. Fonksiyonlar konusunda main() fonksiyonuna özel olarak değineceğiz.

      Derleyicimiz Türkçe karakter kabul etmediği için "Devam etmek için bir tuşa basın." cümlesi bozuk çıkıyor. Bunu önemsemiyoruz ancak bu cümleyi "Hello World!" cümlesinin bir alt satırına taşıyabilirsek çıktımızın biraz daha düzgün görünmesini sağlayabiliriz. Bunu "Hello World"den sonra Enter'a basıp bir alt satıra inerek yapamayız elbette. Böyle yaptığımız taktirde derleyici printf() fonksiyonunun olduğu satırda kapanış parantezini ve noktalı virgülü bulamayacak ve hata verecektir. Bunu kaçış karakterleri dediğimiz özel karakterlerle yapacağız. Kaçış karakterleri için ayrı bir ders ayıracağız ancak o derse kadar sık sık kullanacağımız new-line karakterini bilmekte fayda var.

      Yeni bir satıra geçmek için ters-slash(\) işaretini ve new line'dan gelen n harfini kullanacağız. Şu şekilde; \n
#include <stdio.h>

int main() 
{ 
 printf("Hello World\n");
 system("pause");
}

      Şimdi de bir alt satıra Türkçe olarak "Merhaba Dunya" yazdıralım. Bunu yapmak için iki seçeneğimiz var ister yeni bir printf() fonksiyonu oluşturup onun içine yazarız. İster mevcut printf() fonksiyonu içinde yazmaya devam ederiz. Şu şekilde;
#include <stdio.h>

int main() 
{ 
 printf("Hello World\n");
 printf("Merhaba Dunya\n");
 system("pause");
}
      veya
#include <stdio.h>

int main() 
{ 
 printf("Hello World\nMerhaba Dunya\n");
 system("pause");
}
      Her ikisi de aynı çıktıyı verecektir.


      "Peki hangisini kullanmalıyım?" sorusunun cevabıysa tamamen size kalmış. Eğer okunabilirlik sizin için ön plandaysa yeni bir fonksiyon açabilirsiniz. Daha az fonksiyon çağırıyım, daha az kod içersin dolayısıyla daha hızlı çalışsın diyorsanız mevcut fonksiyonu kullanabilirsiniz. Hız ve okunabilirlik! Bu iki kriter bazı durumlarda sizi karar vermek zorunda bırakacaktır. Elbette bu seçim böyle basit programlar için değil çok daha kompleks programlarda önem kazanacak.

      Bu dersle birlikte, yaptığınız ilk program dünyaya merhaba derken siz de C dünyasına merhaba diyerek güzel bir giriş yapmış oldunuz. Derslerimizi takip ederek kendinizi geliştirmeye devam edin. Anlamadığınız bir yer veya sormak istediğiniz bir soru olursa yorum olarak bizimle paylaşabilirsiniz.
Alt Developer

15 Nisan 2015 Çarşamba

Standart C Kütüphanesi


      Altprogramlama yeteneği olan programlama dilleriyle yazılmış programlar parçacıklardan -teknik ismiyle modüllerden- oluşur. C'de bu modüllere fonksiyon adı verilir. Fonksiyonlar programcı tarafından yazılabileceği gibi Standart C Kütüphanesindeki hazır fonksiyonlar da kullanılabilir. Bunların bir kısmı alternatifi olmayan fonksiyonlar olsa da büyük bir bölümünü programcı kullanmayıp kendi fonksiyonunu yazabilir. Örneğin;  kütüphane içindeki <stdio.h> başlık dosyasında bulunan printf() fonksiyonu olmadan ekrana yazı yazdırmak olanaksızdır. Ancak <math.h> başlık dosyasındaki pow() fonksiyonu kullanmadan da üst alma işlemi yapılabilir. Bunlar gibi birçok örnek verilebilir ancak biz bu yazımızda fonksiyonları incelemeye kalkarsak buradan çıkamayız. Bunu her fonksiyon için ayrı bir başlık açarak, detaylı bir anlatımla yapacağız. Bu yazımızda Standart Kütüphaneyi kullanmamın sağladığı faydalardan bahsedeceğiz.

      Az önce pow() fonkiyonu kullanmadan da üst alma işlemi yapılabilir dedim. Çok daha karmaşık fonksiyonlar için de bunu söyleyebilirdik. Peki Standart Kütüphane içindeki fonksiyonları kullanmak mı daha avantajlı yoksa aynı işlemi yapan bir fonksiyon yazmak mı? Bunu Paul & Harvey Deitel kardeşlerin yazdığı "C How To Program" adlı kitabından yapacağım tek cümlelik bir alıntıyla cevaplamak isterim. "Avoid reinventing the wheel!" Evet tekerleği yeniden icat etmekten kaçının. Bu size bir şey kazandırmayacağı gibi en çok ihtiyacınız olan zamanınızı da kaybettirmiş olacak. Üstelik icat ettiğiniz tekerleğin araçlarla uyumsuzluk problemiyle de karşı karşıya kalabileceksiniz. Çünkü Standart Kütüphanedeki fonksiyonlar tüm sistem derleyicilerinde ortak tanımlanmıştır ve sorunsuz bir şekilde tüm işletim sistemlerinde çalışırlar. Sizin yarattığınız fonksiyonlar ise -komutların taşınabilirliği konusunda fikir sahibi değilseniz- her zaman risk içerirler. Tabi bu demek değildir ki fonksiyon yazmayalım. Aksine en verimli ve hızlı çalışan programın fonksiyonlardan meydana geldiğini tekrar hatırlatalım. Burada anlatmaya çalıştığımız aynı işi yapan fonksiyon yazmak yerine Standart Kütüphanedeki fonksiyonları kullanmanın daha doğru olduğudur. Nitekim onlar daha özenli yazılmışlardır ve daha kararlı çalışırlar.

      Bir de başka programcıların yazdığı fonksiyonlar vardır. Bu fonksiyonları da tıpkı kendi yazdığınız fonksiyonlar gibi kullanabilirsiniz. Ancak bunları iyice incelemek ve komutların tam olarak ne yaptığından emin olmak gerekir. Aksi taktirde sizi ve programı yazdığınız şirketi büyük zararlara uğratabilir.

Tavsiye

Ülkemizde üniversite hocaları "İngilizce bilmeniz gerekir" bahanesiyle derslerini yabancı kaynaklardan anlatmaya alıştıkları için Türkçe kaynak sıkıntısı her alanda kendini belli ediyor. Yabancı kaynakların çoğunun Türkiye'ye ulaşmaması da cabası. Millet olarak bilgi üretimi konusunda bu isteksizliğimiz bilgiyi de ithal etmemize sebep oluyor. Bu da beraberinde çok ciddi sorunlar getiriyor. Bu konu hakkında uzun bir makale yazılabilir ancak konumuzla ne alakası var diye soranları daha fazla bekletmek istemem. Standart C Kütüphanesindeki fonksiyonları bilmemiz gerektiğini söylemiştim. Bunları derslerimizde de anlatacağız ama içinizden birileri "Tüm fonksiyonları bulabileceğim bir kitap yok mu?" diye merak ediyorsa "The Standard C Library" adlı P.J.Plauger'ın yazdığı çok faydalı bir kitap var. Ben üniversite kütüphanesinde rast gelmiştim ancak satın almak için araştırma yaptığımda tek seçenek Amazon'du. Amerika'dan gelen kitap dile gelip "Noluyo lan!" der diye vazgeçtim. Yani sonuç olarak kitap yok, siz monitöre bir göz dinlendirici bakın.


Sonuç

Standart kütüphanedeki fonksiyonlar özenle yazıldığı için bunları kullanmak programın performansını ve verimini arttırır. Aynı zamanda tüm sistemlere uyumlu olduklarından dolayı taşınabilirliğe de önemli katkısı olur.

Mustafa Altun

14 Nisan 2015 Salı

Programlama Dillerinin Popülerliği

Programla dillerinin popülerliği göreceli bir kavramdır. Döküman sayısına göre, arama motoru sonuçlarına göre, sosyal medya aktifliğine göre, eğitim videolarına göre farklı değerlendirmeler vardır. Bunun için programlama dillerinin popülerliğini değerlendiren birçok site genel olarak farklı sonuçlara ulaşır. Biz http://www.langpop.com/ verilerini kullanarak değerlendirme yapacağız.

Bu sitede tüm değerlendirmelerden çıkan sonuçlar birleştirilerek şöyle bir genel sonuca ulaşılmış;


Bu grafikten C dilinin en üst sırada yer aldığını görebiliyoruz. Tabi bunlar bilimsel veriler değildir ve "En popüler dil C dilidir." demek her ne kadar yadırganmasa da doğru bir ifade değildir.  Burada C# ve Visual Basic dillerini bu kadar aşağıda görmek sizi biraz şaşırtmış olabilir. Beni de şaşırttı. Demek ki bazı değerlendirilmelerde diğerlerinin epey gerisinde kalmışlar.

Şimdi de Google'ın arama trendlerinden oluşturulmuş grafiğe bakalım. Az önceki grafikte yerini yadırgayan C# ve Visual Basic bu grafikten biraz daha memnun olabilecek gibi gözüküyor.




Sonuç olarak  C dilinin 1972 yılında geliştirilmesine rağmen popülerliğinin hiç düşmemiş olduğunu görebiliyoruz. En yakın takipçilerinin ise yine C diliyle yazılmış Java, C++, C#, PHP, JavaScript olduğunu görüyor ve C dilinin programlama dillerinin yaşayan atası olduğunu söyleyebiliyoruz.

Şunu da ekleyerek yazımıza son veriyoruz; C dilinden bu kadar bahsetmemizin sebebi C eğitimi verecek olmamız değil. Nitekim C eğitimi bittikten sonra diğer diller için de eğitime başlayacağız. Ama C dilinin yazılım dünyasında konumu, bizim ondan sürekli bahsetmemize neden oluyor ve de uzun yıllar boyunca böyle olacak gibi gözüküyor.

Mustafa Altun