c programlama

Visual basic , Delphi , C , C++ - c programlama ...

Cevapla
c programlama
Dram-Like isimli Üye şimdilik offline konumundadır

Dram-Like

Webmaster

Standart

c programlama

Alt 22-02-2009 #1
Sponsorlu Bağlantılar

c programlama
c programlama
c programlama
Yazılım mühendisi ve Özgür Yazılımcı Sayın Çağatay Cebi'nin hazırladığı C eğitim paketini derleyerek yazı dizisi haline getirdim. Ders I- II şeklinde yayınlayacağım.

C Programlama Dersi - I

Merhaba;
Sanırım, C ve C++ adını bilgisayarla az çok haşır neşir olan herkes en az bir kez duymuştur. Sizde bu isimleri duyanlardansanız ve nedir, ne değildir, nasıl kullanılır gibi birçok soruya yanıt arıyorsanız, doğru yerdesiniz. Çünkü bu yazıyla başlayarak C ve C++ ile programlamaya gireceğiz. Önce C ile yolumuza koyulup, belli bir olgunluğa ulaştıktan sonra C++ ile devam edeceğiz.
Okuyucularımızın genelini düşünerek, konuyu en temelden almayı daha doğru buldum. Yani hedefimiz, programlamayı hiç bilmeyen bir insanın burada okuduklarıyla belli bir yerlere ulaşması. İleri derece de olanlarsa sıkılmamak için biraz beklemeli. Lafı fazla uzatmadan başlayalım.
Bilgisayar ve Programlama nedir?
Bilgisayar çok basit düşündüğümüzde üç ana görevi yerine getiren bir makinedir. Girilen bilgiyi alır (INPUT), işler (PROCESSING) ve bu işlenmiş veriden bir sonuç (OUTPUT) çıkarır. Bilgisayar, sadece donanım olarak çalışmaz. Çünkü yazılım olmadan, donanım ne yapacağını bilemez. Bilgisayar donanımına ne yapacağını söyleyecek bir komutlar dizisi gerekir. Yapacağı görevleri, ona anlatan komutlara program diyebiliriz. Yani donanıma “sen şunu yap, sonra bulduğun sonucu şöyle şuraya ekle” gibisinden işler yaptırmak programın veya bir başka deyişle yazılımın işidir. Bir programcı olarak bundan fazlasını bilmek elbette ki avantajdır. Ama bilgisayarın bütün özelliklerini bilmeniz gerekmez. Yani yazacağınız bir program için o bilgisayarın özelliklerini bilmeseniz de olur.
Bilgisayarın anladığı tek dil, Makine Dilidir. Bu 16’lık (Hexadecimal) sistemden oluşan bir programlama tipidir. Makine dilini anlamak çok zordur ve bu dili kullanmak için o bilgisayarın donanım özelliklerini mutlaka bilmeniz gerekir. C de ekrana yazı yazmanızı sağlayan “printf();” gibi çok basit bir fonksiyon, makine dilinde 1A BB 0D BC D5 FF C2 F7... gibi çok daha karmaşık ve hiçbir anlam ifade etmeyen bir hâle dönüşür. Makine dili programlama dilleri arasında en alt seviyedir.
Makine dilinden sonra Assembler Dili gelir. Makine dilini kullanmanın zorluğu ve karmaşası üzerine geliştirilen Assembler, daha basit bir yapıdadır. Ama yine de C ile mukayese ederseniz çok daha zordur ve kullandığınız bilgisayarın donanımına dair hâlen bilgiye gereksinim duyarsınız. Assembler aşağıdaki gibi karmaşık bir yapıdadır.

SEGMENT COM WORD PUBLIC ‘CODE’
ASSUME CS : COMDS : COM
ORG 100H
ENTRY: MOV DVX,OFFSET MSG
MOV AH,g
.
.
.

Şuan bunu anlamaya çalışıp, hiç zamanınızı harcamayın. Çünkü öğreneceğimiz dil C, işlerimizi ve dolayısıyla hayatımızı çok daha kolaylaştırmaktadır. C, orta seviye bir programlama dilidir. Bunun anlamı, hem yazması kolay, hemde üst seviye dillere göre daha çok erişim hakkınızın olduğudur. Üst seviye programlama dilleri ise BASIC, PASCAL, gibi dillerdir. Üst seviye dillerde, yazması göreceli olarak daha kolay olsa da C ile yapabileceklerimiz daha çoktur.

Program yazmak için ne gerekir?

Program yazabilmek için hiçbir şeye ihtiyacınız yoktur. Program yazmak için Windows’un not defterini veya Linux'da Gedit, Kwrite gibi bir program bile kullanabilirsiniz. Önemli olan yazılan programın derlenmesidir. Derlemeye “compile” ve derleme işini yapan derleyiciyeyse “compiler” denir. C için internet üzerinden birçok Compiler bulabilirsiniz. Ben, program uygulamalarını GCC üzerinden yapacağım. Aynı şekilde bu derleyiciyi kurmanızı tavsiye ederim. GCC gelmiş geçmiş en iyi derleyicilerden biri olduğu gibi, özgür bir yazılımdır! Richard Stallman tarafından açık kaynak koduyla sunulmuştur ve arzu ettiğiniz takdirde, sonuna kadar değişiklik yapma imkanınız vardır.
Şayet Windows işletim sisteminiz varsa GCC'yi kurmanız biraz sıkıntılı olabilir. Basit bir Google araştırmasıyla, Bloodshed Dev-C++ adında bir program buldum. GCC üzerine kurulmuş bir yapısı varmış. GCC ile uğraşmak istemeyen Windows kullanıcıları, bu programı deneyebilir.
Algoritma Geliştirmek
C dilini ve komutlarını öğrenmek, programlamaya başlamak için şarttır ama algoritma oluşturamadığımız sürece bir program oluşturmazsınız. Algoritma, mantıktır. Yani neyi, nasıl yapacağınızı belirtir. Algoritma türetmek için geliştirilmiş bir metot yok. Her program için o metodu sizin bulmanız gerekiyor. Ama hiç merak etmeyin, yazdığınız program sayısı arttıkça, algoritma kurmanız daha kolaylaşır.
Algoritma, programlamanın bel kemiğidir. C dilinde kullanılan komutlar, BASIC veya FORTRAN gibi başka dillerde işe yaramaz. Fakat programlama mantığını bir kere oturttursanız, C komutlarının yerine pekâlâ başka dillere ait komutları da öğrenebilir ve büyük bir zorluk çekmeden diğer dillerde de program yazabilirsiniz.
Basit bir örnek üzerinden düşünelim. Bir markete gittiniz, kasada ki görevliye aldığınız ürünü gösterdiniz, parayı uzattınız, paranın üstünü aldınız. Günlük hayatta gayet normal olan bu durumu biraz değiştirelim. Karşınızda insan değil, elektronik bir kasiyer olsun. Ona göre bir algoritma geliştirirsek,

1-) Ürüne bak;
2-) Ürün Fiyatını bul;
3-) Parayı al;
4-) Alınan paradan ürün fiyatını çıkar;
5-) Kalan parayı ver.

İnsan zekasının otomatik hâle getirdiği eylemleri, ne yazık ki bilgisayar bilmez ve ona biz öğretmek zorundayız. Öğretirken de hata yapma hakkımız yoktur, çünkü yanlış öğreti yanlış programlamayla sonuçlanır.

C Programlama Dili

Temel Giriş/Çıkış İşlemleri (BASIC I/O):

C ile ilgili olarak bu ve önümüzdeki yazılarda birçok komut/fonksiyon göreceğiz. Ama hep kullanacağımız ve ilk öğrenmemiz gerekenler temel giriş çıkış fonksiyonlarıdır. C de klavyeden bir değer alabilmek için scanf(); fonksiyonunu kullanırız. Ekrana herhangi bir şey yazdırmak içinse printf(); fonksiyonu kullanılır.
Bir örnekle görelim;

#include<stdio.h>
int main( void )
{
printf("Hello World");
}

Eğer bunu derleyicinizde yazıp derlerseniz ve sonrasında çalıştırırsanız ekrana Hello World yazılacaktır. #include<stdio.h>, standart giriş çıkış başlık dosyasını, programa dahil et gibi bir anlam taşır. C'de (ve hemen hemen bütün diğer programlama dillerinde) bir kütüphaneyi dahil etmek son derece rutin bir iştir. Aksi halde giriş-çıkış fonksiyonlarını dahi her seferinde bizim baştan tanımlamamız gerekirdi.
main( ), bir programdaki ana fonksyiondur. Ondan sonra gelen ayraç standarttır. Bir bloğu temsil eder. İki ayraç işareti arasındaki alan main fonksiyonuna ait bir bloğu oluşturur. printf ise yazdığımız metini, ekrana bastırmaya yarayan, standart bir fonksiyonudur. Çift tırnak işaretleri içersine yazdığınız herşey printf sayesinde ekrana basılır.
Dikkat ettiyseniz, her satır sonuna noktalı virgül koyduk. Aslında her satır değil, her komutan sonra noktalı virgül koyduğumuzu söylemek daha doğru olacak. Çünkü noktalı virgül C dilinde komut ayracı anlamına gelir.
Şimdi yukarıda yazdığımız basit programı, biraz daha geliştirelim:

#include<stdio.h>
int main( void )
{
printf("Hello World\n");
printf("Merhaba Dünya");
return 0;
}

Birkaç yeni satır görüyorsunuz. Sırayla ne olduklarını açıklayalım. Az evvel yazdığımız "Hello World" yazısının sonuna "\n" ekledik. "\n" bir alt satıra geç anlamına geliyor. Eğer "\n" yazmazsak, ekranda "Hello WorldMerhaba Dünya" şeklinde bir yazı çıkar. "\n" kullanırsak, "Hello World" yazıldıktan sonra, bir alt satıra geçilir ve ikinci satırda "Merhaba Dünya" yazdırılır. En altta "return 0;" adında yeni bir komut fark etmişsinizdir. Bunu eklemezseniz, program yine çalışır; ancak uyarı verir. Çünkü main fonksiyonu, geriye bir tam sayının dönmesini beklemektedir. Yazmış olduğumuz return ifadesiyle bu uyarılardan kurtulabilirsiniz. Detayına girmek için henüz erken, return konusuna ileride değineceğiz.
Yukarıda ki programın aynısını şöyle de yazabilirdik:

#include<stdio.h>
int main( void )
{
printf("Hello World");
printf("\nMerhaba Dünya");
return 0;
}

Bir önce ve şimdi yazdığımız programların ekran çıktısı aynıdır. Bu örnekle anlatmak istediğim, printf( ) fonksiyonunda '\n' konulan yerden sonrasının bir alt satıra düşeceğidir.

#include<stdio.h>
int main( void )
{
printf("Hello World\nMerhaba Dünya");
return 0;
}

Gördüğünüz gibi tek bir printf( ); kullanarak aynı işlemi yaptırdık.
Varsayalım, ekrana çok uzun bir cümle yazmamız gerekti. Örneğin;

#include<stdio.h>
int main( void )
{
printf("Benim adım Çağatay ÇEBİ ve Yazılım Mühendisiyim.\n");
return 0;
}

Bu yazdığımız program hata vermemesine karşın, çalışma verimini azaltır. Çünkü yazacaklarınız editör penceresine sığmazsa, yazılanı okumak daha zahmetli olur. Önemsiz bir detay gibi gelebilir, ama kod yazma verimini ciddi oranda düşüreceğinden emin olabilirsiniz.
Bu programı aşağıdaki gibi yazmamız daha uygundur:

#include<stdio.h>
int main( void )
{
printf("Benim adım "
"Çağatay ÇEBİ"
"ve Yazılım Mühendisiyim.\n");
return 0;
}

Tek bir printf( ); fonksiyonu kullanılmıştır. Ancak alt alta yazarak, metini tek seferde görülebilir hâle getirdik. Programı derleyip çalıştırırsanız, alt alta üç satır yazılmaz. Cümle bütün olarak gösterilir ve bir önceki örnekle tamamen aynıdır. (Satırların alt alta görünmesini isteseydik; daha önce bahsettiğimiz gibi '\n' koymamız gerekirdi.)
Ekrana, Ali: "Naber, nasılsın?" dedi. şeklinde bir yazı yazdırmamız gerekiyor diyelim. Bu konuda ufak bir problem yaşayacağız. Çünkü printf( ); fonksiyonu gördüğü ilk iki çift tırnak üzerinden işlem yapar. Böyle bir şeyi ekrana yazdırmak için aşağıdaki gibi bir program yazmamız gerekir:

#include<stdio.h>
int main( void )
{
printf("Ali: \"Naber, nasılsın?\" dedi.\n");
return 0;
}

