HARİTA MÜHENDİSLERİ İÇİN C DİLİ UYGULAMALARI
Transkript
HARİTA MÜHENDİSLERİ İÇİN C DİLİ UYGULAMALARI
HARİTA MÜHENDİSLERİ İÇİN C DİLİ UYGULAMALARI C BİLGİSAYAR BİLGİSAYAR PROGRAMLAMA DERSLERİ İÇİN UYGULAMALAR HAZIRLAYAN Prof.Dr. İ. Öztuğ BİLDİRİCİ İÇİNDEKİLER 1. PROGRAMLAMA ORTAMI ...................................................................................................3 1.1 Proje Klasörü .................................................................................................................3 1.2 Visual Studio .NET EXPRESS 2010.............................................................................5 2. BASİT PROGRAMLAR .........................................................................................................10 2.1 İlk Program ..................................................................................................................10 2.2 printf ile hesaplama......................................................................................................10 2.3 Tam Sayılarla Hesaplama ............................................................................................11 2.4 Reel Sayılarla Hesaplama ............................................................................................11 2.5 Formatlı Sayı Gösterimi...............................................................................................12 2.6 İki nokta arasındaki kenar hesabı.................................................................................13 2.7 İki Nokta Arasında Açıklık Açısı Hesabı.....................................................................14 2.8 for Çevrimi ile Toplama...............................................................................................15 2.9 Faktöriyel .....................................................................................................................16 2.10 İç İçe for Çevrimi: Çarpım Tablosu Programı .............................................................17 2.11 Alan Hesabı..................................................................................................................17 2.12 e Sayısının Hesabı........................................................................................................19 3. KARAKTER, DİZİ ve POINTER KULLANILAN ÖRNEKLER ..........................................19 3.1 Dizi Kullanarak Alan Hesabı .......................................................................................19 3.2 Pointer Kullanımı.........................................................................................................20 3.3 Karakter Dizileri Örneği ..............................................................................................20 4. FONKSİYON KULLANILAN PROGRAMLAR...................................................................22 4.1 Fonksiyonlara Değer Aktarma .....................................................................................22 4.2 Açıklık Açısının Fonksiyon Olarak Programlanması ..................................................23 4.3 Açıklık Açısı ve Kenarı Birlikte Döndüren Fonksiyon................................................25 4.4 Fonksiyonlar Arası Dizi Aktarma ................................................................................26 4.5 Fonksiyon Olarak Alan Hesabı ....................................................................................27 İ.Ö.BİLDİRİCİ, 02.04.12 1 5. DOSYA KULLANIMI ............................................................................................................28 5.1 Dosyadan Okuma.........................................................................................................29 5.2 Dosyaya Yazma ...........................................................................................................30 5.3 İki Boyutlu Dizilerle Çalışma: Matris Çarpımı............................................................31 6. İLERİ TEKNİKLER................................................................................................................33 6.1 Struct, Union ve Typedef .............................................................................................33 6.2 Struct ve Dosya Kullanımı...........................................................................................35 6.3 Komut Satırından Parametre Almak ............................................................................36 6.4 Sisteme Komut Göndermek .........................................................................................37 6.5 Header File Kullanmak ................................................................................................38 7. C++ ÖRNEKLERİ...................................................................................................................39 7.1 Ekrandan Veri Giriş Çıkışı...........................................................................................39 7.2 Dosya İşlemleri ............................................................................................................40 7.3 Nesneye Yönelik Programlama ...................................................................................41 İ.Ö.BİLDİRİCİ, 02.04.12 2 1. PROGRAMLAMA ORTAMI Metinde verilen uygulamalar herhangi bir yazılım geliştirme ortamına bağlı değildir. Laboratuar uygulamalarında yazılım geliştirme ortamı olarak Microsoft Visual Studio 6.0 ya da Microsoft Visual Studio.Net kullanılmaktadır. Bu bölümde her iki ortamda da “console application” (komut satırından çalışan program) oluşturma konusunda kısaca bilgi verilecektir. Günümüzde kullanılan tüm yazılım geliştirme ortamları proje mantığına göre çalışırlar. Proje mantığında proje dosyasında projeyi oluşturan kod dosyalarının adresleri ve proje ile ilgili genel ayarlamalar saklanır. Kod dosyaları yanında başka dosyalarda oluştuğundan proje bir klasörde saklanır. 1.1 Proje Klasörü Projeniz için ilk olarak Windows Explorer (Windows Gezgini) ile bir klasör oluşturun. Windows Explorer iki şekilde açılabilir: 1. Masaüstünde My Computer ikonuna sağ tuş ile tıklayın . Burada “Explore” (Araştır) seçin. 2. Windows tuşu ve “e” tuşuna birlikte basın. Windows tuşu klavyede sol tarafta Ctrl ve Alt tuşları arasındaki tuştur. Windows tuşu Ctrl Alt Aşağıdaki şekilde Windows Explorer penceresi görülmektedir. Pencerenin sol tarafında bilgisayarınızdaki kayıt ortamları (disket, sabit diskler, CD, masaüstü vb). Sağ tarafta ise sol tarafta seçilen elemanın içeriği görülmektedir. Çalışma klasörü olarak d:\harita\xxxxxxxxx\prjy (x’ler yerine numaranızı yazınız, y yerine proje no yazınız) kullanılacaktır. Klasör açmak için sol pencerede D diskini seçin sağ pencerede boş alanda farenin sağ tuşuna basın “New Folder” (Yeni Klasör) seçin. Kullandığınız bilgisayarda D diski yok ise aynı işlemi C diskinde yapınız. Bu anda “New Folder” olarak adlandırılmış bir klasör oluşacaktır. Bu yazı seçilmiş durumda iken (karartılmış durumda) klavyeden klasör ismini girip enter tuşuna basın. Klasör ismi değişmiş olacaktır. Fare ile çift tıklayarak bu klasörü açabilirsiniz. Klasör ismi olarak “harita” girerken mutlaka küçük harflerle yazınız! İ.Ö.BİLDİRİCİ, 02.04.12 3 Disket Sabit diskler CD Bu alanda farenin sağ tuşu ile tıklayın! Klasörler açılmış ise yeniden açmaya çalışmayınız! Örneğin harita klasörü varsa açın, içinde numaranız olup olmadığına bakın yoksa açın. İşlemi doğru yapmış iseniz Windows Explorer penceresi aşağıdaki gibi görünecektir. Pencereyi minimize edip programlama ortamını çalıştırın. İ.Ö.BİLDİRİCİ, 02.04.12 4 Pencereyi minimize etmek için bu ikona tıklayın! Sağ pencerede daha sonra kendi klasörünüz altında oluşturacağınız proje klasörünüzü diskete kopyalamak için sol pencerede proje klasörü üzerinde farenin sağ tuşuna tıklayın. Açılan menüden “Send to Floppy” seçin. Klasörü seçip, sürükleyip disket sürücü (Floppy A:) ikonu üzerine bırakarak da aynı işlemi yapabilirsiniz. Disketten proje klasörü kopyalamak için ise D diskinde açtığınız klasör (numaranız) görünürken disket sürücü (Floppy A:) ikonuna tıklayın sağ tarafta disketin içeriği görünecektir. Buradan proje klasörünü seçin, sürükleyip D diskinde açtığınız klasöre (numaranız) sürükleyin. 1.2 Visual Studio .NET EXPRESS 2010 Laboratuarda VisualStudio.NET yüklü ise bu bölümdeki açıklamaları takip ediniz. VisualStudio6.0 kullanılıyorsa bu bölümü atlayabilirsiniz. Start (Başlat) > Programs (Programlar) > Microsoft Visual C++ 2010 Express seçerek programı çalıştırın. Yeni projeye başlamak için File > New > Project ile aşağıdaki pencerenin görüntülenmesini sağlayın. İ.Ö.BİLDİRİCİ, 02.04.12 5 Installed templates kısmından Win32 seçin, sağ taraftaki pencereden Win32 Console Application seçin. Location kutusunun yanındaki butona (Browse...) basarak açmış olduğunuz klasörü gösterin (D:\HARITA\), name olarak “proje1” girin. Create directory for solution kutusunu işaretlemeyin! OK butonuna basın. Next butonuna bastıktan sonra gelen pencerede Empty Project seçin. İ.Ö.BİLDİRİCİ, 02.04.12 6 Projeniz açılınca, görünüm aşağıdaki gibi olmalıdır. Sol tarafta bulunan Solution Explorer penceresinde Surce Files ikonuna farenin sağ tuşu ile tıklayın, açılan penceren add new item seçin. İ.Ö.BİLDİRİCİ, 02.04.12 7 C++ File seçin ve dosya adı olarak proje1 (ya da başka bir isim) verin. Kod dosyası eklendikten sonra dosya adının üzerine farenin sağ tuşu ile tıklayın. Açılan menüden rename seçerek dosyanın uzantısını c yapın. İ.Ö.BİLDİRİCİ, 02.04.12 8 Benzer şekilde projenize başlık dosyası da (Header File) ekleyebilirsiniz. Yazdığınız kodu derlemek ve bağlamak için (compile & link) build menüsünden build ... (kısayol F7), kodu çalıştırmak için ise Debug menüsünden Start Without Debugging ... (kısayol Ctrl F5) seçilir. Projenizi kaydetmek için File > Save all seçin. Projenizi sık sık kaydetmeniz sizin yararınızadır! İ.Ö.BİLDİRİCİ, 02.04.12 9 Dikkat: Bir projede yalnızca bir main fonksiyonu olabilir. Bir programı bitirip yeni bir programa geçmek için yeni bir proje oluşturmak gerekir. Önceden kaydettiğiniz projenizi açmak için proje klasöründe oluşan vcxproj ya da sln uzantılı dosyayı (örneğin proje1.sln) açınız. Kod dosyasını (örneğin proje1.c) tıklayarak açmayınız!!! Projenizi yedeklerken geçici olarak proje klasörü altında oluşturulan ve diskte fazla yer kaplayan Debug klasörünü silebilirsiniz. 2. BASİT PROGRAMLAR 2.1 İlk Program Ekrana “Merhaba” mesajı yazdıran bir program kodu aşağıdaki gibidir: /*prg01*/ #include <stdio.h> main() { printf("\nMerhaba"); } yukarıdaki kodu inceleyelim: • • • • • • include tanımlamaları hemen her C programının başında yer alır. Burada programda kullanılan fonksiyonların hangi kütüphaneden alınacağı bildirilir. { ve } ile bir programlama bloğu tanımlanır. Programlama blokları içi içe kullanılabilir. printf ekranda veri görüntülemek için kullanılan temel C fonksiyonlarından biridir. Her ifade ; ile sonlandırılır. C dilinde bir program fonksiyonlardan (alt program parçacıklarından) oluşur. Bir programda en az bir fonksiyon olmak zorundadır. Programın çalışmaya başlayacağı fonksiyon “main” olarak adlandırılır. Bu ad değiştirilemez. Bu bağlamda bir program tek bir fonksiyondan oluşuyorsa o fonksiyonun adı “main” olmak zorundadır. /* ve */ işaretleri arasında kalan bölüm derleyici tarafından dikkate alınmaz. Bu bölüme program hakkında notlar yazılabilir. 2.2 printf ile hesaplama printf fonksiyonu altında hesaplama da yapmak mümkündür: /*prg02*/ #include <stdio.h> /* printf fonksiyonu ile hesaplama */ main() { printf("\n12*2=%i",12*2); printf("\n12/2=%i",12/2); } Buradaki %i ifadesi ile ilgili yerde integer tipli bir değişken görüntüleneceği belirtilmektedir. \n ile ekranda imlecin bir alt satıra geçmesi sağlanır. \t tab anlamında olup imleci sekiz boşluk sağa öteler, \a ise alarm anlamında olup kısa bir ses çalınmasını sağlar. Programın çalışması sonucunda aşağıdaki gibi bir ekran görüntüsü elde edilir: 12*2=24 İ.Ö.BİLDİRİCİ, 02.04.12 10 12/2=6 2.3 Tam Sayılarla Hesaplama Verilen iki sayının toplamını, çıkarmasını, çarpmasını yapan bir program için aşağıdaki kod kullanılabilir: /*prg03*/ #include <stdio.h> int main() { int x,y; printf("\n\tHesaplayici\n"); printf("\nx="); scanf("%i",&x); printf("\ny="); scanf("%i",&y); printf("\n\nx+y=%i\tx-y=%i",x+y,x-y); printf("\n\nx*y=%i\tx/y=%i",x*y,x/y); return 0; } Yukarıdaki kodu kısaca inceleyelim. İlk olarak integer (tam sayı) tipinde x ve y değişkenleri tanımlanmıştır. Önceki kodlardan farklı olarak printf içerisinde \t kullanılmıştır. Bunun anlamı ekranda kürsörün sekiz karakter sağa ötelenmesidir. Bunu klavyeden tab tuşuna basılmış gibi düşünebiliriz. scanf fonksiyonunda ise ilk olarak tırnak içerisinde ekrandan okunacak değerin formatı belirtilir. Burada %i bir tamsayı değerin okunacağı anlamına gelir. & işareti ise ileride ayrıntıları verilecek olarak pointer anlamındadır. Burada sadece &x kodunun x değişkenine bellekte ayrılan adresi gösterdiğinin bilinmesi yeterlidir. main fonksiyonunun önünde yer alan “int” bildirimi main fonksiyonunun geriye tamsayı döndürdüğünü belirtmektedir. Geriye döndürülen değer son satırda return fonksiyonu ile belirtilir. Bu değer bu program için 0 olarak belirlenmiştir. Fonksiyonun geriye bir değer döndürmediği “int” yerine “void” ile belirtilebilir. Ancak main fonksiyonu için void bildirimi LINUX gcc derleyicisi tarafından kabul edilmez. 2.4 Reel Sayılarla Hesaplama Tamsayılarla hesap yapan program (prg03) bölme işleminde tam bölünme olmaması durumunda bölme sonucunun ondalıklı kısımlarını vermez. Ondalıklı kısımları elde etmek için reel sayılarla işlem yapılmalıdır. Bu amaçla C iki değişken tipi içermektedir. Reel sayılar için kullanılan değişken tiplerinden float 4 byte, double 8 byte uzunluğundadır. prg03 kodunu bir kez de float tipi kullanarak yazabiliriz. /*prg04*/ #include <stdio.h> int main() { float x,y; printf("\n\tHesaplayici\n"); printf("\nx="); scanf("%f",&x); printf("\ny="); scanf("%f",&y); printf("\n\nx+y=%f\nx-y=%f",x+y,x-y); printf("\n\nx*y=%f\nx/y=%f",x*y,x/y); return 0; } İ.Ö.BİLDİRİCİ, 02.04.12 11 scanf ve printf fonksiyonlarında bu kez %i yerine %f geldiğini görüyoruz. %f float değişkenler için kullanılan format tanımlamasıdır. Bu kodu çalıştırdığımızda sayıların ondalık kısımlarının da görüntülendiğini görürüz. Aynı kodu double tipi kullanarak yazmak gerekirse, float yerine double %f yerine ise %lf kullanılması gerekir. Reel sayı kullanılması gereken programlarda yeterli hesap inceliğini riske atmamak için genel olarak float değil double değişken tipi tercih edilir. 2.5 Formatlı Sayı Gösterimi Verilen üç sayının toplamını ve ortalamasını bulan bir program yazarak, sonuçların iki basamaklı olarak gösterilmesi sağlayalım. /*prg05*/ #include <stdio.h> int main() { double top=0.0,sayi; printf("\n\tHesaplayici\n"); printf("\n1.sayi="); scanf("%lf",&sayi); top=top+sayi; printf("\n2.sayi="); scanf("%lf",&sayi); top=top+sayi; printf("\n3.sayi="); scanf("%lf",&sayi); top=top+sayi; printf("\ntoplam=%.2lf",top); top=top/3; printf("\nortalama=%.2lf",top); return 0; } Değişken tanımlamalarında, double top=0.0 ifadesi top adlı değişkenin başlangıç değerinin sıfır olarak atandığını ifade etmektedir. C dilinde değişkenlere başlangıç değeri vermek çoğu zaman gerekli ve yararlıdır. Çünkü başlangıç değeri belirtilmemiş değişkenlerin programın başlama anındaki değerleri kullanılan derleyiciye göre sıfır olmayabilir. C bu açıdan diğer pek çok programlama dilinden ayrılır. top=top+sayi şeklinde bir ifade matematiksel açıdan geçersiz olarak düşünülebilir. Matematiksel olarak bu eşitliğin sağlanabilmesi için sayi değişkeninin sıfıra eşit olması gerekir. Ancak buradaki = işareti eşitlik anlamında değil değer ataması anlamında kullanılmıştır. Bu ifade bilgisayar programlama açısından “top değişkeninin halihazırdaki değerine sayi değişkeninin değeri ekle ve elde edilen değeri tekrar top değişkenine ata” şeklinde anlaşılmalıdır. Bu mantıktan hareketle neden top değişkenine başlangıç değeri atandığı daha kolay anlaşılabilir. printf fonksiyonlarında kullanılan %.2f format bildirimleri, ilgili değişkenin değerinin ondalık kısmının iki basamak olarak gösterilmesini sağlar. Printf fonksiyonunda kullanılan format bildirimleri şunlardır: d o x u c s f desimal oktal heksadesimal unsigned (işaretsiz) karakter string (karakter katarı) float (kayar nokta) İ.Ö.BİLDİRİCİ, 02.04.12 12 Bu harfler, bir yüzde işaretinden sonra kullanırlar. Bu iki harf arasına şunlar ilave edilebilir: (n) . (m) l sahasının içinde sola dayanmış minimum saha uzunluğunu belirler n ile m yi birbirinden ayırır float tipi için noktadan sonraki hane sayısı 'long' tipi olduğunu belirtmek için Değişik formatlı gösterimler için aşağıdaki programı çalıştırıp inceleyin. /*prg06*/ #include <stdio.h> int main() { int a; long int b; short int c; unsigned int d; char e; float f; double g; a b c d e f g = = = = = = = /* basit tamsayı tipi /* uzun tamsayı tipi /* kısa tamsayı tipi /* işaretsiz (+ - siz) tamsayı /* karakter tipi /* reel sayı (tek incelikli) /* çift incelikli reel sayıkta */ */ */ */ */ */ */ 1023; 2222; 123; 1234; 'X'; 3.14159; 3.1415926535898; printf("a = %d\n",a); printf("a = %o\n",a); printf("a = %x\n",a); printf("b = %ld\n",b); printf("c = %d\n",c); printf("d = %u\n",d); printf("e = %c\n",e); printf("f = %f\n",f); printf("g = %f\n",g); printf("\n"); printf("a = %d\n",a); printf("a = %7d\n",a); printf("a = %-7d\n",a); printf("\n"); printf("f = %f\n",f); printf("f = %12f\n",f); printf("f = %12.3f\n",f); printf("f = %12.5f\n",f); printf("f = %-12.5f\n",f); return 0; /* /* /* /* /* /* /* /* /* desimal */ oktal */ heksadesimal */ uzun desimal */ kısa desimal */ işaretsiz */ karakter */ reel sayı */ çift incelikli reel sayı */ /* basit 'int' çıktı */ /* 7 uzunlukta bir saha kullan*/ /* sola dayalı 7 lik saha */ /* /* /* /* /* tek incelikli reel sayı */ 12 lik bir saha kullan*/ noktadan sonra 3 hane */ noktadan sonra 5 hane */ sola dayalı 12 hane */ } 2.6 İki nokta arasındaki kenar hesabı Verilen iki noktanın koordinatlarından iki nokta arasındaki kenar, s= (x2 − x1 )2 + ( y 2 − y1 )2 ifadesinden hesaplanır. Burada karekök almak için sqrt fonksiyonu, math.h kütüphanesindedir. /*prg07*/ #include<stdio.h> #include<math.h> int main() İ.Ö.BİLDİRİCİ, 02.04.12 13 { double x1,y1,x2,y2,s; printf("\nx1="); scanf("%lf",&x1); printf("\ny1="); scanf("%lf",&y1); printf("\nx2="); scanf("%lf",&x2); printf("\ny2="); scanf("%lf",&y2); s=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); printf("\nKenar=%.2f",s); return 0; } 2.7 İki Nokta Arasında Açıklık Açısı Hesabı İki nokta arasında açıklık açısı (semt) hesabı, y − y1 t12 = arctan 2 − x x 2 1 bağıntısından hesaplanır. Buradan elde edilen açılara bölge düzeltmelerinin getirilmesi gerekir. Bölge düzeltmeleri ise pay ve paydanın negatif ya da pozitif olmasına göre yapılır. + − − ⇒ +200 g ⇒ +400 g ⇒ +200 g − + − C de trigonometrik fonksiyonlar yalnızca radyan birimi ile çalışır. π sayısını veren bir kütüphane fonksiyonu yoktur. Bu nedenle yeterli incelikte π sayısı trigonometrik ters fonksiyonlar yardımıyla elde edilebilir. π = 2 arcsin(1) /*prg08*/ #include<stdio.h> #include<math.h> int main() { double x1,y1,x2,y2,t,pi; printf("\nx1="); scanf("%lf",&x1); printf("\ny1="); scanf("%lf",&y1); printf("\nx2="); scanf("%lf",&x2); printf("\ny2="); scanf("%lf",&y2); pi=2*asin(1.0); x1=x2-x1; y1=y2-y1; t=atan(y1/x1); t=t*200/pi; if(x1<0) { t=t+200; } if(t<0) { t=t+400; İ.Ö.BİLDİRİCİ, 02.04.12 14 } printf("\nAciklik Acisi=%.5f",t); return 0; } Yukarıdaki kodu incelersek bölme işleminde, sıfıra bölüm olasılığına karşı bir önlem alınmadığını görürüz. Başka bir deyişle arctan fonksiyonu kullanılmadan önce açıklık açısının 0, 100, 200 ve 300 gibi bir değeri olup olmadığı araştırılmalıdır. Bu düşünceye göre program kodu aşağıdaki gibi değiştirilebilir. /*prg09*/ #include<stdio.h> #include<math.h> int main() { double x1,y1,x2,y2,t,pi; printf("\nx1="); scanf("%lf",&x1); printf("\ny1="); scanf("%lf",&y1); printf("\nx2="); scanf("%lf",&x2); printf("\ny2="); scanf("%lf",&y2); pi=2.0*asin(1.0); if(abs(x2-x1)<=1.e-7) { if(y2>y1) { t=100.0; } else { t=300.0; } } else { x1=x2-x1; y1=y2-y1; t=atan(y1/x1); t=t*200/pi; if(x1<0) { t=t+200; } if(t<0) { t=t+400; } } printf("\nAciklik Acisi=%.5lf\n",t); return 0; } 2.8 for Çevrimi ile Toplama for çevrimi kullanılarak kullanıcı tarafından verilen sayıda sayının toplamını ve ortalamasını hesaplayan bir program kodu aşağıda verilmiştir. /*prg10*/ #include<stdio.h> int main() { İ.Ö.BİLDİRİCİ, 02.04.12 15 int i,j; double top=0.0,sayi; printf("\n kac sayi toplanacak?"); scanf("%i",&j); for (i=1;i<=j;i=i+1) { printf("%i.sayi=",i); scanf("%lf",&sayi); top=top+sayi; } printf("\ntoplam=%.2lf\tortalama=%.2lf",top,top/(i-1)); return 0; } 2.9 Faktöriyel Verilen sayının faktöriyelini hesaplayan program: /*prg11*/ #include<stdio.h> int main() { int x,i; double fa=1.0; printf("\nx="); scanf("%i",&x); for (i=x;i>=1;i=i-1) { fa=fa*i; } printf("\nx!=%.0lf",fa); return 0; } Matematiksel olarak faktöriyel değeri tam sayı olmasına karşın yukarıdaki program kodunda fa değişkeni double olarak tanımlanmıştır. Bunun nedeni, hızla büyüyen faktöriyel değerini int tipi ile hesaplamadan doğan güçlüktür. fa değişkeni int ve long int olarak da tanımlanarak denenebilir. Bu durumda printf içindeki format ifadesi “%.0lf” yerine int için “%i” long int için “%ld” şeklinde değiştirilmelidir. Ancak yukarıdaki kod belli bir büyüklükten sonra (yaklaşık 168!) double tipi ile de hesaplama yapamayacağından program kırılır. Buna karşı bir önlem olarak program aşağıdaki gibi geliştirilebilir. Aşağıdaki kod, negatif bir sayı verilmedikçe, hesaplamaya da devam etmektedir. /*prg12*/ #include<stdio.h> int main() { int x=1,i; double fa=1.0; printf("\a\tFaktoriyel Programi, cikis icin negatif sayi girin"); while(x>=0) { fa=1.0; printf("\nx ="); scanf("%i",&x); if(x>=0&&x<=168) { for (i=x;i>=1;i=i-1) { fa=fa*i; } printf("x!=%.0lf",fa); } else İ.Ö.BİLDİRİCİ, 02.04.12 16 { printf("Hesaplanamiyor"); } } printf("\n\tbitti---"); return 0; } 2.10 İç İçe for Çevrimi: Çarpım Tablosu Programı Aşağıdaki kısa kod 1 den 10 a kadar sayılar için çarpım tablosunu ekranda gösterir: /*prg13*/ #include<stdio.h> int main() { int x,y; for (x=1;x<=10;x=x+1) { printf("\n"); for (y=1;y<=10;y=y+1) { printf("%4i",x*y); } } return 0; } Program çalışması sonucu aşağıdaki ekran görüntüsü elde edilir. 1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 10 18 20 27 30 36 40 45 50 54 60 63 70 72 80 81 90 90 100 printf fonksiyonu içinde kullanılan “%4i" ifadesi ekranda dört karakterlik yere x*y çarpımının sonucunu sağa dayalı olarak yazdırmaktadır. Sola dayalı yazdırmak için “%-4i” kullanılmalıdır. 2.11 Alan Hesabı Köşe koordinatları bilinen bir şeklin alanı, F= 1 ∑ (x n y n+1 − xn+1 y n ) 2 bağıntısı ile hesaplanır. Buna göre nokta koordinatlarını sıra ile alan, kullanıcı esc tuşuna basınca alanı hesaplayan bir program kodu aşağıdaki gibidir. /*prg14*/ /*Bu program LINUX altinda calismaz!*/ #include<stdio.h> #include<conio.h> #include<math.h> int main() İ.Ö.BİLDİRİCİ, 02.04.12 17 { double x1,y1,xn,yn,xm,ym,f=0.0; int i=0,j=0; do { j=j+1; printf("\nx%i=",j); scanf("%lf",&xm); printf("\ny%i=",j); scanf("%lf",&ym); if(j==1) { x1=xm; y1=ym; } else { f=f+(xn*ym-xm*yn); } yn=ym; xn=xm; printf("\ndevam icin bir tusa basin, cikis esc"); i=_getch(); } while(i!=27); f=f+(xm*y1-x1*ym); f=fabs(f)/2.0; printf("\nf=%.2lf",f); return 0; } Kullanıcıdan nokta sayısı sorularak alan hesaplanmak istenirse kod aşağıdaki gibi değiştirilebilir: /*prg15*/ #include<stdio.h> #include<math.h> int main() { double x1,y1,xn,yn,xm,ym,f=0.0; int j,n; printf("\nNokta Sayisi="); scanf("%i",&n); for(j=1;j<=n;j++) { printf("\nx%i=",j); scanf("%lf",&xm); printf("\ny%i=",j); scanf("%lf",&ym); if(j==1) { x1=xm; y1=ym; } else { f=f+(xn*ym-xm*yn); } yn=ym; xn=xm; } f=f+(xm*y1-x1*ym); f=fabs(f)/2.0; printf("\nf=%.2lf",f); return 0; } Test amacıyla aşağıdaki veriler kullanılabilir: NN Y İ.Ö.BİLDİRİCİ, 02.04.12 X 18 1 145.00 2 348.00 3 710.00 4 896.00 5 484.00 F=284636.00 549.00 752.00 827.00 398.00 192.00 2.12 e Sayısının Hesabı Doğal logaritmanın tabanı olan e sayısı seri yardımıyla hesaplanabilir. e = 1+ 1 1 1 + + + ... 1! 2! 3! double tipinin verebildiği maksimum inceliği elde etmek için, serinin terim değeri 10-14den küçük oluncaya kadar hesaplama yapılacaktır. Program doğru çalışırsa 18 terim hesaplanacaktır (derleyici ve işlemciye göre değişebilir). /*prg16*/ #include<stdio.h> int main() { int i=0,j; double e=1.0,payda,fark=1.e-15; do { i=i+1; payda=1.0; for(j=i;j>=1;j--) { payda=payda*j; } e=e+1.0/payda; } while (1.0/payda>=fark); printf("\n%i terim ile hesaplanan e=%.14lf",i,e); return 0; } 3. KARAKTER, DİZİ ve POINTER KULLANILAN ÖRNEKLER 3.1 Dizi Kullanarak Alan Hesabı Dizi kullanılarak aşağıdaki gibi bir program yazılabilir: /*prg17*/ #include<stdio.h> #include<conio.h> #include<math.h> #define max 100 int main() { double x[max],y[max],f=0.0; int j,n; char cevap='e'; do { f=0.0; İ.Ö.BİLDİRİCİ, 02.04.12 19 printf("\nNokta Sayisi(max%i)=",max-2); scanf("%i",&n); if(n>2&&n<max-1) { for(j=0;j<=n-1;j++) { printf("\nx%i=",j); scanf("%lf",&x[j]); printf("\ny%i=",j); scanf("%lf",&y[j]); } x[n]=x[0]; y[n]=y[0]; for(j=0;j<=n-1;j++) { f=f+(x[j]*y[j+1]-x[j+1]*y[j]); } f=fabs(f)/2.0; printf("\nf=%.2lf",f); } printf("\nDevam mI?e/h"); cevap=getch(); } while(cevap=='e'); printf("\n----b i t t i---"); return 0; } #define ile sabitler tanımlanır. Yukarıdaki kodda dizi boyutu max adlı sabit ile tanımlanmıştır. Bu şekilde tanımlamanın avantajı sadece #define satırında değişiklik yapılarak dizi boyutunun değiştirilebilmesidir. C dilinde dizi indisleri sıfırdan başlar. Bu nedenle x ve y dizilerinin indisleri 0-99 arasındadır. 3.2 Pointer Kullanımı Pointer, bir değişkene bellekte ayrılan yerin adresini içeren bir değişken tipidir. /*prg18*/ #include<stdio.h> #include<conio.h> int main() { int i; int *ptr; char cvp; do { printf("\nBir sayi girin"); scanf("%i",&i); ptr=&i; printf("Girdiginiz sayi=%i, adresi=%u",i,ptr); printf("Devam mI? e/h"); cvp=getch(); } while(cvp=='e'||cvp=='E'); return 0; } 3.3 Karakter Dizileri Örneği char değişken tipi tek bir karakteri tanımlar. Bir kelime ya da cümleyi saklayabilmek için char tipinde bir dizi kullanmak gerekir. Dizi kullanılmasından dolayı, dizi boyutunun yani saklayacağımız karakter bilginin uzunluğunu belirlemek zorunludur. Karakter dizilerinde girilen karakterin bitişi \0 ile belirlenir. Bu karakter ASCII kodu sıfır olan karakter olup, rakam olarak İ.Ö.BİLDİRİCİ, 02.04.12 20 0 ile ilgisi yoktur. Karakterin bitişi bu şekilde belirtilmek zorunda olduğundan tanımlanan uzunluğun tamamı kullanılamaz, bir eksiğine kadar kullanılabilir. Örnek: 0 S 1 e 2 l 3 a 4 m 5 \0 Uzunluğu 6 olan bu dizide son karakter \0 olmak zorunda olduğundan beş karakterlik kısmı kullanılabilir. Yukarıdaki değişkenin uzunluğu 10 olsaydı, 0 S 1 e 2 l 3 a 4 m 5 \0 6 7 8 9 Dört karakterlik kısım kullanılmazdı. Kullanılamayan kısımlar (6,7,8,9) aslında boş değildir. Buralarda compiler tarafından atanmış rasgele değerler ya da önceden kalma değerler olabilir. Karakter işlemleri için çok sayıda kütüphane fonksiyonu olduğundan, çoğu kez karakterin sonlandırılmasıyla uğraşılmasına gerek kalmaz. Sadece tanımlanan uzunluğun bir karakterinin \0 için kullanılacağının bilinmesi yeterlidir. Aşağıdaki kod kullanıcıya adı ve soyadını sorarak, bir karakter dizisine atamaktadır. Ardından ilk boşluk aranarak (space) onun yerine \0 atanıp, karakterin soyadı kısmı kesilmektedir. /*prg19*/ #include<stdio.h> #include<string.h> #include<conio.h> int main() { int i; char cvp, adsoyad[80]; do { printf("\nAdinizi soyadinizi girin:"); gets(adsoyad); printf("\nAdiniz soyadiniz:%s",adsoyad); printf("\nUzunlugu=%i",strlen(adsoyad)); for (i=0;i<=79;i++) { if(adsoyad[i]==' ') { adsoyad[i]='\0'; break; } } printf("\nAdiniz:%s",adsoyad); printf("\nDevam mI? e/h"); cvp=getch(); } while(cvp=='e'||cvp=='E'); return 0; } Yukarıda kullanılan gets ve strlen fonksiyonları, string.h kütüphanesine ait fonksiyonlardır. gets, scanf fonksiyonu gibi çalışır, ekrandan karakter okunmasını sağlar. Strlen ise karakterin geçerli uzunluğunu verir. Yukarıdaki kodda adsoyad dizisinin tanımlı uzunluğu 80 dir. Ancak bu 80 karakterin bir kısmı kullanılır. strlen programın çalışması sırasında kullanıcı tarafından girilen kısmının uzunluğunu verir. Örneğin kullanıcı “Ali Kuş” şeklinde bir giriş yapmış ise, strlen geriye 7 değerini döndürür. Bunun anlamı ilk 7 karakterlik kısım dolu, sekizinci karakterde \0 mevcut demektir, geri kalan karakterler kullanılmamaktadır. İ.Ö.BİLDİRİCİ, 02.04.12 21 4. FONKSİYON KULLANILAN PROGRAMLAR 4.1 Fonksiyonlara Değer Aktarma Fonksiyonlar arası değer aktarma iki şekilde olabilir. Çağıran fonksiyon çağırılan fonksiyona ilgili değişkenlerin değerini aktarabilir ya da adresini aktarabilir. Değer aktarma durumunda çağırılan fonksiyonda yapılan değişiklik çağıran fonksiyonda etkili olmaz. Değişikliklerin etkili olması için adres aktarması yapmak gereklidir. Bu amaçla pointer kullanılması gereklidir. İki değişkenin değerini değiş tokuş etmek amacıyla aşağıdaki kodu yazalım. /*prg20*/ #include <stdio.h> void degistokus(int, int ); /*fonksiyon prototipi*/ int main() { int x,y; printf("\nx="); scanf("%i",&x); printf("\ny="); scanf("%i",&y); degistokus(x,y); /*değer aktarma*/ printf("\nx=%i\ty=%i",x,y); return 0; } void degistokus(int a, int b) { int c; c=a; a=b; b=c; } Yukarıdaki kodu çalıştırın. Ana fonksiyonda x ve y değişkenlerine atanan değerlerin degistokus fonksiyonunda değiş tokuş edilmesine rağmen ana fonksiyonda etkili olmadığı görülecektir. Bunun nedeni ana fonksiyondaki değişkenlerin bir kopyalarının alt fonksiyona aktarılmasıdır. Alt fonksiyondaki değişikliğin etkili olması için yukarıdaki kod aşağıdaki şekilde düzenlenmelidir. /*prg21*/ #include <stdio.h> void degistokus(int *, int *); /*fonksiyon prototipi*/ int main() { int x,y; printf("\nx="); scanf("%i",&x); printf("\ny="); scanf("%i",&y); degistokus(&x,&y); /*adres aktarma*/ printf("\nx=%i\ty=%i",x,y); return 0; } void degistokus(int *a, int *b) { int c; İ.Ö.BİLDİRİCİ, 02.04.12 22 c=*a; *a=*b; *b=c; } Yukarıdaki kodlarda & operatörü kullanılmıştır. Adres operatörü olarak tanımlanan & operatörü bir değişkenin adresini verir. Bunun tersi * operatörüdür. * operatörü verilen adresteki değeri döndürür (içerik alma operatörü). 4.2 Açıklık Açısının Fonksiyon Olarak Programlanması Açıklık açısını hesaplayan kod bir fonksiyon olarak yazılırsa, değişik programlarda kolaylıkla yeniden kullanılabilir. /*prg22*/ #include<stdio.h> #include<conio.h> #include<math.h> double aciklik_acisi(double x1,double y1,double x2,double y2) { double pi,t; /* pi sayısı ...*/ pi=2.0*asin(1.0); /* açıklık açısı */ if(abs(x2-x1)<=1.e-7) /*payda sıfır ise*/ { if(y2>y1) { t=100.0; } else { t=300.0; } } else { x1=x2-x1; y1=y2-y1; t=atan(y1/x1)*200.0/pi; if(x1<0)t=t+200; if(t<0) t=t+400; } return(t); } int main() { double x1,y1,x2,y2,t; char cvp; do { printf("\nx1="); scanf("%lf",&x1); printf("y1="); scanf("%lf",&y1); printf("x2="); scanf("%lf",&x2); printf("y2="); scanf("%lf",&y2); t=aciklik_acisi(x1,y1,x2,y2); printf("\nAciklik Acisi=%.5lf",t); printf("\nDevam mi?e/h"); cvp=_getch(); } while(cvp!='h'); İ.Ö.BİLDİRİCİ, 02.04.12 23 printf("\n---->bitti"); return 0; } Fonksiyon prototipi kullanılarak yazım: /*prg23*/ #include<stdio.h> #include<conio.h> #include<math.h> double aciklik_acisi(double,double,double,double); int main() { double x1,y1,x2,y2,t; char cvp; do { printf("\nx1="); scanf("%lf",&x1); printf("y1="); scanf("%lf",&y1); printf("x2="); scanf("%lf",&x2); printf("y2="); scanf("%lf",&y2); t=aciklik_acisi(x1,y1,x2,y2); printf("\nAciklik Acisi=%.5lf",t); printf("\nDevam mi?e/h"); cvp=_getch(); } while(cvp!='h'); printf("\n---->bitti"); return 0; } double aciklik_acisi(double x1,double y1,double x2,double y2) { double pi,t; /* pi sayısı ...*/ pi=2.0*asin(1.0); /* açıklık açısı */ if(abs(x2-x1)<=1.e-7) /*payda sıfır ise*/ { if(y2>y1) { t=100.0; } else { t=300.0; } } else { x1=x2-x1; y1=y2-y1; t=atan(y1/x1)*200.0/pi; if(x1<0)t=t+200; if(t<0) t=t+400; } return(t); } İ.Ö.BİLDİRİCİ, 02.04.12 24 4.3 Açıklık Açısı ve Kenarı Birlikte Döndüren Fonksiyon Bir fonksiyonun iki değer döndürebilmesi için pointer kullanmak gerekir. Fonksiyon geriye direkt olarak bir değer döndürmemekte, çağıran fonksiyondan (main) gönderilen iki değişkenin adresini alarak hesaplanan değerleri bu adresler yoluyla çağıran fonksiyona aktarmaktadır. Öte yandan, fonksiyon kodu main fonksiyonundan sonra yer aldığı için, main fonksiyonundan önce fonksiyonun prototipi verilmiştir. /*prg24*/ #include<stdio.h> #include<conio.h> #include<math.h> void aci_kenar(double,double,double,double,double *,double *); int main() { double x1,y1,x2,y2,t,s; char cvp; do { printf("\nx1="); scanf("%lf",&x1); printf("y1="); scanf("%lf",&y1); printf("x2="); scanf("%lf",&x2); printf("y2="); scanf("%lf",&y2); aci_kenar(x1,y1,x2,y2,&t,&s); printf("\nAciklik Acisi=%.5lf\tkenar=%.2lf",t,s); printf("\nDevam mi?e/h"); cvp=_getch(); } while(cvp!='h'); printf("\n---->bitti"); return 0; } void aci_kenar(double x1,double y1,double x2,double y2,double *t,double *s) { double pi; /* kenar hesabı*/ *s=sqrt(pow((x2-x1),2)+pow((y2-y1),2)); /* pi sayısı ...*/ pi=2.0*asin(1.0); /* açıklık açısı */ if(abs(x2-x1)<=1.e-7) /*payda==0 mi?*/ { if(y2>y1) { *t=100.0; } else { *t=300.0; } } else { x1=x2-x1; y1=y2-y1; *t=atan(y1/x1)*200.0/pi; if(x1<0) { *t=*t+200; } if(*t<0) İ.Ö.BİLDİRİCİ, 02.04.12 25 { *t=*t+400; } } } 4.4 Fonksiyonlar Arası Dizi Aktarma Fonksiyonlara değişkenlerin aktarılmasını daha önce inceledik. Fonksiyonlar arası dizi değişkenlerinin aktarılması biraz farklıdır. Dizi değişkenleri için tanımlanan değişken ismi parantezsiz kullanılırsa o dizinin ilk elemanının pointerını tanımlar. x biri dizi olmak üzere aşağıdaki iki ifade birbiri ile eşdeğerdir. x &x[0] Aşağıdaki örnekte 5 elemanına atama yapılan bir dizinin bir fonksiyona aktarılarak ekranda görüntülenmesi sağlanmaktadır. Burada dizinin aktarılma şekline ve fonksiyon prototipinin nasıl tanımlandığına dikkat edin. /*prg25*/ #include <stdio.h> #define max 100 void diziyaz(double *,int); /*fonksiyon prototipi*/ int main() { double x[max]; int i,j; i=5; for(j=0;j<i;j++) { x[j]=2*j+1; } diziyaz(x,i); return 0; } void diziyaz (double *x,int i) { int j; for(j=0;j<i;j++) { printf("\nx(%i)=%.0lf",j,x[j]); } } Aşağıdaki örnek ise karakter dizileri fonksiyonlara aktarılmaktadır. Buradaki fonksiyonlardan yaz1 de fonksiyona aktarılan karakter dizisinin içeriği, dizi kullanılarak ekrana yazılmakta, yaz2 de ise aynı işlem pointer kullanılarak gerçekleştirilmektedir. Bu örnekte pointer ve dizi kavramlarının birbirleriyle ilişkisi daha açık olarak görülmektedir. /*prg26*/ #include <stdio.h> void yaz1(char *text) { int x=0; while(text[x]!='\0') { putchar(text[x]); x++; } } void yaz2(char *text) { İ.Ö.BİLDİRİCİ, 02.04.12 26 while(*text) { putchar(*text++); } } int main () { char text[80]; printf("\nBir cumle yazin: "); gets(text); yaz1(text); yaz2(text); return 0; } 4.5 Fonksiyon Olarak Alan Hesabı Daha önce de incelenen alan hesabı probleminin fonksiyon olarak kullanımı için aşağıdaki kodu inceleyin. Burada koordinatlar ana programda iki diziye yazılmakta, hesaplama alanhesap adlı fonksiyon içinde yapılmaktadır. /*prg27*/ #include <stdio.h> #include<math.h> #define max 1000 double alanhesap(double *,double *, int); /*fonksiyon prototipi*/ int main() { double x[max],y[max],a; int n=max,j; while(n>2) { printf("\nNokta Sayisi / Cikis -->0 (max%i)=",max-1); scanf("%i",&n); n--; if(n>=2&&n<=max-1) { for(j=0;j<=n;j++) { printf("\nx%i=",j+1); scanf("%lf",&x[j]); printf("\ny%i=",j+1); scanf("%lf",&y[j]); } a=alanhesap(x,y,n); printf("\nalan=%.2lf",a); } } return 0; } double alanhesap (double *x,double *y, int n) { int j; double f=0.0; x[n+1]=x[0]; y[n+1]=y[0]; for(j=0;j<=n;j++) { f=f+(x[j]*y[j+1]-x[j+1]*y[j]); } f=fabs(f)/2.0; return(f); } İ.Ö.BİLDİRİCİ, 02.04.12 27 5. DOSYA KULLANIMI Programların verileri ve ürettikleri sonuçlar dosyalarda saklanır. Şimdiye kadar ki basit örneklerde, programın giriş verileri ve sonuçları için ekran kullanılmıştı. Bu şekilde elde edilen sonuçlar ekranda göründükten sonra kaybolurlar. Oysa elde edilen sonuçların kaybedilmesi istenen bir şey değildir. Bu bölümde verileri dosyalardan okuyan ve ürettikleri sonuçları dosyalara yazan programlar incelenecektir. Dosyalar sequential ve random olmak üzere temel olarak ikiye ayrılırlar. Sequential dosyalar ASCII File, Text File olarak da isimlendirilirler. Bu bölümde bu tip dosyalar üzerinde örnekler verilecektir. Bir dosya ile çalışmanın ilk adımı onu açmaktır. Bu şekilde işletim sistemi tarafından diskte kullanılabilir bir alan hazırlanır. Dosya açma amacıyla fopen fonksiyonu kullanılır. Dosya açılıp işlendikten sonra fclose fonksiyonu ile kapatılır. Sadece bir dosyayı açıp tekrar kapatan aşağıdaki kodu inceleyin. /*prg28*/ #include <stdio.h> int main() { FILE *dosya_ptr; dosya_ptr=fopen("abc.txt","w"); if(dosya_ptr != NULL) { fclose(dosya_ptr); } return 0; } Yukarıda ilk olarak dosya tipinde dosya_ptr adlı bir pointer tanımlanmaktadır. Eğer dosya açma işlemi başarılı olmuş ise if bloğu içinde dosya tekrar kapatılmaktadır. Eğer çalışılan klasörde abc.txt adlı bir dosya var ise, bu dosya yok olacaktır. Bunun nedeni fopen fonksiyonundaki ikinci parametredir (“w”). İkinci parametre değerleri ve anlamları aşağıdaki gibidir: • • • r (read) dosya okunmak üzere açılır. Eğer dosya mevcut değilse açma işlemi başarısız olur. w (write) dosya yazılmak üzere açılır. Dosya mevcut ise üzerine yazılır, değilse yeniden oluşturulur. a (append) dosya yazılmak üzere açılır ve dosyanın sonuna gidilir. Eğer dosya yok ise yeniden oluşturulur. Dosya tipi (FILE) daha önce kullanılan tiplerden farklıdır. Bu önceden tanımlanmış bir tip olup stdio.h kütüphanesi içinde yer almaktadır. Büyük harflerle yazılması gerekir. Eğer dosya açılamazsa dosya_ptr ye NULL ataması yapılır. NULL da stdio.h içinde tanımlıdır. Yukarıdaki program biraz daha geliştirilerek aşağıdaki hale getirilebilir. /*prg29*/ #include <stdio.h> int main() { FILE *dosya_ptr; char dosya_adi[80]; printf("\nAcilacak dosya adini girin: "); gets(dosya_adi); dosya_ptr=fopen(dosya_adi,"r"); if(dosya_ptr != NULL) İ.Ö.BİLDİRİCİ, 02.04.12 28 { printf("\n%s adli dosya acildi!\n",dosya_adi); fclose(dosya_ptr); } else { printf("\n%s adli dosya acilaMadi!\n",dosya_adi); } return 0 } 5.1 Dosyadan Okuma Dosyalardan veri okuma için çeşitli kütüphane fonksiyonları vardır. Dosyadan her seferinde bir karakter okumak için fgetc fonksiyonu kullanılır. Aşağıdaki kodu denemeden önce çalışma klasörünüzde notepad ile bir dosya oluşturun. Bu dosya içine bir kaç satır yazı yazın, kaydederek kapatın. Programı çalıştırırken hazırladığınız dosyanın adını verin. /*prg30*/ #include <stdio.h> #include <stdlib.h> int main() { FILE *stream; char dosya_adi[80]; int ch; printf("\nDosya adi: "); gets(dosya_adi); if((stream=fopen(dosya_adi,"r"))==NULL) { printf("\nDosya acilamadi!"); return 0; } ch=fgetc(stream); while(!feof(stream)) { putchar(ch); ch=fgetc(stream); } fclose(stream); return 0; } Yukarıdaki örnekte dosyadan her defasında bir karakter okunmaktadır. Tek tek karakter okumak genel olarak programlama mantığına uygun değildir. fgets fonksiyonu ile satir satir okuma mümkündür. Buna göre değiştirilmiş kod aşağıdaki gibidir: /*prg31*/ #include <stdio.h> #include <stdlib.h> int main() { FILE *stream; char dosya_adi[80], satir[80]; printf("\nDosya adi: "); gets(dosya_adi); if((stream=fopen(dosya_adi,"r"))==NULL) { printf("\nDosya acilamadi!"); return 0; } while(!feof(stream)) { fgets(satir, 100, stream); printf("%s",satir); İ.Ö.BİLDİRİCİ, 02.04.12 29 } fclose(stream); return 0; } fscanf, scanf fonksiyonuna benzer olarak dosyadan formatlı değer okuma işlemini gerçekleştirir. Aşağıdaki kodu uygulamadan önce çalışma klasörünüzde notepad ile bir dosya oluşturun. Dosyaya toplam uzunluğu 12 karakteri aşmayan reel sayılar yazın. Ondalık ayıracı olarak nokta kullanın, virgül kullanmayın! Hazırladığınız dosyayı programı çalıştırırken kullanın. /*prg32*/ #include <stdio.h> #include <stdlib.h> int main() { FILE *stream; char dosya_adi[80]; int i=-1; double liste[80]; printf("\nDosya adi: "); gets(dosya_adi); if((stream=fopen(dosya_adi,"r"))==NULL) { printf("\nDosya acilamadi!"); return 0; } while(!feof(stream)) { i++; fscanf(stream,"%12lf",&liste[i]); printf("\nliste(%i)=%lf",i,liste[i]); } fclose(stream); return 0; } 5.2 Dosyaya Yazma Dosyaya yazma işlemi fscanf fonksiyonun eşi olarak düşünülebilecek fprintf fonksiyonu ile gerçekleştirilir. fprintf ve fscanf fonksiyonları tamamen printf ve scanf fonksiyonları gibi davranırlar. Aralarındaki tek fark giriş çıkış ortamının ekran ya da dosya olmasıdır. Aşağıdaki örnekte prg13 kodunda ekranda oluşturulan çarpım tablosu bu kez bir dosyada oluşturulmaktadır. /*prg33*/ #include <stdio.h> int main() { FILE *stream; char dosya_adi[80]; int x,y; printf("\nDosya adi: "); gets(dosya_adi); if((stream=fopen(dosya_adi,"w"))==NULL) { printf("\nDosya acilamadi!"); } else { for (x=1;x<=10;x=x+1) { for (y=1;y<=10;y=y+1) İ.Ö.BİLDİRİCİ, 02.04.12 30 { fprintf(stream,"%4i",x*y); } fprintf(stream,"\n"); } fclose(stream); } return 0; } Dosyaya yazdığımız bilgileri tekrar okuma amaçlı olarak aşağıdaki kodu uygulayın. Burada çarpım tablosu içeriği iki boyutlu bir diziye alınarak, kontrol amaçlı olarak ekranda görüntülenmektedir. /*prg34*/ #include <stdio.h> int main() { FILE *stream; char dosya_adi[80]; int x,y; int n[10][10]; printf("\nDosya adi: "); gets(dosya_adi); if((stream=fopen(dosya_adi,"r"))==NULL) { printf("\nDosya acilamadi!"); } else { for (x=0;x<=9;x++) { for (y=0;y<=9;y++) { fscanf(stream,"%4i",&n[x][y]); } } fclose(stream); for (x=0;x<=9;x++) { for (y=0;y<=9;y++) { printf("%4i",n[x][y]); } printf("\n"); } } return 0; } Yukarıda iki boyutlu dizinin kullanımına dikkat edin. Önce dosya açılarak dizi doldurulmakta, daha sonra dizinin elemanları ekranda görüntülenmektedir. Bu şekilde diske kaydettiğimiz verileri herhangi bir kayıp olmadan tekrar okuyup, değişkenlere aktarmış olduk. 5.3 İki Boyutlu Dizilerle Çalışma: Matris Çarpımı Matris işlemleri için iki boyutlu dizilerle çalışmak gereklidir. Bu bölümdeki örnekte iki matrisi bir dosyadan okuyan ve matris çarpımını başka bir dosyaya yazan bir program kodu verilecektir. /*prg35*/ #include<stdio.h> #define matboy 100 void matrisoku(FILE *stream, int *sa, int *su, double n[matboy][matboy]) { int i,j; fscanf(stream,"%12i%12i",sa,su); İ.Ö.BİLDİRİCİ, 02.04.12 31 for(i=1;i<=*sa;i++) { for(j=1;j<=*su;j++) { fscanf(stream,"%12lf",&n[i][j]); } } } void matrisyaz(FILE *stream, int *sa, int *su, double n[matboy][matboy]) { fprintf(stream,"\n%12i%12i\n",*sa,*su); int i,j; for(i=1;i<=*sa;i++) { for(j=1;j<=*su;j++) { fprintf(stream,"%12lf",n[i][j]); } fprintf(stream,"\n"); } } void matrisyazekr(int *sa, int *su, double n[matboy][matboy]) { int i,j; for(i=1;i<=*sa;i++) { for(j=1;j<=*su;j++) { printf("%12lf",n[i][j]); } printf("\n"); } } int main() { FILE *dosya1; char dosya_adi[80]; int asa,asu,bsa,bsu,csa,csu,i,j,k; double a[matboy][matboy],b[matboy][matboy],c[matboy][matboy]; printf("\nDosya adi: "); gets(dosya_adi); if((dosya1=fopen(dosya_adi,"r"))==NULL) { printf("\nDosya acilamadi!"); } else { matrisoku(dosya1,&asa,&asu,a); matrisoku(dosya1,&bsa,&bsu,b); if(asu==bsa) { csa=asa;csu=bsu; for(i=1;i<=csa;i++) { for(j=1;j<=csu;j++) { c[i][j]=0; for(k=1;k<=asu;k++) { c[i][j]=c[i][j]+a[i][k]*b[k][j]; } } } } İ.Ö.BİLDİRİCİ, 02.04.12 32 matrisyazekr(&csa,&csu,c); fclose(dosya1); if((dosya1=fopen(dosya_adi,"a"))!=NULL) { matrisyaz(dosya1,&csa,&csu,c); fclose(dosya1); } } return 0; } Matrislerin dosyadan okunması, matris çarpım sonucunun ekranda gösterilmesi ve dosyaya yazdırılması matrisoku, matrisyaz, matrisyazekr adlı fonksiyonlar yardımıyla yapılmaktadır. Bu programda kullanılmak üzere Notepad/Not Defteri (ya da benzeri bir editör) ile rakamlar 12 karakterlik alanlara gelmek üzere aşağıdaki gibi bir dosya hazırlayın. 3 4 1.0000 -5.0000 1.1000 4 5.0000 -2.2000 -5.0000 3.2000 5.0000 -2.2500 1.5000 4.0000 -0.2250 1.5000 5.0000 2.5000 2.0000 2.2000 2.0000 4.5000 5.0000 3.0000 1.0000 2.2500 8.0000 5 2.5000 -6.0000 1.1000 6.0000 -5.0000 0.0000 6.0000 7.0000 Burada ilk iki tamsayı rakam (3 ve 4) takip eden matrisin satır ve sütun sayısını ifade etmektedir. Birinci matristen sonra gelen iki tamsayı (4 ve 5) yine takip eden matrisin boyutlarını ifade etmektedir. Bu matrisler çarpıldığında (ilk matris ikinci ile çarpıldığında) aşağıdaki sonuç elde edilecektir: 3 5 -14.980000 30.200000 28.925000 37.500000 2.000000 -29.425000 34.100000 27.100000 -18.830000 27.200000 26.050000 -8.562500 24.700000 83.000000 -20.575000 prg35 kodunda dosya (FILE) değişkeninin ve iki boyutlu dizilerin fonksiyonlara nasıl aktarıldığına dikkat edin. 6. İLERİ TEKNİKLER 6.1 Struct, Union ve Typedef Bir struct, kullanıcı tarafından tanımlanmış bir veri tipidir. Standart veri tiplerinden çok daha karmaşık olanları, bu yolla tanımlayabilirsiniz. Bir struct, daha önce tanımlanmış olan veri tiplerinin bir araya gelmiş halidir - ki bu veri tiplerine, daha önce tanımlanan struct’lar da dahildir (iç içe struct tanımlamaları). Struct’lar, verilerin program kodunun daha anlaşılır olması için gruplanması olarak düşünülebilir. Struct yapısını daha iyi anlamak için aşağıdaki kodu inceleyin. /*prg36*/ #include<stdio.h> int main() { struct { char bas_harf; İ.Ö.BİLDİRİCİ, 02.04.12 /* Soyadın bas harfi */ 33 int yas; int not; } oglan,kiz; /* çocuğun yaşı */ /* okulda not ortalaması (100 üzerinden) */ oglan.bas_harf = 'R'; oglan.yas = 15; oglan.not = 75; kiz.yas = oglan.yas - 1; kiz.not = 82; kiz.bas_harf = 'H'; /* o, oglandan bir yas küçük */ printf("%d yasindaki %c'nin aldigi not, %d dir.\n", kiz.yas, kiz.bas_harf, kiz.not); printf("%d yasindaki %c'nin aldigi not, %d dir.\n", oglan.yas, oglan.bas_harf, oglan.not); return 0; } Üç değişkenden oluşan bir struct tipi olarak oglan ve kiz adli değişkenler tanımlanmaktadır. Bu değişkenlerin bileşenlerine “.” yazım tarzı ile ulaşılmaktadır (örneğin oglan.yas). Prg36 kodu tanımlanan struct tipine bir ad verilerek aşağıdaki gibi düzenlenebilir. /*prg37*/ #include<stdio.h> struct ogrenci{ char bas_harf; int yas; int not; }; /* Soyadın bas harfi */ /* çocuğun yaşı */ /* okulda not ortalaması (100 üzerinden) */ int main() { struct ogrenci oglan,kiz; /*ogrenci tipli degiskenlerin tanımlanması*/ oglan.bas_harf = 'R'; oglan.yas = 15; oglan.not = 75; kiz.yas = oglan.yas - 1; kiz.not = 82; kiz.bas_harf = 'H'; /* o, oglandan bir yas küçük */ printf("%d yasindaki %c'nin aldigi not, %d dir.\n", kiz.yas, kiz.bas_harf, kiz.not); printf("%d yasindaki %c'nin aldigi not, %d dir.\n", oglan.yas, oglan.bas_harf, oglan.not); return 0; } Burada ogrenci adlı tip global olarak tanımlanmıştır. Main fonksiyonu içinde ise, kiz ve oglan adlı değişkenler ogrenci tipinde tanımlanmıştır. Global olan ogrenci tipi bir header file içinde de olabilir. Bu şekilde önceden hazırlanmış tipler değişik programlarda kullanılabilirler. Bu tip kullanımı kolaylaştırma amacıyla ogrenci tipini standart değişken tipi gibi tanımlamak için typedef yapısı kullanılır. Typedef var olan değişken tiplerinin (standart değişkenler ya da struct’lar) başka bir adla (daha basit bir adla) tanımlanmalarını sağlar. Typedef kullanarak kodun değiştirilmiş hali aşağıdaki gibidir. /*prg38*/ #include<stdio.h> struct ogrenci { char bas_harf; İ.Ö.BİLDİRİCİ, 02.04.12 /* Soyadın bas harfi */ 34 int yas; int not; /* çocuğun yaşı */ /* okulda not ortalaması (100 üzerinden) */ }; typedef struct ogrenci ogr; int main() { ogr oglan,kiz; /*ogrenci tipindeki değişkenlerin tanımlanması*/ oglan.bas_harf = 'R'; oglan.yas = 15; oglan.not = 75; kiz.yas = oglan.yas - 1; kiz.not = 82; kiz.bas_harf = 'H'; /* o, oglandan bir yas küçük */ printf("%d yasindaki %c'nin aldigi not, %d dir.\n", kiz.yas, kiz.bas_harf, kiz.not); printf("%d yasindaki %c'nin aldigi not, %d dir.\n", oglan.yas, oglan.bas_harf, oglan.not); return 0; } Union yapısı tamamen struct yapısına benzer. Aralarındaki fark struct yapısında tüm bileşenler kullanılabilir. Union’da ise yalnızca bileşenlerden biri kullanılabilir. Bir bileşene atama yapıldıktan sonra bir başka bileşene atama yapılırsa önceki silinir. 6.2 Struct ve Dosya Kullanımı Struct ile tanımlanan tipte bir değişken ve dosya kullanımı aşağıdaki kodla incelenebilir. Burada nokta tipi oluşturulmakta, kullanıcıdan alınan bilgiler bir binary dosyaya yazılmaktadır. Daha sonra dosya içeriği ekranda gösterilmektedir. /*prg39*/ #include<stdio.h> struct nokta { char nno[10]; double x; double y; }; void noktaal(FILE *stream, int n, struct nokta *p) /*verilen n ci sıradaki noktayı okur ve p değişkenine aktarır*/ { fseek(stream,(n-1)*26,SEEK_SET); fread( p->nno, sizeof(p->nno), 1, stream); fread( &p->x, sizeof(p->x) , 1, stream); fread( &p->y, sizeof(p->y) , 1, stream); } int main() { FILE *stream; struct nokta nok; int i; if( (stream = fopen( "test.dat", "w+" )) != NULL ) { fseek( stream, 0, SEEK_END); /*Dosya sonuna git */ while(1==1) /*noktaların ekrandan alınması*/ { printf("\nNokta adi [Devam >> * ]="); scanf("%s",nok.nno); if(nok.nno[0]=='*') break; İ.Ö.BİLDİRİCİ, 02.04.12 35 printf("\nx="); scanf("%lf",&nok.x); printf("\ny="); scanf("%lf",&nok.y); fwrite(nok.nno, sizeof(nok.nno),1, stream); fwrite(&nok.x, sizeof(nok.x) , 1, stream); fwrite(&nok.y, sizeof(nok.y) , 1, stream); } rewind(stream); /*dosyayı başa sar*/ printf("\nGirdiginiz Noktalar"); i=0; while(i>=-1 ) { printf("\nKacinci kayit?[Cikis >> -2/Tum kayitlar >> -1]:"); scanf("%i",&i); if(i>=0) { noktaal(stream,i,&nok); printf("\n%3i %10s %10.2lf %10.2lf",i,nok.nno,nok.x,nok.y); } else if(i==-1) { i=0; do /*dosya içeriği*/ { i++; noktaal(stream,i,&nok); printf("\n%3i %10s %10.2lf %10.2lf",i,nok.nno,nok.x,nok.y); } while(!feof(stream)); } } printf("\nBitti\n"); fclose(stream); } return 0; } bu örnekte kullanılan test.dat adlı dosya içeriği Notepad gibi bir editör ile görülemez. fwrite ve fread fonksiyonları dosyalara formatsız yazma ve okuma işlemlerinde kullanılırlar. fseek fonksiyonu ise dosyada işaretçinin (cursor) belli bir başlangıçtan itibaren belli sayıda byte kadar ilerlemesini sağlar. Nokta tipli olarak tanımlanan nok adlı değişkenin dosyadan okunarak doldurulması noktaal adlı fonksiyonda gerçekleştirilmektedir. Bu fonksiyona struct olarak tanımlı değişkenin parametre olarak nasıl aktarıldığına dikkat edin. Değişkenin değeri çağıran fonksiyona aktarılmak zorunda olduğundan burada pointer kullanılarak aktarma yapılması gerekmektedir. Burada, p->x biçimindeki yazım, (*p).x şeklindeki yazım ile eşdeğerdir. Burada . operatörünün * operatörüne göre önceliği olması nedeniyle parantez kullanılması gereklidir. -> işaretleri ile yazım daha anlaşılması kolay olduğu için tercih edilir. 6.3 Komut Satırından Parametre Almak Çoğu konsol uygulamada (Console Application) programa bazı parametreler komut satırından sonra yazılarak aktarılır. Örneğin, Print deneme.txt İ.Ö.BİLDİRİCİ, 02.04.12 36 Burada print programına yazıcıya göndereceği dosya ismi aktarılmaktadır. Programlara bu şekilde veri aktarma kullanım kolaylığı yanında programların başka programlarla kullanılmasına da olanak sağlar. /*prg40*/ #include<stdio.h> #include<stdlib.h> int main(int argc, char *argv[]) { int i; if(argc<2) { printf("\nKomut satirinda parametre yok!"); return 0; } for(i=1;i<argc;i++) { printf("\nParametre %i=%s",i,argv[i]); } return 0; } Burada main fonksiyonu işletim sisteminden iki parametre almaktadır. argc parametrelerin sayısını, argv[] ise parametreleri içermektedir. Bu değişken isimleri farklı olabilir, ancak bu isimler genellikle değiştirilmeden kullanılır. argc değişkeninin değeri 1 ise, komut satırında hiç bir parametre yok demektir. Bu durumda işletim sistemi birinci değer olarak programın kendi ismini göndermiş demektir. argv tanımlaması gereği (char *argv[]) bir karakter değişkenini gösteren bir pointerin pointeridir. Başka bir deyişle argv pointerlar içeren bir dizinin pointeridir. Bu dizideki pointerlar, parametreleri göstermektedirler. Bu kodu exe dosyasını oluşturduktan sonra, editörden değil bir komut istemi penceresinden (command prompt) çalıştırın. Program isminden sonra boşluklarla ayrılmış olarak parametreler girin. 6.4 Sisteme Komut Göndermek Programlardan komut satırından kullanılan DOS komutlarını, ya da başka programları işletim sistemine komut göndererek çalıştırmak mümkündür. Bu amaçla system fonksiyonu kullanılır. Aşağıdaki kod ile oluşturduğunuz programı yine komut istemi penceresinde çalıştırın. Program tamamen dir komutu gibi çalışır. /*prg41*/ #include<stdio.h> #include<process.h> #include<string.h> int main(int argc, char *argv[]) { char line[80]; strcpy(line,"dir "); if(argc>1) { strcat(line,argv[1]); } system(line); return 0; } İ.Ö.BİLDİRİCİ, 02.04.12 37 6.5 Header File Kullanmak Şimdiye kadar yazdığımız bütün kodlarda en az bir tane header file kullandık. Kullandığımız dosyalar c derleyicisi ile gelen standart kütüphanelerdi. Kullanıcılar tarafından da header file lar hazırlanabilir. Bu şekilde test edilmiş fonksiyonlar bir header file da toplanır ve çeşitli programlarda kullanılabilir. Uygulama amacıyla matris işlemleri yaptığımız prg35 kodunu ele alalım. Buradaki fonksiyonları ayrı bir dosyaya kopyalayın. Bu dosyanın içeriği aşağıdaki gibi olmalıdır. #define matboy 100 void matrisoku(FILE *stream, int *sa, int *su, double n[matboy][matboy]) { int i,j; fscanf(stream,"%12i%12i",sa,su); for(i=1;i<=*sa;i++) { for(j=1;j<=*su;j++) { fscanf(stream,"%12lf",&n[i][j]); } } } void matrisyaz(FILE *stream, int *sa, int *su, double n[matboy][matboy]) { fprintf(stream,"\n%12i%12i\n",*sa,*su); int i,j; for(i=1;i<=*sa;i++) { for(j=1;j<=*su;j++) { fprintf(stream,"%12lf",n[i][j]); } fprintf(stream,"\n"); } } void matrisyazekr(int *sa, int *su, double n[matboy][matboy]) { int i,j; for(i=1;i<=*sa;i++) { for(j=1;j<=*su;j++) { printf("%12lf",n[i][j]); } printf("\n"); } } Dosyayı örneğin jeomat.h olarak adlandırıp, proje klasörü altına kaydedin. Program kodu aşağıdaki gibi olmalıdır. (VS 6.0 ya da VS.NET kullanıyorsanız önce File>New menüsünden yeni “C++ Header File” oluşturun yukarıdaki kodu bu dosya içine yazın). Proje klasörü altında yer alan header dosyasının deklere edilmesi şekil olarak standart header dosyalarının deklere edilmesinden farklıdır. /*prg42*/ #include<stdio.h> #include"jeomat.h" int main() { FILE *dosya1; char dosya_adi[80]; İ.Ö.BİLDİRİCİ, 02.04.12 38 int asa,asu,bsa,bsu,csa,csu,i,j,k; double a[matboy][matboy],b[matboy][matboy],c[matboy][matboy]; printf("\nDosya adi: "); gets(dosya_adi); if((dosya1=fopen(dosya_adi,"r"))==NULL) { printf("\nDosya acilamadi!"); } else { matrisoku(dosya1,&asa,&asu,a); matrisoku(dosya1,&bsa,&bsu,b); if(asu==bsa) { csa=asa;csu=bsu; for(i=1;i<=csa;i++) { for(j=1;j<=csu;j++) { c[i][j]=0; for(k=1;k<=asu;k++) { c[i][j]=c[i][j]+a[i][k]*b[k][j]; } } } } matrisyazekr(&csa,&csu,c); fclose(dosya1); if((dosya1=fopen(dosya_adi,"a"))!=NULL) { matrisyaz(dosya1,&csa,&csu,c); fclose(dosya1); } } return 0; } 7. C++ ÖRNEKLERİ Bu bölümde basit C++ örnekleri verilecektir. 7.1 Ekrandan Veri Giriş Çıkışı C dilindeki printf ve scanf fonksiyonlarına benzer olarak C++ dilinde cin ve cout fonksiyonları kullanılır. Cin ve cout fonksiyonları karakter dizileri okumak için önemli yararlar sağlar. /*prg43*/ #include <iostream.h> int main () { char ad[20]; char soyad[20]; cout << "\nAdiniz:"; cin >> ad; cout << "\nSoyadiniz:"; cin >> soyad; cout << "\nSayin \t" << ad << " " << soyad; cout << "\nHosgeldiniz\n"; return 0; İ.Ö.BİLDİRİCİ, 02.04.12 39 } C++ ile I/O işlemrinde özellikle reel sayılara ilişkin biçimlendirme C’nin printf ve scanf fonksiyonlarından biraz farklıdır. C++’da çıktıyı ekrana yazmak için cout komutuyla birlikte insertion << operatörünün kullanılması zorunludur. cin komutunda ise >> operatörü kullanılır. Aşağıdaki örnekte ekrandan cin komutu ile alınan üç reel sayı, başka bir değişkende toplandıktan sonra ortalaması alınmaktadır. Toplam sonucu noktadan sonra iki, ortalama ise üç basamak olarak yazdırılmak isteniyor. Standart I/O kütüphanesinin (iostream.h) yanı sıra sonuçların biçimlendirilmesi için iomanip.h kütüphanesi de programa dahil edilmelidir. Burada setiosflags ile sayının biçimlendirilmesinde kullanılacak bayrak ayarlanıyor. Desimal sayıların gösterimi için açılan bu bayrak fixed dır. Basamak sayısının ayarlanması ise setprecision komutu ile sağlanır. Fonksiyonun alacağı değer basamak sayısını gösterir. /*prg44*/ #include <iostream.h> #include <iomanip.h> int main() { double top=0.0,sayi=0.0; cout << "\n\tHesaplayici\n"; cout << "\n1.sayi="; cin >> sayi; top=top+sayi; cout << "\n2.sayi="; cin >> sayi; top=top+sayi; cout <<"\n3.sayi="; cin >> sayi; top=top+sayi; cout << setiosflags(ios::fixed) << setprecision(2) << "\ntoplam= " << top; // Desimal sayilarin gosterimi // Noktadan sonra iki basamak top=top/3; cout << setprecision(3) << "\nOrtalama= " << top << endl; return 0; } 7.2 Dosya İşlemleri Dosya işlemlerine örnek olarak prg33 kodu C++ fonksiyonları ile yeniden düzenlenecektir. prg33 kodundan farklı olarak dosyada oluşturulan çarpım tablosu, dosyadan tekrar okunarak ekranda görüntülenmektedir. C++’da dosya dosyaları okuma ve yazma (I/O) işlemleri fstream.h kütüphanesi kullanılarak yapılır. Okuma ve yazma akımları (nesneleri) sırasıyla ifstream ve ofstream sınıf örnekleriyle yaratılır. Adı kullanıcı tarafından isteğe bağlı olarak belirtilen bu nesneler, ekran giriş/çıkış komutları olarak kullanılan cin ve cout nesnelerine karşılık gelir. Bu nedenle çıkış akımı için << operatörü, giriş akımı içinse >> operatörü kullanılmalıdır. I/O komutlarının tümü birer nesne olduğu için nesneye ait üye değişken ve fonksiyonlara . ile erişilebilir. /*prg45*/ #include <iostream.h> #include <fstream.h> #include <iomanip.h> İ.Ö.BİLDİRİCİ, 02.04.12 40 int main() { ofstream stream1; ifstream stream2; char dosya_adi[80]; char satir[80]; int x,y; cout << "\nDosya adi: "; cin >> dosya_adi; stream1.open(dosya_adi,ios::out); if(stream1.fail()) { cout << "\nDosya acilamadi!"; } else { for (x=1;x<=10;x=x+1) { for (y=1;y<=10;y=y+1) { stream1 << setw(4) << x*y; } stream1 << "\n"; } } stream1.close(); /* Acilan dosyanin tekrar okunmasi*/ stream2.open(dosya_adi,ios::in); if(!stream2.fail()) { stream2.getline(satir,80,'\n'); cout << satir << endl; while (!stream2.eof()) { stream2.getline(satir,80,'\n'); cout << satir << endl; } } stream2.close(); return 0; } 7.3 Nesneye Yönelik Programlama C++ ile ilgili ikinci örneğimiz ise nesneye yönelik programlama (object oriented programming). Nesneye yönelik programlama C++’nın C’ye göre en üstün yanını oluşturmaktadır. Şimdiye değin temel değişken tipleriyle (char, float, double vb) program yazmaya çalıştık. C’de kullanıcıya özgü değişken tipleri daha önceden de bildiğiniz gibi struct komutuyla tanımlanıyordu. C++’da bu yöntemin karşılığı, nesne yani class oluşturmaktır. Kısaca tanımlamak gerekirse nesne, içerisinde veri ve fonksiyon fonksiyon bulunduran bir yapı bloğudur. Standart değişkenlerin tanımlanmasında nasıl değişken türü ve değişken adı şeklinde bir kodlama yapıyorsak, aynı durum nesne oluşturmak için de geçerlidir. Örneğin aşağıda olduğu gibi temel ödev hesaplarının yapılmasına yönelik içinde üye değişken ve üye fonksiyon bulunduran sınıf örneği hazırlanmış olsun. Bu sınıf örneğinden yararlanarak, TemelOdev12 odev2(X1, Y1, X2, Y2); komutuyla bir odev2 nesnesi yaratabiliriz. Bundan sonra yapılması gereken, nesne içerisinde saklanacak verileri nesneye göndermek ve üye fonksiyonlar aracılığıyla işlenen sonuçları gerektiğinde geri almak. İ.Ö.BİLDİRİCİ, 02.04.12 41 Nesneyi (ya da sınıf örneğini) oluşturan değişken ve fonksiyonlar iki gruba ayrılır: private ve public. Private değişken ya da fonksiyonun sadece sınıf içerisinde tanımlıdır. Public değişken ve fonksiyonlara ise sınıf içerisinden erişilebileceği gibi sınıf dışından da erişilebilir. /*prg46*/ #include <iostream.h> #include <iomanip.h> #include <math.h> const double pi=3.14159265358979; class TemelOdev12 { private: double x1, y1, x2, y2; double dx, dy; public: double kenar(); double semt(); TemelOdev12(double xa, double ya, double xb, double yb); }; double TemelOdev12::kenar() { return sqrt(dx*dx+dy*dy); } double TemelOdev12::semt() { double aci=0.0; aci=atan2(dy,dx); if(aci<0) aci+=2*pi; return aci; } TemelOdev12::TemelOdev12(double xa, double ya, double xb, double yb) { x1=xa; y1=ya; x2=xb; y2=yb; dx=x2-x1; dy=y2-y1; } int main() { double X1, Y1, X2, Y2; cout << "\nKoordinatlari giriniz\n"; cout << "x1= cin >> X1; cout << "y1= cin >> Y1; cout << "x2= cin >> X2; cout << "y2= cin >> Y2; İ.Ö.BİLDİRİCİ, 02.04.12 "; "; "; "; 42 TemelOdev12 odev2(X1, Y1, X2, Y2); cout << "\n\nKoordinatlar\n"; cout << " nn x y \n"; cout << "======= ============ ===========\n\n"; cout.setf(ios::fixed); cout.setf(ios::showpoint); cout << " 1 cout << " 2 " << setw(12) << setprecision(3) << X1 << setw(12) << setprecision(3) << Y1 << endl; " << setw(12) << setprecision(3) << X2 << setw(12) << setprecision(3) << Y2 << endl; cout << "Kenar = " << odev2.kenar() << " m" << endl; cout << "Semt = " << setprecision(4) << odev2.semt()*200/pi << " g" << endl; return 0; } İ.Ö.BİLDİRİCİ, 02.04.12 43