printf( ); fonksiyonunu kullanmayı sanırım iyice anladınız. printf( yazıp, sonra çift tırnak açıyor, yazmak istediklerimizi yazıyor, çift tırnağı sonra da parantezi kapatıyor, sonuna noktalı virgül ekliyoruz. Alt satıra geçmek içinse, yazdıklarımızın sonuna '\n' ekliyoruz. Çift tırnaklı bir şey kullanmak içinse \“ ... \” kullanıyoruz. Hepsi bu!
scanf(); fonksiyonuna gelince, bu başında bahsettiğimiz gibi bizim giriş (Input) fonksiyonumuzdur. Ancak yazımı burada noktalıyorum. Çünkü değişkenler işin içine girmekte ve onları anlatmam uzun sürecek. Gelecek haftaki yazımda kaldığımız yerden devam edeceğiz. Yazdıklarımla ilgili öneri, eleştiri veya sorunuz varsa, bana ulaşabilirsiniz.


C Programlama Dersi - II

Geçen hafta bilgisayar ve programlamaya dair temel bilgileri ve printf( ); fonksiyonunu öğrendik. Bu hafta, kaldığımız yerden devam edeceğiz. İlk yazıyla ilgili herhangi bir sorunuz varsa, bana [email protected]********** adresinden ulaşabilirsiniz. Bu ufak bilgiden sonra, kaldığımız yerden devam edelim.
Bloodshed Dev-C++ http://prdownloads.sourceforge.net/d....9.2_setup.exe
Okuyucularımızın bir kısmı, Bloodshed Dev-C++'in kullanımıyla ilgili çeşitli sorunlar yaşamış. Programı nasıl kullanabileceğinize dair ufak bir açıklamayla yazımıza başlamak yerinde olacaktır. ( Bu bölüm C derleyicisi olmayanlara yardımcı olmak için yazılmıştır. Eğer hâli hazırda bir derleyiciniz varsa ve sorunsuz kullanıyorsanız, "Değişken nedir? Tanımı nasıl yapılır?" bölümünden devam edebilirsiniz. )
Dev-C++ kullanımı oldukça basit bir program. Bloodshed Dev-C++ web sitesinin Download kısmından Dev-C++'i indirebilirsiniz. Dilerseniz bu bağlantıya tıklayarak yüklemeniz de mümkün. ( Zaman içinde bağlantı adresi çalışmayabilir. ) Programı başarıyla indirip kurarsanız, geriye yapacak fazla bir şey kalmıyor.
Program menülerinden, File -> New-> Source File yaparak yeni bir kaynak dosyası açın. ( Ctrl + N ile de aynı işlemi yapabilirsiniz. ) Aşağıdaki kodu deneme amacıyla, açtığınız dosyaya yazın:

#include<stdio.h>
int main( void )
{
// Hello World yazar.
printf( "Hello World" );
// Sizden herhangi bir giriş bekler.
// Böylece program çalışıp, kapanmaz.
getchar( );
return 0;
}
File -> Save As sekmesiyle, yazdığınız dosyayı kaydedin. ( Ctrl + S ile de kaydedebilirsiniz. ) Dosyanın adını verdikten sonra sonuna .c yazın. Örneğin deneme.c gibi...
Execute -> Compile sekmesine tıklayın. ( Kısayol olarak Ctrl + F9'u kullanabilirsiniz. ) Artık programınız derlendi ve çalışmaya hazır. Execute -> Run ile programınızı çalıştırın. ( Ctrl + F10'u da deneyebilirsiniz. ) Ekrana "Hello World" yazacaktır.
Eğer yazdığınız kodu tek seferde derleyip, çalıştırmak isterseniz, Execute -> Compile & Run yolunu izleyin. ( Bu işlemin kısayol tuşu, F9'dur. )
Yazdığınız kodu nereye kaydederseniz, orada sonu .exe ile biten çalıştırılabilir program dosyası oluşacaktır. Örneğin C:\Belgelerim klasörüne deneme.c şeklinde bir dosya kaydedip, F9'a bastığınızda, deneme.c'nin bulunduğu klasörde deneme.exe diye bir dosya oluşur. Oluşan bu dosyayı istediğiniz yere taşıyabilir, dilediğiniz gibi çalıştırabilirsiniz.
Değişken nedir? Tanımı nasıl yapılır?
Değişkenler, girdiğimiz değerleri alan veya programın çalışmasıyla bazı değerlerin atandığı, veri tutucularıdır. Değişken tanımlamaysa, gelecek veya girilecek verilerin ne olduğuna bağlı olarak, değişken tipinin belirlenmesidir. Yani a isimli bir değişkeniniz varsa ve buna tamsayı bir değer atamak istiyorsanız, a değişkenini tamsayı olarak tanıtmanız gerekir. Keza, a'ya girilecek değer eğer bir karakter veya virgüllü sayı olsaydı, değişken tipinizin ona göre olması gerekirdi. Sanırım bir örnekle açıklamak daha iyi olacaktır.

#include<stdio.h>
int main( void )
{
int a;
a = 25;
printf("a sayısı %d",a);
return 0;
}

Şimdi yukarıdaki programı anlamaya çalışalım. En baş satıra, int a -int, İngilizce de integer'ın kısaltmasıdır- dedik. Bunun anlamı, tamsayı tipinde, a isimli bir değişkenim var demektir. a=25 ise, a değişkenine 25 değerini ata anlamına geliyor. Yani, a artık 25 sayısını içinde taşımaktadır. Onu bir yerlerde kullandığınız zaman program, a'nın değeri olan 25'i işleme alacaktır. printf(); fonksiyonunun içersine yazdığımız %d ise, ekranda tamsayı bir değişken değeri gözükecek anlamındadır. Çift tırnaktan sonra koyacağımız a değeri ise, görüntülenecek değişkenin a olduğunu belirtir. Yalnız dikkat etmeniz gereken, çift tırnaktan sonra, virgül koyup sonra değişkenin adını yazdığımızdır. Daha gelişmiş bir örnek yaparsak;

#include<stdio.h>
int main( void )
{
int a;
int b;
int toplam;
a = 25;
b = 18;
toplam = a + b;
printf("a sayısı %d ve b sayısı %d, Toplamı %d.\n", a, b, toplam);
return 0;
}

Açıklama: (a ile b 25 ile 18 in değerin aldığı için onların rengine büründü, toplam da a+b ye eşit olduğu için a+b nin rengine büründü)

Bu programın ekran çıktısı şöyle olur; a sayısı 25 ve b sayısı 18, Toplamı 43. Yazdığımız bu programda, a, sonra b, üçüncü olarakta toplam ismiyle 3 adet tamsayı değişken tanıttık. Daha sonra a'ya 25, b'ye 18 değerlerini atadık. Sonraki satırdaysa, a ile b'nin değerlerini toplayarak, toplam ismindeki değişkenimizin içersine atadık. Ekrana yazdırma kısmı ise şöyle oldu: üç tane %d koyduk ve çift tırnağı kapattıktan sonra, ekranda gözükme sırasına göre, değişkenlerimizin adını yazdık. printf(); fonksiyonu içersinde kullanılan %d'nin anlamı, bir tamsayı değişkenin ekranda görüntüleneceğidir. Değişkenlerin yazılma sırasındaki olaya gelince, hangisini önce görmek istiyorsak onu başa koyar sonra virgül koyup, diğer değişkenleri yazarız. Yani önce a değerinin gözükmesini istediğimiz için a, sonra b değerinin gözükmesi için b, ve en sonda toplam değerinin gözükmesi için toplam yazdık.
Bu arada belirtmekte fayda var, elimizdeki 3 tamsayı değişkeni, her seferinde int yazıp, belirtmek zorunda değiliz. int a,b,toplam; yazarsakta aynı işlemi tek satırda yapabiliriz.
Şimdi, elimizdeki programı bir adım öteye taşıyalım:

#include<stdio.h>
int main( void )
{
int saat;
float ucret, toplam_ucret;
char bas_harf;
printf("Çalışanın baş harfini giriniz> ");
scanf("%c",&bas_harf);
printf("Çalışma saatini giriniz> ");
scanf("%d",&saat);
printf("Saat ücretini giriniz> ");
scanf("%f",&ucret);
toplam_ucret = saat * ucret;
printf("%c başharfli çalışanın, alacağı ücret: %f\n",bas_harf,toplam_ucret);
return 0;
}
Bu yazdığımız program basit bir çarpım işlemini yerine getirerek sonucu ekrana yazdırıyor. Yazılanların hepsini bir anda anlamaya çalışmayın, çünkü adım adım hepsinin üzerinde duracağız. Programı incelemeye başlarsak; değişken tanımını programımızın başında yapıyoruz. Gördüğünüz gibi bu sefer farklı tiplerde değişkenler kullandık. Biri int, diğer ikisi float ve sonuncusunu da char. int'ın tamsayı anlamına geldiğini az evvel gördük. float ise 2.54667 gibi virgüllü sayılar için kullanılır. char tipindeki değişkenler, a,H,q,... şeklinde tek bir karakter saklarlar. Konu biraz karmaşık gözükse de, değişken tanımında bütün yapmanız gereken, değişkeninizin taşıyacağı veriye göre programın başında onun tipini belirtmektir. Bunun için de tıpkı yukarıdaki programda olduğu gibi, önce tipi belirtir, sonra da adını yazarsınız.
Programımıza dönersek, çalışma saati bir tamsayı olacağından, onu saat isminde bir int olarak tanıttık. Ücret virgüllü bir sayı olabilirdi. O nedenle onu float (yani virgüllü sayı) olarak bildirdik. Adını da saatucret koyduk. Farkettiğiniz gibi, toplamucret isimli değişkenimiz de bir float. Çünkü bir tamsayı (int) ile virgüllü sayının (float) çarpımı virgüllü bir sayı olmaktadır. Tabii 3.5x2=7 gibi tam sayı olduğu durumlarda olabilir. Ancak hatadan sakınmak için toplamucret isimli değişkenimizi bir float olarak belirtmek daha doğrudur.
Üsteki programımızda olmasına karşın, şuana kadar scanf(); fonksiyonunun kullanımına değinmedik. scanf(); geçen haftaki yazımızdan da öğrendiğimiz gibi bir giriş fonksiyonudur. Peki nasıl kullanılır, tam olarak ne işe yarar? scanf(); kabaca klavyeden girdiğiniz sayıyı veya karakteri almaya yarar. Kullanımı ise şöyledir: önce scanf yazar, sonra parantez ve ardından çift tırnak açar, daha sonra alınacak değişkene göre, %d, %f veya %c yazılır. %d int, %f float, %c char tipindeki değişkenler için kullanılır. Bundan sonra çift tırnağı kapatıp, virgül koyarsınız. Hemen ardından & işareti ve atanacak değişken adını yazarsınız. Son olarak, parantezi kapatıp noktalı virgül koyarsınız. Hepsi budur.
Yukarıdaki programda da scanf(); fonksiyonu gördüğünüz gibi bu şekilde kullanılmıştır. Sanırım gereğinden çok laf oldu ve konu basit olduğu halde zor gibi gözüktü. Yukardaki sıkıntıdan kurtulmak için çok basit bir program yazalım. Bu programın amacı, klavyeden girilen bir sayıyı, ekrana aynen bastırmak olsun.

#include<stdio.h>
int main( void )
{
int sayi;
printf("Değer giriniz> ");
scanf("%d",&sayi);
printf("Girilen değer: %d\n",sayi);
return 0;
}
Gördüğünüz gibi hiçbir zor tarafı yok. Klavyeden girilecek bir tamsayınız varsa, yapmanız gereken önce değişkenin tipini ve adını belirtmek, sonra scanf( ); fonksiyonunu kullanmak. Bu fonksiyonu kullanmaya gelince, scanf(" yazdıktan sonra değişken tipine göre %d, %c, veya %f, yazıp, ardından & işaretini kullanarak atanacak değişkenin adını belirtmekten ibaret. Fark etmişsinizdir, printf(); ve scanf(); fonksiyonlarının her ikisinde de %d koyduk. Çünkü scanf( ); ve printf( ); fonksiyonların değişken tipi simgeleri aynıdır. Aşağıdaki tablodan hangi değişken tipinin nasıl deklare edileceğini, kaç byte yer kapladığını, maksimum/minimum alabileceği değerleri ve giriş/çıkış fonksiyonlarıyla nasıl kullanılabileceğini bulabilirsiniz. Tanımlamalar ve fonksiyon uygulamaları, degisken isimli bir değişken için yapılmıştır.
Bu mesajdan alıntı yap
Sponsor Links

Grafikerler.net Reklamları

Dram-Like isimli Üye şimdilik offline konumundadır

Dram-Like

Webmaster

Standart
Alt 22-02-2009 #2
                             Sponsorlu Bağlantılar
TİP DKLRSYON printf( ); scanf( ); Min. Max Byte
Karakter Chr.D.; printf("%c",degisken); scanf("%c",&degisken); -128 127 1
Ksa T Sayı S.D; printf("%d",degisken); scanf("%d",&degisken); -32768 32767 2
Tamsayı I.D; printf("%d",degisken); scanf("%d",&degisken); -32768 32767 2
Uzun Tsayı L.I.D ; printf("%ld",degisken); scanf("%ld",&degisken); -2147483648 2147483647 4
İşrtsiz Tsayı U.D; printf("%u",degisken); scanf("%u",&degisken); 0 65535 2
İşsz U.T.S. long U. D.; printf("%lu",degisken); scanf("%lu",&degisken); 0 4294967295 4
Virgüllü Sayı F.D printf("%f",degisken); scanf("%f",&degisken); 1,17549e-38 3,40282e+38 4
U. V. Sayı double D. ; printf("%lf",degisken); scanf("%lf",&degisken); 2,22504e-308 1,79769e+308 8
Verilen bu değerler; işletim sisteminden, işletim sistemine, farklılık gösterebilir. En doğru değerleri almak için sizeof( ), fonksiyonunu kullanmak gerekir. Aşağıda yazmış olduğum bir program bulacaksınız. Kendi bilgisayarınızda derleyip, çalıştırırsanız, size değişkenlerin boyutunu ve alabileceği maksimum-minimum değerleri verecektir:

#include<stdio.h>
#include<limits.h>
#include<float.h>
int main( void )
{
printf( "\nTIP\t\t BOYUT\t\t MIN\t \tMAX\n" );
printf("========================================== ====================\n");
printf( "char\t\t: %d byte(s)\t%d\t\t%d\n", sizeof(char),CHAR_MIN,CHAR_MAX );
printf( "short\t\t: %d byte(s)\t%d\t\t%d\n", sizeof(short), SHRT_MIN, SHRT_MAX );
printf( "int\t\t: %d byte(s)\t%d\t%d\n", sizeof(int), INT_MIN, INT_MAX );
printf( "unsigned int\t: %d byte(s)\t\t\t%u\n",sizeof(unsigned),UINT_MAX );
printf( "long\t\t: %d byte(s)\t%ld\t%ld\n", sizeof(long), LONG_MIN, LONG_MAX );
printf( "float\t\t: %d byte(s)\t%e\t%e\n", sizeof(float), FLT_MIN, FLT_MAX );
printf( "double\t\t: %d byte(s)\t%e\t%e\n\n", sizeof(double), DBL_MIN, DBL_MAX );

return 0;
}

Programı inceleyip, detaylara girmeyin. Sadece çalıştırıp, sonuçları görmeniz yeterli. Örneğin, Ubuntu yüklü x86 tabanlı bir bilgisayarda, karşınıza şöyle bir ekran gelecektir:

TIP BOYUT MIN MAX
================================================== ============
char : 1 byte(s) -128 127
short : 2 byte(s) -32768 32767
int : 4 byte(s) -2147483648 2147483647
unsigned int : 4 byte(s) 4294967295
long : 4 byte(s) -2147483648 2147483647
float : 4 byte(s) 1.175494e-38 3.402823e+38
double : 8 byte(s) 2.225074e-308 1.797693e+308

Sanırım hiç istemediğim bir şey yaparak, kafanızı karıştırdım. Dilerseniz, burada keselim ve bunlar ileriye dönük olarak bir kenarda dursunlar. Yine de daha fazla bilgi isterseniz, Teach Yourself C in 21 Days yazısına göz atabilirsiniz. Ama dediğim gibi bunların sonraya bırakılması, uygun olacaktır.
Şu ana kadar öğrendiklerimizle girilen herhangi iki sayısının ortalamasını hesaplayan bir program yazalım. Başlamadan önce, değişkenlerimizin kaç tane ve nasıl olacağını düşünelim. Şurası kesin ki, alacağımız iki sayı için 2 farklı değişkenimiz olmalı. Bir de ortalamayı hesapladığımızda bulduğumuz değeri ona atayabileceğimiz bir başka değişkene ihtiyacımız var. Peki değişkenlerimizin tipleri ne olacak? Başında belirttiğimiz gibi yazmamız gereken program herhangi iki sayı için kullanılabilmeli. Sadece tamsayı demiyoruz, yani virgüllü bir sayı da girilebilir. O halde, girilecek iki sayının değişken tipi float olmalı. Bunu double da yapabilirsiniz, fakat büyüklüğü açısından gereksiz olacaktır. Ortalamaların atanacağı üçüncü değişkene gelince, o da bir float olmalı. İki virgüllü sayının ortalamasının tamsayı çıkması düşünülemez. Oluşturduğumuz bu önbilgilerle programımızı artık yazabiliriz.

#include<stdio.h>
int main( void )
{
float sayi1,sayi2,ortalama;
printf("İki sayı giriniz> ");
scanf("%f%f",&sayi1,&sayi2);
ortalama = ( sayi1 + sayi2 ) / 2;
printf("Ortalama sonucu: %f'dir",ortalama);
return 0;
}
Yukarıda yazılı programda, bilmediğimiz hiçbir şey yok. Gayet basit şekilde izah edersek, 2 sayı alınıp, bunlar toplanıyor ve ikiye bölünüyor. Bulunan değerde ortalama isminde bir başka değişkene atanıyor. Burada yabancı olduğumuz, sadece scanf(); kullanımındaki değişiklik. scanf(); fonksiyonuna bakın. Dikkat edeceğiniz gibi, değişkenlerden ikisine de tek satırda değer atadık. Ayrı ayrı yazmamız da mümkündü, ancak kullanım açısından böyle yazmak açık şekilde daha pratiktir. Bu konuda bir başka örnek verelim. Diyelim ki, biri int, diğeri float, sonuncusuysa char tipinde 3 değişkeni birden tek scanf(); ile almak istiyorum. Değişkenlerin isimleri, d1,d2 ve d3 olsun. Nasıl yaparız?

scanf("%d%f%c",&d1,&d2,&d3);
Peki aldığımız bu değişkenleri ekrana tek printf(); ile nasıl yazdırabiliriz?

printf("%d %f %c",d1,d2,d3);

Görüldüğü gibi bu işin öyle aman aman bir tarafı yok. Fonksiyonların kullanımları zaten birbirine benziyor. Tek yapmanız gereken biraz pratik ve el alışkanlığı.
Aritmetik Operatör ve İfadeleri
Üste yazdığımız programların hemen hemen hepsinde aritmetik bir işlem kullandık. Ama aritmetik işlemleri tam olarak anlatmadık. Kısaca;
.
( + ) : Artı

( - ) : Eksi

( / ) : Bölme

( * ) : Çarpma

( % ) : Modül

Burada bilinmeyen olsa olsa modül işlemidir. Modül kalanları bulmaya yarar. Yani diyelim ki 15'in 6'ya olan bölümünden kalanını bulmak istiyorsunuz. O halde 15%6 = 3 demektir. Veya, 7'nin 3'e bölümünden kalanı bulacaksanız, o zamanda 7%3 = 1 elde edilir. Bu C'de sıkça kullanacağımız bir aritmetik operatör olacak.
İşlem sırasına gelince, o da şöyle olur. En önce yapılan işlem parantez ( ) içidir. Sonra * / % gelir. Çarpma, bölme ve modül için, soldan sağa hangisi daha önce geliyorsa o yapılır. En son yapılanlarsa artı ve eksidir. Keza, bu ikisi arasında, önce olan solda bulunandır.
Bölme işlemine dair, bir iki ufak olay daha var. 4/5 normalde 0.8 etmektedir. Ancak C için 4/5 sıfır eder. Çünkü program, iki tamsayının bölünmesiyle, sonucu tamsayı elde etmeyi bekler. İleride tipleri birbiri arasında değiştirmeye değineceğiz. Ama şimdilik bu konuda bir-iki örnek yapalım:

* 8/4+2 => 2 + 2 => 4
* 8-4*2+-12 => 8 - 8 + -12 => -12
* 15*4/2%4*7 => 60/2%4*7 => 30%4*7 => 2*7 => 14
* 31+7/2-83%5*2-2 => 31+ 3 - 3 * 2 - 2 => 31 + 3 - 6 - 2 => 26
* (31-7) * 2 + 83 / (5%2) => 24 * 2 + 83 / 1 => 48 + 83 => 131

Bu aritmetik ifadeleri henüz bir C programı için denemedik. Ancak burada keselim. Bunu yapmayı diğer yazımıza saklayalım. Eğer uğraşmak isterseniz klavyeden alınacak 3 sayının ortalamasını bulan bir program yazabilirsiniz. Yada girilecek 2 tamsayı arasında bütün aritmetik işlemleri -ikisin çarpımını, toplamını, birbirine bölümünü ve farkını- bulan ve sonuçları ekrana yazdıran bir program da yazmanız mümkün. Herhangi bir yerde takılır ve bana ulaşmak isterseniz mail adresime yazmanız kafi. Haftaya görüşürüz.

C Programlama Dersi - III

Kodlarınıza açıklama (comment) koymak
Yazılım mühendislerinin en büyük sıkıntısı kod yazmak değildir. Yazılmış bir kodu okuyup anlamak -hele ki büyük bir projeden söz ediyorsak- asıl başınıza bela olacak konudur. Bundan korunmak için kodlarımıza açıklama/yorum koyarız.
C programlama dilinde iki şekilde açıklama koymak mümkündür. Bunlardan bir tanesi, satır bazında yapılır. Diğeriyse, belirli bir bloğu yorumlamaya yarar. Compiler her iki şekilde de, açıklama olarak belirlemiş yerleri işlemeyecektir. Aşağıdaki örnekte satır ve blok olarak, nasıl kodlarınıza açıklama getirebileceğinizi görebilirsiniz:

/*

Çok satırlı bir açıklama.
Yıldızlar arasında kalan bütün
alan, yorum olarak değerlendirilir
ve derleyici (compiler) tarafından
işlenmez.

*/

#include<stdio.h>
int main( void )
{
//Tek satırlık bir açıklama.
printf("Hello World\n");
}
Cast Operator

Cast operator'un Türkçe karşılığı olacak bir kelime aklıma gelmedi. Ancak cast operatoru şu şekilde açıklayabiliriz. Bir değişken tipini örneğin (Tam sayı-int), bir başka tipe (virgüllü sayı-float) gibi dönüştürmek isterseniz, o zaman cast operator kullanırız.
Aşağıdaki kodu yazıp derleyin.

#include<stdio.h>
int main( void )
{
int bolunen = 12, bolen = 8;
float bolum;
bolum = bolunen / bolen;
printf("Sonuc: %f\n",bolum);
return 0;
}

Program çıktısı; "Sonuc: 1.000000" olacaktır:

Normalde 1.5 çıkmasını beklediğiniz sonucun, 0.000000 çıkmasının nedeni casting kullanmamamızdır. Bir tam sayıyı, bir başka tam sayıya bölerseniz, sonuç bir başka tam sayı çıkar. Ve C programlama dili, bir virgüllü sayıyı tam sayıya atamaya kalktığınızda, herhangi bir yuvarlama işlemi yapmadan, virgülden sonrası atar.
Cast Operator şu şekilde kullanılmalıdır: degisken_1 = ( tip ) degisken_2;
Elimizdeki bu bilgiye göre programımızı tekrar yazalım.

#include<stdio.h>
int main( void )
{
int bolunen = 12, bolen = 8;
float bolum;
bolum = (float)bolunen / bolen;
printf("Sonuc: %f\n",bolum);
return 0;
}

Sonuç bu sefer, beklediğimiz gibi 1.5 çıkacaktır.
Aşağıdaki örneği inceleyelim:

#include<stdio.h>
int main( void )
{
printf("Sonuc: %f\n", 2 / 4);
return 0;
}

Öğrendiğimiz üzere, bunun da sonucu 0.5 yerine, 0 olarak gözükecektir. Sonucu doğru yazdırmak için (float)2/4 şeklinde yazmanız yeterlidir. Ancak dahi basit bir yöntem olarak 2/4.0 veya 2.0/4 yazarsanız yine aynı sonucu elde edersiniz.Çünkü bu durumda sayılardan bir tanesi float olmaktadır.
Kullanılan değişken tiplerinden hangisi büyükse, sonuç o değişkenin tipinde döner. Yüksek değişken bellekte daha fazla yer kaplamaktadır. Bunun doğal bir sonucu olarakta, domine eden o'dur. Değişkenlerin büyüklüğünü daha önceki dersimizde vermiştik. Ancak hatırlamak açısından, aşağıya bakabilirsiniz.
(DÜŞÜK) char <-> int <-> long <-> float <-> double (YÜKSEK)
Çıkan sonucu, daha düşük bir değişken tipine atamaya kalkarsanız, o zaman veri kaybı yaşanır. Ve örneğin float 1.5 olan sonucu int değişkene 1.0 olarak kaydedilir.
Öğrendiklerinizin pekişmesi için bir program yazalım. Bu programda, klavyeden girilen, bir virgüllü sayının, yuvarlanıp, tam sayı olması gösterilsin:

#include<stdio.h>
int main( void )
{
float girilen_sayi;
printf("Lütfen bir sayı giriniz> ");
scanf("%f",&girilen_sayi);
printf("Sayının yuvarlanmış hali: %d\n", (int)(girilen_sayi+0.5));
return 0;
}

Koşullu (Conditional) İfadeler

if

Bilgisayarda yapılan bütün mantıksal işlemler kaba bir temele dayanır. Şartlar sağlandığı halde yapılacak işlem belirlenir. Ve şartlar sağlandığında, bu işlemler yapılır. Şartların kontrol edilmesini, C (ve daha birçok) programlama dilinde if operatörünü kullanarak yaparız.

if operatörünün genel kullanım yapısı şu şekildedir:

if( koşul ) {
komut(lar)
}Eğer if'in altında birden çok komut varsa, ayraç işareti (veya küme parantezi) koymamız gerekir. Şayet if'ten sonra, tek komut bulunuyorsa, ayraç koyup-koymamak size kalmıştır. Zorunluluğu yoktur.
Örnek bir program yazalım. Bu programda kullanıcının klavyeden, bir tam sayı girsin. Ve bizde girilen sayı, 100'den büyükse, ekrana yazdıralım:

#include<stdio.h>
int main( void )

{
int girilen_sayi;
printf("Lütfen bir tam sayı giriniz> ");
scanf("%d",&girilen_sayi);
if( girilen_sayi > 100 )
printf("Girilen sayı 100'den büyüktür\n");
return 0;
}

if-else

Bazı durumlarda, bir koşulun doğruluğuna göre sonuç yazdırmak yetmez. Aksi durumda da ne yapacağımızı belirtmek isteriz. Bunun için if-else yapısını kullanırız.

if-else yapısı şu şekildedir:

if( koşul ) {
komut(lar)
}

else {
komut(lar)
}

Önceki yazdığımız programı düşünelim; 100'den büyük olduğunda, ekrana çıktı alıyorduk. Bu programa bir özellik daha ekleyelim ve 100'den küçükse, bunu da söyleyen bir yapıyı oluşturalım:


#include<stdio.h>
int main( void )
{
int girilen_sayi;
printf("Lütfen bir tam sayı giriniz> ");
scanf("%d",&girilen_sayi);
if( girilen_sayi > 100 )
printf("Girilen sayı 100'den büyüktür\n");
else
printf("Girilen sayı 100'den küçüktür\n");
return 0;
}

Örnekte gördüğünüz gibi, bir koşulun doğruluğunu program kontrol ediyor ve buna doğru olursa, bazı işlemler yapıyor. Şayet verilen koşul yanlışsa, o zaman daha başka bir işlem yapıyor. Ancak ikisini de yapması gibi bir durum söz konusu değil.Aşağıdaki akış diyagramlarında (flowchart) her iki durumu da görebilirsiniz.

if Yapısı: if-else Yapısı:
c programlama c programlama
Bu mesajdan alıntı yap
Dram-Like isimli Üye şimdilik offline konumundadır

Dram-Like

Webmaster

Standart
Alt 22-02-2009 #3
İlişkisel (Relational) Operatörler

Koşullu operatörlerde, koşulun doğruluğunu kontrol ederken kullandığımız ilişkisel operatörler, aşağıda verilmiştir:
< Küçüktür
> Büyüktür
== Eşittir
<= Küçük eşittir
>= Büyük eşittir
!= Eşit değildir
Birleşik (Compound) Operatörler

Bazı durumlarda, kontrol edeceğimiz koşul, tek bir parametreye bağlı değildir. Örneğin, bir kişinin yaşının 65'den küçük olup olmadığına bakabiliriz. Ama 65'den küçük ve 18 yaşından büyük olup olmadığına karar vermek istersek, o zaman Birleşik/Birleştirici Operatörler'i kullanmamız uygun olacaktır.

Compound operator'ler aşağıdaki gibidir:

&& and ve
|| or veya
! not tersi

Bu operatörlerin mantıksal (logical) doğruluk tablosu da şu şekildedir:


p q p&&q p||q !p
0 0 0 0 1
0 1 0 1 1
1 0 0 1 0
1 1 1 1 0
Örnek Sorular

Soru 1: Klavyeden alınacak bir değerin, 18 ile 65 arasında olup olmadığını kontrol eden bir program yazınız:
Cevap için tıklayınız...
Sorunun Cevabı:

/*
Girilen yaşın, 18 ile 65 arasında olup olmadığını belirler.
*/
#include<stdio.h>
int main( void )
{
int girilen_yas;
printf("Lütfen yaşınızı giriniz> ");
scanf("%d",&girilen_yas);
if( girilen_yas >= 18 && girilen_yas <= 65 )
printf("Girilen yaş, 18 ile 65 arasındadır.\n");
//Girilen yaş 18 ile 65 arasında değilse, aşağıdaki else
//bloğu çalışır.
else {
//Girilen yaş 18'den küçükse
if( girilen_yas < 18 )
printf("Girilen yaş, 18'den küçüktür.\n");
//Girilen yaş 65'ten büyükse
else
printf("Girilen yaş, 65'ten büyüktür.\n");
}
}
Soru 2: Kendisine verilen iki tam sayıyı, bölecek ve sonucu virgüllü sayı olarak gösterecek bir bölme işlemini programı hazırlayınız. (Şayet bölen 0 olarak verilirse, bölme işlemi yapılmamalıdır.)

Cevap için tıklayınız...

Soru 2 nin cevabı:
/*
Kendisine verilen iki tam sayıyla bölme işlemi yapan program.
*/

#include<stdio.h>
int main( void )
{
int bolunen, bolen;
float sonuc;
printf("Bölünecek sayıyı giriniz> ");
scanf("%d",&bolunen);
printf("Bölen sayıyı giriniz> ");
scanf("%d",&bolen);
//Bolen, 0 ise, bir sayı sıfıra bölünemeyeceğinden,
//program sorun çıkartacaktır. Bu yüzden,
//bolenin 0 olmaması kontrol ediliyor.
if( bolen != 0 ) {
sonuc = (float)bolunen / bolen;
//.2f, virgülden sonra 2 basamak gösterilmesi
//içindir.
printf("Sonuc: %.2f\n",sonuc);
}
else
printf("Hata: Sayı 0'a bölünemez!\n");

}
Not: Yukarda verilmiş çözümler, daha efektif olabilirdi. Ancak verdiğim cevapların herkes tarafından anlaşılmasını istediğimden, işi biraz uzatmış olabilirim. Sizin vereceğiniz cevapların gidiş yolları elbette ki farklı olabilir.
C Programlama Dersi - IV

İçiçe geçmiş (Nested) İfadeler

Daha önceki yazımızda, koşullu ifadeleri görmüştük. Hatırlatmak için üzerinden geçersek, if ile bir ifadeyi kontrol ediyor ve doğruysa, buna göre işlemler yapıyorduk. Bir de if - else yapısı vardı. if - else yapısında da, koşulu gene kontrol ediyor, doğruysa if bloğunun altında kalanları yapıyorduk; yanlışsa, else bloğunda olan kodlar işleme alınıyordu. Son derece basit bir mantık üzerine kurulmuş bu yapıyla, yapılamayacak kontrol yoktur. Ancak öyle durumlar vardır ki, if - else yapısı yeterli verimliliği sunamaz.
Diyelim ki, birden fazla kontrol yapmanız gereken bir durum oluştu. Hatta örnek vererek konuyu daha da somutlaştıralım. İstenilen bir programda, klavyeden size yaş bilgisi veriliyor. Siz de bu bilgiye göre, şayet yaş 18'den küçükse çocuk; 18-30 yaş arasında genç; 30-50 yaş arasında ortayaş diye bir mesaj bastırıyorsunuz. Basit bir program.
Şimdi bunu sadece if yapısıyla kuruyor olsaydık, her seferinde yaşın uygun aralıklara düşüp düşmediğini kontrol eder ve ona göre sonucu ekrana bastırırdık. Ama bu son derece verimsiz bir yöntem olurdu. Çünkü zaten yaş bilgisinin genç olduğuna dair bir karar vermişsek, sonrasında tutup bunun yaşlı olup olmadığını kontrol etmenin bir esprisi olmayacaktır. Verilebilecek en kötü cevabı aşağıda bulabilirsiniz:

/*
Sorulan soruya verilebilecek en
kötü cevap.

*/
#include<stdio.h>
int main( void )
{
int girilen_yas;
printf("Lütfen yaşınızı giriniz> ");
scanf("%d",&girilen_yas);
if( girilen_yas < 18 )
printf("Daha çocuk yaştasınız, hayatın başındasınız.\n");
if( girilen_yas >= 18 && girilen_yas <= 30 )
printf("Gençliğin, güzelliği bambaşka!\n");
if( girilen_yas > 30 && girilen_yas <= 50 )
printf("Hepsini boşverin, olgunluk ortayaşta başlar!\n");
return 0;
}
Yukarda ki kodu if - else kullanarak daha efektif hale getirebiliriz:
/*
if - else yapısıyla daha
efektif bir yapı
*/
#include<stdio.h>
int main( void )
{
int girilen_yas;
printf("Lütfen yaşınızı giriniz> ");
scanf("%d",&girilen_yas);
if( girilen_yas < 18 )
printf("Daha çocuk yaştasınız, hayatın başındasınız.\n");
else {
if( girilen_yas >= 18 && girilen_yas <= 30 )
printf("Gençliğin, güzelliği bambaşka!\n");
else {
if( girilen_yas > 30 && girilen_yas <= 50 )
printf("Hepsini boşverin, olgunluk ortayaşta başlar!\n");
}
}
return 0;
}

Yukardaki program daha efektif bir yapı sunmuş olmasına rağmen, eğer kontrol ettiğimiz aralıkların sayısı çok fazla olsaydı, tam bir başbelası olacaktı! Çünkü if - else içinde, bir başka if - else bloğu ve onun içinde bir başkası... bu böyle sürüp gidecekti. Kısacası performans olarak çok bir şey değişmese de, kodu yazan ve/veya okuyacak olan için tam bir eziyete dönüşecekti. İşte bu nedenlerle daha efektif yapılara ihtiyaç duyuyoruz.

if - else if Merdiveni

if - else if merdiveni yukarda verdiğimiz örnekler için biçilmiş kaftandır. if - else if merdiveni, doğru bir şey bulduğu zaman kontrolu orada keser ve diğer koşulları kontrol etmeden blok sonlandırılır.
Aşağıda if - else if yapısını ve akış diyagramını bulabilirsiniz:

if - else if Yapısı

if( koşul 1 ) {
komut(lar) 1
}
else if( koşul 2 ) {
komut(lar) 2
}
.
.
.
else if( koşul n ) {
komut(lar) n
}
else {
komut(lar) n
}

if - else if Akış Diyagramı
c programlama

if - else if ile söylenebilecek son bir şey sonunda ki else'tir. else koymak zorunlu değildir. Ancak hiçbir koşula uymayan bir durumla karşılaştığınızda, else devreye girer. Örneğin yukarda anlatıp, kodunu vermiş olduğumuz programda, belirtilen yaş aralıklarında değer girilmezse, hiçbir şey ekrana bastırılmayacaktır. Çünkü programa tanınmayan yaş aralığında ne yapılacağı öğretilmemiştir. Şimdi bu durumu da içerecek şekilde, programamımızı if - else if yapısıyla tekrar yazalım:

#include<stdio.h>
int main( void )
{
int girilen_yas;
printf("Lütfen yaşınızı giriniz> ");
scanf("%d",&girilen_yas);

if( girilen_yas < 18 )
printf("Daha çocuk yaştasınız, hayatın başındasınız.\n");
else if( girilen_yas >= 18 && girilen_yas <= 30 )
printf("Gençliğin, güzelliği bambaşka!\n");
else if( girilen_yas > 30 && girilen_yas <= 50 )
printf("Hepsini boşverin, olgunluk ortayaşta başlar!\n");
else
printf("HATA: Girilen yaş tanımlı değildir!\n");

return 0;
}

swicth - case ifadesi

switch - case, if - else if yapısına oldukça benzer bir ifadedir. Ancak aralarında iki fark vardır. Birincisi, switch - case yapısında, aralık değeri girmezsiniz. Direkt olarak ifadelerin bir şeylere eşit olup olmadığına bakarsınız. İkinci farksa, switch - case yapılarında, illa ki uygun koşulun sağlanmasıyla yapının kesilmek zorunda olmayışıdır. 'break' komutu kullanmadığınız takdirde, diğer şartların içindeki işlemleri de yapma imkanınız olabilir. switch case en tepeden başlayarak şartları tek tek kontrol eder. Uygun şart yakalanırsa, bundan sonra ki ifadeleri kontrol etmeden doğru kabul eder. Ve şayet siz break koymamışsanız, eşitlik uygun olsun olmasın, alt tarafta kalan case'lere ait komutlarda çalıştırılacaktır. if - else if ise daha önce söylemiş olduğumuz gibi böyle değildir. Uygun koşul sağlandığında, yapı dışarsına çıkılır.
switch case yapısında ki durumu, aşağıdaki tabloda görebilirsiniz:

switch case Yapısı

switch( degisken ) {
case sabit1:
komut(lar)
[break]
case sabit2:
komut(lar)
[break]
.
.
.
case sabitN:
komut(lar)
[break]
default:
komut(lar);
}
Bu mesajdan alıntı yap
Dram-Like isimli Üye şimdilik offline konumundadır

Dram-Like

Webmaster

Standart
Alt 22-02-2009 #4
[size=10pt]switch case Akış Diyagramı[/size]



Sanırım gözünüze biraz farklı gözüktü. Yapı olarak şimdiye kadar görmüş olduğunuz if else gibi gözükmese de, bir örnekten sonra arasında pek bir fark olmadığını göreceksiniz. Her komut sonunda koyduğum break komutu, zorunlu değildir ve o nedenle köşeli parantezle belirtilmiştir. break koyduğuz takdirde, uygun koşul sağlandıktan sonra, daha fazla kontrol yapılmayacak ve aynen if - else if yapısında olduğu gibi program orada kesilecektir. Ama break koymazsanız, altında kalan bütün işlemler -bir daha ki break'e kadar- yapılacaktır.
Kodun sonunda gördüğünüz default komutu, if - else if yapısında ki sonuncu else gibidir. Uygun hiçbir şart bulunamazsa, default komutu çalışır.
Öğrendiğimiz bilginin pekişmesi için biraz pratik yapalım. Bir not değerlendirme sistemi olsun. 100 - 90 arası A, 89 - 80 arası B, 79 - 70 arası C, 69 - 60 arası D, 59 ve altıysa F olsun. Eğer 100'den büyük veya negatif bir sayı girilirse, o zaman program hatalı bir giriş yapıldığını konusunda bizleri uyarsın. Bunu şimdiye kadar öğrendiğiniz bilgilerle, if - else if yapısını kullanarak rahatlıkla yanıtlayabilirsiniz. Ama şu an konumuz switch case olduğundan, cevabını öyle verelim:

#include<stdio.h>
int main( void )
{
int not;
printf("Lütfen notu giriniz> ");
scanf("%d",&not);
switch( not / 10 ) {
case 10:
case 9: printf("NOT: A\n"); break;
case 8: printf("NOT: B\n"); break;
case 7: printf("NOT: C\n"); break;
case 6: printf("NOT: D\n"); break;
case 5:
case 4:
case 3:
case 2:
case 1:
case 0: printf("NOT: F\n"); break;
default:
printf("HATA: Bilinmeyen bir değer girdiniz!\n");
}

return 0;
}

[size=10pt]Algoritmaya bakalım: [/size]

Önce sayıyı alıyor ve 10'a bölüyoruz. Yani girilen not, 57 ise 5.7 sonucunu elde ediyoruz. Ancak iki tam sayının sonucu bir virgüllü sayı veremez, tıpkı işleme giren değişkenler gibi tam sayı olarak döner. Dolayısıyla bilgisayarın elde edeceği sonuç, 5.7 değil, sadece 5'tir. switch case yapısında koşullar yukardan başlayarak kontrol ediliyor. case 5'e gelindiğinde eşitlik sağlanıyor. Ama break konmadığı için, switch case'ten çıkılmıyor. Ve altında kalan işlemlerde yapılıyor. Altında herhangi bir işlem veya break olmadığından case 0'a kadar bu böyle sürüyor. Ve case 0'da ekrana bir çıktı alıp switch case yapısı break ile sonlandırılmaktadır.
switch case, if - else if yapısının sunduğu esnekliğe sahip değildir. Daha çok menü olarak sunulacak işlerde kullanılır. Örneğin Unix'in ünlü listeleme komutu ls içersinde, verilen parametrelerin kontrolü switch case kullanılarak sağlanmıştır. Open Solaris, FreeBSD veya Linux kodlarını incelerseniz bunun gibi yüzlerce örnek bulabilirsiniz.
Arttırma (Increment) ve azaltma (decrement) işlemleri
Daha önceki derslerimizde, aritmetik işlemlerden bahsetmiştik. Bunların dışında yapabileceğimiz başka şeylerde bulunmaktadır. Bunlardan biri de, arttırma ve azaltma işlemleridir.
Eğer i adında bir değişkenin değerini 1 arttırmak isterseniz, i = i + 1 olarak yazarsınız. Veya 1 azaltmak isterseniz, benzer şekilde i = i - 1 de yazabilirsiniz. Arttırma ve azaltma işlemleri bu olayı daha basit bir forma sokmaktadır. i = i + 1 yazmak yerine i++ veya i = i - 1 yazmak yerine i-- yazabilirsiniz.
Arttırma ve azaltma işlemleri temelde iki çeşittir. Birinci yöntemde yukarda yazdığımız gibi, arttırma/azaltma sonradan yapılır. İkinci yöntemdeyse arttırma/azaltma ilk başta yapılır. Aşağıdaki örneklere bakalım.

[color=blue]/*
Bu programda, arttırma ve azaltma
işlemleri önce yapılacaktır.

*/
#include<stdio.h>
int main( void )
{
int i = 10, j = 60;
printf("i = %d ve j = %d\n", ++i, --j);
return 0;
}

Yukardaki programı yazar ve çalıştırısanız elde edeceğiniz çıktı şu şekilde görünecektir:

i = 11 ve j = 59

Çünkü arttırma ve azaltma işlemleri ekrana bastırmadan önce yapılmış ve i ile j'nin değerleri değiştirilmiştir. Şimdi programı değiştirip şöyle yazalım:

/*
Bu programda, arttırma ve azaltma
işlemleri sonra yapılacaktır.
*/
#include<stdio.h>
int main( void )
{
int i = 10, j = 60;
printf("i = %d ve j = %d\n", i++, j--);
return 0;
}

Bu sefer program çıktısı şöyle olacaktır:

i = 10 ve j = 60

Farkettiğiniz üzere hiçbir değişiklik yapılmamış gibi duruyor. Aslında değişiklik yapıldı ve program sonlanmadan önce i 10 olurken, j'de 59 oldu. Ama arttırma ve azaltma işlemleri printf komutu çalıştırıldıktan sonra yapıldığı için, biz bir değişiklik göremedik.
Kısacası önce arttırma (pre-increment) veya önce azaltma (pre-decrement) kullandığınızda, ilgili komut satırında çalışacak ilk şey bu komutlar olur. Ancak sonra arttırma (post increment) veya sonra azaltma kullanırsanız, o zaman bu işlemlerin etkileri ilgili komut satırından sonra geçerli olacaktır. Aşağıdaki özel tabloya bakabilirsiniz:
Form Tip İsim Açıklama
i++ postfix post-increment İşlem sonrası arttırma
++i prefix pre-increment İşlem öncesi arttırma
i-- postfix post-decrement İşlem sonrası azaltma
--i prefix pre-decrement İşlem öncesi azaltma

[size=10pt]Gelişmiş atama (Advanced Assignment) yöntemleri[/size]

C'de yazım kolaylığı amacıyla sunulmuş bir başka konu da, gelişmiş aşama yöntemleridir. Biraz daha uzun yazacağınız kodu, kısaltmanıza yaramaktadır.

degisken_1 = degisken_1 (operator) degisken_2 şeklinde yazacağınız ifadeleri, daha kısa yazabilmeniz için, degisken_1 (operator) = degisken_2 şeklinde ifade edebilirsiniz. Gelişmiş atamalarda sunulan genel formlar şu şekildedir:

+= , -= , *= , /= , %=

Sanırım aşağıdaki örneklere bakarsanız, konuyu çok daha net anlayacaksınız:



1-) j = j * ( 3 + x ) ==> j *= ( 3 + x )
2-) a = a / ( 5 - z ) ==> a /= ( 5 - z )
3-) x = x - 5 ==> x -= 5

[size=10pt]Conditional Operator ( ? ) [/size]

Türkçe karşılık bulamadığım bir başka C kavramı da, Conditional Operator. Aslında mot a mot çeviri yaparsam, koşullu operatör anlamına geliyor. Ama şu ana kadar gördüğümüz birçok yapıyı da bu şekilde tanımlamak mümkünken, koşullu operatör ifadesini kullanmayı pek tercih etmiyorum. Neyse lafı uzatmayalım...
Conditional Operator, if-else ile tamamen aynı yapıdadır. Hiçbir farkı yoktur. Tek farkı koda bakıldığında anlaşılmasının biraz daha zor oluşudur. Bir de if - else gibi yazıyla ifade edilmez. Onun yerine soru işareti (?) ve iki nokta üst üste ( : ) kullanarak yazarız. Aşağıdaki tabloda if else yapısıyla karşılaştırılmalı olarak, Conditional Operator verilmiştir:

[size=10pt]if-else Yapısı [/size]

if( koşul ) {
if_komut(lar)
}
else {
else_komut(lar)
} koşul?if_komut(lar):else_komutlar

[size=10pt]Conditional Operator ( ? ) Yapısı [/size]





[size=10pt]Conditional Operator ( ? ) Akış Diyagramı [/size]


Şimdi de aynı programı, hem if-else, hem de conditional operator kullanarak yazalım:

/*
Girilen tam sayının
10'dan büyük olup
olmadığını gösteren
program
*/
#include<stdio.h>
int main( void )
{
int sayi;
printf("Lütfen bir sayı giriniz> ");
scanf("%d",&sayi);
if( sayi > 10 )
printf("Sayı 10'dan büyüktür\n");
else
printf("Sayı 10'dan küçüktür veya 10'a eşittir\n");
return 0;
}


Şimdi de aynı programı conditional operator kullanarak yazalım:


/*
Girilen tam sayının
10'dan büyük olup
olmadığını söyleyen
program

*/
#include<stdio.h>
int main( void )
{
int sayi;
printf("Lütfen bir sayı giriniz> ");
scanf("%d",&sayi);
( sayi > 10 ) ? printf("Sayı 10'dan büyüktür\n"):
printf("Sayı 10'dan küçüktür veya 10'a eşittir\n");
return 0;
}

Program gördüğünüz gibi biraz daha kısaldı.

Conditional Operator'ler pek kullanmayı sevmediğim bir yapıdır. Çünkü kodun kısa olmasından çok, anlaşılabilir olması önemli. Ve conditional operator kullanmak ne yazık ki, kodu daha karmaşık hale getiriyor. UNIX filozofisinde bir şeyi akıllıca yapacağınıza, temiz/açık yapın diye bir yaklaşım mevcut. Belki bu yüzden veya belki de tembellik, conditional operator'lere alışamadım gitti...
Şimdi örnek sorularımıza gelelim...

[size=10pt]Örnek Sorular[/size]

Soru 1: Aşağıdaki kodu yorumlayınız:

s = ( x < 0 ) ? -1 : x * x

Cevap

Soru 1 in cevabı:

Eğer x, 0'dan küçük bir değerse, s değişkenine, -1 değeri atanır. Eğer x, 0'dan büyükse,
x'in karesi, s değişkenine atanır. (Gördüğünüz gibi ilk bakışta kodu yorumlamak biraz
sıkıcı olabiliyor. Sanırım yukarda ne demek istediğimi anlamışsınızdır.)

Soru 2: İki tam sayı alacak ve verilecek operatöre göre (+, -, *, /, %) işlem yapacak bir program yazınız.
2. Cevap

#include<stdio.h>
int main( void )
{
int sayi_1, sayi_2;
char operator_simgesi;
printf("Lütfen işlem simgesi giriniz> ");
scanf("%c",&operator_simgesi);
printf("Lütfen birinci sayıyı giriniz> ");
scanf("%d",&sayi_1);
printf("Lütfen ikinci sayıyı giriniz> ");
scanf("%d",&sayi_2);
switch( operator_simgesi ) {
case '+':
printf("%d %c %d = %d\n",sayi_1,operator_simgesi, sayi_2, sayi_1 + sayi_2); break;
case '-':
printf("%d %c %d = %d\n",sayi_1,operator_simgesi, sayi_2, sayi_1 - sayi_2); break;
case '%':
printf("%d %c %d = %d\n",sayi_1,operator_simgesi, sayi_2, sayi_1 % sayi_2); break;
case '*':
printf("%d %c %d = %d\n",sayi_1,operator_simgesi, sayi_2, sayi_1 * sayi_2); break;
case '/':
printf("%d %c %d = %.2f\n",sayi_1,operator_simgesi, sayi_2, (float)sayi_1 / sayi_2);break;
default:
printf("HATA: Tanımsız bir operatör girdiniz!\n");
}
return 0;
}

Soru 3: Verilecek üç sayıdan en büyüğünü ekrana yazdıracak bir program yazınız.

s3. Cevap


#include<stdio.h>
int main( void )
{
int sayi_1, sayi_2, sayi_3;
printf("Üç sayı giriniz> ");
scanf("%d %d %d", &sayi_1, &sayi_2, &sayi_3);
if( sayi_1 >= sayi_2 && sayi_1 > sayi_3 )
printf("%d en büyük sayıdır!\n", sayi_1);
else if( sayi_2 >= sayi_1 && sayi_2 >= sayi_3 )
printf("%d en büyük sayıdır!\n", sayi_2);
else if( sayi_3 >= sayi_1 && sayi_3 >= sayi_1 )
printf("%d en büyük sayıdır!\n", sayi_3);
return 0;
}

[size=14pt]C Programlama Dersi - V
Bu yazıda öğrenecekleriniz:[/size]

- Döngü kavramı

- while döngüsü

- do while döngüsü

- for döngüsü

- break komutu

- continue komutu

- goto Yapısı

- Konuyla ilgili örnek sorular

Döngü Kavramı
Programlama konusunda -hangi dil olursa olsun- en kritik yapılardan biri döngülerdir. Döngüler, bir işi, belirlediğiniz sayıda yapan kod blokları olarak düşünülebilir. Ekrana 10 kere "Merhaba Dünya" yazan bir programda, "Merhaba Dünya" yazdıran kodu aslında tek bir defa yazarsınız, döngü burada devreye girip, sizin için bu kodu istediğiniz sayıda tekrarlar.

Döngüleri bu kadar kritik yapan unsur; iyi yazılıp, optimize edilmediği takdirde, bilgisayarınızın işlem gücünü gereksiz yere tüketmesi ve harcanan zamanı arttırmasıdır. Benzer şekilde, iyi yazılmış bir döngü, programınızı hızlı çalıştıracaktır.

Bütün döngüler temelde iki aşamayla özetlenebilir. Aşamalardan biri, döngünün devam edip etmeyeceğine karar verilen mantıksal sorgu kısmıdır. Örneğin, ekrana 10 kere "Merhaba Dünya" yazdıracaksanız, kaçıncı seferde olduğunu, koşul kısmında kontrol edersiniz. Diğer aşama, döngünün ne yapacağını yazdığınız kısımdır. Yani ekrana "Merhaba Dünya" yazılması döngünün yapacağı iştir.

Döngünün devam edip etmeyeceğine karar verilen aşamada, hatalı bir mantık sınaması koyarsanız, ya programınız hiç çalışmaz ya da sonsuza kadar çalışabilir.

C programlama diline ait bazı döngüler; while, do while, for yapılarıdır. Bunlar dışında, goto döngü elemanı olmasına rağmen, kullanılması pek tavsiye edilmemektedir.
while Döngüsü

while döngüsü, en temel döngü tipimizdir. Bir kontrol ifadesiyle döngünün devam edilip edilmeyeceği kontrol edilirken, scope içinde ( yani ayraç işaretleri arasında ) kalan bütün alan işleme sokulur. İşleme sokulan kod kısmı döngü yapılacak adet kadar tekrar eder.

while döngüsünün genel yapısını ve akış şemasını aşağıda görebilirsiniz:
while Yapısı while Akış Diyagramı

while( koşul ) {
komut(lar)
}




Yukarda 10 kere ekrana "Merhaba Dünya" yazan programdan bahsettik. Gelin bir anlaşma yapalım ve döngülerle alakalı bütün ilk örneklerimiz bu programın nasıl yazılacağını göstersin.

while döngüsü kullanarak, ekrana 10 kere "Merhaba Dünya" yazan program aşağıdaki gibidir:

/*
Ekrana 10 kere "Merhaba Dünya"
yazan program
*/
#include<stdio.h>
int main( void )
{
//i değişkenine bir başlangıç değeri atıyoruz.
//i'ye ilk deger atanmazsa, döngümüz yanlış çalışır.
int i = 0;
//i'nin degeri kontrol işleminden
//sonra 1 artar.
while( i++ < 10 ) {
//2d bir tam sayının yazdırılacağı
//ancak bu sayı tek rakamdan oluşsa da
//2 rakamlık yer ayırılmasını belirtir.
printf("%2d: Merhaba Dünya\n",i);
}
return 0;
}

Yukardaki program aslında son derece basit. i değişkenine ilk değer olarak 0 atıyoruz. Daha sonra, while döngüsüne başlıyoruz. İfadenin doğruluğu ( yani i'nin 10'dan küçük olup olmadığı) kontrol ediliyor. Eğer doğruysa, döngü içindeki kodların çalışması başlatılıyor. Elbette kodların başlamasından bir önceki adımda, i değişkeni arttırılıyor. ( Önceki derste anlatmış olduğumuz post-increment işlemini hatırlayın. ) Bu yapı toplamda 10 kere tekrar ediyor ve en sonunda i'nin degeri 10'a eşit olunca, döngü sonlandırılıyor.

Yandaki işlem basit bir toplama ifadesidir. Yanda gördüğümüz ifade de, n değerini kullanıcıdan alacağımızı düşünerek bir program yazalım. Bu program, alacağı n değerine göre, kendisine kadar olan sayıların karelerinin toplamını gösterecektir. Bu programı yazarsak:

#include<stdio.h>
int main( void )
{
int i = 0, toplam_deger = 0;
int n;
printf("Lütfen n değerini giriniz> ");
scanf("%d",&n);
while( i <= n ) {
toplam_deger += i*i;
i++;
}
printf("Sonuç: %d\n",toplam_deger);
return 0;
}

do while Döngüsü

Göreceğimiz ikinci döngü çeşidi, do while döngüsüdür. Yaptığı iş, while ile hemen hemen aynıdır; verilen işi, döngü koşulu bozulana kadar sürdürür. Ancak while'a göre önemli bir farkı vardır.

while döngülerinde, döngü içersindeki işlem yapılmadan önce, sunulan koşul kontrol edilir. Şayet koşul sağlanmıyorsa, o while döngüsünün hiç çalışmama ihtimali de bulunmaktadır. do while döngülerindeyse, durum böyle değildir. İlk çalışmada koşul kontrolü yapılmaz. Dolayısıyla, her ne şartta olursa olsun, döngünüz -en azından bir kere- çalışacaktır.

Bazı durumlarda, döngü bloğu içersindeki kodların en azından bir kere çalışması gerektiğinden, do while yapısı kullanılır. do while ile ilgili genel yapıyı ve akış şemasını aşağıda bulabilirsiniz:
do while Yapısı do while Akış Diyagramı

do {
komut(lar)
} while( koşul );



Önce Merhaba Dünya örneğimizi yapalım:

#include<stdio.h>
int main( void )
{
int i = 0;
do {
//Önce i'nin değeri arttırılıyor
//sonra ekrana Merhaba Dünya yazdırılıyor.
printf("%2d: Merhaba Dünya\n",++i);
} while( i < 10 );
return 0;
}

Gördüğünüz gibi, bir önceki örneğimize oldukça benzer bir yapıda, yazıldı. Tek fark i'nin değeri 0'da olsa, 1000'de olsa, en azından bir kez Merhaba Dünya'nın yazılacak olmasıdır. Ancak while'de kontrol önce yapıldığı için, hiçbir şey ekrana yazılmaz.

Şimdi do while'in kullanılmasının daha mantıklı olacağı bir program yapalım. Kullanıcıdan iki sayı alınsın. Bu iki sayı toplandıktan sonra, sonucu ekrana yazdırılsın. Yazdırma sonunda "Devam etmek istiyor musunuz?" sorusu sorulsun ve klavyeden 'E' veya 'e' karakterlerinden birisi girilirse, program devam etsin. Yok farklı birşey girilirse, program sonlandırılsın. Örnek programımızı aşağıda bulabilirsiniz:

#include<stdio.h>
int main( void )
{
int sayi_1, sayi_2;
char devam_mi;
do {
printf("Birinci sayıyı giriniz> ");
scanf("%d",&sayi_1);
printf("İkinci sayıyı giriniz> ");
scanf("%d",&sayi_2);
printf("%d + %d = %d\n", sayi_1, sayi_2, sayi_1 + sayi_2);
printf("Devam etmek ister misiniz? ");
//C'de tek karakter okuma işlemi biraz sıkıntılı
//olduğundan, burada da bir do while kullandık.
do {
scanf("%c",&devam_mi);
}while( devam_mi == '\n' );
printf("\n");
} while( devam_mi == 'E' || devam_mi == 'e' );

return 0;
}
Bu mesajdan alıntı yap
Dram-Like isimli Üye şimdilik offline konumundadır

Dram-Like

Webmaster

Standart
Alt 22-02-2009 #5
Program, kullanıcıdan iki sayı alıp, toplamını ekrana bastıktan sonra, yeniden işlem yapıp yapmak istemediğimizi sormaktadır. Bu programı while ile de yazabilirdik. Ancak while ile yazabilmek için, devam_mi değişkenine önceden 'E' değerini atamamız gerekmekteydi. do while döngüsündeyse, bu zorunluluğa gerek kalmamıştır.

Not: Yukardaki programda, farketmiş olduğunuz gibi karakter okumayı biraz farklı yaptık. Normalde, scanf( ) fonksiyonunu kullanmak yeterliyken, burada, işin içine bir de, do while girdi. Açıklayacak olursak, C'de karakter okumaları, biraz sıkıntılıdır. Eğer giriş tampon belleğinde (Buffer) veri bulunuyorsa, bu direkt karaktere atanır. Bundan kurtulmak için birçok yöntem olduğu gibi, uygulanabilecek bir yöntem de, yukarda yazılmış olan döngü şeklinde değer almaktır. Çünkü siz daha bir şey girmeden, ilk değer '\n' geleceğinden, döngünün ikinci çalışmasında, doğru değer atanacaktır. İlerki konularda, daha detaylı ele alacağımız bir problem olarak şimdilik önemsemeyelim. Sadece karakter okuyacağınız zaman problem çıkarsa, yukardaki gibi bir yöntem uygulanabileceğini bilmeniz -şimdilik- yeterli.
[size=10pt]for Döngüsü[/size]

while ve do while dışında, üçüncü bir döngü tipi olarak, for yapısı bulunmaktadır. Diğer iki döngüden farklı olarak, for yapısı, yenilemeli-tekrarlamalı (İngilizce iterative) yapılarda kullanıma daha uygundur. Bunu performans anlamında söylemiyorum. Demek istediğim yazım tekniği olarak, for döngüsünün daha kullanışlı olmasıdır. Örneğin birbirini, sürekli tekrar eden işlemlerin yapıldığı Nümerik Analiz gibi alanlar, for döngüsü için iyi bir örnek olabilir. Ancak bu dediklerim sizi yanıltmasın; for döngüsü sadece soyut alanlarda çalışsın diye yaratılmış bir şey değildir.

Programlarda, diğer iki döngüden çok daha fazla for kullanırsınız. Çünkü for sadece matematiksel hesaplama işlemlerinde değil, diziler ( array ) gibi konularda sürekli kullanılan bir yapıdır. Yazımı diğerlerine nazaran daha sade olduğundan, iteratif işlemlerde kullanılması elbette ki tesadüf olarak düşünülemez.

Aşağıda for döngüsünün genel yazımını ve akış diyagramını göreceksiniz:
for Yapısı for Akış Diyagramı

for( ilk_deger_atama; koşul; arttırma/azaltma ){
komut(lar)
}



İlk atacağımız adım; elbette ki ekrana 10 kere "Merhaba Dünya" yazdırmak olacak. ( Umarım bu Merhaba Dünya'larla sizi fazla sıkıp, programlama işinden vazgeçirmemişimdir. Programlama mantığını kaptıktan sonra, dünyayı daha farklı görmeye başlayacak ve Merhaba Dünyalar'ın sebebini daha iyi anlayacaksınız. Ve inanın bütün bu eziyete değer... ) Buyrun programımız:

#include<stdio.h>
int main( void )
{
int i;
for( i = 0 ; i < 10; i++ ) {
printf("%2d: Merhaba Dünya\n",(i+1));
}
return 0;
}

Gördüğünüz gibi çok daha sade ve açık gözükür bir kod oldu. for altında tek satır komut olduğundan, küme parantezleri koymamız opsiyoneldi ama ne yaptığınızı karıştırmamak için, her zaman koymanızı öneririm.

for döngüleriyle ilgili bazı özel durumlarda vardır. for döngüsü içersine yazdığınız ilk değer atama, kontrol ve arttırma işlemlerini tanımlama esnasında yapmanız gerekmez. Aşağıda verilen kod, yukardakiyle tamamen aynı işi yapar. Farkı, i'nin daha önce tanımlanmış olması ve arttırma/azaltma işinin döngü içinde yapılmasıdır.

#include<stdio.h>
int main( void )
{
int i;
i = 0;
for( ; i < 10; ) {
printf("%2d: Merhaba Dünya\n",(i+1));
i = i + 1;
}
return 0;
}

break Komutu

Bazı durumlarda, döngüyü aniden sonlandırmak isteriz. Bunun için 'break' komutunu kullanırız. Döngüyü aniden sonlandırmak veya döngüyü kırmak işlemini, zaten daha önce switch case'lerde kullanmıştık. Bahsetmediğimiz şey, bunun her döngü içersinde kullanılabileceğiydi.

Aşağıdaki programı inceleyelim:

/*
0 ile 99 arasında tesadüfi sayılar üreten
bir programın, kaçıncı seferde 61 sayısını
bulacağını yazan program aşağıdadır.
*/
#include<stdio.h>
int main( void )
{
int i,tesadufi_sayi;
int deneme_sayisi = 0;
//while içinde 1 olduğundan sonsuza kadar döngü çalışır.
while( 1 ){
//tesadufi_sayi değişkenine, 0 ile 99 arasında
//her seferinde farklı bir sayı atanır.
//rand( ) fonksiyonu tesadüfi sayı atamaya yarar.
//mod 100 işlemiyse, atanacak sayının 0 ile 99
//arasında olmasını garantiler.
tesadufi_sayi = rand() % 100;
//Döngünün kaç defa çalıştığını deneme_sayisi
//değişkeniyle buluruz.
deneme_sayisi++;
//Eğer tesadufi sayı 61'e eşit olursa,
//döngü kırılıp, sonlandırılır.
if( tesadufi_sayi == 61 ) break;
}
printf("Toplam deneme sayısı: %d\n",deneme_sayisi);
return 0;
}

Program için koyulmuş açıklamalar ( comment ) zaten neyin n'olduğunu açıklıyor. Kısaca bir şeyler eklemek gerekirse, bitişinin nerede olacağını bilmediğimiz bir döngüyü ancak, break komutuyla sonlandırabiliriz. Şartlar sağlandığında, break komutu devreye girer ve döngü sonlandırılır. Bunun gibi bir çok örnek yaratmak mümkündür.
continue Komutu

break komutunun, döngüyü kırmak için olduğundan bahsetmiştik. Bunun dışında işlem yapmadan döngüyü devam ettirmek gibi durumlara da ihtiyacımız vardır. Bunun içinde continue ( Türkçe: devam ) komutunu kullanırız.

/*
Sadece tek sayıları yazdıran bir
program
*/
#include<stdio.h>
int main( void )
{
int i;
for( i = 0; i < 10; i++ ) {
//i değişkeninin 2'ye göre modu
//0 sonucunu veriyorsa, bu onun
//bir çift sayı olduğunu gösterir.
//Bu durumda ekrana yazdırılmaması
//için döngü bir sonraki adıma geçer.
if( i%2 == 0 ) continue;
printf("%2d\n",i);
}
return 0;
}

0 ile 10 arasındaki tek sayıları gösteren program örneğini yukarda görebilirsiniz. Elbette ki bu işi daha farklı ve daha iyi yapan bir program yazabilirdik. Ama şimdilik continue komutunun nasıl kullanıldığını inceleyelim.

Program bir for döngüsü çalıştırmaktadır. Her defasında i değişkenin 2'ye göre modu alınır. Eğer sonuç 0'sa, bu sayının çift olduğunu gösterir. Dolayısıyla, bunun ekrana yazdırılmaması gerekir. Bu yüzden, döngü içersindeki işlemleri sürdürmek yerine, altta kalan kodları atlarız. Burada continue komutu kullanılır ve kullanıldığı noktadan itibaren olan işlemler yapılmaz. Döngü başa döner, aynı işlemleri yapar. Bu sefer i tek sayı olacağından continue komutu çalışmaz ve sayıyı ekrana bastırırız.
goto Yapısı

C programlama dilinde bulunan bir başka yapı, goto deyimidir. Koyacağınız etiketler sayesinde, programın bir noktasından bir başka noktasına atlamanızı sağlar. goto, bir döngü değildir ancak döngü olarak kullanılabilir.

goto, çalışabilmek için etiketlere ihtiyaç duyar. Etiketler, vereceğiniz herhangi bir isme sahip olabilir. Etiket oluşturmak için bütün yapmanız gereken; etiket adını belirleyip, sonuna iki nokta üst üste eklemek ( : ) ve programın herhangi bir yerine bunu yazmaktır. goto deyimi kullanarak bu etiketleri çağırırsanız, etiketin altında bulunan kodlardan devam edilir. goto ve etiketlere dair genel yapıyı, akış diyagramıyla birlikte aşağıda bulabilirsiniz:
goto Yapısı goto Akış Diyagramı

label_name:
.
.
.

if( kosul ) {
goto label_name
}
.
.
.





NOT: goto deyimi tek başına da kullanılabilir. Fakat mantıksal bir sınama olmadan, goto yapısını kullanmanız, sonsuz döngüye neden olacaktır.

Şimdi goto ifadesiyle basit bir döngü örneği oluşturalım. Önceki seferlerde olduğu gibi ekrana 10 defa "Merhaba Dünya" yazdıralım:

#include<stdio.h>
int main( void )
{
int i = 0;
// baslangic_noktasi adinda bir etiket koyuyoruz.
// i degiskeni 10 degerine ulasmadigi surece,
// program buraya donecektir.
baslangic_noktasi:
printf( "Merhaba Dünya\n" );
// i degerini arttiriyoruz.
i++;
// i degeri kontrol ediliyor. Sayet 10'dan kucukse,
// en basa donuyor.
if( i<10 ) goto baslangic_noktasi;

return 0;
}

İstediğiniz sayıda etiket koyup, goto kullanarak, programın herhangi bir noktasına ulaşabilirsiniz. Programınız, etiket altında kalan kısımdan itibaren çalışır. goto yapısıyla gelen esneklik, ilk bakışta oldukça güzel görünüyor. Ancak goto için birçok kaynak, "ya hiç kullanmayın ya da olabildiğince az kullanın" demektedir.

Okunup, anlaşılması zor ve üzerinde çalışılması güç bir koddan, herkesin uzak durması gerekir. İngilizce'de, karman çorman koda, "spagetti kod" adı verilmiştir. goto deyimi, kodunuzun spagetti koda dönüşmesine neden olur. Çünkü program akışının takibini zorlaştırıp, kodun okunabilirliğini azaltır. Diliyorsanız, goto deyimini kullanabilirsiniz. Ama zorunlu kalmadıkça kaçınmak en iyisi...
Örnek Sorular

Soru 1: Klavyeden girilen sayının faktöriyelini hesaplayıp, ekrana yazdıran bir program yazınız.

Cevap için tıklayınız...


#include<stdio.h>
int main( void )
{

int sayi,i;
int faktoriyel = 1;

printf("Sayı giriniz> ");
scanf("%d",&sayi);

//Şayet sayı 0'a büyük eşitse, faktoriyel
//hesaplanır.
if( sayi >= 0 ) {
//Şayet sayı 0 ise, alttaki döngü
//hiç çalışmaz.
for( i = sayi; i > 0; i-- ) {
faktoriyel *= i;
}
printf("Faktoriyel = %d\n",faktoriyel);
}
//Şayet sayı 0'dan küçükse, değer hesaplanamaz.
else
printf("HATA: Sayı 0'dan küçük olamaz!\n");
return 0;
}

Soru 2: Klavyeden girilen sayının tersini (örneğin 1234 ==> 4321 gibi) ekrana bastıran programı yazınız.

Cevap için tıklayınız...


#include<stdio.h>
int main( void )
{

int sayi;
int yazilacak_rakam;

printf("Sayıyı giriniz> ");
scanf("%d",&sayi);

printf("Sayının tersi: ");
while( sayi>10 ) {
//Sayının son rakamı alınıp
//ekrana bastırılıyor.
yazilacak_rakam = sayi % 10;
printf("%d",yazilacak_rakam);
//Son rakam ekrana bastırıldığı
//için sayının son hanesi atılıyor.
sayi /= 10;
}
printf("%d\n",sayi);

return 0;
}

Soru 3: Kullanıcıdan sınırsız sayıda, pozitif sayı alacak ve aldığı sayıların ortalamasını ekrana bastıracak bir program yazınız. Kullanıcı negatif bir sayı girdiği takdire, bu sayı hesaba alınmayacak ve program sonlandırılıp, o zamana kadar girilmiş pozitif sayıların ortalamasını yazdıracaktır.

Cevap için tıklayınız...


#include<stdio.h>
int main( void )
{
int girilen_sayi_adedi = 0;
int sayi_toplami = 0;
int girilen_sayi;
//Sonsuz döngü oluşturuyoruz.
for( ; ; ) {
printf("Lütfen bir sayı giriniz> ");
scanf("%d",&girilen_sayi);
if( girilen_sayi < 0 ) break;
sayi_toplami += girilen_sayi;
girilen_sayi_adedi++;
}
printf("Toplam %d adet sayı girilmiştir.\n",girilen_sayi_adedi);
printf("Bunların toplam değeri %d olarak bulunmuştur.\n",sayi_toplami);
printf("Ortalaması %.3f olarak hesaplanmıştır\n",(float)sayi_toplami/girilen_sayi_adedi);
return 0;
}

Soru 4: Aşağıdaki çıktıyı üreten programı yazınız:

*
* *
* * *
* * * *
* * * * *

Cevap için tıklayınız...


#include<stdio.h>
int main( void )
{
int i, j;
for( i = 0 ; i < 5; i++ ) {
for( j = 0; j < i+1; j++ ) {
printf("* ");
}
printf("\n");
}
return 0;
}

Soru 5: 4 numaralı sorunun cevabında bulunan for döngülerini, while döngülerine çeviriniz.

Cevap için tıklayınız...


#include<stdio.h>
int main( void )
{
int i=0,j;
while( i < 5 ) {
j = 0;
while( j < i+1 ) {
printf("* ");
j++;
}
printf("\n");
i++;
}
return 0;
}
Bu mesajdan alıntı yap
Dram-Like isimli Üye şimdilik offline konumundadır

Dram-Like

Webmaster

Standart
Alt 22-02-2009 #6
var GGAff = {id:15145,width:728,height:90,direction:"Vertical" ,performance:"high"};GGAff.errorMessage = '';




C Programlama Dersi - VI
Bu yazıda öğrenecekleriniz:

- Sayı tabanları

- Bit Bazında ( Bitwise ) Operatörler

- AND ( & ) Operatörü

- OR ( | ) Operatörü

- NOT ( ~ ) Operatörü

- XOR ( ^ ) Operatörü

- Kaydırma ( Shift ) Operatörleri

- Operatör Öncelikleri

Sayı Tabanları

Bilgisayar programlamayla, matematik arasında çok güçlü bir ilişki vardır. Geçmişe bakarsanız, bilgisayar alanında önemli adımların, hep matematik kökenli insanlar tarafından atıldığını görürsünüz. Bir bilgisayar programcısı için, matematikten uzak durmak düşünülemez.

Bugün ki dersimizde, biraz matematik içersine gireceğiz ve sayı sistemleriyle, Boole Cebiri (Boolean Algebra) konularını ele alacağız.

Genel kabul görmüş sayı sistemleri vardır ve içlerinde en yaygını, hepimizin gündelik hayatta kullandığı 10'luk sayı sistemidir. Yazması, okunması ve işlem yapması son derece kolay olduğundan bunu daha çocuk yaşta öğrenir ve bu şekilde sürdürürüz. Ancak bilgisayarlar bizim gibi işlem yapabilme yetisine sahip değildir. Onlar için iki ihtimal vardır. Bir şey ya 1'dir ya da 0. Bunu ikilik sayı sistemi olarak adlandırırız. Yani bizim yazdığımız bütün sayılar, bütün harfler ve aklınıza gelen-gelmeyen bütün işaretler, bilgisayar için 0 ve 1'in kombinasyonlarından ibarettir. İşte bu yüzden bizlerin, ikilik sayı sistemine hakim olması gerekir.

Sayı sistemlerini genel olarak aşağıdaki gibi ifade edebiliriz:
c programlama

Burada, N sayı tabanına göstermektedir. k sayının hangi hanesinde olduğumuzu ifade ederken, dk ise, ilgili sayıdaki rakamı temsil eder. Şimdi basit bir örnek yapalım ve ikilik tabandaki 10011 sayısının, 10 tabanındaki eş değerini bulalım:

( d4d3d2d1d0 )2 = ( d0 . 20 ) + ( d1 . 21 ) + ( d2 . 22 ) + ( d3 . 23 ) + ( d4 . 24 )
( 10011 )2 = ( 1 . 20 ) + ( 1 . 21 ) + ( 0 . 22 ) + ( 0 . 23 ) + ( 1 . 24 ) = 19

ikilik sayı sistemi dışında, 16'lık (Hexadecimal) sayı sistemi de oldukça önemli bir başka tabandır. 16'lık sayı sisteminde, rakamları ifade etmek için 16 adet sembole gereksinim duyarız. Bu yüzden 0 ile 9 arasında olan 10 rakamı kullandıktan sonra, A, B, C, D, E ve F harflerini de rakam olarak değerlendiririz.
Decimal : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Hexadecimal : 0 1 2 3 4 5 6 7 8 9 A B C D E F

Hexadecimal/16'lık sayı tabanıyla ilgili aşağıdaki örneklere göz atalım:

( 3FC )16 = ( 3 . 162 ) + ( F . 161 ) + ( C . 160 ) = 768 + 240 + 12 = 1020
( 1FA9 )16 = ( 1 . 163 ) + ( F . 162 ) + ( A . 161 ) + ( 9 . 160 ) = 4096 + 3840 + 160 + 9 = 8105
( 75 )16 = ( 7 . 161 ) + ( 7 . 160 ) = 112 + 5 = 117

16'lık sayı sisteminin diğer bir ismi Hexadecimal olduğundan, bazı yerlerde, bunu ifade etmek için 16 yerine 'H' harfi de kullanılabilir:

( BA3 )16 = ( BA3 )H ; ( A1E )16 = ( A1E )H gibi...

Tabanlar arasında dönüştürme işlemi, üzerinde duracağımız bir başka konudur. Elinizde 16'lık sayı sisteminde bir sayı varsa ve bunu 2'lik sayı sistemiyle yazmak isterseniz önce 10'luk sayı sistemine çevirip daha sonra 2'lik sayı sistemine dönüştürebilirsiniz. Ancak 16'lık ve 2'lik sayı sistemlerini çok daha kolay birbirine dönüştürmeniz mümkündür. Aşağıdaki tabloda 16'lık sayı sistemindeki rakamlar ve bunun 2'lik sayı sistemindeki karşılığı verilmiştir:
Hexadecimal : 0 1 2 3 4 5 6 7 8 9 A B C D E F
Binary ( İkilik ) : 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

Bu durumu bir örnekle şöyle gösterebiliriz:
( A3F1 )H : A 3 F 1
: 1010 0011 1111 0001

16'lık tabandaki her rakamın, 2'lik tabandaki karşılığını koyduğumuzda yukardaki eşitliği elde ediyoruz ve buna göre ( A3F1 ) = ( 1010 0011 1111 0001 )2 eşitliğini kurabiliyoruz. (2'lik tabandaki sayıya ait boşluklar, sayının daha rahat okunması için bırakılmıştır.) Bu tarz dönüşümler, 2 ve 2'nin katında olan sayı tabanlarında rahatlıkla yapılabilir.

Hatırlarsanız, değişken tiplerinde, işaretli ve işaretsiz değişken tanımlamalarından bahsetmiştik. Şimdi olayın biraz daha derinine inelim. Bir char, 1 byte alan kaplar ve 1 byte, 8 bit'ten oluşur. Aşağıdaki kutuların her birini bir bit ve kutuların oluşturduğu bütünü bir byte olarak düşünün:
a7 a6 a5 a4 a3 a2 a1 a0

Yukardaki kutuların toplamı olan bir byte, char değişkeninin kapladığı alanı temsil etmektedir. Pozitif sayıları ifade etmeyi zaten öğrenmiştik. Sayının karşılığını, 2'lik tabanda yazarak, gerekli sonuca ulaşırız. Ancak sayımız Negatif değerliyse, işler biraz farklılaşır. Burada devreye işaret biti (sign bit) devreye girer. Yukardaki şekilde, diğer kutulardan farklı renkte olan a7 işaret bitidir. Özetle, a7 0 ise, sayı pozitiftir. Eğer a7 1 ise, sayı negatiftir.

İkilik tabandaki işaretli bir sayının, 10'luk tabandaki karşılığını şu şekilde bulabiliriz:

( a7a6a5a4a3a2a1a0 )2 = ( a7 . -27 ) + ( a6 . 26 ) + ... + ( a1 . 21 ) + ( a0 . 20 )

İkilik tabanda yazılmış ( 10000011 )2 sayısı, işaretsiz olarak düşünülürse, 131'e eşittir. Ancak işaretli bir sayı olduğu düşünülürse, karşılığı, -125 olacaktır. Konunun pekişmesi açısından aşağıdaki örneklere göz atabilirsiniz:

* ( 1011 1011 )2 = -69 (Sayı işaretliyse)
( 1011 1011 )2 = 187 (Sayı işaretsizse)
* ( 1100 1101 )2 = -51 (Sayı işaretliyse)
( 1100 1101 )2 = 205 (Sayı işaretsizse)
* ( 0110 1101 )2 = 109 (Sayı işaretliyse)
( 0110 1101 )2 = 109 (Sayı işaretsizse)

Negatif bir sayının 2'lik tabandaki karşılığını bulmak için, önce (i) sayıyı pozitif olarak ikilik tabanda yazarız. Daha sonra, (ii) ikilik tabanda yazılmış sayının 1 yazan rakamları 0, 0 yazan rakamları 1'e çevrilir. Son olarak (iii) çıkan sayıya, 1 eklenir. Bu size istediğiniz sayının ikilik tabanındaki eşini verecektir. Şimdi bir uygulama yapalım ve -7 sayını ikilik tabana çevirmeye çalışalım:

i ) -7 ==> ( 7 )10 = ( 0000 0111 )2

ii ) ( 0000 0111 ) ==> ( 1111 1000 )

iii ) ( 1111 1000 ) + 1 = ( 1111 1001 ) ==> ( -7 )10 = ( 1111 1001 )2
Bit Bazında ( Bitwise ) Operatörler

Bit bazında operatörlerin, İngilizce'deki karşılığı Bitwise Operators ( yani Bit bit Operatörler ) olarak geçmektedir. Bit bazında operatörler, ikilik sayı tabanında yapabileceğimiz işlemleri temsil eder. Kullanılan operatörleri aşağıda inceleyeceğiz.
AND ( & ) Operatörü

AND operatörü, kendisine verilen iki değişkenin bütün bitleri 1'e eşit olduğu takdirde, geriye 1 döndürür. Aksi halde -yani en ufak bir fark varsa- 0 değeri dönmektedir.
p q p&q
0 0 0
0 1 0
1 0 0
1 1 1
x 0 0
x 1 x

Şimdi, AND ( & ) operatörünü 25 ve 14 sayılarını karşılaştırmak için kullanalım:

25 ==> ( 0001 1001 )2
14 ==> ( 0000 1110 )2
&
----------------------------
8 ==> ( 0000 1000)2

OR ( | ) Operatörü

İki değişkenden herhangi biri 1 içeriyorsa, geriye 1 döner. Eğer her ikisi de 0 içeriyorsa, geriye 0 dönmektedir.
p q p|q
0 0 0
0 1 1
1 0 1
1 1 1
x 0 x
x 1 1

Daha önce kullandığımız 25 ve 14 sayıları üzerinde OR ( | ) işlemi kullanalım:

25 ==> ( 0001 1001 )2
14 ==> ( 0000 1110 )2
|
----------------------------
31 ==> ( 0001 1111)2

ÖNEMLİ NOT: Bit bazında kullanılan, AND( & ) ve OR ( | ) operatörleri, koşullu ifadelerde kullanılan, AND( && ) ve OR ( || ) ifadelerinden farklıdır. Şayet, & veya | bir koşullu ifade gibi kullanmaya kalkarsanız, işlem yine yapılacaktır. Ancak bunu yapmanız tavsiye edilmez. İlerki konularımızda neden uygun olmadığı, short-circuit ile ilgili bilgi verilirken açıklanacaktır.
NOT ( ~ ) Operatörü

NOT ( ~ ) Operatörü, kendisine verilen sayıya ait bit'leri tam tersine çevirir. Yani 0 gördüğü yeri 1; 1 gördüğü yeri 0 yapar.
p ~p
0 1
1 0

25 ==> ( 0001 1001 )2
~
----------------------------
230 ==> ( 1110 0110 )2

XOR ( ^ ) Operatörü

XOR ( Exclusive OR ) Operatörü,

sadece ve sadece karşılaştırma yapılan bitlerden biri, 1 değerine sahipse, geriye 1 döndürür. Eğer karşılaştırma yapılan bit'lerden her ikisi de 0 veya 1'se, o zaman sonuç 0 olarak çıkar.
.
p q p^q

0 0 0
0 1 1
1 0 1
1 1 0
x 0 x
x 1 ~x

25 ==> ( 0001 1001 )2
14 ==> ( 0000 1110 )2
^
----------------------------
23 ==> ( 0001 0111 )2

Kaydırma ( Shift ) Operatörleri

Kaydırma operatörleri, özellikle Assembly ile uğraşanlara tanıdık gelecektir. Bunları kullanarak son derece hızlı çarpma ve bölme yapılabilir. C'deyse benzer amaçlarla kullanmanız elbette mümkündür. İki çeşit kaydırma operatörü vardır:

i) Sola Kaydırma - Shift Left ( << )

ii) Sağa Kaydırma - Shift Right ( >> )

Her iki durumda da genel kullanım şekli aşağıdaki gibidir:

[ Tam Sayı ][ Operatör ][ Kaydırma Adım Sayısı ]

Aşağıdaki örnek, sola kaydırma operatörü kullanılarak yapılan bir işlemi göstermektedir. x değişkeni, 10 tabanında 22 sayısını tutmaktadır. 2 adım sola kaydırılması sonucu, sayı 88 olmuş ve y'ye atanmıştır.

x = ( 0001 0110 )2 ==> 22
y = x << 2
y = ( 0101 1000 )2 ==> 88

Operatör Öncelikleri

Hatırlarsanız, aritmetik işlemlerde önceliklerin olduğunu ve örneğin çarpmanın, toplamadan daha önce yapılacağını anlatmıştık. Benzer bir durum, operatörler içinde geçerlidir. Altta bulunan tabloda, hangi operatörün daha önce işleme alındığını bulabilirsiniz:
OPERATÖR ÖNCELİK SIRASI
DÜŞÜK | ^ & << >> + - * / % ! ~ - ++ -- ( ) YÜKSEK

Aşağıda bulunan tablo, ilişkisel ve mantıksal operatörlerde ki öncelik sırasını göstermektedir:
İLİŞKİSEL ve MANTIKSAL OPERATÖR ÖNCELİK SIRASI
DÜŞÜK || && == != > >= < <= ! YÜKSEK

Yukardaki tablolarda, aynı hücrede olan operatörlerin işlem öncelikleri aynıdır. Önce hangisi yazılmışsa, ilk olarak o dikkate alınır. Ama bunun dışında tanınan bir işlem önceliği bulunmamaktadır.

Aşağıdaki örnek, operatör önceliklerini pekiştirmek açısından incelenebilir:

7 & 13 ^ 11 % 4 * 2 << 14 / 4
==> 7 & 13 ^ 6 << 3
==> 5 ^ 48 = 53

Şimdi de benzer bir örneği, C programı yazarak yapalım:

#include<stdio.h>
int main( void )
{
printf( "İşlem Sonucu: %d\n", 117 & 11 << 2 * 3 );
return 0;
}

Yukardaki program, 64 sonucunu vermektedir. Programı çalıştırdığınızda, ikilik düzeyde işlemler yapılacak ve 64 cevabına ulaşılacaktır. Siz de hesaplayarak, aynı yanıtı bulabilirsiniz.

Bir sonraki dersimizde, konu anlatımı olmayacak. Onun yerine bol bol örnek yapıp, şimdiye kadar işlediğimiz konuların üzerinden geçeceğiz. Görüşmek üzere.

C Programlama Dersi - VII
Bu yazıda öğrenecekleriniz:

QUIZ

- Bu bölümde, şimdiye kadar işlenmiş konulara dair örnek sorular bulunmaktadır.

Şimdiye kadar işlemiş olduğumuz dersleri pekiştirmek için, bu yazıda örnek sorular çözeceğiz.

Örnek Sorular

Soru 1.a: Aşağıdaki programın çıktısı nedir?
#include<stdio.h>
int main( void )
{
int i = 0;
for( ; i < 12; i++ ) {
if( ( i++ + 1 ) == 5 )
printf( "%d\n",i );
else
if( i % 2 == 0 ) break;
else if( i % 3 == 0)
continue;
else
printf("%d\n", i );
}
return 0;
}

Cevap:


1
5
7
11



Soru 1.b: Aşağıdaki programı doğru olarak yazınız.


#include<stdio.h>
int main( void )
{
int sum;
float average;
int weight_1, weight_2;
printf( "1.agirlik> " );
scanf( "%d", &weight_1 );
sum += weight_1;
printf( "2.agirlik> " );
scanf( "%d", weight_2 );
sum += weight_2;
average = sum / 2;
printf( "Ortalama: %.2f\n", average );
return 0;
}


Cevap :



Cevap için tıklayınız...

#include<stdio.h>
int main( void )
{
int sum = 0;
float average;
int weight_1, weight_2;
printf( "1.agirlik> " );
scanf( "%d", &weight_1 );
sum += weight_1;
printf( "2.agirlik> " );
scanf( "%d",&weight_2 );
sum += weight_2;
average = sum / 2.0;
printf( "Ortalama: %.2f\n", average );
return 0;
}

Soru 2: Bir üçgende, iki kenarın toplam uzunluğu, üçüncü kenardan az olamaz. Ayrıca iki kenarın birbirinden farkının mutlak değeri, üçüncü kenardan büyük olmamalıdır. Bu bilgileri kullanarak, verilen üç kenar uzunluğuna göre bir üçgen çizilip çizilmeyeceğini gösteren programı yazınız. Girilecek kenar uzunlukları tam sayı olacaktır.

Cevap için tıklayınız...


/* Girilen 3 tamsayinin bir ucgenin kenari olup olmadigi kontrol edilir */

#include<stdio.h>
int main( void )
{
int a, b, c;
int temp;

printf("Birinci kenar uzunlugu> ");
scanf("%d", &a);
printf("Ikinci kenar uzunlugu> ");
scanf("%d", &b);
printf("Ucuncu kenar uzunlugu> ");
scanf("%d", &c);

/* a ile b den buyuk olan a ya kucuk olan b ye atanir */
if(a < b) {
temp = a;
a = b;
b = temp;
}

if( ((a + b) < c) || ((a - b) > c) )
printf("Bu kenar uzunluklarina sahip bir ucgen olamaz.\n");
else
printf("Bu kenar uzunluklarina sahip bir ucgen cizilebilir.\n");

return 0;
}

Soru 3: Klavyeden girilecek bir sayının asal sayı olup olmadığını ekrana basan bir program yazınız.

Cevap:


/*
Bir sayının asal olup olmadığını bulmak için çeşitli metodlar
vardır. Aşağıda bu metodlardan basit bir tanesi yazılmıştır.
Eğer sayının yarısına kadar kontrol etmek yerine, kareköküne
kadar olan sayıları test ederseniz, yine aynı sonuç çıkacaktır.
Ancak anlaşılma konusunda sorun olmaması için soru bu şekilde
çözülmüştür.
*/
#include<stdio.h>
int main( void )
{
int sayi, i;
//Sayıyı ilk başta asal kabul ediyoruz.
//asal_mi değişkeni 1 ise, sayi asaldir.
int asal_mi = 1;

//Klavyeden, test edilmek üzere bir sayı alınıyor.
printf( "Bir sayı giriniz> " );
scanf("%d",&sayi);

//Girilen sayının, başka sayılara göre sırayla modunu
//alıyoruz. Bir sayının modunu aldığınızda, kalan 0 ise
//bu sayının bölünebildiğine ve dolayısıyla
//asal olmadığına dair bilgi verir. Bu işlemi yapabilmek
//için 2'den başlayarak, sayının yarısına kadar olan
//bütün değerler deneniyor.
for( i = 2; i <= sayi/2; i++ ) {
if( sayi%i == 0 ) {
//Sayı i değişkenine kalansız bölünmektedir.
//Dolayısıyla, sayı asal değildir ve döngüyü
//sürdürmeye gerek yoktur.
asal_mi = 0;
break;
}
}
//Sayının asal olup olmama durumuna göre, çıktı yazdırılıyor.
if( asal_mi == 1 )
printf( "%d sayısı asaldır.\n", sayi );
else
printf( "%d sayısı asal değildir.\n", sayi );

return 0;
}
Bu mesajdan alıntı yap
Dram-Like isimli Üye şimdilik offline konumundadır

Dram-Like

Webmaster

Standart
Alt 22-02-2009 #7
Soru 4: Klavyeden girilecek 0 ile 999 arasında bir tam sayının, yazıyla ifade eden ( örneğin 49, 'kırkdokuz' gibi ) bir program oluşturunuz.

Cevap:


/*
Girilen sayının, nasıl okunduğunu ekrana yazdıran programdır.
Fonksiyon kullanımıyla daha efektif olarak yazılabilir.
Ancak henüz işlenmeyen bir konu olduğundan, basit bir şekilde
yazılmıştır.
*/
#include<stdio.h>
int main( void )
{
int sayi;

//Klavyeden girilecek sayinin 0 ile 999 sınırlarında
//olup olmadığı kontrol ediliyor. Eğer değilse,
//uyarı verilip, yeni bir sayı isteniyor. Bu işlem
//doğru bir değer girilene kadar devam ediyor.
do {
printf( "Sayıyı giriniz> " );
scanf("%d",&sayi);
if( sayi>999 || sayi<0 )
printf("Girdiğiniz sayı uygun değildir.\n"
"0 ile 999 arasında olmalıdır.\n");
else
break;
}while( 1 );

printf( "%d sayısı, '",sayi );

//Verilen sayıyı, yazıyla ifade edebilmemiz için,
//yüzler, onlar ve birler basamaklarına ayırmamız
//gerekmektedir.

//Sayının yüzler basamağı ayrıştırılıyor.
//Bunun için sayıyı, 100'e bölmek yeterli.

//YÜZLER BASAMAĞI:
switch( sayi/100 ) {
case 9: printf( "dokuzyüz" ); break;
case 8: printf( "sekizyüz" ); break;
case 7: printf( "yediyüz" ); break;
case 6: printf( "altıyüz" ); break;
case 5: printf( "beşyüz" ); break;
case 4: printf( "dörtyüz" ); break;
case 3: printf( "üçyüz" ); break;
case 2: printf( "ikiyüz" ); break;
case 1: printf( "yüz" ); break;
}

//Onlar basamağını bulmak için, sayının
//yüze bölümünden kalan değeri, 10'a
//bölüyoruz. Yüzler basamağını bir önceki
//adımda ele aldığımız için, bu adımda,
//sayının yüze bölümünü değil, bölümünden
//kalanı kullandık.

//ONLAR BASAMAĞI:
switch ( (sayi%100)/10 ) {
case 9: printf( "doksan" ); break;
case 8: printf( "seksen" ); break;
case 7: printf( "yetmiş" ); break;
case 6: printf( "altmış" ); break;
case 5: printf( "elli" ); break;
case 4: printf( "kırk" ); break;
case 3: printf( "otuz" ); break;
case 2: printf( "yirmi" ); break;
case 1: printf( "on" ); break;
}

//Birler basamağını bulabilmek için, sayının
//10'a bölümünden kalana bakıyoruz.

//BİRLER BASAMAĞI:
switch ( (sayi%10) ) {
case 9: printf( "dokuz" ); break;
case 8: printf( "sekiz" ); break;
case 7: printf( "yedi" ); break;
case 6: printf( "altı" ); break;
case 5: printf( "beş" ); break;
case 4: printf( "dört" ); break;
case 3: printf( "üç" ); break;
case 2: printf( "iki" ); break;
case 1: printf( "bir" ); break;
}

//Eğer sayı 0 ise, yukarda ki düzeneğe
//uymayacağından, onu ayrıca ele alıyoruz.
if( sayi == 0 )
printf( "sıfır" );

printf( "' şeklinde okunur.\n" );

return 0;

}

Soru 5: Dört basamaklı bir sayının rakamları ters yazılıp, 4 ile çarpılırsa, çıkan sonuç, kendisiyle aynıdır. Dört basamaklı bu sayıyı bulunuz.

Cevap için tıklayınız...


/*
Dört basamaklı bir sayının rakamları, ters yazılıp, 4 ile
çarpılırsa, sayının kendisine eşit olmaktadır. Bu program,
bahsedilen dört basamaklı bu sayıyı bulmaktadır.
*/
#include<stdio.h>
int main( void )
{
//Dört basamaklı bir sayının tersinin dört katına
//eşit olmasını hesaplamamız gerektiğinden, her
//basamağı ayrı ayrı düşünmemiz gerekmektedir.
//Bilinmeyen bu sayıyı, abcd olarak düşünebiliriz.
int a,b,c,d;
int sayi, sayinin_tersi;
for( a = 0; a < 10; a++ )
for( b = 0; b < 10; b++ )
for( c = 0; c < 10; c++ )
for( d = 0; d < 10; d++ ) {
//Burada sayinin degeri bulunmaktadir.
sayi = a * 1000 + b * 100 + c * 10 + d;

//Burada da sayinin tersi hesaplanmaktadir.
sayinin_tersi = d * 1000 + c * 100 + b * 10 + a;

//Sayinin tersinin 4 katinin ilk sayiya
//esit olup olmadigi kontrol ediliyor.
//Ayrica sayinin 0 olmamasi gerekmektedir.
//Bu kontrol de yapilmaktadir.
if( sayi == 4 * sayinin_tersi && sayi != 0 ) {

//Sayi ve uygun olan tersi gosterilir:
printf( "Sayı: %d, tersi: %d\n", sayi, sayinin_tersi );

//return ifadesi programin daha fazla devam
//etmemesi icin burada kullanilmistir.
//Program donguye devam etmez ve burada kesilir.
//return, main fonksiyonunu sonlandirir.
return 0;
}
}
//Uygun bir sayi bulunamazsa, program burada sonlanacaktir.
return 0;
}

Soru 6: Fibonacci serisinin ilk iki elemanı 0 ve 1'dir. Bundan sonra gelen sayılar, kendisinden önceki iki sayının toplamıyla bulunur. Yani seri elemanları 0 1 1 2 3 5 8 13 21 ... şeklinde gitmektedir. Verilecek adım sayısına göre, Fibonnaci serisinin elemanlarını gösterecek bir program yazınız.

Cevap :


/* Fibonacci sayilarini ekrana yazar */

#include<stdio.h>int main( void )
{
int a = 0; /* a[n] */
int b = 1; /* a[n+1] */
int c; /* a[n+2] */
int n;
int i;

printf("Fibonacci serisi kacinci elemana kadar yazilsin> ");
scanf("%d", &n);

for( i = 1; i <= n ; i++ ) {
printf( "%4d. Eleman: %d\n", i, a );
c = a + b;
a = b;
b = c;
}

return 0;
}

Soru 7: Verilecek kenar uzunluğuna göre, yıldız (*) işareti kullanarak kare çizen, bir program yazınız.

Cevap :


/* '*'ler kullanarak kenar uzunlugu verilen kareyi cizer */

#include<stdio.h>
int main( void )
{
int kenar;
int i;
int j;

printf("Karenin kenar uzunlugu: ");
scanf("%d", &kenar);

/* Gecerli bir deger mi */
while((kenar < 0) || (kenar > 20)) {

printf("Lutfen 0 ile 20 arasinda bi deger giriniz.");
printf("Karenin kenar uzunlugu");
scanf("%d", &kenar);
}

/* karenin cizilmesi */
for(i = 1; i <= kenar; i++) {

if(kenar == 0)
break;

/* alt ve üst kenarlarin cizimi */
if((i == 1) || (i == kenar)) {

for(j = 1; j <= kenar; j++)
printf("*");
printf("\n");
continue;
} /* if sonu */

/* sag ve sol kenarlarin cizimi */
for(j = 1; j <= kenar; j++)
if((j == 1) || (j == kenar))
printf("*");
else
printf(" ");

printf("\n");
} /* for sonu */

return 0;
}

Soru 8: Aşağıdaki eşkenar dörtgen çıktısını üretecek bir program yazınız:

*
***
*****
*******
*********
*******
*****
***
*

Cevap :


/* '*'ler yardimiyla eskenar dortgen cizer */

#include<stdio.h>
int main( void )
{
int i, j;

for(i = 1; i <= 5; i++) {
for(j = 1; j <= 9; j++)
if((j <= (9 - (2*i - 1))/2) || (j > (i + 4)))
printf(" ");
else
printf("*");

printf("\n");
}
for(i = 4; i >= 1; i--){
for(j = 1; j <= 9; j++)
if((j <= (9 - (2*i - 1))/2) || (j > (i + 4)))
printf(" ");
else
printf("*");

printf("\n");
}

return 0;
}

Soru 9: Hipotenus'u 500 birime kadar olan dik üçgenlerin, kenar uzunluklarını gösteren bir program yazınız. Kenar uzunlukları, sadece tam sayı olacaktır.

Cevap :


/* Hipotenusu 500'e kadar olan pisagor uclulerini ekrana yazar. */

#include<stdio.h>
int main( void )
{
int a; /* birinci dik kenar */
int b; /* ikinci dik kenar */
int hipotenus;

for(a = 1; a < 500; a++)
for(b = a; b < 500; b++)
for(hipotenus = b+1; hipotenus <= 500; hipotenus++)
if( (a*a + b*b) == hipotenus*hipotenus )
printf("%5d%5d%5d\n", a, b, hipotenus);
return 0;
}
Bu mesajdan alıntı yap
Dram-Like isimli Üye şimdilik offline konumundadır

Dram-Like

Webmaster

Standart
Alt 22-02-2009 #8
C Programlama Dersi - VIII
Bu yazıda öğrenecekleriniz:

- Kısa Devre Değerlendirme

- Önişlemci Komutları

- #define Önişlemci Komutu

- #undef Önişlemci Komutu

- #ifdef ve #ifndef Önişlemci Komutları

- #if, #else, #endif, #elif Önişlemci Komutları

- #include Önişlemci Komutu

Kısa Devre Değerlendirme

Kısa devre değerlendirme, ne yazık ki pek iyi bir çeviri olmadı ve bu yüzden hiçbir anlam ifade etmeyebilir. İngilizce'de, Short Circuit Evaluation olarak geçen bu konu, mantıksal ifadelerle ilgilidir.

Hatırlarsanız, daha önce ki derslerimizde iki farklı AND ve OR operatörü görmüştük. Bu yapılardan biri AND için && işaretini kullanıyorken, diğeri sadece tek & simgesini kullanıyordu. Keza, OR ifadesi bir yerde, || şeklinde gösteriliyorken, diğer yerde, tek bir | simgesiyle ifade edilmekteydi. Bu işaretler, aynı sonucu üretiyor gibi görünseler de, farklı şekilde çalışırlar.

Çift şekilde yazılan operatörler, ( yani && ve || ) kısa devre operatörleridir. İngilizce, Short Circuit Operator olarak isimlendirilirler. Tek sembolle yazılan operatörlerden farkı, işlemleri kısaltmalarıdır.

Bir koşul içersinde AND ( && ) operatörü kullandığınızda, koşulun sol tarafı yanlışsa, sağ tarafı kontrol edilmez. Çünkü artık sağ tarafın doğru veya yanlış olmasının önemi yoktur; sonuç her şekilde yanlış olacaktır.

Benzer bir mantık OR ( || ) operatörü içinde geçerlidir. Eğer sol taraf doğruysa, sağ tarafın kontrol edilmesine gerek yoktur. Çünkü OR operatöründe taraflardan birinin doğru olması durumunda, diğerinin önemi kalmaz ve sonuç doğru döner.

Aşağıdaki örnekleri inceleyelim:
&& Operatörü & Operatörü

#include<stdio.h>
int main( void )
{
int i, j;
i = 0;
j = 5;
if( i == 1 && j++ ) {
printf( "if içersine girdi\n" );
}
else {
printf( "if içersine girmedi\n" );
printf( "i: %d, j: %d\n", i, j );
}
return 0;
}



#include<stdio.h>
int main( void )
{
int i, j;
i = 0;
j = 5;
if( i == 1 & j++ ) {
printf( "if içersine girdi\n" );
}
else {
printf( "if içersine girmedi\n" );
printf( "i: %d, j: %d\n", i, j );
}
return 0;
}

if içersine girmedi
i: 0, j: 5



if içersine girmedi
i: 0, j: 6

Gördüğünüz gibi, program çıktıları birbirinden farklıdır. Bunun sebebi, ilk örnekte, i == 1 koşulu yanlış olduğu için, && operatörünün ifadenin sağ tarafına bakmamasıdır. İkinci örnekteyse, & operatörü, koşulun her iki tarafına da bakar. Bu yüzden, j değişkenine ait değer değişir. Benzer bir uygulamayı, OR için || ve | kullanarak yapabilirsiniz.

ÖNEMLİ NOT: Özetle işlemlerinizi hızlandırmak istiyorsanız; AND kullanacağınız zaman, && operatörüyle çalışın ve yanlış olması muhtemel olan koşulu sol tarafa koyun. Eğer OR operatörü kullanacaksanız, doğru olma ihtimali fazla olan koşulu, ifadenin soluna koyun ve operatör olarak || ile çalışın. Bu şekillde yazılan bir program, kısa devre operatörleri sayesinde, gereksiz kontrolden kaçınarak işlemlerinizi hızlandıracaktır.

Elbette & veya | operatörlerinin kullanılması gereken durumlarda olabilir. Her n'olursa olsun, koşulun iki tarafınında çalışmasını istiyorsanız, o zaman & ve | operatörlerini kullanmanız gerekmektedir.
Önişlemci Komutları

Bir program yazdığınızı düşünün... Bu programda, PI değerini birçok yerde kullanmanız gerekiyor. Siz de PI değeri olması gereken her yere, 3.14 yazıyorsunuz. Oldukça sıkıcı bir iş. İleride PI'yi, 3.141592653 olarak değiştirmek isterseniz daha da sıkıcı hâle dönüşebilir. Veya canınız istedi, printf( ) fonksiyonu yerine ekrana_yazdir( ) kullanmaya niyetlendiniz... İşte bu gibi durumlarda, Önişlemci Komutlarını ( Preprocessor ) kullanırız. Önişlemci komutlarının amacı, bir şeyi başka bir şekilde ifade etmektir.

Konuya devam etmeden önce ufak bir uyarı da bulunmakta yarar var. Önişlemci komutlarını, değişkenler veya fonksiyonlarla karıştırmamak gerekiyor. Değişkenlerin ve fonksiyonların daha dinamik ve esnek bir yapıları varken, önişlemci komutları statiktir. Programınıza direkt bir kod yazdığınızı düşünün. Bu kod herhangi bir şey (sembol, program parçası, sayı, karakter vs...) olabilir. Örneğin, her yerde PI'nin karşılığı olarak 3.14 girmek yerine, PI diye bir sembol tanımlarız ve bunun görüldüğü her yere 3.14'ü koyulmasını isteriz. Önişlemci komutları bu gibi işlerde, biçilmiş kaftandır.
#define Önişlemci Komutu

#define komutu, adından da anlaşılabileceği gibi tanımlama işlemleri için kullanılır. Tanımlama komutunun kullanım mantığı çok basittir. Bütün yapmamız gereken, neyin yerine neyi yazacağımıza karar vermektir. Bunun için #define yazıp bir boşluk bıraktıkan sonra, önce kullanacağımız bir isim verilir, ardından da yerine geçeceği değer.

Altta ki program, PI sembolü olan her yere 3.14 koyacak ve işlemleri buna göre yapacaktır:

/* Çember alanını hesaplar */

#include<stdio.h>
#define PI 3.14
int main( void )
{
int yaricap;
float alan;
printf( "Çemberin yarı çapını giriniz> " );
scanf( "%d", &yaricap );
alan = PI * yaricap * yaricap;
printf( "Çember alanı: %.2f\n", alan );
return 0;
}

Gördüğünüz gibi, PI bir değişken olarak tanımlanmamıştır. Ancak #define komutu sayesinde, PI'nin aslında 3.14 olduğu derleyici (compiler) tarafından kabul edilmiştir. Sadece #define komutunu kullanarak başka şeylerde yapmak mümkündür. Örneğin, daha önce dediğimizi yapalım ve printf yerine, ekrana_yazdir; scanf yerine de, deger_al isimlerini kullanalım:

/* Yarıçapa göre daire alanı hesaplar */

#include<stdio.h>
#define PI 3.14
#define ekrana_yazdir printf
#define deger_al scanf
int main( void )
{
int yaricap;
float alan;
ekrana_yazdir( "Çemberin yarı çapını giriniz> " );
deger_al( "%d", &yaricap );
alan = PI * yaricap * yaricap;
ekrana_yazdir( "Çember alanı: %.2f\n", alan );
return 0;
}

#define komutunun başka marifetleri de vardır. İlerki konularımızda göreceğimiz fonksiyon yapısına benzer şekilde kullanımı mümkündür. Elbette ki, fonksiyonlar çok daha gelişmiştir ve sağladıkları esnekliği, #define tutamaz. Bu yüzden #define ile yapılacakların sınırını çok zorlamamak en iyisi. Ancak yine de bilginiz olması açısından aşağıda ki örneğe göz atabilirsiniz:

/* Istenen sayida, "Merhaba" yazar */

#include<stdio.h>
#define merhaba_yazdir( x ) int i; for ( i = 0; i < (x); i++ ) printf( "Merhaba\n" );
int main( void )
{
int yazdirma_adedi;
printf( "Kaç defa yazdırılsın> " );
scanf( "%d", &yazdirma_adedi );
merhaba_yazdir( yazdirma_adedi );
return 0;
}

#undef Önişlemci Komutu

Bazı durumlarda, #define komutuyla tanımladığımız şeyleri, iptal etmek isteriz. Tanımlamayı iptal etmek için, #undef komutu kullanılır. Örneğin #undef PI yazdığınız da, o noktadan itibaren PI tanımsız olacaktır. #define ile oluşturduğunuz sembolleri belirli noktalardan sonra geçerliliğini iptal etmek veya yeniden tanımlamak için #undef komutunu kullanabilirsiniz.
#ifdef ve #ifndef Önişlemci Komutları

Önişlemci komutlarında bir sembol veya simgenin daha önce tanıtılıp tanıtılmadığını kontrol etmek isteyebiliriz. Tanıtılmışsa, şöyle yapılsın; yok tanıtılmadıysa, böyle olsun gibi farklı durumlarda ne olacağını belirten yapılar gerekebilir. Bu açığı kapatmak için #ifdef (if defined - şayet tanımlandıysa) veya #ifndef (if not defined - şayet tanımlanmadıysa) operatörleri kullanılır.

#include<stdio.h>
#define PI 3.14
int main( void )
{
// Tanımlı PI değeri, tanımsız hâle getiriliyor.
#undef PI

int yaricap;
float alan;
printf( "Çemberin yarı çapını giriniz> " );
scanf( "%d", &yaricap );

// PI değerinin tanımlı olup olmadığı kontrol ediliyor.
#ifdef PI
//PI tanımlıysa, daire alanı hesaplanıyor.
alan = PI * yaricap * yaricap;
printf( "Çember alanı: %.2f\n", alan );
#else
//PI değeri tanımsızsa, HATA mesajı veriliyor.
printf("HATA: Alan değeri tanımlı değildir.\n");
#endif

return 0;
}

Yukardaki örneğe bakacak olursak, önce PI değeri tanımlanıyor ve sonrasında tanım kaldırılıyor. Biz de sürprizlerle karşılaşmak istemediğimizden, PI değerinin tanım durumunu kontrol ediyoruz. Tek başına çalışan biri için gereksiz bir ayrıntı gibi gözükse de, ekip çalışmalarında, bazı şeylerin kontrol edilmesi ve istenmeyen durumlarda, ne yapılacağı belirlenmelidir. Yukarda ki programı şöyle de yazabilirdik:

#include<stdio.h>
int main( void )
{
int yaricap;
float alan;
printf( "Çemberin yarı çapını giriniz> " );
scanf( "%d", &yaricap );

// Şu noktaya kadar tanımlı bir PI değeri bulunmuyor.
// #ifndef opertörü bu durumu kontrol ediyor.
// Eğer tanımsızsa, PI'nin tanımlanması sağlanıyor.
#ifndef PI
#define PI 3.14
#endif

alan = PI * yaricap * yaricap;
printf( "Çember alanı: %.2f\n", alan );

return 0;
}

#if, #else, #endif, #elif Önişlemci Komutları

Bazen bir değerin tanımlanıp, tanımlanmadığını bilmek yetmez. Bazı değerler, bayrak (flag) olarak kullanılır. Yani eğer doğruysa, böyle yapılması lâzım, aksi hâlde böyle olacak gibi... Bazı programlar, önişlemci komutlarından yararlanır. Değişken yerine, önişlemcileri kullanarak tanımlanan simgeler, bu programlarda flag görevi görür.

Konumuza dönersek, #if, #else, #endif yapısı daha önce işlemiş olduğumuz if-else yapısıyla hemen hemen aynıdır. if-elif yapısı da if-else if yapısına benzer. Her ikisinin de genel yazım kuralı aşağıda verilmiştir:
#if - #else Yapısı: #if - #elif Yapısı:

#if koşul
komut(lar)
#else
komut(lar)
#endif



#if koşul 1
komut(lar) 1
#elif koşul 2
komut(lar) 2
.
.
.
#elif koşul n-1
komut(lar) n-1
#else
komut(lar) n
#endif

Bir program tasarlayalım. Bu programda, pi sayısınının virgülden sonra kaç basamağının hesaba katılacağına karar veren bir mekanizma olsun. Soruyu, şu ana kadar gördüğümüz, if - else gibi yapılarla rahatça yapabiliriz. Önişlemci komutuyla ise, aşağıdakine benzer bir sistem oluşturulabilir:

/* Daire alanını hesaplar */

#include<stdio.h>
#define HASSASLIK_DERECESI 2
int main( void )
{
int yaricap;
float alan;
printf( "Çemberin yarı çapını giriniz> " );
scanf( "%d", &yaricap );

// Hassaslık derecesi, pi sayısının virgülden kaç
// basamak sonrasının hesaba katılacağını belirtir.
// Eğer hassaslık derecesi bunlara uymuyorsa, alan
// değeri -1 yapılır.

#if ( HASSASLIK_DERECESI == 0 )
alan = 3 * yaricap * yaricap;
#elif ( HASSASLIK_DERECESI == 1 )
alan = 3.1 * yaricap * yaricap;
#elif ( HASSASLIK_DERECESI == 2 )
alan = 3.14 * yaricap * yaricap;
#else
alan = -1;
#endif

printf( "Çember alanı: %.2f\n", alan );
return 0;
}
Bu mesajdan alıntı yap
Dram-Like isimli Üye şimdilik offline konumundadır

Dram-Like

Webmaster

Standart
Alt 22-02-2009 #9
#include Önişlemci Komutu

#include oldukça tanıdık bir operatördür. Her programımızda, #include önişlemci komutunu kullanırız. Şayet kullanmasak, printf( ) veya scanf( ) gibi fonksiyonları tekrar tekrar yazmamız gerekirdi. #include komutu, programımıza bir başlık dosyasının (header file) dâhil edileceğini belirtir. Bu başlık dosyası, standart giriş çıkış işlemlerini içeren bir kütüphane olabileceği gibi, kendimize ait fonksiyonların bulunduğu bir dosya da olabilir.

Eğer sistem kütüphanelerine ait bir başlık dosyasını programınıza dâhil edeceksek, küçüktür ( < ) ve büyüktür ( > ) işaretlerini kullanırız. Örneğin stdio.h sisteme ait bir kütüphane dosyasıdır ve Linux'ta /usr/include/stdio.h adresinde bulunur. Dolayısıyla stdio.h kütüphanesini programımıza eklerken, #include<stdio.h> şeklinde yazarız. Kendi oluşturduğumuz başlık dosyaları içinse, durum biraz daha farklıdır.

Çalışma ortamımızla aynı klasörde olan bir başlık dosyasını, programımıza eklemek için #include "benim.h" şeklinde yazarız. İlerki derslerimizde, kendi başlık dosyalarımızı oluşturmayı göreceğiz. Ancak şimdilik burada keselim...
Önemli Noktalar...

Konuyu noktalarken, söylemek istediğim bazı şeyler bulunuyor. Olabildiğince, önişlemci komutlarından - #include komutu hariç - uzak durun. Çünkü bu komutlar, esnek bir yapıya sahip değiller ve bu durum, bir noktadan sonra başınızı ağrıtacaktır. Önişlemci komutlarıyla yazılmış kodları takip etmek oldukça zordur ve debug edilemezler. Java gibi gelişmiş dillerde, #define komutu bulunmaz. Modern dillerde, bu yapıdan uzaklaşılmaya başlanmıştır.

Yukarda saydıklarıma rağmen, bazı durumlarda, önişlemci komutlarını kullanmak uygun olabilir. Kaldı ki bu komutların kullanıldığı birçok yer bulunuyor ve biz kullanmasak bile, bilmeye mecbur durumdayız. Sözün özü; bu konuyu es geçmek uygun değil. Ancak üzerine düşmek oldukça gereksiz.

C Programlama Dersi - IX
Bu yazıda öğrenecekleriniz:

- Fonksiyonlar

- main( ) fonksiyonu

- Fonksiyon oluşturma

- Argüman aktarımı

- Yerel ( local ) ve global değişkenler

- return ifadesi

- Konuyla ilgili örnek sorular

Fonksiyonlar

C gibi prosedürel dillerin önemli konularından birisi fonksiyonlardır. Java veya C# gibi dillerde metot (method) ismini alırlar. Adı n'olursa olsun, görevi aynıdır. Bir işlemi birden çok yaptığınızı düşünün. Her seferinde aynı işlemi yapan kodu yazmak oldukça zahmetli olurdu. Fonksiyonlar, bu soruna yönelik yaratılmıştır. Sadece bir kereye mahsus yapılacak işlem tanımlanır. Ardından dilediğiniz kadar, bu fonksiyonu çağırırsınız. Üstelik fonksiyonların yararı bununla da sınırlı değildir.

Fonksiyonlar, modülerlik sağlar. Sayının asallığını test eden bir fonksiyon yazıp, bunun yanlış olduğunu farkederseniz, bütün programı değiştirmeniz gerekmez. Yanlış fonksiyonu düzeltirsiniz ve artık programınız doğru çalışacaktır. Üstelik yazdığınız fonksiyonlara ait kodu, başka programlara taşımanız oldukça basittir.

Fonksiyonlar, çalışmayı kolaylaştırır. Diskten veri okuyup, işleyen; ardından kullanıcıya gösterilmek üzere sonuçları grafik hâline dönüştüren; ve işlem sonucunu diske yazan bir programı baştan aşağı yazarsanız, okuması çok güç olur. Yorum koyarak kodun anlaşılabilirliğini, artırabilirsiniz. Ancak yine de yeterli değildir. İzlenecek en iyi yöntem, programı fonksiyon parçalarına bölmektir. Örneğin, diskten okuma işlemini disten_oku( ) isimli bir fonksiyon yaparken; grafik çizdirme işini grafik_ciz( ) fonksiyonu ve diske yazdırma görevini de diske_yaz( ) fonksiyonu yapabilir. Yarın öbür gün, yazdığınız kodu birileri incelediğinde, sadece ilgilendiği yapıya göz atarak, aradığını çok daha rahat bulabilir. Binlerce satır içinde çalışmaktansa, parçalara ayrılmış bir yapı herkesin işine gelecektir.

Bu yazımızda, fonksiyonları açıklayacağız.
main( ) Fonksiyonu

Şimdiye kadar yazdığımız bütün kodlarda, main( ) şeklinde bir notasyon kullandık. Bu kullandığımız ifade, aslında main( ) fonksiyonudur. C programlama dilinde, bir kodun çalışması main( ) fonksiyonun içersinde olup olmamasına bağlıdır. Bir nevi başlangıç noktası olarak düşünebiliriz. Her programda sadece bir tane main( ) fonksiyonu bulunur. Başka fonksiyonların, kütüphanelerin, kod parçalarının çalıştırılması main( ) içersinde direkt veya dolaylı refere edilmesiyle alakalıdır.

main( ) fonksiyonuna dair bilgimizi pekiştirmek için bir program yazalım. Aşağıdaki çizimi inceleyip, C programlama diliyle bunu çizen programı oluşturalım.

/\
/ \
/ \
/ \
----------
| |
| |
| |
----------

Ev veya kule benzeri bu şekli aşağıdaki, kod yardımıyla gösterebiliriz:

/* Ev sekli cizen program */
#include<stdio.h>
int main( void )
{
printf( " /\\ \n" );
printf( " / \\ \n" );
printf( " / \\ \n" );
printf( " / \\\n" );
printf( "----------\n" );
printf( "| |\n" );
printf( "| |\n" );
printf( "| |\n" );
printf( "----------\n" );

return 0;
}

Programın özel bir yanı yok. '\' simgesi özel olduğu için bundan iki tane yazmamız gerekti. Bunu önceki derslerimizde işlemiştik. Bunun dışında kodun herhangi bir zorluğu olmadığı için açıklamaya girmiyorum. Dikkat etmeniz gereken tek şey, kodun main( ) fonksiyonuyla çalışması.

Bilgilerimizi özetleyecek olursak; main( ) fonksiyonu özel bir yapıdır. Hazırladığımız program, main( ) fonksiyonuyla çalışmaya başlar. main( ) fonksiyonu içersinde yer almayan kodlar çalışmaz.
Fonksiyon Oluşturma

Kendinize ait fonksiyonlar oluşturabilirsiniz. Oluşturacağınız fonksiyonlar, vereceğiniz işlemi yapmakla görevlidir ve çağrıldıkça tekrar tekrar çalışır.

Yukardaki ev örneğine geri dönelim. Her şeyi main( ) içinde, tek bir yerde yazacağımıza, çatıyı çizen ayrı, katı çizen ayrı birer fonksiyon yazsaydık daha rahat olmaz mıydı? Ya da birden çok kat çizmemiz gerekirse, tek tek kat çizmekle uğraşmaktansa, fonksiyon adını çağırmak daha akıllıca değil mi? Bu soruların yanıtı, bizi fonksiyon kullanmaya götürüyor. Şimdi yukarda yazdığımız kodu, iki adet fonksiyon kullanarak yapalım:

/* Ev sekli cizen program */
#include<stdio.h>
// Evin catisini cizen fonksiyon.
void catiyi_ciz( void )
{
printf( " /\\ \n" );
printf( " / \\ \n" );
printf( " / \\ \n" );
printf( " / \\\n" );
printf( "----------\n" );
}

// Evin katini cizen fonksiyon.
void kat_ciz( void )
{
printf( "| |\n" );
printf( "| |\n" );
printf( "| |\n" );
printf( "----------\n" );
}

// Programin calismasini saglayan
// ana fonksiyon.
int main( void )
{
catiyi_ciz( );
kat_ciz( );

return 0;
}

Yazdığımız bu kod, ilk başta elde ettiğimiz çıktının aynısını verir. Ama önemli bir fark içerir:. Bu programla birlikte ilk defa fonksiyon kullanmış olduk!

Fonksiyon kullanmanın, aynı şeyleri baştan yazma zahmetinden kurtaracağından bahsetmiştik. Diyelim ki bize birden çok kat gerekiyor. O zaman kat_ciz( ) fonksiyonunu gereken sayıda çağırmamız yeterlidir.

/* Ev sekli cizen program */
#include<stdio.h>
// Evin catisini cizen fonksiyon.
void catiyi_ciz( void )
{
printf( " /\\ \n" );
printf( " / \\ \n" );
printf( " / \\ \n" );
printf( " / \\\n" );
printf( "----------\n" );
}

// Evin katini cizen fonksiyon.
void kat_ciz( void )
{
printf( "| |\n" );
printf( "| |\n" );
printf( "| |\n" );
printf( "----------\n" );
}

// Programin calismasini saglayan
// ana fonksiyon.
int main( void )
{
catiyi_ciz( );
// 3 adet kat ciziliyor.
kat_ciz( );
kat_ciz( );
kat_ciz( );

return 0;
}

Yukarda yazılı kod, bir üstekinden pek farklı durmasa bile, bu sefer üç katlı bir evin çıktısını elde etmiş olacaksınız.

Yaptığımız örneklerde, kullanılan void ifadesi dikkatinizi çekmiş olabilir. İngilizce bir kelime olan void, boş/geçersiz anlamındadır. C programlama dilinde de buna benzer bir anlam taşır. kat_ciz( ); fonksiyonuna bakalım. Yapacağı iş için herhangi bir değer alması gerekmiyor. Örneğin verilen sayının asallığını test eden bir fonksiyon yazsaydık, bir değişken almamız gerekirdi. Ancak bu örnekte gördüğümüz kat_ciz( ); fonksiyonu, dışardan bir değere gerek duymaz. Eğer bir fonksiyon, çalışmak için dışardan gelecek bir değere ihtiyaç duymuyorsa, fonksiyon adını yazdıktan sonra parantez içini boş bırakabiliriz. Ya da void yazarak, fonksiyonun bir değer almayacağını belirtiriz. ( Sürekli olarak main( ) fonksiyonuna void koymamızın sebebi de bundandır; fonksiyon argüman almaz. ) İkinci yöntem daha uygun olmakla birlikte, birinci yöntemi kullanmanın bir mahsuru yok. Aşağıda bulunan iki fonksiyon aynı şekilde çalışır:

// Evin katini cizen fonksiyon.
// void var

void kat_ciz( void )
{
printf( "| |\n" );
printf( "| |\n" );
printf( "| |\n" );
printf( "----------\n" );
}




// Evin katini cizen fonksiyon.
// void yok

void kat_ciz( )
{
printf( "| |\n" );
printf( "| |\n" );
printf( "| |\n" );
printf( "----------\n" );
}
Bu mesajdan alıntı yap
Dram-Like isimli Üye şimdilik offline konumundadır

Dram-Like

Webmaster

Standart
Alt 23-02-2009 #10
[COLOR=#a52a2a][FONT=Times New Roman]// Evin katini cizen fonksiyon.
// sol ve sag degiskenleri fonksiyon [/FONT]
[FONT=Times New Roman]// parametreleridir.[/FONT]
[FONT=Times New Roman]void kat_ciz( char sol, char sag ) [/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]printf( "%c %c\n", sol, sag );[/FONT]
[FONT=Times New Roman]printf( "%c %c\n", sol, sag );[/FONT]
[FONT=Times New Roman]printf( "%c %c\n", sol, sag );[/FONT]
[FONT=Times New Roman]printf( "----------\n" );[/FONT]
[FONT=Times New Roman]}[/FONT][/COLOR]

[COLOR=#0000ff][FONT=Times New Roman]// Programin calismasini saglayan [/FONT]
[FONT=Times New Roman]// ana fonksiyon. [/FONT]
[FONT=Times New Roman]int main( void )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]char sol_duvar, sag_duvar;[/FONT]
[FONT=Times New Roman]printf( "Kullanılacak karakterler> " );[/FONT]
[FONT=Times New Roman]scanf( "%c%c",&sol_duvar, &sag_duvar );[/FONT]
[FONT=Times New Roman]catiyi_ciz( );[/FONT]

[FONT=Times New Roman]// sol_duvar ve sag_duvar, fonksiyona [/FONT]
[FONT=Times New Roman]// giden argumanlardir. [/FONT]
[FONT=Times New Roman]kat_ciz( sol_duvar, sag_duvar );[/FONT]
[FONT=Times New Roman]kat_ciz( sol_duvar, sag_duvar );[/FONT]
[FONT=Times New Roman]kat_ciz( sol_duvar, sag_duvar );[/FONT]

[FONT=Times New Roman]return 0;[/FONT]
[FONT=Times New Roman]}[/FONT]

[/COLOR][COLOR=#a52a2a][FONT=Times New Roman]Argümanların değer olduğunu unutmamak gerekiyor. Yukardaki örneğimizden, değişken olması gerektiği yanılgısına düşebilirsiniz. Ancak bir fonksiyona değer aktarırken, direkt olarak değeri de yazabilirsiniz. Programı değiştirip, sol_duvar ve sag_duvar değişkenleri yerine, '*' simgesini koyun. Şeklin duvarları, yıldız işaretinden oluşacaktır.[/FONT]

[FONT=Times New Roman]Yazdığımız kat_ciz( ) fonksiyonunu incelemek için, aşağıda bulunan grafiğe göz atabilirsiniz:[/FONT]
[FONT=Times New Roman][Void Function Structure][/FONT]

[FONT=Times New Roman]Şimdi de başka bir örnek yapalım ve verilen herhangi bir sayının tek mi yoksa çift mi olduğuna karar veren bir fonksiyon oluşturalım:[/FONT]

[/COLOR][FONT=Times New Roman][COLOR=blue]/* Sayının tek veya çift olmasını [/COLOR][/FONT]
[FONT=Times New Roman]kontrol eder. */[/FONT]
[FONT=Times New Roman]#include<stdio.h>[/FONT]
[FONT=Times New Roman]void tek_mi_cift_mi( int sayi )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]if( sayi%2 == 0 )[/FONT]
[FONT=Times New Roman]printf( "%d, çift bir sayıdır.\n", sayi );[/FONT]
[FONT=Times New Roman]else[/FONT]
[FONT=Times New Roman]printf( "%d, tek bir sayıdır.\n", sayi );[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]int main( void )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]int girilen_sayi;[/FONT]
[FONT=Times New Roman]printf( "Lütfen bir sayı giriniz> " );[/FONT]
[FONT=Times New Roman]scanf( "%d",&girilen_sayi );[/FONT]
[FONT=Times New Roman]tek_mi_cift_mi( girilen_sayi );[/FONT]

[FONT=Times New Roman]return 0;[/FONT]
[FONT=Times New Roman]}[/FONT]

[FONT=Times New Roman][COLOR=#a52a2a]Yerel ( Local ) ve Global Değişkenler[/COLOR][/FONT]


[COLOR=#a52a2a][FONT=Times New Roman]Kendi oluşturacağınız fonksiyon içersinde, main( ) fonksiyonunda ki her şeyi yapabilirsiniz. Değişken tanımlayabilir, fonksiyon içinden başka fonksiyonları çağırabilir veya dilediğiniz operatörü kullanabilirsiniz. Ancak değişken tanımlamalarıyla ilgili göz ardı etmememiz gereken bir konu bulunuyor. Bir fonksiyon içersinde tanımladığınız değişkenler, sadece o fonksiyon içersinde tanımlıdır. main( ) veya kendinize ait fonksiyonlardan bu değişkenlere ulaşmamız mümkün değildir. main( ) içinde tanımladığınız a isimli değişkenle, kendinize özgü tanımladığınız kup_hesapla( ) içersinde tanımlanmış a isimli değişken, bellekte farklı adresleri işaret eder. Dolayısıyla değişkenlerin arasında hiçbir ilişki yoktur. kup_hesapla( ) içersinde geçen a değişkeninde yapacağınız değişiklik, main( ) fonksiyonundakini etkilemez. Keza, tersi de geçerlidir. Şu ana kadar yaptığımız bütün örneklerde, değişkenleri yerel olarak tanımladığımızı belirtelim.[/FONT]

[FONT=Times New Roman]Yerel değişken dışında, bir de global değişken tipi bulunur. Programın herhangi bir noktasından erişebileceğiniz ve nerede olursa olsun aynı bellek adresini işaret eden değişkenler, global değişkenlerdir. Hep aynı bellek adresi söz konusu olduğun için, programın herhangi bir noktasında yapacağınız değişiklik, global değişkenin geçtiği bütün yerleri etkiler. Aşağıdaki örneği inceleyelim:[/FONT]

[/COLOR][FONT=Times New Roman][COLOR=green]#include<stdio.h>[/COLOR][/FONT][COLOR=green]
[FONT=Times New Roman]// Verilen sayinin karesini hesaplar[/FONT]
[FONT=Times New Roman]void kare_hesapla( int sayi )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]// kare_hesapla fonksiyonunda [/FONT]
[FONT=Times New Roman]// a degiskeni tanimliyoruz. [/FONT]
[FONT=Times New Roman]int a;[/FONT]
[FONT=Times New Roman]a = sayi * sayi;[/FONT]
[FONT=Times New Roman]printf( "Sayının karesi\t: %d\n", a );[/FONT]
[FONT=Times New Roman]}[/FONT][/COLOR]

[FONT=Times New Roman][COLOR=orange]// Verilen sayinin kupunu hesaplar[/COLOR][/FONT][COLOR=orange]
[FONT=Times New Roman]void kup_hesapla( int sayi )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]// kup_hesapla fonksiyonunda [/FONT]
[FONT=Times New Roman]// a degiskeni tanimliyoruz. [/FONT]
[FONT=Times New Roman]int a;[/FONT]
[FONT=Times New Roman]a = sayi * sayi * sayi;[/FONT]
[FONT=Times New Roman]printf( "Sayının küpü\t: %d\n", a );[/FONT]
[FONT=Times New Roman]}[/FONT]
[/COLOR]
[FONT=Times New Roman][COLOR=#a52a2a]i[/COLOR][COLOR=blue]nt main( void )[/COLOR][/FONT][COLOR=blue]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]// main( ) fonksiyonunda [/FONT]
[FONT=Times New Roman]// a degiskeni tanimliyoruz. [/FONT]
[FONT=Times New Roman]int a;[/FONT]
[FONT=Times New Roman]printf( "Sayı giriniz> ");[/FONT]
[FONT=Times New Roman]scanf( "%d",&a );[/FONT]
[FONT=Times New Roman]printf( "Girdiğiniz sayı\t: %d\n", a );[/FONT]
[FONT=Times New Roman]kare_hesapla( a );[/FONT]
[FONT=Times New Roman]// Eger a degiskeni lokal olmasaydi, [/FONT]
[FONT=Times New Roman]// kare_hesapla fonksiyonundan sonra, [/FONT]
[FONT=Times New Roman]// a'nin degeri bozulur ve kup yanlis [/FONT]
[FONT=Times New Roman]// hesaplanirdi. [/FONT]
[FONT=Times New Roman]kup_hesapla( a );[/FONT]
[FONT=Times New Roman]return 0;[/FONT]
[FONT=Times New Roman]}[/FONT]
[/COLOR]
[COLOR=#a52a2a][FONT=Times New Roman]Kod arasına konulan yorumlarda görebileceğiniz gibi, değişkenler lokal olarak tanımlanmasa, a'nin değeri farklı olurdu. Sayının karesini bulduktan sonra, küpünü yanlış hesaplardık. Değişkenler lokal olduğu için, her aşamada farklı bir değişken tanımlandı ve sorun çıkartacak bir durum olmadı. Benzer bir programı global değişkenler için inceleyelim:[/FONT]

[/COLOR][FONT=Times New Roman][COLOR=blue]#include<stdio.h>[/COLOR][/FONT][COLOR=blue]
[FONT=Times New Roman]int sonuc = 0;[/FONT]

[FONT=Times New Roman]// Verilen sayinin karesini hesaplayip,[/FONT]
[FONT=Times New Roman]// global 'sonuc' degiskenine yazar.[/FONT]
[FONT=Times New Roman]void kare_hesapla( int sayi )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]sonuc = sayi * sayi;[/FONT]
[FONT=Times New Roman]}[/FONT]

[FONT=Times New Roman]int main( void )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]// main( ) fonksiyonunda [/FONT]
[FONT=Times New Roman]// a degiskeni tanimliyoruz. [/FONT]
[FONT=Times New Roman]int a;[/FONT]
[FONT=Times New Roman]printf( "Sayı giriniz> ");[/FONT]
[FONT=Times New Roman]scanf( "%d",&a );[/FONT]
[FONT=Times New Roman]printf( "Girdiğiniz sayı\t: %d\n", a );[/FONT]
[FONT=Times New Roman]kare_hesapla( a );[/FONT]
[FONT=Times New Roman]printf("Sayının karesi\t: %d\n", sonuc );[/FONT]
[FONT=Times New Roman]return 0;[/FONT]
[FONT=Times New Roman]}[/FONT]
[/COLOR]
[COLOR=#a52a2a][FONT=Times New Roman]Gördüğünüz gibi, sonuc isimli değişken her iki fonksiyonun dışında bir alanda, programın en başında tanımlanıyor. Bu sayede, fonksiyon bağımsız bir değişken elde ediyoruz.[/FONT]

[FONT=Times New Roman]Global değişkenlerle ilgili dikkat etmemiz gereken bir iki ufak nokta bulunuyor: Global bir değişkeni fonksiyonların dışında bir alanda tanımlarız. Tanımladığımız noktanın altında kalan bütün fonksiyonlar, bu değişkeni tanır. Fakat tanımlanma noktasının üstünde kalan fonksiyonlar, değişkeni görmez. Bu yüzden, bütün programda geçerli olacak gerçek anlamda global bir değişken istiyorsanız, #include ifadelerinin ardından tanımlamayı yapmanız gerekir. Aynı ismi taşıyan yerel ve global değişkenleri aynı anda kullanıyorsak, iş birazcık farklılaşır.[/FONT]

[FONT=Times New Roman]Bir fonksiyon içersinde, Global değişkenle aynı isimde, yerel bir değişken bulunduruyorsanız, bu durumda lokal değişkenle işlem yapılır. Açıkcası, sınırsız sayıda değişken ismi vermek mümkünken, global değişkenle aynı adı vermenin uygun olduğunu düşünmüyorum. Program akışını takip etmeyi zorlaştıracağından, ortak isimlerden kaçınmak daha akıllıca.[/FONT]

[FONT=Times New Roman]Lokal ve global değişkenlere dair son bir not; lokal değişkenlerin sadece fonksiyona özgü olması gerekmez. Bir fonksiyon içersinde 'daha lokal' değişkenleri tanımlayabilirsiniz. Internet'te bulduğum aşağıdaki programı incelerseniz, konuyu anlamanız açısından yardımcı olacaktır.[/FONT]

[/COLOR][FONT=Times New Roman][COLOR=blue]#include<stdio.h>[/COLOR][/FONT][COLOR=blue]
[FONT=Times New Roman]int main( void )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]int i = 4;[/FONT]
[FONT=Times New Roman]int j = 10;[/FONT]

[FONT=Times New Roman]i++;[/FONT]

[FONT=Times New Roman]if( j > 0 ){[/FONT]
[FONT=Times New Roman]printf("i : %d\n",i); /* 'main' icinde tanımlanmis 'i' degiskeni */[/FONT]
[FONT=Times New Roman]}[/FONT]

[FONT=Times New Roman]if (j > 0){[/FONT]
[FONT=Times New Roman]int i=100; /* 'i' sadece bu if blogunda gecerli [/FONT]
[FONT=Times New Roman]olmak uzere tanimlaniyor. */ [/FONT]
[FONT=Times New Roman]printf("i : %d\n",i);[/FONT]
[FONT=Times New Roman]} /* if blogunda tanimlanan ve 100 degerini [/FONT]
[FONT=Times New Roman]tasiyan 'i' degiskeni burada sonlaniyor. */[/FONT]

[FONT=Times New Roman]printf("i : %d\n",i); /* En basta tanimlanan ve 5 degerini tasiyan [/FONT]
[FONT=Times New Roman]'i' degiskenine donuyoruz */[/FONT]
[FONT=Times New Roman]}[/FONT][/COLOR]

[COLOR=#a52a2a][FONT=Times New Roman]return İfadesi[/FONT]

[FONT=Times New Roman]Yazımızın üst kısımlarında fonksiyonların geriye değer döndürebileceğinden bahsetmiştik. Bir fonksiyonun geriye değer döndürüp döndürmemesi, o fonksiyonu genel yapı içersinde nasıl kullanacağınıza bağlıdır. Eğer hazırlayacağınız fonksiyonun, çalışıp, üreteceği sonuçları başka yerlerde kullanmayacaksanız, fonksiyondan geriye değer dönmesi gerekmez. Ancak fonksiyonun ürettiği sonuçları, bir değişkene atayıp kullanacaksanız, o zaman fonksiyonun geriye değer döndürmesi gerekir. Bunun için 'return' ifadesini kullanırız.[/FONT]

[FONT=Times New Roman]Daha önce gördüğümüz geriye değer döndürmeyen fonksiyonları tanımlarken, başına void koyuyorduk. Geriye değer döndüren fonksiyonlar içinse, hangi tipte değer dönecekse, onu fonksiyon adının başına koyuyoruz. Diyelim ki fonksiyonumuz bir tamsayı döndürecekse, int; bir karakter döndürecekse char diye belirtiyoruz. Fonksiyon içersinden neyin döneceğine gelince, burada da return ifadesi devreye giriyor.[/FONT]

[FONT=Times New Roman]Fonksiyonun neresinde olduğu farketmez, return sonuç döndürmek üzere kullanılır. Döndüreceği sonuç, elle girilmiş veya değişkene ait bir değer olabilir. Önemli olan döndürülecek değişken tipiyle, döndürülmesi vaad edilen değişken tipinin birbirinden farklı olmamasıdır. Yani int kup_hesapla( ) şeklinde bir tanımlama yaptıysanız, double tipinde bir sonucu döndüremezsiniz. Daha doğrusu döndürebilirsiniz ama program yanlış çalışır. Tip uyuşmazlığı genel hatalardan biri olduğu için, titiz davranmanızı öğütlerim.[/FONT]

[FONT=Times New Roman]Şimdi return ifadesini kullanabileceğimiz, bir program yapalım. Kullanıcıdan bir sayı girilmesi istensin; girilen sayı asal değilse, tekrar ve tekrar sayı girmesi gereksin:[/FONT]

[/COLOR][FONT=Times New Roman][COLOR=blue]#include<stdio.h>[/COLOR][/FONT][COLOR=blue]

[FONT=Times New Roman]// Verilen sayinin asal olup olmadigina [/FONT]
[FONT=Times New Roman]// bakar. Sayi asalsa, geriye 1 aksi hâlde[/FONT]
[FONT=Times New Roman]// 0 degeri doner. [/FONT]
[FONT=Times New Roman]int sayi_asal_mi( int sayi )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]int i;[/FONT]
[FONT=Times New Roman]for( i = 2; i <= sayi/2; i++ ) {[/FONT]
[FONT=Times New Roman]// Sayi asal degilse, i'ye tam olarak [/FONT]
[FONT=Times New Roman]// bolunur.[/FONT]
[FONT=Times New Roman]if( sayi%i == 0 ) return 0;[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]// Verilen sayi simdiye kadar hicbir [/FONT]
[FONT=Times New Roman]// sayiya bolunmediyse, asaldir ve [/FONT]
[FONT=Times New Roman]// geriye 1 doner.[/FONT]
[FONT=Times New Roman]return 1;[/FONT]
[FONT=Times New Roman]}[/FONT]

[FONT=Times New Roman]// main fonksiyonu[/FONT]
[FONT=Times New Roman]int main( void )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]int girilen_sayi;[/FONT]
[FONT=Times New Roman]int test_sonucu;[/FONT]
[FONT=Times New Roman]do{[/FONT]
[FONT=Times New Roman]printf( "Lütfen bir sayı giriniz> " );[/FONT]
[FONT=Times New Roman]scanf( "%d",&girilen_sayi );[/FONT]
[FONT=Times New Roman]test_sonucu = sayi_asal_mi( girilen_sayi );[/FONT]
[FONT=Times New Roman]if( !test_sonucu ) [/FONT]
[FONT=Times New Roman]printf("Girilen sayı asal değildir!\n");[/FONT]
[FONT=Times New Roman]} while( !test_sonucu );[/FONT]
[FONT=Times New Roman]printf( "Girilen sayı asaldır!\n" );[/FONT]

[FONT=Times New Roman]return 0;[/FONT]
[FONT=Times New Roman]}[/FONT][/COLOR]

[COLOR=#a52a2a][FONT=Times New Roman]Dikkat edilmesi gereken bir diğer konu; return koyduğunuz yerde, fonksiyonun derhâl sonlanmasıdır. Fonksiyonun kalan kısmı çalışmaz. Geriye değer döndürmeye fonksiyonlar için de aynı durum geçerlidir, onlarda da return ifadesini kullanabilirsiniz. Değer döndürsün, döndürmesin yazdığınız fonksiyonda herhangi bir yere 'return;' yazın. Fonksiyonun bu noktadan itibaren çalışmayı kestiğini farkedeceksiniz. Bu fonksiyonu çalıştırmanın uygun olmadığı şartlarda, kullanabileceğiniz bir yöntemdir. Bir kontrol ekranında, kullanıcı adı ve/veya şifresini yanlış girildiğinde, programın çalışmasını anında kesmek isteyebilirsiniz. Böyle bir durumda 'return;' kullanılabilir.[/FONT]

[FONT=Times New Roman]Dersimizi burada tamamlayıp örnek sorulara geçmeden önce, fonksiyonlara ait genel yapıyı incelemenizi öneririm.[/FONT]

[/COLOR][FONT=Times New Roman][COLOR=blue]donus_tipi fonksiyon_adi( alacagi_arguman[lar] )[/COLOR][/FONT][COLOR=blue]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman].[/FONT]
[FONT=Times New Roman].[/FONT]
[FONT=Times New Roman]FONKSİYON İÇERİĞİ [/FONT]
[FONT=Times New Roman]( YAPILACAK İŞLEMLER )[/FONT]
[FONT=Times New Roman].[/FONT]
[FONT=Times New Roman].[/FONT]
[FONT=Times New Roman][return deger][/FONT]
[FONT=Times New Roman]}[/FONT]
[/COLOR]
[FONT=Times New Roman][COLOR=red]NOT: [/COLOR][COLOR=#a52a2a]Köşeli parantez gördüğünüz yerler opsiyoneldir. Her fonksiyonda yazılması gerekmez. Ancak oluşturacağınız fonksiyon yapısına bağlı olarak yazılması şartta olabilir. Mesela dönüş tipi olarak void dışında bir değişken tipi belirlediyseniz, return koymanız gerekir.[/COLOR][/FONT]
[FONT=Times New Roman][COLOR=blue]Örnek Sorular[/COLOR][/FONT]

[FONT=Times New Roman][COLOR=red]Soru 1c programlama/COLOR][COLOR=#a52a2a] Kendisine argüman olarak verilen bir tamsayıyı tersine çevirip, sonucu ekrana yazacak bir fonksiyon yazınız.[/COLOR][/FONT]

[FONT=Times New Roman][COLOR=red]Cevap[/COLOR][COLOR=#a52a2a] için tıklayınız...[/COLOR][/FONT]

[FONT=Times New Roman][COLOR=green]// Verilen sayının tersini ekrana yazar.[/COLOR][/FONT][COLOR=green]
[FONT=Times New Roman]void sayi_tersini_bul( int sayi )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]while( sayi>0 ) {[/FONT]
[FONT=Times New Roman]printf( "%d", sayi%10 );[/FONT]
[FONT=Times New Roman]sayi /= 10;[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]printf("\n");[/FONT]
[FONT=Times New Roman]}[/FONT]

[FONT=Times New Roman]Soru 2: Kendisine argüman olarak verilen bir tamsayıyı tersine çevirip, sonucu döndürecek bir fonksiyon yazınız.[/FONT]

[FONT=Times New Roman]Cevap için tıklayınız...[/FONT]

[FONT=Times New Roman]// Verilen sayının tersini geriye dondurur.[/FONT]
[FONT=Times New Roman]int sayi_tersini_bul( int sayi )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]int en_sag_rakam;[/FONT]
[FONT=Times New Roman]int sonuc = 0;[/FONT]
[FONT=Times New Roman]while( sayi>0 ) {[/FONT]
[FONT=Times New Roman]en_sag_rakam = sayi%10;[/FONT]
[FONT=Times New Roman]sonuc = sonuc * 10 + en_sag_rakam;[/FONT]
[FONT=Times New Roman]sayi /= 10;[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]return sonuc;[/FONT]
[FONT=Times New Roman]} [/FONT]
[/COLOR]
[FONT=Times New Roman][COLOR=red]Soru 3c programlama/COLOR][COLOR=#a52a2a] En ve boy parametrelerine göre, '*' simgeleriyle dikdörtgen çizen bir fonksiyon yazınız.[/COLOR][/FONT]

[FONT=Times New Roman][COLOR=red]Cevap[/COLOR][COLOR=#a52a2a] için tıklayınız...[/COLOR][/FONT]

[COLOR=#a52a2a][FONT=Times New Roman]// Verilen olculere gore, dortgen cizer[/FONT]
[FONT=Times New Roman]void dortgen_ciz( int en, int boy )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]int i, j;[/FONT]
[FONT=Times New Roman]for( i = 0; i < boy; i++) {[/FONT]
[FONT=Times New Roman]for( j = 0; j < en; j++ ) {[/FONT]
[FONT=Times New Roman]printf("*");[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]printf("\n");[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]} [/FONT]

[/COLOR][FONT=Times New Roman][COLOR=red]Soru 4c programlama/COLOR] Kendisine verilen iki sayının OBEB (Ortak Bölenlerin En Büyüğü) değerini hesaplayıp, geriye döndüren fonksiyonu yazınız.[/FONT]

[FONT=Times New Roman][COLOR=red]Cevap[/COLOR] için tıklayınız...[/FONT]

[FONT=Times New Roman][COLOR=green]// Verilen iki sayının OBEB'ini bulan fonksiyon[/COLOR][/FONT][COLOR=green]
[FONT=Times New Roman]int obeb_bul( int sayi_1, int sayi_2 )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]int obeb = 1;[/FONT]
[FONT=Times New Roman]int bolen = 2;[/FONT]
[FONT=Times New Roman]while( sayi_1 > 1 || sayi_2 > 1 ) {[/FONT]
[FONT=Times New Roman]// Sayilardan her ikiside, bolen [/FONT]
[FONT=Times New Roman]// degiskenine bolundugu takdirde, [/FONT]
[FONT=Times New Roman]// obeb hesabina katilir.[/FONT]
[FONT=Times New Roman]if( sayi_1 % bolen == 0 &&[/FONT]
[FONT=Times New Roman]sayi_2 % bolen == 0 ) {[/FONT]
[FONT=Times New Roman]obeb *= bolen;[/FONT]
[FONT=Times New Roman]sayi_1 /= bolen;[/FONT]
[FONT=Times New Roman]sayi_2 /= bolen;[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]else if( sayi_1 % bolen == 0 ) {[/FONT]
[FONT=Times New Roman]sayi_1 /= bolen;[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]else if( sayi_2 % bolen == 0 ) {[/FONT]
[FONT=Times New Roman]sayi_2 /= bolen;[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]else {[/FONT]
[FONT=Times New Roman]bolen++;[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]return obeb;[/FONT]
[FONT=Times New Roman]}[/FONT][/COLOR]

[FONT=Times New Roman][COLOR=red]Soru 5: [/COLOR]Kendisine verilen iki sayının OKEK (Ortak Katların En Küçüğü) değerini hesaplayıp, geriye döndüren fonksiyonu yazınız.[/FONT]

[FONT=Times New Roman][COLOR=red]Cevap[/COLOR] için tıklayınız...[/FONT]

[FONT=Times New Roman][COLOR=green]// Verilen iki sayının okekini bulan fonksiyon[/COLOR][/FONT][COLOR=green]
[FONT=Times New Roman]int okek_bul( int sayi_1, int sayi_2 )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]int okek = 1;[/FONT]
[FONT=Times New Roman]int bolen = 2;[/FONT]
[FONT=Times New Roman]while( sayi_1 > 1 || sayi_2 > 1 ) {[/FONT]
[FONT=Times New Roman]// Sayilardan her ikiside, bolen [/FONT]
[FONT=Times New Roman]// degiskenine bolunuyorsa [/FONT]
[FONT=Times New Roman]if( sayi_1 % bolen == 0 &&[/FONT]
[FONT=Times New Roman]sayi_2 % bolen == 0 ) {[/FONT]
[FONT=Times New Roman]okek *= bolen;[/FONT]
[FONT=Times New Roman]sayi_1 /= bolen;[/FONT]
[FONT=Times New Roman]sayi_2 /= bolen;[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]// Sayilardan ilki, bolen [/FONT]
[FONT=Times New Roman]// degiskenine bolunuyorsa [/FONT]
[FONT=Times New Roman]else if( sayi_1 % bolen == 0 ) {[/FONT]
[FONT=Times New Roman]okek *= bolen;[/FONT]
[FONT=Times New Roman]sayi_1 /= bolen;[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]// Sayilardan ikincisi, bolen [/FONT]
[FONT=Times New Roman]// degiskenine bolunuyorsa [/FONT]
[FONT=Times New Roman]else if( sayi_2 % bolen == 0 ) {[/FONT]
[FONT=Times New Roman]okek *= bolen;[/FONT]
[FONT=Times New Roman]sayi_2 /= bolen;[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]else {[/FONT]
[FONT=Times New Roman]bolen++;[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]}[/FONT]
[FONT=Times New Roman]return okek;[/FONT]
[FONT=Times New Roman]} [/FONT]
[/COLOR]

[FONT=Times New Roman][size=14pt][COLOR=blue]C Programlama Dersi - X[/COLOR][/size][/FONT]


[FONT=Times New Roman][size=12pt][COLOR=blue]Bazı Aritmetik Fonksiyonlar[/COLOR][/size][/FONT]

[FONT=Times New Roman]Geçen dersimizde, fonksiyonları ve bunları nasıl kullanılacağını görmüştük. Ayrıca kütüphanelerin hazır fonksiyonlar içerdiğinden bahsetmiştik. Bazı matematiksel işlemlerin kullanımı sıkça gerekebileceği için bunları bir liste hâlinde vermenin uygun olduğuna inanıyorum. Böylece var olan aritmetik fonksiyonları tekrar tekrar tanımlayarak zaman kaybetmezsiniz.[/FONT]

[FONT=Times New Roman]* double ceil( double n ) : Virgüllü n sayısını, kendisinden büyük olan ilk tam sayıya tamamlar. Örneğin ceil(51.4) işlemi, 52 sonucunu verir.[/FONT]
[FONT=Times New Roman]* double floor( double n ) : Virgüllü n sayısının, virgülden sonrasını atarak, bir tam sayıya çevirir. floor(51.4) işlemi, 51 sayısını döndürür.[/FONT]
[FONT=Times New Roman]* double fabs( double n ) : Verilen n sayısının mutlak değerini döndürür. fabs(-23.5), 23.5 değerini verir.[/FONT]
[FONT=Times New Roman]* double fmod( double a, double b ) : a sayısının b sayısına bölümünden kalanı verir. (Daha önce gördüğümüz modül (%) operatörü, sadece tam sayılarda kullanılırken, fmod fonksiyonu virgüllü sayılarda da çalışır.)[/FONT]
[FONT=Times New Roman]* double pow( double a, double b ) : Üstel değer hesaplamak için kullanılır; ab değerini verir.[/FONT]
[FONT=Times New Roman]* double sqrt( double a ) : a'nın karekökünü hesaplar.[/FONT]

[FONT=Times New Roman]Yukarda verilmiş fonksiyonlar, matematik kütüphanesi ( math.h ) altındadır. Bu fonksiyonlardan herhangi birini kullacağınız zaman, program kodununun başına #include<math.h> yazmalısınız. Ayrıca derleyici olarak gcc'yle çalışıyorsanız, derlemek için -lm parametresini eklemeniz gerekir. (Örneğin: "gcc test.c -lm" gibi...)[/FONT]
[FONT=Times New Roman]Bellek Yapısı ve Adresler[/FONT]

[FONT=Times New Roman]Şimdiye kadar değişken tanımlamayı gördük. Bir değişken tanımlandığında, arka plânda gerçekleşen olaylara ise değinmedik. Hafızayı küçük hücrelerden oluşmuş bir blok olarak düşünebilirsiniz. Bir değişken tanımladığınızda, bellek bloğundan gerekli miktarda hücre, ilgili değişkene ayrılır. Gereken hücre adedi, değişken tipine göre değişir. Şimdi aşağıdaki kod parçasına bakalım:[/FONT]

[FONT=Times New Roman][COLOR=blue]#include<stdio.h>[/COLOR][/FONT][COLOR=blue]
[FONT=Times New Roman]int main( void )[/FONT]
[FONT=Times New Roman]{[/FONT]
[FONT=Times New Roman]// Degiskenler tanımlanıyorc programlama/FONT]
[FONT=Times New Roman]int num1, num2;[/FONT]
[FONT=Times New Roman]float num3, num4;[/FONT]
[FONT=Times New Roman]char i1, i2;[/FONT]

[FONT=Times New Roman]// Degiskenlere atama yapiliyorc programlama/FONT]
[FONT=Times New Roman]num1 = 5;[/FONT]
[FONT=Times New Roman]num2 = 12;[/FONT]
[FONT=Times New Roman]num3 = 67.09;[/FONT]
[FONT=Times New Roman]num4 = 1.71;[/FONT]
[FONT=Times New Roman]i1 = 'H';[/FONT]
[FONT=Times New Roman]i2 = 'p';[/FONT]

[FONT=Times New Roman]return 0;[/FONT]
[FONT=Times New Roman]}[/FONT][/COLOR]

[FONT=Times New Roman]Yukarda bahsettiğimiz hücrelerden oluşan bellek yapısını, bu kod parçası için uygulayalım. Değişken tiplerinden int'in 2 byte, float'un 4 byte ve char'ın 1 byte yer kapladığını kabul edelim. Her bir hücre 1 byte'lık alanı temsil etsin. Değişkenler için ayrılan hafıza alanı, 4300 adresinden başlasın. Şimdi bunları temsili bir şekle dökelim:[/FONT]
Bu mesajdan alıntı yap
Sponsor Links

Grafikerler.net Reklamları

Cevapla

Tags
c programlama dersi

Benzer Konular
Konu Konu Bilgileri Forum Cevaplar Son Mesaj
İstanbul' da web tasarımı web programlama ile ilgili iş aramaktayım asit Sonuçlanan İlanlar 11 09-05-2011 13:31:07
C Programlama Dilinin Tarihi Dram-Like Visual basic , Delphi , C , C++ 0 22-02-2009 23:10:37
Web programlama, web tasarım, gazete ve dergi tasarımları işleri arıyorum incidesign Sonuçlanan İlanlar 1 12-12-2008 18:15:52
Freelance web tasarım ve programlama yapıyoruz include Sonuçlanan İlanlar 1 28-11-2008 12:25:32
PIc Basic Pro ile Programlama graphic00 Visual basic , Delphi , C , C++ 4 23-02-2008 21:59:10

Kapat
Şifremi Unuttum?