Genel Standart C-programlama dili '' kitap '' STANDART C PROGRAMLAMA D İL İ Fedon Kadifeli A. C. Cem Say M. Ufuk Ça ğlayan Özgün metin © 1990, 1988 M. U. Ça ğlayan, F. Kadifeli ve A. C. C. Say. Geni şletilmi ş Türkçe baskı © 2000, 1993 F. Kadifeli, A. C. C. Say ve M. U. Ça ğlayan. Her hakkı mahfuzdur. Bu yayının hiçbir bölümü, yazarların izni olmadan fotokopi, teksir veya ba şka bir yolla ço ğaltılamaz, saklanamaz veya yayınlanamaz. Kitabın İngilizcesi ilk defa Türkiye’de 1990 A ğustos’unda yayınlanmı ştır. Türkçeye uyarlayan ve güncelleyen Fedon Kadifeli. Apple, Macintosh, MacWrite, MacDraw ve MacPaint, Apple Computer, Inc.’ın onaylı markalarıdır. Courier, Smith-Corona Corporation’ın onaylı bir markasıdır. IBM, International Business Machines Corp.’ın onaylı bir markasıdır. Microsoft, MS, MS-DOS, CodeView, QuickC ve Word, Microsoft Corp.’ın onaylı markalarıdır. OS/2, Microsoft’a lisanslı onaylı bir markadır. PDP, Digital Equipment Corp.’ın ticari bir markasıdır. Times ve Times Roman, Linotype AG ve/veya şubelerinin onaylı markalarıdır. UNIX, AT&T Bell Laboratories’in onaylı bir markasıdır. Windows, Microsoft QuickBasic ve Visual C++, Microsoft Corp.’ın ticari markalarıdır. Ailelerimize vii ÖNSÖZ C programlama dili, günümüzde en yaygın kullanılan dillerden biridir. C dili, COBOL, FORTRAN, PL/I gibi eski programlama dilleri grubuna dahil edilemeyece ği gibi, Ada, Modula-2 gibi yeni sayılabilecek dil grubuna da girmez. C dili, klasik programlama dilleri kavramlarının, yeni, basit ve kolay kullanılır bir şekilde sa ğlandı ğı pratik bir dildir. C’nin popülaritesi daha çok UNIX’inki ile ili şkilidir, çünkü C, ilk olarak, UNIX dünyasının programlama dili olarak ortaya çıkmı ştır. Bu popülarite, ki şisel bilgisayarların ço ğalması ve bunlar üzerindeki güçlü derleyici ile programlama ortamlarının kullanılabilir hale gelmesinden sonra daha çok artmı ştır. Bu ders kitabı, programlama dilleri üzerine Türkiye’de hazırlanan ders kitapları açı ğını kapatma amacını gütmektedir. Bilgisayar sistemlerine giri ş, sistem programlama, sistem yazılımı ve i şletim sistemleri gibi, C dilinin programlama projeleri geli ştirilmesinde ö ğretildi ği ve kullanıldı ğı dersler için tasarlanmı ştır. Kitap, üniversite birinci ve ikinci sınıfında okuyan ö ğrenciler için hedeflenmi ştir, ancak daha yüksek düzeyde de bir ba şvuru kitabı olarak kullanılabilir. Bu kitabı okuyacakların, en az bir yapısal programlama dilini—örne ğin Pascal, QuickBasic veya COBOL—bilmeleri ve veri yapıları konusunda temel bilgilere sahip olmaları beklenmektedir. Bu kitap, özellikle yazılım geli ştirme projelerinde C dilini kullanmayı dü şündükleri için, programlama dili bilgilerini geni şletmek isteyen bilgi i şlem uzmanları gibi ki şilerin kendi ba şlarına okuyabilecekleri şekilde de hazırlanmı ştır. Bu ders kitabı, C programlama dilinin bütün yönlerini kapsaması açısından tamdır. Önemli miktarda örnek program ve alı ştırmalar verilmi ştir. Okuyucuların, en azından bir IBM ki şisel bilgisayarını veya uyumlusunu ve Microsoft C Derleyicisi Uyarlama 5.00 veya daha yukarısını kullanabilecekleri beklenmektedir. Ancak, ekler dı şında, kitapta verilen bilgiler de ği şik C programlama ortamları için de geçerlidir. Bu kitabın Bo ğaziçi Üniversitesi Yayınları arasında İngilizce olarak yapılan ilk basımı halen Bo ğaziçi Üniversitesi Bilgisayar Mühendisli ği Bölümü’nde İşletim Sistemleri dersinde yardımcı ders kitabı olarak kullanılmaktadır. Kitap şu anda tamamen viii ÖNSÖZ güncelle ştirilmi ştir ve ANSI Standardının tüm özelliklerini kapsamaya çalı şmaktadır. Bu kitap sayesinde, yeni C derleyicileri tarafından desteklenen, Standart C’nin hem yeni hem de eski C programcıları tarafından kullanılmaya ba şlanaca ğını umuyoruz. Bu kitabın hazırlanması ve yayınlanmasında de ğerli önerileri, düzeltmeleri, destekleri ve katkıları olan Rasim Mahmuto ğulları, Sema Akgün, O ğuz Sinano ğlu, Ülkü Karada ğ, Ahmet Demirhan, Mustafa Elbir, Hasan Gültekin, Nezihe Bahar ve adını sayamayaca ğımız daha birçok ki şiye te şekkürlerimizi borç biliriz. Yük. Müh. F. Kadifeli Y. Doç. Dr. A. C. C. Say Doç. Dr. M. U. Ça ğlayan İstanbul Ekim 1993 ix İÇ İNDEK İLER ÖNSÖZ ............................................................................................................................vii İÇ İNDEK İLER................................................................................................................ix ŞEK İLLER VE Ç İZELGELER L İSTES İ ....................................................................xv BÖLÜM 0: G İRİŞ ............................................................................................................ 1 0.1. C Dilinin Kısa Bir Tarihi......................................................................................1 0.2. C Dilinin Üstünlükleri ..........................................................................................2 0.3. Kullanılan Sistem..................................................................................................3 0.4. Kitabın Yapısı Ve Kullanılan Kurallar .................................................................4 Problemler ...................................................................................................................4 BÖLÜM 1: TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş...................................5 1.1. Açıklamalar, Tanıtıcı Sözcükler Ve Anahtar Sözcükler .......................................5 1.2. De ği şmezler..........................................................................................................7 1.3. Temel Veri Tipleri Ve Tanımlar...........................................................................9 1.4. #define Ve #include Öni şlemci Emirleri ............................................................12 1.5. İşleçler, İfadeler Ve Atama Deyimleri................................................................13 1.6. Tip Dönü şümü Ve Kalıplar ................................................................................16 x İÇ İNDEK İLER 1.7. Basit Girdi/Çıktı .................................................................................................17 1.8. C Deyimleri Ve Program Gövdesi......................................................................21 1.9. Bir C Programı Nasıl İşletilir..............................................................................22 1.10. Örnek Programlar .............................................................................................24 Problemler .................................................................................................................26 BÖLÜM 2: DEY İMLER VE KONTROL AKI ŞI........................................................29 2.1. C Dilinin Deyimleri ............................................................................................29 2.2. Ba ğıntısal Ve Mantıksal İşleçler.........................................................................30 2.3. Do ğruluk-De ğerli İfadeler ..................................................................................32 2.4. if Deyimi Ve Ko şullu İşleç .................................................................................33 2.5. while Deyimi ......................................................................................................35 2.6. do Deyimi ...........................................................................................................36 2.7. for Deyimi Ve Virgül İşleci................................................................................37 2.8. continue Deyimi..................................................................................................38 2.9. break Deyimi ......................................................................................................39 2.10. goto Deyimi Ve Etiketler..................................................................................39 2.11. switch Deyimi...................................................................................................40 2.12. Bir Örnek—Sayı Sıralama................................................................................42 Problemler .................................................................................................................43 BÖLÜM 3: GÖSTERGELER VE B İT İŞLEME.........................................................45 3.1. Gösterge De ği şkenleri Ve İşlemleri....................................................................45 3.1.1. & Ve * İşleçleri ...............................................................................................46 3.1.2. Gösterge De ği şkenleri Bildirimleri..................................................................47 3.1.3. Gösterge Aritmeti ği .........................................................................................47 3.2. Göstergeler Ve Diziler........................................................................................49 3.3. Karakter Dizileri.................................................................................................51 3.4. Bitsel İşleçler......................................................................................................53 3.5. İşleç Önceli ği Ve Birle şme.................................................................................57 Problemler .................................................................................................................58 İÇ İNDEK İLER xi BÖLÜM 4: FONKS İYONLAR VE PROGRAM YAPISI ..........................................59 4.1. Fonksiyon Tanımlama ........................................................................................60 4.2. Fonksiyon Ça ğrıları ............................................................................................62 4.2.1. De ğer İle Ça ğrı ................................................................................................64 4.2.2. Referans İle Ça ğrı............................................................................................65 4.2.3. main Fonksiyonunun Parametreleri .................................................................67 4.3. Bellek Sınıfları....................................................................................................69 4.3.1. auto De ği şkenler..............................................................................................70 4.3.2. register De ği şkenler.........................................................................................70 4.3.3. static De ği şkenler Ve Fonksiyonlar .................................................................71 4.3.4. Fonksiyonlar Ve extern De ği şkenler................................................................72 4.3.5. İlkleme.............................................................................................................73 4.4. Özça ğrı ...............................................................................................................75 4.5. Fonksiyonlara Göstergeler..................................................................................78 4.6. Bir Örnek—8 Vezir Problemi.............................................................................80 Problemler .................................................................................................................84 BÖLÜM 5: TÜRET İLM İŞ T İPLER VE VER İ YAPILARI.......................................87 5.1. Sayım Tipleri......................................................................................................87 5.2. Yapılar................................................................................................................89 5.3. Yeni Tip Tanımlama...........................................................................................92 5.4. sizeof İşleci.........................................................................................................94 5.5. Birlikler ..............................................................................................................95 5.6. Alanlar................................................................................................................96 5.7. Bellek Ayırma.....................................................................................................98 5.8. Karma şık Tipler..................................................................................................98 5.8.1. Dizi Dizileri.....................................................................................................99 5.8.2. Dizilere Göstergeler.......................................................................................100 5.8.3. Gösterge Dizileri ...........................................................................................101 5.8.4. Göstergelere Göstergeler ...............................................................................102 5.9. Bir Örnek—Dosya Sıralama.............................................................................103 xii İÇ İNDEK İLER Problemler ...............................................................................................................107 BÖLÜM 6: ÖN İŞLEMC İ ............................................................................................ 109 6.1. #define Ve #undef Emirleri ..............................................................................110 6.2. #include Emri ...................................................................................................112 6.3. Ko şullu Derleme...............................................................................................113 6.4. Di ğer Emirler....................................................................................................115 6.5. Önceden Tanımlanmı ş İsimler..........................................................................115 6.6. Bir Örnek—ctype.h Ba şlık Dosyası..................................................................116 Problemler ...............................................................................................................117 BÖLÜM 7: DOSYALAR VE G İRD İ/ÇIKTI ............................................................. 119 7.1. Dosya Esasları ..................................................................................................119 7.2. Dosya Eri şimi—Ba şka Yöntemler....................................................................121 7.3. Rastgele Eri şim.................................................................................................123 7.4. Dosyalarla İlgili Ba şka Bilgiler ........................................................................124 7.5. Sistem İle İlgili Fonksiyonlar............................................................................125 7.6. Dosya Tanımlayıcıları Ve İlgili Fonksiyonlar ..................................................126 7.7. Bir Örnek—Ö ğrenci Veritabanı .......................................................................128 Problemler ...............................................................................................................132 EK A: KARAKTER KODLARI Ç İZELGES İ........................................................... 135 EK B: MICROSOFT C DERLEY İC İS İ HAKKINDA TEMEL B İLG İLER.......... 145 B.1. Bellek Modelleri ..............................................................................................145 B.1. QC Kütüphanesi...............................................................................................146 B.3. CL Eniyile ştirici Derleyicisi.............................................................................147 EK C: MICROSOFT CODEVIEW HATA DÜZELT İC İS İNE GENEL B İR BAKI Ş .................................................................................................................... 15 1 EK D: MICROSOFT LIB VE NMAKE YARDIMCI PROGRAMLARINA GENEL B İR BAKI Ş.............................................................................................. 155 İÇ İNDEK İLER xiii D.1. LIB Yardımcı Programı...................................................................................155 D.2. NMAKE Yardımcı Programı...........................................................................156 EK E: D İLLERARASI ÇA ĞRILAR .......................................................................... 159 E.1. Birle ştirici İle Ba ğlayıcının Kullanılması.........................................................159 E.2. Satıriçi Birle ştiricisinin Kullanılması ...............................................................162 E.3. Bir Örnek—Disket Saklama.............................................................................163 EK F: STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLER İ ..................................................................................................... 169 F.1. C Dünyanın Her Yerinde—Yöreler..................................................................169 F.2. Geni ş Karakterler Ve Çokbaytlı Karakterler ....................................................170 F.3. Üçlü Karakterler...............................................................................................170 F.4. Zaman Fonksiyonları........................................................................................171 F.5. Standart Ba şlık Dosyaları.................................................................................173 F.6. Çevirme Sınırları ..............................................................................................181 EK G: SEÇ İLM İŞ PROBLEMLERE YANITLAR................................................... 183 EK H: TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ.............................................................................................................. 187 H.1. Türkçe- İngilizce Sözlük...................................................................................187 H.2. İngilizce-Türkçe Sözlük...................................................................................198 B İBL İYOGRAFYA ......................................................................................................209 D İZ İN.............................................................................................................................2 13 xv ŞEK İLLER VE ÇİZELGELER L İSTES İ Ç İZELGE 2.1 C dilinin deyimleri.....................................................................................30 Ç İZELGE 2.2 C i şleç önceli ği ve birle şme.......................................................................32 ŞEK İL 2.1 while ve do deyimleri için akı ş çizenekleri.....................................................36 Ç İZELGE 3.1 C i şleç önceli ği ve birle şme.......................................................................57 ŞEK İL 4.1 main fonksiyonuna geçirilen komut satırı argümanları...................................69 ŞEK İL 5.1 Bir örnek ikili a ğaç .......................................................................................104 1 BÖLÜM 0: G İR İŞ /* Ilk program */ #include void main (void) { int kar; if ((kar=getchar())!='\n') main(); putchar(kar); } E ğer bir C programının nasıl göründü ğünü merak ettiyseniz, yukarıda, “yararlı ve anlamlı” bir i ş yapan tam bir C programının durdu ğunu ö ğrenmek sizi şa şırtabilir. Bir C derleyiciniz varsa ve nasıl kullanaca ğınızı biliyorsanız, bu programı yazın, derleyin ve çalı ştırın. Fakat önce, programın ne yapabilece ği konusunda çılgın tahminlerde bulunmaktan da çekinmeyin. ... E ğer tahmininiz do ğru çıkmadıysa, üzülmeyin. Bu, sadece C hakkında ilginizi çekmek içindi ve umarız öyle oldu! Bu basit gibi görünen, ancak C’nin birtakım ileri özelliklerini kullanan programı, kitabın yarısını bitirinceye kadar anlamanızı beklemiyoruz ve bu kitabı bitirdi ğinizde çok daha karma şık programları bile anlayabilece ğinizi ve yazabilece ğinizi bekliyoruz. 0. 1. C Dilinin Kısa Bir Tarihi UNIX i şletim sistemi ile C programlama dili birbirleriyle yakından ili şkilidir. Tarihleri 70’lerin ba şında ba şlar. İlginç olan şey de, AT&T Bell Laboratuvarları’ndan Ken Thompson tarafından yazılan bir bilgisayar oyun programından kaynaklanmalarıdır. 2G İR İŞ BÖLÜM 0 Thompson, programını bir PDP-7 bilgisayarına uyarlamak istedi ğinde, bu küçük makina hakkında çok şey ö ğrendi, ancak i şletim sistemini pek be ğenmedi. Bunun üzerine, o zamanlar daha büyük bir makinada kullanılan MULTICS i şletim sisteminin basitle ştirilmi ş ve de ği ştirilmi ş bir uyarlamasını yazmaya karar verdi. Daha sonra, Dennis M. Ritchie de ona katıldı ve Brian W. Kernighan tarafından UNICS (Uniplexed Information and Computing Service—Birle ştirilmi ş Bilgi ve Hesaplama Hizmeti) adı verilen i şletim sisteminin ilk uyarlaması do ğdu. Bu üç ki şi C ve UNIX’in tarihinde en önemli rolü oynadılar. Ba şlangıçta, Thompson, daha önceleri 1967 civarında geli ştirilen BCPL adlı “tipsiz” dilden de büyük ölçüde etkilenerek B dilini tasarımladı. Bundan sonra, Ritchie UNIX’i daha kolay bir şekilde yazma amacıyla C adında yeni bir dil tasarımladı. 1973 yılında ise Ritchie ve Thompson C’yi kullanarak UNIX’i yeni ba ştan yazdılar. Sonuç o kadar iyiydi ki, 1983’te ACM’in Turing Ödülü’nü almaya hak kazandılar. O zamandan beri, C çok de ği şmedi. Dilde yapılan bazı küçük geni şletmeler, Dennis M. Ritchie tarafından hazırlanan The C Programming Language—Reference Manual (C Programlama Dili—Ba şvuru Elkitabı) adlı, 1983 basımlı, Bell Laboratuvarları yayınında anlatılmaktadır. ANSI’nin (American National Standards Institute—Amerikan Ulusal Standartlar Enstitüsü) X3J11 komitesi tarafından 1988 Ekim’inde sunulan, C Standardının son tasla ğı bu de ği şiklikleri resmile ştirmekte ve kendi ba şına yenilerini eklemektedir. Yapılan düzenlemelerle, birtakım programcı hatalarını azaltmak için derleyici kontrolleri artırılmı ş ve dile yararlı birkaç özellik daha katılmı ştır. Ancak, tasarımcılarının felsefesine aykırı oldu ğu için dilin daha fazla geni şletilmesi beklenmemelidir. Bunun yerine, bu dilden yeni diller ortaya çıkmaktadır. Bir örnek, C++’dır. Bu dil, nesneye yönelik programlama ve veri soyutlama teknikleri sa ğlarken, Standart C ile uyumlu kalmaya çaba göstermektedir. Bu özellikleri, dili daha kapsamlı bir uygulama programlama dili yapmaktadır. Yakın zamanda ise C++’nın C’nin yerini alması beklenmektedir, ancak yine de C++ ö ğrenecek birisinin önce Standart C’yi bilmesi gerekmektedir. 0.2. C Dilinin Üstünlükleri Önceki kısımdan, C’nin pratik gereksinmelerden ortaya çıktı ğı sonucuna varabiliriz; yani belirli bir sistem için yapay hazırlanmı ş bir dil de ğildir. C, birle ştirici dilinin sorunlarını kısmen çözmek için, dü şük düzeyli programlamayı destekleyici kolaylıkları olan yüksek düzeyli bir dil olarak tasarımlanmı ştır. Örne ğin, dilde girdi/çıktı deyimleri yoktur. Kullanıcı, girdi/çıktı yapmak için “getchar” ve “putchar” gibi bazı fonksiyonları ça ğırır. Derleyici bu fonksiyonların anlamı hakkında hiçbir şey bilmez. Sadece, C kütüphanesinde tanımlı olan bu fonksiyonlara ça ğrılar üretir. Bu da, iyi bir kütüphanenin C’ye çok şey kazandıraca ğı anlamına gelir. C’nin di ğer dillere göre bazı avantajları vardır. Bunlar a şa ğıda özetlenmektedir: C, kısa, özlü, verimli, esnek ve ifadeli bir dildir. Az sayıda anahtar sözcü ğe sahiptir, fakat do ğru kontrol yapıları, güçlü i şleçleri (di ğer adıyla, i şlem operatörleri) ve kolayca birle ştirilen veri tipleri vardır. Bu da, dili ö ğrenmenin ve bir C derleyicisinin yazılmasının kolay oldu ğu ve bu dilde yazılan programların kısa, fakat bazen izlemesi zor oldu ğu BÖLÜM 0 G İR İŞ 3 anlamına gelir. Bazı i şleçler di ğer dillerde yoktur, fakat bunlar kolayca makine diline çevrilebilirler, bu da C dilinde yazılan programların di ğer dillerde yazılanlara göre daha verimli çalı şmalarının nedenini açıklar. Bundan dolayı, bazı sistemlerde C, birle ştirici dilinin yerini almı ştır. C, popüler bir i şletim sistemi olan UNIX’in temel dilidir. Bu da, en azından bu i şletim sisteminde, bu dili vazgeçilmez kılmaktadır. Buna ra ğmen, C ba şka sistemlerde de kullanılmaya ba şlanmı ştır ve, ta şınabilme özelli ğinden dolayı, bir sistem için yazılmı ş programlar kolayca ba şka sistemlere de aktarılabilmekte ve orada bazı ufak tefek de ği şikliklerden sonra derlenip do ğru bir şekilde çalı ştırılabilmektedir. Bu durum dilin amaçlarından biridir: programcının makine ba ğımlılıklarını bir tarafta ayırması ve gereksinim duydu ğunda programı yeni ortamlara kolayca uyarlayabilmesi. C öni şlemcisi bu konuda önemli bir rol üstlenmektedir. C modüler programlamayı te şvik etmektedir. Di ğer ça ğda ş programlama dilleri kadar yaygın olmamasına ra ğmen, programcının bunu sa ğlaması için bazı seçimler sunar. Çe şitli bellek sınıfları çe şitli düzeylerde gizlilik ve modülarite sa ğlar. Dildeki tek modül yapısı olan fonksiyon tanımı için C tek bir düzeye izin verir; bütün fonksiyonlar dı şsaldır. Programcı, kolayca, kullanıcı tarafından tanımlanmı ş kaynak veya amaç kütüphaneleri yaratabilir ve bu yolla çok büyük programlar hazırlayabilir. C’nin dezavantajları da vardır. C dilinde yazılan programların izlenmesi bir miktar zor olabilir, çünkü zengin i şleç kümesi program okunaklılı ğını azaltır. C katı-tiplenmi ş bir dil de ğildir; bir dizinin sınırları dı şında indisleme yapmaya çalı şmak gibi, bazı programcı hataları için yürütme zamanı deste ği sa ğlamaz; bazı durumlarda, derleyici, ifadeler içindeki alt-ifadelerin veya argüman listeleri içindeki ifadelerin hesaplanma sıralarını de ği ştirebilir; aynı simgelerin birden fazla amaca hizmet etmesi bazı programlama hatalarına yol açabilir—e şitlik testi ve atama i şleçlerinin karı ştırılması gibi; bazı yapılar— örne ğin switch deyimi—daha iyi tasarlanabilirdi. Bu sorunların bazıları, C’nin ANSI Standardını izleyen bazı yeni derleyicilerde iyile ştirilmi ştir. Ayrıca, C’ye dayanarak geli ştirilen C++ dili, bazı sorunları çözmü ş ve birçok yeni özellikler katmı ştır. Gerçek bir C programcısının, C’nin dezavantajları ile birlikte ya şamayı ö ğrenmesi gerekti ğine inanıyoruz. 0.3. Kullanılan Sistem C “ta şınabilir bir dil” olmasına ra ğmen—ki, bu da, belirli bir sistem için yazılmı ş olan bir C programının ba şka bir sisteme aktarıldı ğında orada ba şarılı bir şekilde derlenip yürütülebilece ği anlamına gelir—sistemler arasında bazı farklılıklar olabilmektedir. Bu kitapta verilen program veya program parçaları Microsoft QuickC Uyarlama 1.01 (1988), Microsoft C Derleyicisi Uyarlama 5.00 (1987) ve Microsoft C/C++ Eniyile ştirici Derleyicisi Uyarlama 8.00 (1993) kullanılarak denenmi ştir. Kullandı ğımız i şletim sistemi IBM uyumlu bir PC’de çalı şan MS-DOS Uyarlama 5.00 (1991) veya daha yukarısıdır. Bir sonraki bölümde bu ortamların nasıl kullanılabilece ği konusunda daha detaylı bazı bilgiler verilmi ştir. Ayrıca Ek B’ye bakınız. 4G İR İŞ BÖLÜM 0 0.4. Kitabın Yapısı Ve Kullanılan Kurallar Bu kitabın İngilizce olan ilk uyarlaması bir Apple Macintosh Plus’ta Word ve MacDraw isimli yazılımlar kullanılarak hazırlanmı ştır. Kitap en son olarak, IBM uyumlu bir PC’de çalı şan Windows için Word Uyarlama 2.0c kullanılarak güncelle ştirilmi ş ve Türkçe baskıya hazır hale getirilmi ştir. Temel yazı tipi Times Roman’dır. Sözdizimsel gösterimde, sözdizimsel sınıflar italik yazı stili ile gösterilmi ştir. İste ğe ba ğlı bölümler, arkalarında satır altına yazılan opt simgesiyle gösterilmi ştir. Program bölümleri, ekran veya yazıcı ç ıktısına benzetilmek için, Courier yazı tipiyle yazılmı ştır. C anahtar sözcükleri koyu, program açıklamaları ise italik ile yazılmı ştır. Bilgisayar girdi/çıktısı da Courier yazı tipiyle gösterilmi ştir; çıktı, girdiden ayırt edilmesi için, alt çizgili yazılmı ştır. Kitabın geri kalan kısmında 7 bölüm, 8 ek ve C programlama diliyle ilgili bazı kaynakların liste halinde verildi ği bir bibliyografya vardır. Bölüm 1’de dile bir giri ş yapılmakta ve çok basit programlar yazmak için gerekli olan genel bilgiler verilmektedir. Bölüm 2, C dilindeki kontrol deyimlerini ve do ğruluk-de ğerli, yani mantıksal, ifadeleri anlatmaktadır. Bölüm 3 göstergeler ve bit i şlemleri hakkındadır. Bölüm 4’te fonksiyonlar ve de ği şkenlerle fonksiyonlara uygulanabilecek çe şitli bellek sınıfları anlatılmaktadır. Bölüm 5, karma şık veri yapıları tanımlamada anahtar olan, bütün türetilmi ş veri tiplerini kapsamaktadır. Bölüm 6, C öni şlemcisine ayrılmı ştır ve bütün öni şlemci emirlerini anlatmaktadır. Bölüm 7’de, di ğer bazı fonksiyonlarla beraber, Standart C kütüphanelerinde tipik olarak rastlanan girdi/çıktı i şlemleri anlatılmaktadır. Ekler ise Microsoft C Derleyicisi ve çevresinin bazı özelliklerini anlatmakta, bazı problemlerin yanıtlarını vermekte ve kitapta kullanılan terimlerin İngilizce kar şılıklarını bulmak için bir Türkçe- İngilizce ve İngilizce-Türkçe terimler sözlü ğü içermektedir. Kitapta, olanaklar dahilinde, yaygın olarak kullanılan Türkçe terimler tercih edildi ği için, İngilizce bilgisayar terimleri hakkında bilgi sahibi olan okuyucu, bu kitapta kullanılan Türkçe terimleri anlamak için sık sık Ek H’de verilen bu sözlüklere ba şvuracaktır. Problemler 1. Bu bölümün ba şında verilen programı sisteminizde çalı ştırın. E ğer herhangi bir zorlukla kar şıla şırsanız sisteminizin yardım özellikleri, elkitapları veya deneyimli programcılara ba şvurun. Bu programı çalı ştırmak için kaç komuta gereksiniminiz var? 2. Bir önceki alı ştırmadaki programı tekrar yazın (veya de ği ştirin), fakat bu kez, iki satırı, tek satırda, arada bir bo şluk karakteri bırakarak yazın. # ile ba şlayan satırın arkasına bir şey yazmamaya dikkat edin. Derleyicinin aynı şekilde kabul etmesi gerekir. Şimdi, program içinde, rastgele yerlere bo şluklar, satır ba şları veya duraklar (tab) ekleyin. Derlerken ortaya çıkacak hata mesajları varsa, bunları anlamaya ve düzeltmeye çalı şın. 5 BÖLÜM 1: TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş Şimdi, C dilinin temel yapı ta şlarını anlatıp, birtakım temel programlama kavramlarının C dilinde nasıl gerçekle ştirildi ğini gösterece ğiz. Bu bölümün amacı, mümkün oldu ğu kadar çabuk, basit C programları yazmak ve çalı ştırmak için gerekli olan bilginin okuyucuya kazandırılmasıdır. Okuyucunun zaten en az bir programlama dilini bildi ği farz edildi ği için, burada bahsedilecek olan temel programlama kavramları detaylı olarak açıklanmayacaktır. Bir sonraki bölümden ba şlayarak, bu kavramlar C dilinin genel çerçevesi içinde ele alınarak derinlemesine açıklamalar verilecektir. 1. 1. Açıklamalar, Tanıtıcı Sözcükler Ve Anahtar Sözcükler Açıklamalar Bölü-yıldız (/*) ile ondan sonraki ilk yıldız-bölü (*/) arasında bulunan herhangi bir karakter dizisi bir program açıklamasıdır ve derleyici açısından bir bo şlu ğa e şde ğer olarak kabul edilir. Bir açıklama grubunun şöyle yazılması önerilmektedir: /* * * * * * * * * * * * * * * * * * * * * * * * * * *\ * * * Buyuk bir aciklama obegi... * * * \* * * * * * * * * * * * * * * * * * * * * * * * * * */ veya /* Daha kucuk bir aciklama obegi... */ 6 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş BÖLÜM 1 Program açıklamaları bu kitapta italik olarak yazılmı ş ve sistemler arasındaki uyumsuzluklardan kaçınmak için Türkçe karakterler kullanılmamı ştır. Tanıtıcı Sözcükler De ği şkenler, deyim etiketleri, tip isimleri, fonksiyon isimleri gibi, programcı tarafından olu şturulan bütün nesneleri isimlendirmek için tanıtıcı sözcükler, bir di ğer adıyla, program isimleri kullanılır. Tanıtıcı sözcükler için şu kurallar geçerlidir: 1. Herhangi bir sayıda karakterlerden olu şur, ancak ilk 31 karakter dikkate alınır. 2. İlk karakter bir harf veya altçizgi (_) olmalıdır. 3. Geri kalan bütün karakterler bir harf, rakam veya altçizgi olabilir. Örnek olarak, A12, a12, sayfa_basi de ği şken ismi olarak kullanılabilir. Küçük ve büyük harflerin farklı oldu ğuna dikkat ediniz, yani A12 ile a12 farklı tanıtıcı sözcüklerdir. Ancak, bazı ortamlarda küçük büyük harf ayırımı yapılmayabilir. Bundan dolayı, aynı program içinde, harf ayrımı d ı şında, birbirine benzeyen iki farklı isim kullanmaktan kaçının. Ayrıca, bir tanıtıcı sözcükte, ilk karakter olarak altçizgiden kaçınılması önerilir, çünkü bu tip isimler derleyiciye özgü bazı anahtar sözcükler veya di ğer isimler için kullanılmaktadır. Anahtar Sözcükler C dilinde 32 adet anahtar sözcük vardır; hepsi küçük harfle yazılır. Anahtar sözcükler tanıtıcı sözcük olarak kullanılamazlar; kendilerine özgü kullanım alanları vardır. C dilindeki bütün anahtar sözcüklerin sınıflandırılmı ş bir listesi a şa ğıda verilmi ştir. Program içinde kullanaca ğınız isimlerin a şa ğıdaki listede olmamasına dikkat edin. veri tipi bellek sınıfı deyim i şleç char auto break sizeof const extern case double register continue enum static default float typedef do int else long for short goto signed if struct return union switch unsigned while void volatile Kullanılan makine ve derleyiciye ba ğlı olarak, C dilinin özel durumundan dolayı ba şka anahtar sözcükler de olabilir. Bunlar genelde altçizgi karakteriyle ba şlarlar. BÖLÜM 1 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş 7 1.2. De ği şmezler C dilinde, tamsayı, kayan noktalı, yani gerçek sayı, karakter ve karakter dizisi de ği şmezleri bulunur. Tamsayı De ği şmezleri Tamsayı de ği şmezleri, program içinde, ondalık, sekizli veya onaltılı sayılar şeklinde belirtilebilirler ve derleyicinin tipine göre, 16 bit veya 32 bit şeklinde saklanırlar. A şa ğıdaki örneklerde bazı tamsayı de ği şmezleri görülmektedir: 123 ondalık 123 0123 sekizli 123 = ondalık 83 083 geçersiz bir sayı 0x123 onaltılı 123 = ondalık 291 0XFF onaltılı FF = ondalık 255 Sayının önündeki bir sıfır rakamının, geri kalan rakamların sekizli (yani, 0-7) ve sayı önündeki bir sıfırla onun arkasından gelen küçük veya büyük x harfinin, geri kalan rakamların onaltılı (yani, 0-9, A-F veya a-f) olması gerekti ğini gösterdi ğine dikkat edin. Sayının program içindeki gösterimi ne olursa olsun, makine içinde her zaman bitler halinde ikili sistemde saklanır; ancak bu durum genelde programcıyı ilgilendirmez. Bir tamsayı de ği şmezi, e ğer de ğeri 16 bite sı ğıyorsa, kısa formda (16 bit) saklanır, aksi takdirde uzun formda (32 bit) saklanır. Tamsayı bir de ği şmezin uzun formda saklanmasını zorlamak için de ği şmezin arkasına l veya L harfi eklenmelidir. 1 sayısı ile karı ştırılmaması için, küçük l yerine büyük L harfinin kullanılması önerilir. 123 16 bitte saklanır 123l 32 bitte saklanır 123L 32 bitte saklanır 077 000077 şeklinde, 16 bitte saklanır 077L 0...077 şeklinde, 32 bitte saklanır 0xFFFF 16 bitte saklanır 0xFFFFL 0000FFFF şeklinde, 32 bitte saklanır 0xFFFFF 000FFFFF şeklinde, 32 bitte saklanır Bir sekizli veya onaltılı tamsayı de ği şmezi, daha büyük bir bellek alanına yerle ştirildi ği zaman, soluna sıfır konur. Yani böyle de ği şmezlerin i şaretsiz oldu ğu varsayılır. Ondalıklı bir tamsayı de ği şmezinin i şaretsiz olarak i şlem görmesini sa ğlamak için arkasına u veya U eki konulmalıdır, örne ğin 65000U. Kayan Noktalı Sayı De ği şmezleri Kayan noktalı sayı de ği şmezleri ya tamsayı ile kesir kısmı arasına nokta konarak yada bilimsel gösterimde belirtilirler. İkinci yöntem, genelde, çok büyük veya çok küçük sayılar için kullanılır. A şa ğıda bazı örnekler vardır: 8 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş BÖLÜM 1 1.123 1.23E20 = 1.23×10 20 1.23e20 = 1.23×10 20 (büyük veya küçük harf olabilir) 123E18 = 1.23×10 20 1.23E-20 = 1.23×10 -20 De ği şmezin içinde herhangi bir bo şlu ğun olmaması gerekti ğine dikkat edin. Normalde, kayan noktalı de ği şmezler 8 baytta, yani double (çift) duyarlıkta, saklanır. E ğer kayan noktalı de ği şmezde f veya F eki bulunuyorsa, o zaman 4 baytta, yani tek duyarlıkta; e ğer l veya L eki kulanılırsa, o zaman long double (uzun çift veya dörtlü) duyarlıkta saklanır. Karakter De ği şmezleri Bir karakter de ği şmezi, 'A', 'a', '%' gibi tırnak i şaretleri arasına konulan tek bir karakter veya tek bir karaktere e şde ğer olan bir kaçı ş sırasıdır. Bir kaçı ş sırası bir ters bölü i şareti ile bir harf veya rakamlardan olu şur. C dilinde sadece şu kaçı ş s ıraları kullanılır: \n yeni satır \b geri alma \r satırba şı \t durak (tab) \f sayfa ilerletme \v dikey durak \a zil \' tek tırnak \" çift tırnak \? soru i şareti \\ ters bölü \ddd sekizli kodu ddd olan karakter \xhhh onaltılı kodu hhh olan karakter (Ek A’ya bakınız) Ek olarak, a şa ğıda bazı karakter de ği şmezleri örnekleri vardır: '\0' boş karakter '\'' bir karakter de ği şmezi olarak tek tırnak '\"' bir karakter de ği şmezi olarak çift tırnak '\\' bir karakter de ği şmezi olarak ters bölü '\101' sekizli kodu 101 olan karakter (ASCII sisteminde 'A' harfi) '\x041' onaltılı kodu 41 olan karakter (ASCII sisteminde 'A' harfi) Bir karakter de ği şmezinin tipi int’tir. Karakterler ise tipik olarak bir baytta (8 bit) saklanır ve tamsayı gibi i şlem görürler. Ancak signed (i şaretli) veya unsigned (i şaretsiz) oldukları veya kullanılan kodlama sistemi C Standardında belirtilmemi ştir. Bizim sistemimizde, ASCII kodlama sistemi kullanılır (Ek A’ya bakınız). Normal karakterlerin (örne ğin, sistemimizdeki 7 bitlik ASCII karakterlerinin) i şaretsiz oldukları BÖLÜM 1 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş 9 garanti edilmi ştir. Gerekti ğinde, bir karakter de ği şkeninin i şaretli olup olmadı ğı programcı tarafından açıkça belirtilmelidir. Karakter Dizisi De ği şmezleri Bir karakter dizisi de ği şmezi çift tırnaklar arasında yazılmı ş herhangi bir sayıda karakter veya yukarıda listesi verilmi ş kaçı ş sırasından olu şur. İşte bazı örnekler. Son örnekteki, yeni satır (\n) ve tek tırnak (\') kaçı ş sıralarına dikkat edin. "" boş karakter dizisi "Merhaba" 7 karakterlik bir karakter dizisi "Isminizi girin,\nveya ENTER\'a basin" iki satırdan olu şan bir karakter dizisi Bir karakter dizisi de ği şmezi bellekte saklandı ğı zaman, dizinin sonuna otomatik olarak boş karakter (\0) eklenir; bundan dolayı diziyi saklamak için kullanılan bayt sayısı dizinin uzunlu ğundan bir fazladır. Bir program içinde, aralarına hiçbir i şaret koymadan pe şpe şe yazılan karakter dizisi de ği şmezleri birle ştirilir ve tek bir dizi de ği şmezi olarak alınırlar. Diziler, bazı sistemlerde, salt-okunur belle ğe yerle ştirilebilirler, bu da onları de ği ştirilemez kılabilir. Ayrıca, birbirine tıpatıp benzeyen iki veya daha fazla karakter dizisi aynı bellek bölgesinde saklanabilir. Sistemler arasındaki uyumsuzluklardan kaçınmak için, bu kitaptaki karakter dizisi de ği şmez örneklerinde Türkçe karakterler kullanılmamı ştır. Bir Sonraki Satıra Devam Etme Bir deyim veya karakter dizisi de ği şmezi programın tek bir satırına sı ğmıyorsa ve bir sonraki satıra devam etmek gerekiyorsa, satırın sonuna ters bölü (\) i şareti konup bir sonraki satıra devam edilebilir. Ayrıca, uzun bir karakter dizisi de ği şmezi iki satırda iki ayrı karakter dizisi şeklinde de yazılabilir. 1.3. Temel Veri Tipleri Ve Tanımlar Bir de ği şken ismi, de ği şkenin alaca ğı de ğerlerin türü ve i şlevini yansıtacak şekilde dikkatlice seçilen bir tanıtıcı sözcüktür. Genelde, kalan_gunler veya kalanGunler şeklinde bir de ği şken ismi x132 gibi bir isme tercih edilmelidir. De ği şken isimlerinde büyük harfler yerine küçük harflerin kullanılması alı şılagelmi ştir. Bir C programında, kullanılmadan önce, tüm de ği şken ve fonksiyonların tanımı veya bildirimi yapılmalıdır. Temel veri tiplerinin, yani tamsayı, kayan noktalı sayılar ve karakterlerin bildiriminde kullanılan anahtar sözcükler şunlardır: 10 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş BÖLÜM 1 int tamsayı signed, unsigned i şaretli veya i şaretsiz tamsayılar short, long kısa veya uzun tamsayılar float, double tek veya çift duyarlıklı kayan noktalı sayılar char karakter Bir tanım, bir tip ismi ile tanımlanmakta olan nesnelerin virgülle ayrılmı ş listesinden olu şur ve bir noktalı virgül ile sona erer. A şa ğıda birkaç örnek tanım gösterilmi ştir: int x; int x1, y1, z1; long d, d1; char c; char c1, c2, c3; float a; float a1, a2, a3; int u[3]; float k[10*20]; Son iki tanımda, tek boyutlu ve üç elemanlı bir tamsayı dizisi ile tek boyutlu ve 200 elemanlı kayan noktalı sayılardan olu şan bir dizi tanımlanmı ştır. Dizinin boyunun derleme esnasında hesaplanabilen de ği şmez bir ifade oldu ğuna dikkat edin. A şa ğıda görüldü ğü gibi, de ği şkenler tanımlandıkları zaman ilk de ğerleri de verilebilir: int x = 0; int x1 = 10, x2 = 20, x3 = 30, x4 = 60 * 60; /* ilk deger degismez bir ifadedir */ char c1 = 'a', c2 = 'z'; Buna ilkleme diyoruz. İlk de ğer olarak bir ifadenin de yazılabilece ğine dikkat edin. Tanımlanan de ği şkenlerin ilklenmesi iyi bir alı şkanlıktır. İsimlendirilmi ş de ği şmezler, yani de ğerleri de ği ştirilemeyecek olan de ği şkenler, const tip niteleyicisi kullanılarak tanımlanırlar: int const x = 100; char const ys = '\n'; float const a = 123.45; Bu tip de ği şmez “de ği şken”lerin const ile tanımlanmasının en azından iki avantajı vardır: 1. Programcı yanlı şlıkla bu tip bir de ği şkene atama yapmaya kalkar veya de ğerini de ği ştirebilecek bir şekilde kullanmaya kalkarsa, derleyici onu uyaracaktır. 2. Çok kullanıcılı sistemlerde bu tip de ği şkenlerin ortak ve de ği ştirilemez bir bellek kesimine yüklenmesi sa ğlanabilir. Aynı anda ba şka bir süreç (program) tarafından kullanılan veya de ği ştirilebilen de ği şkenlerin, derleyicinin olası bir eniyileme yapmasını engellemek için, volatile tip BÖLÜM 1 TEMEL KAVRAMLAR VE GENEL B İR BAKIŞ1 1 niteleyicisi kullanılarak tanımlanması gerekmektedir. Örne ğin, çok kullanıcılı ortamlarda iki de ği şik süreç tarafından ortak kullanılan bir de ği şkenin volatile tanımlanması gerekir. Tanımlanmı ş bir de ği şken, bir deyim içinde ismi verilerek anılır. Dizi elemanlarına ula şmak için çe şitli yollar olmasına ra ğmen, ço ğu zaman dizi isminin arkasına kö şeli parantezler içinde indis belirtilerek kullanılırlar. Eleman sayısı BOY olan bir dizi için indisin alabilece ği de ğerler 0’dan BOY-1’e kadar de ği şir. Yani, yukarıda tanımlanmı ş olan u tamsayı dizisinin elemanları u[0], u[1] veya u[2] şeklinde kullanılabilir. İndisin her zaman de ği şmez bir tamsayı olmasına gerek yoktur; genelde bir ifade olur. Yani, u[x+5] geçerli bir kullanımdır. Do ğal olarak, e ğer “x+5” ifadesinin de ğeri 0, 1 veya 2 de ğilse, beklenmeyen sonuçlar elde edilebilir. Bu tip kullanımları kontrol altında tutmak tamamen programcının sorumlulu ğundadır. De ği şik tiplerde tanımlanmı ş de ği şkenler için, mevcut derleyiciler tarafından ayrılan bellek miktarı ile alt ve üst limit de ğerleri şöyledir: tip anlamı bayt sayısı limitler char ?1 ? -- signed char 1 -127..127 -- unsigned char 1 0..255 short signed short int 2( 1 ) int signed int 2 veya 4 (1) veya (2) long signed long int 4( 2 ) signed short signed short int 2( 1 ) signed signed int 2 veya 4 (1) veya (2) signed long signed long int 4( 2 ) unsigned short unsigned short int 2( 3 ) unsigned unsigned int 2 veya 4 (3) veya (4) unsigned long unsigned long int 4( 4 ) float -- 4( 5 ) double -- 8( 6 ) long double -- 8 veya 10 (6) veya (7) (1) -2 15 .. 2 15 -1 = -32 768 .. 32 767. (16 bitlik bilgisayarlar için) (2) -2 31 .. 2 31 -1 = -2 147 483 648 .. 2 147 483 647. (32 bitlik bilgisayarlar için) (3) 0 .. 2 16 -1 = 0 .. 65 535. (16 bitlik bilgisayarlar için) (4) 0 .. 2 32 -1 = 0 .. 4 294 967 295. (32 bitlik bilgisayarlar için) (5) -10 38 .. -10 -38 , 0, 10 -38 .. 10 38 . (6) -10 308 .. -10 -308 , 0, 10 -308 .. 10 308 . (7) -10 4932 .. -10 -4932 , 0, 10 -4932 .. 10 4932 . Not: 16 bitlik bilgisayarlarda veya derleyicilerde (signed veya unsigned) int 16 bittir; 32 bitliklerde ise 32 bittir. 12 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş BÖLÜM 1 Tam sayılar ve kayan noktalı sayılar için her bilgisayarda farklı olabilecek bu özellikler, tam olarak limits.h ve float.h adlı ba şlık dosyalarında tanımlanmı ştır. Birtakım varsayımlar yapmak yerine, bu ba şlık dosyalarında tanımlanmı ş bulunan de ği şmezlerin kullanılması özellikle önerilir. (Ba şlık dosyaları için bir sonraki kısma ve ayrıca Kısım F.5’e bakınız.) 1.4. #define Ve #include Öni şlemci Emirleri Hemen bütün C derleyicileri, özel öni şlemci emirlerini tanıyan bir öni şlemciyi yapılarında bulundururlar. Öni şlemci emirleri, bir bakıma, C derleyicisinin girdisini, yani kaynak kodu, kontrol etmede kullanılır. Bir öni şlemci emrinin ilk karakteri her zaman numara i şaretidir (#) ve kaynak programda satırın ilk karakteri olmalıdır. Normalde, öni şlemci emirlerinin ço ğu, kaynak programın ba şına, bildirimlerden önce yazılır. C programlarında çokça kullanıldıkları için, bu bölümde sadece #define ve #include öni şlemci emirleri anlatılmaktadır. Di ğer öni şlemci emirlerinin daha detaylı bir anlatımı Bölüm 6’da verilmektedir. #define emri şu şekildedir: #define tanıtıcı_sözcük karakter_dizisi Bu tür bir #define emri, emirden sonra gelen program deyimlerinde tanıtıcı_sözcük bulunan her yerde, onun yerine karakter_dizisinin konulaca ğını gösterir. Örne ğin, #define XYZ 100 emri, daha sonra, XYZ’nin her rastlandı ğı yerde 100 konulmasını sa ğlar. Program içinde kullanılacak de ği şmezleri tanımlamanın yaygın bir yolu da budur. #define emirleriyle tanımlanan tanıtıcı sözcüklerin büyük harfle yazılması alı şılagelmi ştir. #include emri ya #include "dosya_adı" yada #include şeklinde olur ve öni şlemciye #include satırının yerini, belirtilen dosyanın alaca ğını gösterir. E ğer dosya_adı çift tırnak içine alınmı şsa, o zaman öni şlemci, dosyayı kaynak program dosyasının saklandı ğı altdizinde arar. E ğer dosya_adı açılı parantezler içinde ise, o zaman dosya, böyle #include emirleri için aramaların yapıldı ğı “standart” altdizin(ler)de aranır. Normalde, bu \include altdizini olur. #include emri, daha önceden hazırlanan, standart veya kullanıcı tarafından tanımlanan dosyalarda saklanan, sık kullanılan veri ve fonksiyon bildirimlerini programa dahil etmede kullanılır. Böyle dosyalara başlık dosyaları adı verilir ve isimleri dosyaadi.h şeklinde olur. BÖLÜM 1 TEMEL KAVRAMLAR VE GENEL B İR BAKIŞ1 3 1.5. İşleçler, İfadeler Ve Atama Deyimleri C dili, sa ğladı ğı i şleçler (i şlem operatörleri) açısından çok zengindir. İşletilebilir C deyimlerinin ço ğu bir ifade şeklinde yazılır. Bu ifade belirli kurallara uygun olarak olu şturulmu ş bir i şlenenler ve i şleçler karı şımıdır. Di ğer programlama dillerine kar şılık, C dilinde bir atama bile özel bir çe şit ifadedir. Bir ifade içinde, bir i şlenen ya bir de ği şmez, ya bir de ği şkenin kullanılması, ya bir fonksiyon ça ğrısı yada ba şka bir (alt)ifade şeklinde kar şımıza çıkar. İşleçler (i şlem operatörleri), aritmetik i şlemler, atama, ba ğıntısal ve mantıksal kar şıla ştırmalar, bit i şlemleri, adreslerle ilgili i şlemler ve ba şka i şlerde kullanılırlar. C’de kullanılan aritmetik i şleçler ve anlamları liste şeklinde a şa ğıda verilmi ştir: + toplama veya tekli artı - çıkarma veya olumsuzlama * çarpma / bölme % kalan (5%2 ifadesinin de ğeri, 5/2’den arta kalan, yani 1’dir. İşlenenler olumlu tamsayılar olmalıdr.) ++ anlamı, i şlecin, i şlenenin önünde veya arkasında olmasına ba ğlı olarak de ği şir; ancak sonuçta i şlenenin de ğeri bir artırılır -- anlamı, i şlecin, i şlenenin önünde veya arkasında olmasına ba ğlı olarak de ği şir; ancak sonuçta i şlenenin de ğeri bir azaltılır Basit bir atama deyimi şu şekildedir: de ği şken = ifade; ve ifadenin de ğerinin hesaplandıktan sonra, de ği şkenin de ğerinin buna e şitlenece ği anlamına gelir. İfadeden sonraki noktalı virgüle dikkat edin. Bu noktalı virgül deyimi sonuçlandırır. İşte bazı örnekler. Son iki örne ğin, aynı anlamı ta şıdı ğına dikkat edin. a = b + 10; c = d + c * e - f / g + h % j; x = y * sin(z - 3.14); z = u[2] * u[0]; u[1] = -123.45; x = 10; (x) = 10; C dilinde, di ğer programlama dillerine kar şılık, atamanın kendisi de bir ifadedir, bundan dolayı bir de ğere sahiptir. Bir atama ifadesinin de ğeri, de ğeri hesaplanarak sol taraftaki de ği şkene atanan ifadenin de ğeridir. Atama ifadesinin tipi ise soldaki i şlenenin tipiyle aynıdır. Bu olgu, C dilinde çok kullanılır. Örne ğin, bir ifadenin de ğeri aynı anda birden fazla de ği şkene, şu şekilde, atanabilir: a = b = c = 0; 14 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş BÖLÜM 1 c de ği şkeni 0’ın de ğerini, b c’nin de ğerini ve a b’nin de ğerini alır; böylece bütün de ği şkenler 0’a e şitlenir. A şa ğıda ++ ve -- i şleçlerini açıklamak için bazı örnekler verilmi ştir: x = y++; y’nin de ğeri önce x’e atanır, sonra da bir artırılır. Bu şuna e şde ğerdir: x = y; y = y+1; x = ++y; y’nin de ğeri önce bir artırılır, sonra da x’e atanır. Bu şuna e şde ğerdir: y = y+1; x = y; x = y--; y’nin de ğeri önce x’e atanır, sonra da bir azaltılır. Bu şuna e şde ğerdir: x = y; y = y-1; x = --y; y’nin de ğeri önce bir azaltılır, sonra da x’e atanır. Bu şuna e şde ğerdir: y = y-1; x = y; ++ ve -- i şleçleri yan etkisi olan i şleçlerdir, çünkü tek bir atama deyimi ile birden fazla de ği şkenin de ğeri de ği ştirilebilir. Programcıların bu i şleçleri karma şık ifadeler içinde kullanmaları uygun de ğildir, çünkü böyle bir kullanım nispeten daha zor anla şılabilir ve hataların daha zor düzeltildi ği programların ortaya çıkmasına neden olur. Basit atama i şleci (=) dı şında, atamayı aritmetik i şlemlerle birle ştiren atama i şleçleri de vardır. Bunlar +=, -=, *=, /= ve %=’dır. İşte bazı örnekler: x += y; x’e y eklenir, bu da x = x + (y); anlamına gelir. x -= y; x’ten y çıkarılır, bu da x = x - (y); anlamına gelir. x *= y; x y ile çarpılır, bu da x = x * (y); anlamına gelir. x /= y; x y’ye bölünür, bu da x = x / (y); anlamına gelir. x %= y; x’e x’in y’e bölümünden arta kalan atanır, bu da x = x % (y); anlamına gelir. Tabii ki, yukarıdaki deyimlerin herhangi birinde y de ği şkeninin yerine genel bir ifade konulabilir. Sol taraftaki x de ği şkeni yerine de bellekteki belli bir konuma kar şılık gelen daha karma şık bir ifade konulabilir; örne ğin u[a+b]. Bu durumda bu ifade bir kez hesaplanır. Di ğer bazı i şlemlerle atamayı birle ştiren atama i şleçleri daha sonraki bölümlerde tartı şılacaktır. Öncelik Ve Birle şme Kuralları Bir ifade içinde, i şleçlerin i şlenenleri ya 1. C dili tarafından belirlenmi ş bulunan i şleçlerin öncelik ve birle şme özelliklerine, yada 2. i şlenen ifadelerini parantez içine alarak belirlenir. Parantezler, bir i şlecin i şlenenlerini, o i şlecin önceli ğine ba ğlı olmadan belirtmek veya i şleçlerin i şlenenlerini daha açıklayıcı olacak şekilde yazmak için kullanılırlar. İkinci neden kolayca anla şılır ifadeler yazmak için önemlidir, çünkü C dilinde öncelik ve birle şme özellikleri kolayca anımsanamayacak kadar çok i şleç bulunmaktadır. BÖLÜM 1 TEMEL KAVRAMLAR VE GENEL B İR BAKIŞ1 5 Örne ğin a = b + c * d ifadesinde i şleçler ve i şlenenler şöyledir: i şleç i şlenenler *c ve d +b ve (c * d)’nin de ğeri =a ve (b + (c * d))’nin de ğeri E ğer ifade a = b + (c * d) şeklinde yazılırsa, i şlenenler aynıdır, ancak parantezler i şleçlerin i şlenenlerini daha açık hale getirirler. Fakat, ifade a = (b + c) * d şeklinde yazılırsa, i şleçler ve i şlenenler şöyle olur: i şleç i şlenenler +b ve c * (b + c)’nin de ğeri ve d =a ve ((b + c) * d)’nin de ğeri Yukarıdaki örneklerden de görülebilece ği gibi, bir i şlecin öncelik düzeyi i şleçlere atanacak olan i şlenenlerin sırasını belirlemeye yarar. Daha yüksek önceli ği olan bir i şlecin i şlenenleri daha dü şük olan bir i şleçten önce atanacaktır. E ğer i şleçlerin öncelik düzeyleri aynıysa, o zaman birle şme kuralı i şlenenlerin soldan sa ğa mı yoksa sa ğdan sola mı atanaca ğını belirtir. A şa ğıdaki çizelgede, şimdiye kadar anlatılmı ş bulunan i şleçlerin öncelik düzeyleri ve birle şme özellikleri verilmi ştir: i şleç öncelik birle şme [] indisleme en yüksek › +, -, ++, -- tekli : ‹ *, /, % çarpma : › +, - toplama : › =, +=, vs atama en dü şük ‹ Burada, “‹” sa ğdan sola ve “›” soldan sa ğa birle şmeyi gösterir. Örne ğin a/b/c ile (a/b)/c aynı anlama gelir ve a=b=c ile a=(b=c) aynı anlama gelir Bir ba şka örnek olarak c = d + c * e - f / g + h % j 16 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş BÖLÜM 1 ifadesi c = (((d + (c * e)) - (f / g)) + (h % j)) şeklinde, i şleçlerin i şlenenlerini ve ifadenin anlamını de ği ştirmeden, parantezlenebilir. Dikkat: Bir i şlecin i şlenenlerinden hangisinin önce hesaplanaca ğının belirtilmemi ş oldu ğuna dikkat edin. Örne ğin a = ++b - b ifadesinin de ğeri, derleyiciye ba ğlı olarak, ya 0 yada 1 olabilir; bu yüzden bu tür, yan etkisi olan, ifadelerden kaçınılması gerekir. Ayrıca, + ve * gibi, birle şme ve de ği şme özelli ği gösteren i şleçlerde, parantezlerin bulunmasına ra ğmen, birle şme kuralı bazı derleyiciler tarafından dikkate alınmayabilir. De ği şmez İfadeler Bazı i şleçler—örne ğin, atama ve ++ ile -- i şleçleri dı şında, şimdiye kadar ö ğrenmi ş oldu ğumuz i şleçler—de ği şmezlere (veya de ği şmez ifadelere) uygulandıklarında de ği şmez ifadeler olu ştururlar. De ği şmez ifadelerin avantajı derleme sırasında hesaplanabilmeleridir. Derleyici de ği şmez ifadenin de ğerini hesaplayıp yerine de ği şmez de ğeri koyar. De ği şmez ifadeler bir de ği şmezin beklendi ği yerlerde kullanılabilirler. Örne ğin, dizi boyları de ği şmez olmalıdır, bu durumda int a[MAXL*5+4]; tanımı, e ğer MAXL öni şlemci tarafından (#define ile) tanımlanmı ş bir de ği şmez ise kabul edilebilecek, fakat e ğer MAXL bir de ği şken ise reddedilecektir. Programın anla şılabilirli ğini geli ştirebilece ği için de ği şmez ifadelerin kullanımından kaçınmamak gerekir. 1.6. Tip Dönü şümü Ve Kalıplar Bir i şleç, i şlenen(ler)ine uygulandı ğı zaman, belirli bir tipten bir de ğer olu şturur. Meydana çıkan de ğerin tipi, i şlecin i şlenen(ler)ine, i şlecin kendisine ve tip dönü şümü kurallarına ba ğlıdır. Örne ğin, x+y ifadesinin de ğeri hesaplandı ğı zaman, x ve y tamsayı ise ortaya çıkan de ğerin tipi de tamsayı olur. C dilinde i şleçlerin ço ğu, de ği şik tiplerde i şlenenleri kabul ettikleri için genel olma özelli ğini ta şır. Örne ğin, yukarıdaki ifadede e ğer y double olsaydı, ortaya çıkacak de ğer de double tipinde olacaktı. De ği şik tipte i şlenenlerin bulundu ğu ifadelere karı şık-tip ifadeler denir. Karı şık-tip ifadelerin de ğerleri hesaplandı ğında, ara ve/veya sonuç de ğerlerin tipleri, ya dolaylı olarak otomatik tip dönü şümüyle belirlenir yada açık olarak kalıp kullanılarak kontrol edilir. De ği şik tipten iki i şlenen varsa, C dili kurallarına göre, otomatik tip dönü şümü uygulanır. Bu kurallar şöyledir: BÖLÜM 1 TEMEL KAVRAMLAR VE GENEL B İR BAKIŞ1 7 1. Önce, char ve short olan i şlenenleri int’e veya gerekiyorsa unsigned’a dönü ştür. 2. Sonra, a şa ğıdaki listeye uygun bir şekilde, dü şük tipten olan i şlenenin tipini daha yüksek tipten olanınkine dönü ştür: tip düzey long double en yüksek double : float : unsigned long : long : unsigned’ın tüm olası de ğerlerinin long tarafından içerildi ği varsayılırsa unsigned : int en dü şük Tip dönü şümü üzerine birkaç örnek. i, j’nin int, x’in float, d’nin double ve c’nin char oldu ğunu kabul edin. i = j + x + d; c = c + 'A' - 'a'; İlk ifadede, j float’a dönü ştürülür, j+x’in de ğeri double’a dönü ştürülür ve j+x+d’nin de ğeri double’dan int’e çevrilir. İkinci ifadede, c’deki küçük harfi büyü ğe çevirmek için tamsayı aritmeti ği kullanılır. Otomatik tip dönü şümü, programlarda önemli bir hata kayna ğı oldu ğu için, tip dönü şümünün, açıkça kalıplar kullanılarak, kontrol edilmesi önerilir. Bir kalıp, basitçe, ifadenin önüne konulan parantez içine alınmı ş bir tiptir; yani, (tip) ifade ifadenin tipinin parantez içine alınmı ş olan tipe dönü ştürülece ğini gösterir. Gerçekte, parantez içine alınmı ş olan tip, ifadenin de ğerini amaçlanan tipe dönü ştüren özel bir i şleçtir. Bu i şlecin önceli ği di ğer tekli i şleçlerin önceli ği ile aynıdır. İşte bazı örnekler. x, y, z’nin float, i, j’nin int oldu ğunu varsayın. y ve z’nin hesaplanmasındaki farka dikkat edin. x = (float) i; y = (float) (i / j); /* int bolme islemi */ z = (float) i / (float) j; /* float bolme islemi */ i = (int) (x * (float) j); 1.7. Basit Girdi/Çıktı Girdi ve çıktı deyimleri gerçekte C dilinin bir parçası de ğildir. Yani, di ğer programlama dillerinin tersine, C dilinin içine konmu ş girdi/çıktı deyimleri yoktur. Girdi/çıktı i şlemleri, her zaman, fonksiyonlar ça ğrılarak yapılır. Tabii ki, girdi/çıktı yapmak için kullanılan 18 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş BÖLÜM 1 fonksiyonların programcı tarafından yazılmasına gerek yoktur. Hemen hemen bütün C ortamlarında girdi/çıktı fonksiyonları içeren standart kütüphaneler bulunmaktadır. Bu kütüphanelerde tanımlanmı ş bulunan fonksiyonlar (ile alabilecekleri argümanlar) ve ilgili birtakım de ği şkenlerin bildirisi ise bir ba şlık dosyasına konur. stdio.h böyle bir ba şlık dosyasıdır ve herhangi bir standart girdi/çıktı fonksiyonu ça ğrılmadan veya de ği şkenleri kullanılmadan önce #include yazılarak kaynak programın içine kopyalanması gerekir. Kullanıcının girdi/çıktı yapması için, üç girdi/çıktı ara dosyasının tanımı önceden yapılmı ştır. Bunlar şunlardır: stdin standart girdi stdout standart çıktı stderr standart hata çıktısı ve normal olarak kullanıcının klavye ve ekranına ba ğlanmı ştır. Programcının basit girdi/çıktı i şlemleri yapması için, sadece gerekli olan printf, scanf, getchar, putchar, _getch ve _getche fonksiyonları bu kısımda anlatılacaktır. Di ğer girdi/çıktı fonksiyonları için girdi/çıktı ile ilgili bölüme bakınız. printf(kontrol_karakter_dizisi, argüman_listesi opt ) Fonksiyonu Bu fonksiyon stdout’a yapılacak biçimli çıktı içindir. Kontrol_karakter_dizisi, argüman_listesindeki argümanların de ğerlerinin çıktısını denetleyen sıfır veya daha fazla dönü şüm tanımlamaları sa ğlar. Argüman_listesi virgüllerle ayrılmı ş argümanlardan olu şur ve bulunması zorunlu de ğildir. En basit dönü şüm tanımlaması şu şekildedir: %z Burada z’nin yerine a şa ğıdaki dönü şüm karakterlerinden biri gelmelidir: dönü şüm karakteri çıktı c i şaretsiz bir karakter s karakter dizisi (karakter göstergesi) d veya i i şaretli bir ondalık tamsayı u i şaretsiz bir ondalık tamsayı x, X i şaretsiz bir onaltılı tamsayı o i şaretsiz bir sekizli tamsayı f double e, Ee veya E gösteriminde double g, Ge (E) veya f’nin en kısası p bir göstergenin de ğeri n şimdiye kadar yazılmı ş olan karakterlerin sayısı BÖLÜM 1 TEMEL KAVRAMLAR VE GENEL B İR BAKIŞ1 9 Genelde, bir dönü şüm tanımlaması şu şekildedir: %f0w.plz Burada f iste ğe ba ğlı olarak a şa ğıdaki bayraklardan biridir: bayrak anlamı - çıktı alanında sola yana ştır + öne bir i şaret koy # kayan noktalı sayılar için mutlaka nokta konmasını sa ğla; sekizli için öne 0, onaltılı için öne 0x (0X) koy boşluk karakteri e ğer i şaret yoksa bir bo şluk koy İste ğe ba ğlı olan 0, sayının solunu sıfırla doldurmak içindir. İste ğe ba ğlı olan w sayısı, çıktı de ğerini alacak olan çıktı alanının geni şli ğini belirtir. İste ğe ba ğlı olan p sayısı, kayan noktalı bir sayı için kesir kısmındaki rakamların sayısını, bir karakter dizisi için yazılacak en fazla karakter sayısını veya bir tamsayı için yazılacak en az rakam sayısını gösterir. İste ğe ba ğlı olan l ise argümanın kısa (h), uzun (l) bir tamsayı veya uzun (L) bir double oldu ğunu gösterir. float için bir dönü şüm tanımlaması olmadı ğına dikkat edin; herhangi bir float ifadeyi bir kalıp kullanarak double’a dönü ştürün. w ve p’nin yerine konulacak bir *, geni şli ğin argüman_listesindeki bir int argümandan alınaca ğını gösterir. Normalde, de ğerler çıktı alanlarında sa ğa yana ştırılırlar. İşte bazı örnekler. c’nin int, toplam’ın da double oldu ğunu varsayın. Yeni satır karakterlerine dikkat edin. printf("Merhaba\n"); printf("%s\n", "Merhaba"); /* yukaridakiyle ayni cikti */ printf("\nSayi=%d adet", c); /* c'nin degeri gereken */ /* genislikte bir tamsayi olarak yazilir */ printf("\nSayi=%4d adet", c); /* yukaridakiyle ayni, ancak alan genisligi en az 4 */ printf("\nToplam=%5.2f", toplam); printf("\nToplam=%*.*f", 5, 2, toplam); /* toplam'in degeri dd.dd biciminde yazilir */ printf("\nToplam=%5.2f Sayi=%4d", toplam, c); E ğer %’den sonraki karakter geçerli bir karakter de ğilse, sonucun ne olaca ğı belirsizdir; %% tek bir yüzde i şareti basar. printf fonksiyonu hakkında daha fazla bilgi için, ilgili C derleyicisinin girdi/çıktı kütüphane fonksiyonları el kitabına veya çevrimiçi yardım kolaylıklarına bakılması önerilir. scanf(kontrol_karakter_dizisi, argüman_listesi opt ) Fonksiyonu Bu fonksiyon stdin’den biçimli girdi yapmak içindir. Kontrol_karakter_dizisi, argüman_listesindeki argümanlara verilecek de ğerleri kontrol eden sıfır veya daha fazla dönü şüm tanımlamaları sa ğlar. Kontrol_karakter_dizisindeki dönü şüm karakterleri 20 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş BÖLÜM 1 dı şındaki karakterlerin, girdi akımında kar şılık gelen karakterlerle aynı olması beklenir. Argüman_listesi girdi de ğerleri için hedef olan de ği şkenlerin adreslerinin, birbirinden virgülle ayrılarak, yazılmasından olu şur. Yapılmı ş olan ba şarılı dönü şümlerin sayısı, fonksiyonun de ğeri olarak geri döndürülür. Dönü şüm tanımlamaları şu şekildedir: %*wlz Burada * de ğerin argümana atanmasını engeller, w en büyük alan geni şli ğini belirtir, l ise argümanın büyüklü ğünü gösterir. Üçü de iste ğe ba ğlıdır. z dönü şüm karakteri genelde printf’teki gibidir. Girdi akımında, bir alan, beyaz (bo şluk, tab, yeni satır vs) olmayan bir karakterle ba şlayıp, ilk gelen beyaz karakterle veya belirtilen alan uzunlu ğu sonunda biter. İşte bazı örnekler. c1, c2’nin char, i’nin int, y’nin float, d’nin double ve s’nin char dizisi oldu ğunu varsayın. %lf bir sayının okunmasını ve double olarak depolanmasını sa ğlar. long double için %Lf kullanın. & i şlecinin, fonksiyona de ği şkenin de ğerinin de ğil de adresinin iletilmesi için kullanıldı ğına dikkat edin. Bu i şleç Bölüm 3’te anlatılacaktır. scanf("%d", &i); scanf("%4d", &i); scanf("%c%c%*3s%d%f%lf", &c1, &c2, &i, &y, &d); scanf("%[^.].", s); scanf("%[ABC]", s); Son iki örne ğin ilki, (beyaz bo şluk karakterlerinden biriyle de ğil de) bir nokta ile sonlandırılmı ş bir karakter dizisinin okunarak noktanın atlanmasını sa ğlar. Son örnekte, sadece A, B veya C karakterlerini içeren bir karakter dizisi okunmaktadır. scanf fonksiyonunun kullanımı hakkında daha fazla bilgi için, derleyicinizin elkitaplarına veya çevrimiçi yardım kolaylıklarına ba şvurunuz. getchar() Ve putchar() Fonksiyonları Bu fonksiyonlar stdin’den veya stdout’a bir karakterin girilmesini veya çıktısının yapılmasını sa ğlarlar. Tipik bir kullanım şöyledir. c’nin char veya int oldu ğunu farzedin. c = getchar(); putchar(c); E ğer klavyeden girilen bir karakter dizisi arka arkaya getchar fonksiyonunun ça ğrılmasıyla okunursa, getchar()’ın verece ği son karakter satır ilerletme karakteri ('\n') olacaktır, çünkü satırba şı karakteri ('\r') standart girdi/çıktı yordamları tarafından elenmektedir. Aynı şekilde, putchar() kullanıldı ğında, satır sonuna '\n' yazılması yeterlidir; '\r' karakteri otomatik olarak '\n'’nin önüne eklenecektir. BÖLÜM 1 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş 2 1 _getch() Ve _getche() Fonksiyonları Standart olmayan bu fonksiyonlar, klavyedeki bir tu şa yapılan tek bir vuru ştan ortaya çıkan karakteri verirler. Yani programın bilgi alabilmesi için, getchar() gibi, satırın ENTER’la bitirilmesini beklemezler. _getche()’de girilen karakter ekrana yansıtılır, _getch()’de bu olmaz. Not: Bu fonksiyonlar standart olmadıkları için, isimlerinin önünde altçizgi (_) karakteri bulunmaktadır; ancak bazı sistemlerde, örne ğin Microsoft C derleyicisinin eski uyarlamalarında, altçizgi karakteri olmadan kullanılmaları gerekebilir. Verilen örnek programlarda bunu dikkate alarak, kendi sisteminiz için gerekli düzenlemeleri yapabilirsiniz. Girdide Dosya Sonu Kontrolü stdio.h ba şlık dosyasında #define ile tanımlanmı ş bulunan EOF ismi dosya sonunu kontrol etmek için kullanılabilir. Sistemimizde, dosya sonu ASCII ondalık kodu 26 olan CONTROL+Z (klavyedeki CONTROL tu şu basılı iken Z’ye basılarak olu şturulur) karakterinin alınması şeklinde tanımlanmı ştır. Ancak C kütüphanesindeki standart bir fonksiyon tarafından döndürülen dosya sonu i şareti EOF’tur. if deyiminin henüz anlatılmamasına ra ğmen, a şa ğıdaki örnek stdin’den dosya sonunun nasıl anla şılabilece ğini gösterir. Dikkat: c’nin tipi en azından int olmalıdır. c = getchar(); if (c == EOF) { /* eger dosya sonu ise */ ... dosya sonu i şlemleri yapan deyimler ... } 1.8. C Deyimleri Ve Program Gövdesi C programları deyimlerden olu şur. Yazılabilecek en basit deyim bir ifade deyimidir. Bir ifade deyimi, arkasına noktalı virgül konmu ş herhangi bir ifadedir. Örne ğin, a + b * c; i++; iki ayrı ifade deyimidir; ancak bunlardan ilki pek bir i şe yaramaz, oysa ikincisi, yan etkisinden dolayı, bir i şe yarar: i’nin de ğerinin bir artırılmasına neden olur. Bile şik bir deyim dı şında her deyim noktalı virgülle sona erer. Bir bile şik deyim (ayrıca, bildirimler içerdi ği zaman, “blok” da denir), a şa ğıdaki gibi çengelli parantezler arasına alınmı ş bir deyimler sırasıdır. Bile şik deyimden sonra noktalı virgül olmadı ğına dikkat edin. { bildirimler opt deyim 1opt deyim 2opt ... deyim n opt } 22 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş BÖLÜM 1 Sözdizimsel açıdan bir bile şik deyim tek bir deyime e şde ğerdir. İste ğe ba ğlı olarak, bir bile şik deyimin ilk yürütülebilir deyiminden önce de ği şken tanımları ve bildirimleri bulunabilir. Tanımların bir bile şik deyim içine konmasının önemli bir sonucu vardır. Yürütme esnasında, bir bile şik deyim içinde tanımlanmı ş bulunan de ği şkenler için blo ğa girildi ğinde bellek ayrılır; bloktan çıkıldı ğında ise bu bellek bölgesi serbest bırakılır. E ğer bile şik deyim dı şında aynı isimde de ği şkenler varsa, blo ğa girildi ğinde, bunların kimlikleri geçici olarak “unutulur” ve yeni tanımlar etkili olur. Bloktan çıkıldı ğında eski tanımlar etkilerini tekrar kazanırlar. Bu durum içiçe olan bloklar için meydana gelebilir. Şimdilik, bir C programının genel şekli a şa ğıdaki gibi özetlenebilir: /* * * * * * * * * * * * * * * * * * * * * * * * * * *\ * * * Programin ne yaptigini, kimin tarafindan, ne * * zaman yazildigini vs belirten aciklamalar. * * * \* * * * * * * * * * * * * * * * * * * * * * * * * * */ ... bütün öni şlemci emirleri ... void main (void) { ... veri tanımları ... deyimler ... } /* main */ Program gövdesinin büyük bile şik bir deyimden olu ştu ğuna dikkat ediniz. Daha sonra anlatılaca ğı gibi, fonksiyon tanımları da aynı şekilde yazılır, yani ana program da bir bakıma bir fonksiyondur. 1.9. Bir C Programı Nasıl İşletilir Birçok bilgisayar ve i şletim sistemi için çok sayıda C programı geli ştirme ortamları ve derleyicileri mevcuttur. Bu kısımda, IBM Ki şisel Bilgisayarları veya uyumlularının MS- DOS i şletim sistemi altında çalı şan Microsoft QuickC (MS-QC) Uyarlama 1.01’in kullanımı k ısaca anlatılacaktır. Microsoft komut satırı derleyicisi (MS-CL) ise daha detaylı olarak Ek B’de anlatılmaktadır. MS-QC, kullanımı çok kolay olan bir C programlama ortamıdır, bundan dolayı onunla ba şlamanızı öneririz. MS-QC, bütünle şmi ş bir kaynak programı editörü, detaylı sayılabilecek yardım kolaylı ğı ve yürütme zamanı hata düzelticisiyle birlikte gelir. Yeni bir C programcısı, MS-QC ortamından ayrılmadan bir C programı yazabilir, derleyebilir, çalı ştırabilir ve hatalarını düzeltebilir. BÖLÜM 1 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş 23 MS-QC, uygun bir şekilde, hard diskinize yerle ştirilmi şse veya da ğıtım disketi disket sürücünüze yerle ştirilmi şse, i şletim sistemi iletisine QC yazın. İsterseniz, C programınızı içeren kaynak dosya adını da belirtebilirsiniz. Örne ğin, C>QC mprog.c MS-QC, tepesinde birtakım menü maddelerinin bulundu ğu ve komut satırında belirtilen kaynak dosyadan satırlarla doldurulan bir görüntüleme bölgesinden olu şan bir ekran sunacaktır. E ğer kaynak dosya belirtilmemi şse görüntüleme bölgesi bo ş olacaktır. Hemen yeni C programınızı yazmaya ba şlayabilirsiniz veya a şa ğıdaki düzenleme tu şlarını kullanarak eski bir programda de ği şiklikler yapabilirsiniz: Yukarı, a şa ğı, sola, sa ğa oklar, PAGE UP (sayfa yukarı), PAGE DOWN (sayfa a şa ğı) imleç hareketi INSERT araya ekleme/üste yazma DELETE imlecin arkasındaki karakteri silme Di ğer klavye tu şlarının düzenleme i şlevlerini ortaya çıkarmak için deneme yanılma yöntemini kullanın. MS-QC editörünün kullanımı temelde MS-DOS’daki EDIT komutuna benzemektedir. Bir C programı yazıldıktan sonra, bir menü maddesi seçilerek derlenebilir, çalı ştırılabilir, hataları düzeltilebilir veya bir dosyada saklanabilir. E ğer fareniz varsa, seçime do ğru sürün ve tu şlayın. Yoksa, menü maddesinin ilk harfinin x oldu ğunu varsayarsak, ALT+x’e basın. Aynı şekilde, ALT’a basıp, ok tu şlarını kullanarak menü maddesini seçip ENTER’a da basabilirsiniz. MS-QC menü maddesinde altı çizilmi ş harfe basarak ilgili seçenek seçilebilir. Örne ğin, ALT+F: Dosya menüsünü aç X: MS-DOS’a çık S: Programı sakla vs. ALT+R: Geçi ş menüsünü aç C: Derle S: Derlenmi ş programı yürütmeye ba şla vs. vs. ESC: Alt menü penceresini kapa Bir menü maddesinin seçilmesi, diyalog penceresi denilen, ya ek seçimler yada bilgi veren mesajlar sunan ba şka bir pencerenin görüntülenmesine yol açabilir. Bu tip menü maddelerinin sonunda üç nokta bulunur. Sözdizimsel yönden hatalı bir program derlendi ğinde, MS-QC bütün sözdizim hatalarını bulup ilk hatalı deyimi görüntüleyecektir. İmleç, hatanın üzerinde duracak ve ekranın alt tarafındaki diyalog kutusunda bir hata mesajı görüntülenecektir. Bir önceki 24 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş BÖLÜM 1 veya sonraki hata bölgesi SHIFT+F3 veya SHIFT+F4’e basılarak görüntülenebilir. Bu şekilde, tekrar derlemeden önce, bütün hataları bulup düzeltebilirsiniz. Bir C programı ayrıca, basitçe SHIFT+F5’e basılarak veya RUN altmenüsünden START seçilerek derlenip çalı ştırılabilir. Sözdizimsel hatalar az önceki gibi bildirilecektir, fakat uyarı dı şında ba şka hata yoksa, programın yürütülmesine geçilecektir. Programın çıktısı otomatik olarak çıktı ekranında görüntülenir. MS-QC görüntüsüne geri dönmek için ENTER’a basın. Çıktı ekranını tekrar görüntülemek için F4’e basın. Şimdi de hata bulma konusunda bir iki söz. A şa ğıdaki yöntemleri kullanmak için programınızın DEBUG modunda derlenmesi gerekmektedir. Bunun için, önce ALT+R’ye sonra C’ye basın. Gelen pencerenin sa ğ tarafında “Debug” yazısının önünde X i şareti olup olmadı ğını kontrol edin. E ğer yoksa ALT+D’ye basın. Daha sonra ENTER’a basıp programı derleyin. Programınızı çalı ştırmaya ba şlamadan önce, deyime bir kesilme noktası (breakpoint) koyarak, yürütmenin o deyime gelince beklemesini sa ğlayabilirsiniz. Sadece imleci deyimin üstüne götürüp F9’a basmanız yeterlidir. Daha sonra, kesilme noktasını kaldırmak isterseniz aynı i şlemi tekrarlayın. Programın çalı şması devam etti ği esnada bir de ği şkenin ve/veya ifadenin de ğerini görüntüleyebilirsiniz. DEBUG altmenüsündeki ADD WATCH menü maddesini seçin ve sürekli görüntülemek istedi ğiniz de ği şkeni veya ifadeyi yazın. Çalı ştırılmakta olan deyimleri görüntülemek için bir izleme (trace) kolaylı ğı da mevcuttur. Bir fonksiyon ça ğrısı esnasında fonksiyon içindeki deyimleri izlemek için F8’e basın, fonksiyon içindeki deyimlerin izlenmesini atlamak için F10’a basın. QuickC’nin, C programlamasını kolay hale getiren ba şka birtakım kolaylıkları da vardır. Kullanıcının ilgili elkitaplarına bakması ve/veya menü seçimlerini deneyerek bu kolaylıkları ortaya çıkarması önerilir. Microsoft Visual C++ Development System for Windows paketi içindeki Visual Workbench programı kullanım bakımından MS-QC’ye uyumlu, ancak profesyonel kullanıcılara yönelik çok daha geli şmi ş bir ortam sa ğlar. Di ğer etkile şimli C ortamlarında da benzer olanaklar sunulmaktadır. 1. 10. Örnek Programlar Bu kısımdaki örnek programlar, ne i şe yaradıkları hakkında kendi kendilerini açıklayacak şekilde yazılmı şlardır, ancak henüz anlatılmamı ş—if ve while gibi—bazı deyimler ve i şleçler içerirler. Bunların anlamlarını ortaya çıkarmak için, okuyucu, eski programlama deneyimlerine dayanarak bir kestirimde bulunabilir. Örnek Program 1 Bu programda kullanılan _getche fonksiyonu, bir standart girdi fonksiyonu olmadı ğı için, dosya sonu kontrolü MS-DOS standardına uygun olarak CONTROL+Z karakteri BÖLÜM 1 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş 25 kullanılarak yapılmaktadır. Not: _getche fonksiyonunun kullanımından dolayı, bu program ANSI Standardına uygun de ğildir. 1. /* * * * * * * * * * * * * * * * * * * * *\ 2. * * 3. * Bu program, CONTROL+Z girilinceye * 4. * kadar, klavyeden girilen her karak- * 5. * terin ASCII kodunu verir. * 6. * * 7. \* * * * * * * * * * * * * * * * * * * * */ 8. 9. #include 10. #include 11. void main (void) 12. { 13. int c; 14. char ctrlz = 26; /* ASCII ond. kodu 26 (CONTROL+Z) */ 15. 16. printf("\nBazi kontrol karakterleri disinda," 17. "\ngirilen karakterin kodu goruntulenecek."); 18. while (1) { 19. /* Ekrana yansitarak bir klavye tusunu oku. 20. * CONTROL+Z'ye basilmissa programi bitir. 21. */ 22. printf("\nBir karakter girin: "); 23. if ((c = _getche()) == ctrlz) 24. break; 25. /* Girilen karakterle ayni satirda ondalik, onaltili 26. * ve sekizli olarak ASCII kodunu goruntule. 27. */ 28. printf(", ondalik: %d, onaltili: %x, sekizli: %o",c,c,c); 29. } /* while */ 30. } /* main */ Örnek Program 2 1. /* * * * * * * * * * * * * * * * * * * * * * * * * * *\ 2. * * 3. * Bu program, -1 girilinceye kadar, klavyeden * 4. * girilen ondalik sayilari kabul eder, daha sonra, * 5. * girilen sayilarin agirlikli toplamini, ortala- * 6. * masini ve varyansini hesaplayip goruntuler. * 7. * * 8. * Uyari: Cok buyuk sayilarin ve rakam olmayan * 9. * karakterlerin girilmesi sorun yaratabilir. * 10. * * 11. \* * * * * * * * * * * * * * * * * * * * * * * * * * */ 12. 13. #include 14. #define AGIRLIK 1.0 15. /* Eger veri degerleri agirlikli olarak hesaplanacaksa, 16. * agirliga farkli bir deger verin. 17. */ 18. 26 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş BÖLÜM 1 19. void main (void) 20. { 21. int sayi; 22. int adet = 0; 23. double kn_sayi, toplam=0.0, karelerin_toplami=0.0; 24. double ortalama=0.0, varyans=0.0; 25. 26. printf("\nToplam, ortalama ve varyans hesaplayan program." 27. "\n\nLutfen ilk sayiyi (veya cikmak icin -1) girin: "); 28. scanf("%d", &sayi); 29. /* Girilen sayi olumsuzsa programi bitir. */ 30. while (sayi >= 0) { 31. adet++; /* Sayaci artir */ 32. /* Sayiyi double'a cevirip AGIRLIK'la carp. */ 33. kn_sayi = (double)sayi * AGIRLIK; 34. /* Yeni toplami ve karelerin toplamini hesapla. */ 35. toplam += kn_sayi; 36. karelerin_toplami += kn_sayi * kn_sayi; 37. /* Yeni ortalama ve varyansi hesapla. */ 38. ortalama = toplam / (double)adet; 39. varyans = ortalama*ortalama-karelerin_toplami/(double)adet; 40. if (varyans < 0.0) 41. varyans = -varyans; 42. /* Hesaplanan degerleri goruntule. */ 43. printf("\nAdet = %d", adet); 44. printf(", toplam = %.2f", toplam); 45. printf(", ortalama = %.2f", ortalama); 46. printf(", varyans = %.2f", varyans); 47. /* Bir sonraki sayiyi al. */ 48. printf("\nLutfen bir sonraki sayiyi " 49. "(veya cikmak icin -1) girin: "); 50. scanf("%d", &sayi); 51. } /* while */ 52. 53. /* En son hesaplanan degerleri bir daha ve degisik 54. * bir bicimde goruntule. 55. */ 56. printf("\nVerilerin adedi: %12d", adet); 57. printf("\nToplam : %15.2f", toplam); 58. printf("\nOrtalama : %15.2f", ortalama); 59. printf("\nVaryans : %15.2f", varyans); 60. } /* main */ Problemler 1. Kernighan ve Ritchie’nin (1978’de yayınlanan) The C Programming Language adlı kitaplarının ilk baskısında entry adı verilen bir anahtar sözcükten bahsedilmekte idi. Şu anki Standartta ve gördü ğümüz herhangi bir derleyicide mevcut de ğildir; ileride kullanılmak amacıyle ayrıldı ğı söylenmekte idi. Derleyicinizde entry’nin bir anahtar sözcük olup olmadı ğını belirlemede size yardımcı olacak bir program deneyin. 2. Soya ğacınızı basan bir program yazın. (Üç düzey yeterlidir.) 3. A şa ğıdaki deyimin sonucunu açıklamaya çalı şın: BÖLÜM 1 TEMEL KAVRAMLAR VE GENEL B İR BAKI Ş 27 printf("%d", printf("C iyi bir dildir.\n")); 4. A şa ğıdaki geçerli bir deyim midir? ((x) = (5)); 5. A şa ğıdaki geçerli bir C deyimi midir? {{{}}} 6. A şa ğıdaki programın, girdi olarak verilen bir gerçek sayının tamsayı k ısmını görüntüleyece ğine inanılmaktadır: #include void main (void) { float x; scanf("%f", x); printf("%d", x); } Fakat çalı şır gibi gözükmemektedir. Düzeltin. İpucu: Derleyicinin bulamayaca ğı iki ayrı hata bulunmaktadır. 29 BÖLÜM 2: DEY İMLER VE KONTROL AKI ŞI Dü şünülece ği gibi, her deyim, bilgisayara ne yapaca ğını söyleyen, temel bir program adımıdır. Bu bölüme, tüm C deyimlerinin bir listesini vermekle ba şlayaca ğız. Ondan sonra, kontrol akı şı deyimleri içindeki ifadelerde sıkça kullanılan i şleç grubundan bahsedece ğiz. Bölümün geri kalanında, C program deyimlerinin yürütülme sırasını kontrol eden deyimler detaylı olarak anlatılacaktır. Bir C programı main fonksiyonunun ilk deyiminden çalı şmaya ba şlar. E ğer kontrol akı şı ba şka yöne yönlendirilmezse, deyimler, program içindeki sıralarında ard arda i şletilir ve yürütme main’in son deyiminden sonra durur. Kontrol akı şını yönlendirmenin bir yolu da bir fonksiyon ça ğrısı yapmaktır. Bu bölümde ayrıntılı olarak anlatılacak deyimler ise kontrol akı şını kendilerine özgü yollarla etkilerler. Ba şlamadan önce, Pascal-severlere önemli bir uyarımız var: C dilinde, noktalı virgül, deyimleri ayırmak için de ğil, bazı deyimleri bitirmek için kullanılır. Yani, noktalı virgül deyimin bir parçasıdır. Gerek olmadı ğını sandı ğınız bazı yerlere noktalı virgül koymanız gerekebilir. Örnekleri gördükçe, kuralların daha açık olaca ğını umuyoruz. 2. 1. C Dilinin Deyimleri Çizelge 2.1’de bütün C deyimleri liste halinde verilmi ştir. Bu çizelgenin ilk iki maddesi önceki bölümde zaten anlatılmı ştı. Geri kalanlar ise temelde kontrol akı şı deyimleridir ve, return dı şında, hepsi bu bölümde anlatılacaktır. 30 DEY İMLER VE KONTROL AKI ŞIB Ö L Ü M 2 Ç İZELGE 2. 1 C dilinin deyimleri deyim i şlev ifade çe şitli (atama, fonksiyon ça ğırma vs) bile şik birden fazla deyimden tek bir deyim olu şturur if ko şullu yürütme switch (herhangi bir sayıda seçeneklerle) ko şullu yürütme while (devam testinin her yinelemeden önce oldu ğu) döngü for while gibi, fakat bir “ilkleme” bölümü var do (devam testinin her yinelemeden sonra oldu ğu) döngü break bulunulan bloktan dı şarı atlanması continue mevcut yinelemenin geri kalanının atlanması goto (bulunulan fonksiyon içinde) herhangi bir bölgeye atlanması etiketli goto’nun hedefi return (olası bir de ğerle) fonksiyondan dönü ş boş hiç (bazı sözdizimsel kullanımları vardır) 2.2. Ba ğıntısal Ve Mantıksal İşleçler C dilinde dokuz i şleç, doğru veya yanlı ş diye yorumlanabilecek de ğerler verir. C’nin özel bir Boolean (yani mantıksal) veri tipi yoktur ve bu i şleçlerle olu şturulmu ş bir ifadenin de ğeri, e ğer ifade do ğru ise, 1, yanlı şsa 0’dır. Aslında, sıfırdan farklı her sayı C dilinde “do ğru” anlamını ta şır. Böyle bir sonucun tipi her zaman int’tir. A şa ğıda, bu i şleçler, azalan öncelik sıralarına göre anlatılmaktadır. Bütün do ğruluk-de ğerli i şleçler, struct ve türevleri dı şında, her tipten i şlenen kabul eder. Sa ğdan sola do ğru birle şen ! tekli i şleci dı şında, burada anlatılan tüm i şleçler soldan sa ğa birle şirler. Ba ğıntısal ve mantıksal i şleçler de ği şmez ifadelerde de kullanılabilirler. Mantıksal Olumsuzlama İşleci ! ! (“de ğil”) i şleci i şlenenin mantıksal de ğerini olumsuzlar; yani e ğer i şlenen 0’sa 1 verir, e ğer i şlenen sıfırdan farklı ise 0 verir. Örnekler: /* Bu ve bir sonraki kisimda; a=150, b=45.33, c=-132, d=0 */ !a de ğeri 0’dır !c de ğeri 0’dır !d de ğeri 1’dir !(b+c) de ğeri 0’dır !!c de ğeri 1’dir Ba ğıntısal İşleçler <, >, <=, Ve >= Bu i şleçlerin isimleri şöyledir: BÖLÜM 2 DEY İMLER VE KONTROL AKI ŞI3 1 i şleç isim < küçüktür > büyüktür <= küçük veya e şittir >= büyük veya e şittir Ba ğıntısal i şleçler i şlenenlerini kar şıla ştırır ve duruma göre do ğru veya yanlı ş bir de ğer verirler. Örnekler: a=d de ğeri 1’dir a>b>c (a>b)>c’ye e şde ğerdir ve de ğeri 1’dir a= ve e şitlik i şleçlerinin i şlenenleri olarak float tipinde ifadeler kullanmak tehlikelidir. Mantıksal VE İşleci && && i şleci i şlenenlerinin mantıksal VE’sini verir, yani e ğer her iki i şlenen do ğru ise sonuç 1 olur, aksi takdirde 0’dır. Bu tanımdan, e ğer i şlenenlerden biri 0’sa sonucun kesinlikle sıfır olaca ğı ve di ğer i şlenenin de ğerinin hesaplanmasına gerek olmadı ğı açıktır. C, bu gerçe ğe dayanarak, di ğer bazı dillerin tersine, ilk i şlenenin de ğeri 0’sa ikincisini hesaplamaz. Örnekler: /* fn()'nin 657 veren bir fonksiyon oldugunu varsayin */ a&&b de ğeri 1’dir d&&fn() de ğeri 0’dır ve fn() ça ğrılmaz fn()&&d de ğeri 0’dır ve fn() ça ğrılır 32 DEY İMLER VE KONTROL AKI ŞIB Ö L Ü M 2 Mantıksal VEYA İşleci || || i şleci i şlenenlerinin mantıksal VEYA’sını verir, yani e ğer her iki i şlenen yanlı ş ise sonuç 0 olur, aksi takdirde 1’dir. Gördü ğünüz gibi, e ğer i şlenenlerden biri sıfırdan farklı ise, öteki i şlenenin de ğeri ne olursa olsun sonuç 1’dir. Yukarıda anlatılan yararlı özellik burada da geçerli olur; e ğer ilk i şlenen sıfırdan farklı ise, ikinci i şlenen hesaplanmaz. Örnekler: a||d !(!a&&!d)’e e şde ğerdir ve de ğeri 1’dir a||b de ğeri 1’dir c||d de ğeri 1’dir d||(!c) de ğeri 0’dır 2.3. Do ğruluk-De ğerli İfadeler Birçok yeni i şleç ö ğrendi ğimize göre, Bölüm 1’de verilmi ş olan i şleç önceli ği ve birle şme çizelgesinin geni şletilmi ş bir uyarlamasını verelim. Bu Çizelge 2.2’de gösterilmektedir. Ç İZELGE 2.2 C i şleç önceli ği ve birle şme [] › ! ++ -- + - (tip) ‹ * / % › + - › < <= > >= › == != › && › || › = *= /= %= += -= ‹ Bir önceki kısımdaki i şleçler kullanılarak yazılmı ş bazı doğruluk-de ğerli ifade örnekleri şöyledir: !(a<=c) a>c’ye e şde ğerdir ve de ğeri 1’dir !a>c 0>c’ye e şde ğerdir ve de ğeri 1’dir !(a==b) a!=b’ye e şde ğerdir ve de ğeri 1’dir ad 0==0’a e şde ğerdir ve de ğeri 1’dir !a<=b!=c&&d de ğeri 0’dır ve bütün ifadeler hesaplanır !a||d de ğeri 0’dır a!=b||fn() de ğeri 1’dir ve fn() ça ğrılmaz BÖLÜM 2 DEY İMLER VE KONTROL AKI ŞI3 3 2.4. if Deyimi Ve Ko şullu İşleç if deyimi, if anahtar sözcü ğünün arkasına parantez içine yazılmı ş bir ifade ve pe şinden gelen bir deyimden olu şur. Tüm bunların arkasında, iste ğe ba ğlı olarak, bir else anahtar sözcü ğü ve bir deyim bulunabilir. if’in bu iki şekli a şa ğıdaki gösterimde özetlenmektedir: if (ifade) deyim ve if (ifade) deyim else deyim İşte else’i olmayan bir if deyimi örne ği: if (yas > 65) { yasli_kisiler++; printf("Yasli bir kisisiniz.\n"); } E ğer yas 65’ten büyükse, blok içindeki deyimler çalı ştırılır, aksi takdirde, kontrol doğrudan bir sonraki deyime geçer. Bu deyimi, her ya ştan ki şiye hitap edecek şekilde de ği ştirelim: if (yas > 65) { yasli_kisiler++; printf("Yasli bir kisisiniz.\n"); } else printf("Henuz yasli bir kisi degilsiniz.\n"); Şimdi, deyiminiz, e ğer yas 65’in üstünde ise, az önceki deyimle aynı şekilde davranacaktır, aksi takdirde yeni mesaj görüntülenecektir. Genelde, parantez içine alınmı ş ifadenin de ğeri do ğru (sıfırdan farklı) ise, ifadeden sonra gelen deyim i şletilir; ifadenin de ğeri yanlı ş (sıfır) ise, else anahtar sözcü ğünden sonra gelen deyim (varsa) i şletilir. Örneklerimizde de görüldü ğü gibi, bu deyimler bile şik deyimler olabilir, bu da bile şik deyimlerin daha önce belirti ğimiz iyi özelli ğidir: Birçok deyimden tek bir deyim olu ştururlar. Ayrıca, bile şik deyim ba şlatan “{” karakterinin ifade ile aynı satırda, onun kar şılı ğı olan “}” karakterinin de anahtar sözcükle aynı sütuna yazıldı ğına dikkat ediniz. Bu karakterlerin tam yeri—blo ğu do ğru bir şekilde ayırdıkları sürece—derleyiciyi ilgilendirmez, ancak bu şekilde yazmanın programları anlamayı kolayla ştıraca ğı inancındayız ve bunu kitap içinde uygulamaya devam edece ğiz. Şüphesiz, içiçe if deyimleri yazabilirsiniz. Tipik bir örnek şöyle olabilir: 34 DEY İMLER VE KONTROL AKI ŞIB Ö L Ü M 2 if (yas > 65) { yasli_kisiler++; printf("Yasli bir kisisiniz.\n"); } else if (yas > 40) { orta_yastaki_kisiler++; printf("Orta yastasiniz.\n"); } else if (yas > 17) { genc_kisiler++; printf("Gencsiniz.\n"); } else printf("Cocuksunuz.\n"); Bunun tek bir deyim oldu ğuna dikkat ediniz. Şimdi şunun üzerinde dü şünün: if (yas < 65) if (yas > 40) printf("Orta yastasiniz.\n"); else printf("Cok yaslisiniz.\n"); E ğer yas 65’ten büyük veya e şitse ne olacaktır? Di ğer bir deyi şle, else hangi if’e aittir? Mesajlar ve içerlek yazma şekli, bu deyimi yazan ki şinin ilk if’e ait oldu ğunu düşündüğü izlenimini uyandırıyor, fakat bu do ğru de ğil! Kural şöyledir: Her else en yakın else’i olmayan if’e aittir. Bundan dolayı, yukarıda yapılmak istenen i şi doğru şekilde yapan if şudur: if (yas >= 65) printf("Cok yaslisiniz.\n"); else if (yas > 40) printf("Orta yastasiniz.\n"); veya, if (yas < 65) if (yas > 40) printf("Orta yastasiniz.\n"); else ; else printf("Cok yaslisiniz.\n"); else’ten sonraki noktalı virgül bir boş deyim olu şturur. Gördü ğünüz gibi, sözdizimin bir deyim gerektirdi ği, fakat yapılacak bir şey olmadı ğı yerde bo ş deyim kullanılabilir. Ba şka bir yol olarak, ikinci if’i bir blok içine alırsak, bo ş deyimli else kullanmak zorunda kalmayız. if (ifade_ 1) de ği şken = ifade_2; else de ği şken = ifade_3; şeklindeki bir if deyimi, ko şullu i şleç kullanılarak BÖLÜM 2 DEY İMLER VE KONTROL AKI ŞI3 5 de ği şken = ifade_ 1 ? ifade_2 : ifade_3; şeklinde basitçe yazılabilir. Genelde, C dilindeki tek üç-i şlenenli (üçlü) i şleç olan “?:” i şleci, önce ifade_ 1’i hesaplar ve e ğer ifade_ 1 do ğru ise ifade_2’nin de ğerini, aksi takdirde ifade_3’ün de ğerini verir. Son iki ifadeden sadece biri hesaplanır. Sonucun tipi, önceki bölümde anlatılan dönü şüm kurallarına göre ifade_2 ve ifade_3 birlikte dikkate alınarak belirlenir. “?:” i şlecinin sa ğdan sola do ğru birle şme özelli ği vardır ve önceli ği Kısım 2.2’de görülen tüm i şleçlerden dü şük, atama i şlecinden ise yüksektir. “?:” i şlecinin i şleri nasıl kolayla ştırdı ğına bir örnek: printf(yas>65 ? "Yasli birisiniz.\n" : "Henuz yasli degilsiniz.\n"); Gördü ğünüz gibi, hem ifade_2 hem de ifade_3 karakter dizileri ise, sonuç bir karakter dizisidir. “?:” i şleci de ği şmez ifadelerde de kullanılabilir. 2.5. while Deyimi Di ğer programlama dillerinde oldu ğu gibi, while deyimi döngüler olu şturmak için kullanılır. Sözdizimi şöyledir: while (ifade) deyim Önce ifade hesaplanır. E ğer do ğru ise, deyim yürütülür, sonra da ifade tekrar hesaplanır. İfadenin hesaplanmasında yanlı ş (0) sonucu elde edilinceye kadar bu devam eder; bu durumda kontrol bir sonraki deyime geçer. E ğer ba şlangıçta ifade yanlı şsa, tekrarlanan deyim hiç çalı ştırılmaz. Şekil 2.1’deki akı ş çizene ği while deyiminin yürütülme şeklini gösterir. İşte bir while deyimi: while (yas<35) { genc_kisiler++; scanf("%d",&yas); } E ğer yas, bu deyimden önce, 35 veya daha büyük bir sayı ise blok hiç yürütülmeyecektir. Aksi takdirde, 35’ten büyük veya e şit bir sayı girilinceye kadar defalarca yürütülecektir. while kullanarak sonsuz döngüler yazmanın olası oldu ğuna dikkat edin: İfadenin hiçbir zaman yanlı ş olmayaca ğını temin etmeniz yeterlidir. Örne ğin, while (1) printf("C'yi cok seviyorum!\n"); deyimi ile C hakkındaki duygularınızı sonsuza dek yazabilirsiniz. 36 DEY İMLER VE KONTROL AKI ŞIB Ö L Ü M 2 yanlı ş doğru ifadeyi hesapla deyimi yürüt yanlı ş doğru ifadeyi hesapla deyimi yürüt while deyimi do deyimi ŞEK İL 2. 1 while ve do deyimleri için akı ş çizenekleri 2.6. do Deyimi do deyimi while deyiminin yakın bir akrabasıdır; o kadar ki sözdiziminde while anahtar sözcü ğünü içerir: do deyim while (ifade); do’nun while’dan tek farkı ifadeyi, tekrarlanan deyimin yürütülmesinden sonra hesaplamasıdır. Bunun anlamı, ne olursa olsun, do deyiminde en az bir defa döngüye girildi ğidir. Şekil 2.1’de verilen akı ş çizeneklerindeki farklılıklara dikkat edin. Birisinin ya şını sorup, olumlu bir sayı girilinceye kadar sormaya devam eden, örnek bir do deyimi şöyledir: do { printf("Lutfen yasinizi giriniz.\n"); scanf("%d", &yas); } while (yas<=0); Normal olarak, her do deyiminde, burada da oldu ğu gibi, bir blok şeklinde yazılan içteki deyim en az bir defa yürütülür. BÖLÜM 2 DEY İMLER VE KONTROL AKI ŞI3 7 2.7. for Deyimi Ve Virgül İşleci for deyimi, for anahtar sözcü ğü, arkasında parantez içinde iki noktalı virgülle ayrılmı ş üç ifade ve ondan sonra gelen bir deyimden olu şur. İfadelerden herhangi biri var olmayabilir, ancak noktalı virgüller bulunmalıdır. for deyiminin nasıl i şledi ğini anlatmanın en iyi yolu, e şde ğer bir while deyimi ile onu ifade etmektir. Şimdi, eğer for (ifade_ 1 opt ; ifade_2 opt ; ifade_3 opt ) deyim şeklinde bir deyimimiz varsa, ifade_ 1; while (ifade_2) { deyim ifade_3; } deyimi, for deyimi ile aynı i şi yapacaktır. E ğer for deyimindeki ifade_2 boşsa, sürekli olarak do ğru oldu ğu şeklinde yorumlanacak ve sonsuz bir döngünüz olacaktır. İfade_ 1’in döngüyü kontrol eden de ği şkenleri ilklemek için; ifade_2’nin döngüyü durdurmak için gereken ko şulları belirlemede; ifade_3’ün de döngü içindeki bazı de ği şkenlerin de ğerlerini de ği ştirmede kullanılaca ğına dikkat edin. Örnek: for (i=0; i0; a--) { b = -a; if (b==-5) continue; printf("%d sayisinin olumsuzu %d sayisidir.\n", a, b); } deyiminde (5 hariç) 10’dan 1’e kadar bütün tamsayılar, olumsuzları ile birlikte, yazılırlar. Di ğer bir örnek olarak, a = 0; while (a<100) { a++; if (a%4) continue; printf("%d\n", a); } deyimi 100’e kadar 4’ün katlarını görüntüler. continue, kontrolü her zaman içinde kaldı ğı en küçük döngünün sonuna aktarır. Yukarıdaki gibi birçok durumda, if’teki test ko şulunu ters çevirerek ve continue yerine döngüde geri kalan deyimleri bir blok içine koyarak continue’dan kurtulabiliriz. Önceki kısımda, for deyiminin while deyimi şeklindeki yazımını anımsayın. Bu kural, for’un tekrarlanan deyiminde bir continue oldu ğu zaman geçerli olmaz, çünkü BÖLÜM 2 DEY İMLER VE KONTROL AKI ŞI3 9 ifade_3 her yinelemenin sonunda ba ştan hesaplanır. Böylece, bu kısımda verilen for deyiminin while’la yazılmı ş e şde ğeri şöyledir: a=10; while (a>0) { b=-a; if (b==-5) { a--; continue; } printf("%d sayisinin olumsuzu %d sayisidir.\n", a, b); a--; } 2.9. break Deyimi break deyimi continue ile yakından ilintilidir. continue deyimi yeni bir yinelemenin ba şlaması amacıyla döngünün sonuna atlarken, break, içinde kaldı ğı en küçük döngünün dı şına atlar ve döngü deyiminin tamamen sona ermesine yol açar. Ba şka durumlar dı şında, break “sonsuz” döngülerden çıkı ş için kullanılır. Örne ğin: while (1) { scanf("%d", &yas); if (yas<=0) break; printf("Bir sonraki kisi %d yasindadir.\n", yas); } Burada, olumlu olmayan bir sayı girildi ğinde, break deyimi kontrolü while’dan sonraki deyime aktarır. İçinde break bulunan bir program parçası break olmadan da yazılabilece ğine göre, break kullanmak bir tercih sorunudur. break sadece switch (Kısım 2.11), do, while ve for deyimlerinden çıkı ş için kullanılabilir. Ba şka yerlerde kullanılamaz. 2. 10. goto Deyimi Ve Etiketler Her C deyimine, deyimden önce bir tanıtıcı sözcük ve iki nokta üst üste koyarak bir etiket ili ştirilebilir. Bir deyimi etiketlemek suretiyle, gerekti ğinde o deyime ula şmak için kullanılabilecek bir “adres” verilir. Bir fonksiyon içinde birden fazla deyime aynı isim, etiket olarak, verilemez. Bir etiket ve onun arkasına bir deyim yeni bir deyim olu şturur. Bu tür bir deyime etiketli deyim denir: tanıtıcı_sözcük : deyim goto deyimi, kontrolü do ğrudan etiketli deyime aktarır. Sözdizimi söyledir: 40 DEY İMLER VE KONTROL AKI ŞIB Ö L Ü M 2 goto tanıtıcı_sözcük; Tanıtıcı_sözcük aynı fonksiyon içinde var olan bir etiket olmalıdır. goto kullanarak, fonksiyon içinde (dı şında de ğil) herhangi bir yere atlanabilir; ileri veya geriye do ğru, istenildi ği kadar içiçe geçmi ş döngü veya blokların içine veya dı şına, istedi ğiniz bir yere gidebilirsiniz. goto’nun sorumsuzca kullanımı, anla şılması ve bakımı yapılması olanaksız programlar yaratabilir. Kuramsal olarak, anlambilimsel hiçbir yitime u ğratılmadan, goto bir programdan çıkarılıp yerine döngü ve if deyimleri konulabilir. Buna ra ğmen, hata i şleme gibi, bazı durumlarda i şleri kolayla ştırabilir. Örne ğin: while (bir_kosul) { ... do { ... for (...; ...; ...) { ... if (guuum) goto felaket; ... } } while (baska_kosul); ... } ... felaket: hata i şlemleri Bu durumda bile, goto deyimi kaldırılabilir. Hata i şlemlerinin, bazı temizlik i şleri yapıp, olası bir hata kodu ile, ça ğıran fonksiyona dönü ş yaptı ğını varsayın. O zaman, niye bu i şleri goto deyiminin bulundu ğu yerde yapıp bir return kullanmayalım? (return deyimi bir fonksiyondan dönmek için kullanılır ve Bölüm 4’te i şlenmektedir.) break, continue ve return gibi daha uygun yapıların bulundu ğu, C gibi bir dilde, goto’lardan kaçınılabilir ve kaçınılmalıdır. İyi bir programcı goto’yu ve hatta continue’yu hemen hiç bir zaman kullanmaz. switch dı şında da, break deyimini çok seyrek kullanır. Bu arada, goto kullanmadan bile, kontrol akı şı anla şılmayan programlar yazmak olasıdır. Dikkatli tasarım, ayrıntılı belgeleme ve makul içerlek yazma alı şkanlı ğı, bundan kaçınmanın bazı yollarıdır. 2. 11. switch Deyimi switch (ifade) deyim switch deyimi birçok şıktan bir tanesini seçmede kullanılır. İşte kullanıcıya “menüler” sunan bir programda bulunabilecek bir switch: BÖLÜM 2 DEY İMLER VE KONTROL AKI ŞI4 1 switch (_getche()) { case 'r': case 'R': rezervasyon_yapma(); break; case 'l': case 'L': yolcu_listeleme(); break; case 'i': case 'I': rezervasyon_iptali(); break; case 'c': case 'C': cikis(); break; default: printf("Yanlis secenek... Tekrar deneyin.\n"); } Bu örnek switch’in tüm önemli özelliklerini göstermektedir. Parantez içine yazılmı ş tamsayı tipindeki—bu örnekte oldu ğu gibi, bir karakter de olabilir—sayı ifadesi hesaplanır, önüne case anahtar sözcü ğü getirilmi ş olan de ği şmez ifadelerden birinin de ğeri buna uyuyorsa kontrol bu case etiketli deyime aktarılır ve buradan sıralı olarak devam eder. E ğer hiçbir case etiketindeki de ğer ifadenin de ğerine uymuyorsa, iki olasılık vardır: Deyim içinde bir default etiketi varsa, kontrol buraya aktarılır, aksi takdirde switch deyiminden çıkılır. Yukarıdaki deyimde hiçbir break konulmadı ğı takdirde, r veya R girildi ğinde, bütün fonksiyonlar (rezervasyon_yapma, yolcu_listeleme vs) ça ğrılacak ve hata mesajı da basılacaktır. Bundan dolayı hemen hemen bütün switch deyimlerinde break’ler bulunur. Örnekte oldu ğu gibi, switch’teki parantez içindeki ifadeden sonra gelen deyim genelde bir bloktur. case ve default etiketleri switch deyimleri dı şında kullanılamazlar. Ayrıca, bir switch deyimi içinde birden fazla default etiketi ve aynı switch içinde aynı de ğere sahip birden fazla case etiketi olamaz. switch’in öyküsünü ba şka bir ilginç örnekle bitiriyoruz: switch (yas) case 20: case 40: case 60: printf("20, 40 yada 60 yasindasiniz.\n"); 42 DEY İMLER VE KONTROL AKI ŞIB Ö L Ü M 2 2. 12. Bir Örnek—Sayı Sıralama 1. #include 2. #define GOZCU 0 3. #define LIMIT 25 4. 5. void main (void) 6. { 7. int i, j, k; 8. int sayi, gecici; 9. int sayilar[LIMIT]; 10. 11. /* girdi */ 12. i=0; 13. while (isayilar[k]) { 25. gecici=sayilar[k]; 26. sayilar[k]=sayilar[j]; 27. sayilar[j]=gecici; 28. } 29. 30. /* cikti */ 31. k=0; 32. do 33. printf("%d ", sayilar[k++]); 34. while (k<=i); 35. } /* main */ Girilen tamsayıları artan sıraya göre sıralayan, yukarıdaki program, if, while, do, for ve break deyimlerini örneklemek için verilmi ştir. En ba şta tanımlanmı ş olan iki de ği şmez, sırasıyla, girdi için “gözcü” bir de ğer ve içinde sayıların saklanaca ğı dizinin boyudur. Gözcü, girdi akı şında kar şımıza çıktı ğında, daha fazla girdi olmayaca ğını belirten bir de ğerdir. Örnekteki durumda, sıfır rastlandı ğında program girdi okumayı bitirecektir. Program, sırasıyla, girdi, sıralama ve çıktı yapan üç bölümden olu şmu ştur. İlk bölüm (Satır 12-18) klavyeden tamsayılar okur ve bunları s ıfırıncı elemandan ba şlayarak sayilar adlı diziye yerle ştirir. while deyimindeki (isayilar[k] ise iki elemanın de ğerlerini de ği ş toku ş ederiz. Bu i şlemin yapıldı ğı yer Satır 25-27’dir. Üçüncü bölüm (Satır 31-34), bir do kullanarak, (artık sıralanmı ş sayıları içeren) dizideki ilk i+1 elemanı basar. E ğer, en ba şta, ilk (ve son) de ğer olarak sıfır girersek, bu bölüm gereksiz ve ilgisiz bir sayı basacaktır. (Bunun nedenini söyleyebilmemiz gerekir.) Bu, en kısa ve basit gibi görünen programların bile, en beklenmeyen zamanda kendini gösteren, hatalar içerebilece ğini gösterir. Problemler 1. do deyimini ba şka kontrol akı şı deyimleri kullanarak “formüle” edin. 2. A şa ğıdaki if’in görevini yapan bir switch yazın. if (yas == 16) printf("Onumuzdeki yil " "surucu belgesi alabilirsiniz!\n"); 3. while deyimini ba şka kontrol akı şı deyimleri kullanarak yazın. 4. Bir tamsayı okuduktan sonra, 1’den girilen sayıya kadar olan bütün tamsayıların kareleri ile kar şıt (1/sayı) de ğerlerini basan bir program yazın. 5. Sıfırla sonlandırılmı ş bir tamsayı serisini okuyup sonunda sayıların en küçük, en büyük ve ortalamasını veren bir program yazın. 6. Bir karakter sırasını okuyup arka arkaya tam 3 defa rastladı ğı karakterleri basan bir program yazın. Örne ğin bcdaaaefghijjjjkkkop girdisi için, çıktı a k olmalıdır. 7. Tedavülde ( şimdilik) 5, 10, 20, 50, 100, 250, 500 bin ve bir milyonluk banknotlar bulunmaktadır. Fiyatı ve bu cinste gösterilmi ş para miktarını kabul edip geriye verilecek bozuk parayı (yani fiyat ile verilmi ş para arasındaki farkı) liste şeklinde 44 DEY İMLER VE KONTROL AKI ŞIB Ö L Ü M 2 veren bir program yazın. Bu durumda, programın kabul edebilece ği para miktarı 5 binin katı olmalıdır. 8. Kısım 2.12’deki programı, her çe şit bilgi için do ğru çalı şacak şekilde düzeltin. 9. Bir x sayısının b tabanına göre logaritması şu şekilde hesaplanabilir: Sayının 1?x, <=, >=, == ve != kullanarak) kar şıla ştırılabilir, ancak farklı dizilerdeki nesnelere i şaret eden iki göstergeyi kar şıla ştırmak anlamlı (en azından ta şınabilir bir özellik) de ğildir. Do ğal olarak, bunun nedeni iki dizinin ana bellekteki birbirine göre durumları konusunda emin olamayaca ğınızdır. Bu kısımdaki ikinci for’da kullanılan “g<&z[N]” testi uygundur, çünkü g ve &z[N] aynı dizi içindeki (olası de ği şik) yerlere i şaret ederler. &z[N] adresinin z dizisi içinde olmadı ğını söyleyerek, buna kar şı çıkabilirsiniz, zira dizinin son elemanı z[N-1]’dir. Haklısınız, ancak g’nin bu “geçersiz” adrese i şaret etti ği zaman *g’ye bir şey atamamak için, <= yerine < kullanacak kadar dikkatli oldu ğumuzu da gözlemleyin. C Standardı ise, bir nesnenin sınırları dı şında adres üretmeyi—o adresteki bölge de ği ştirilsin de ği ştirilmesin—açıkça yasaklamaktadır. Tek istisna olarak, bir nesnenin son baytından bir sonraki baytı gösteren adresi üretme ğe izin verir. İşte bu özellik “g<&z[N]”de kullanılmı ştır. Bir gösterge (== veya != kullanılarak) 0 tamsayı de ği şmeziyle kar şıla ştırılabilir. Geleneksel olarak 0 de ğerinin hiç bir şeyi göstermedi ği varsayılmı ştır. Bu tamsayı de ği şmezi programlarda o kadar çok kullanılmaktadır ki stdio.h ba şlık dosyasında #define NULL 0 şeklinde bir tanımlama yapılmı ştır. Böylece, e ğer 0 yerine NULL kullanılacak olursa “göstergeler tamsayı de ğildir” kuralı bozulmamı ş gibi görünecektir. Bir göstergenin herhangi bir yeri göstermesini istemiyorsanız g = NULL; atama deyimini kullanın. NULL’un her tip gösterge ile uyumlu oldu ğuna dikkat edin. Bu özel bir durumdur. 3.2. Göstergeler Ve Diziler Şimdi, gelin a şa ğıdakini inceleyelim 50 GÖSTERGELER VE B İT İŞLEME BÖLÜM 3 int z[N], i; ... for (i=0; i void main (void) { char *dd; dd = "dunya"; printf("Merhaba, %s.\n", dd); } Bildi ğiniz gibi, printf’in ilk argümanı bir karakter göstergesi olmalıdır; ikinci argüman da, %s dönü şüm tanımlamasının gerektirdi ği şekilde bir karakter göstergesidir. Yukarıdaki atama ifadesinde oldu ğu gibi, bir ifade içinde kullanılan bir karakter dizisi de ği şmezi bir karakter göstergesidir ve dizinin ilk karakterine i şaret eder. Karakter dizisi, derleyici tarafından, bir tarafta saklanır. Böylece, yukarıdaki atama deyiminde sadece bir gösterge ataması yapılmaktadır; bir karakter dizisi aktarması söz konusu de ğildir. E ğer bir karakter dizisi aktarması yapmak istiyorsak bunu kendimiz yapmalıyız. Örne ğin, char d[10]; d = "bir dizi"; geçersizdir, çünkü derleyici gösterge ataması yapmaya çalı şacaktır. Ancak “=” i şaretinin sol tarafında bir de ği şmez gösterge bulundu ğundan, bu olanaksızdır. Karakterleri tek tek, bir döngü kullanarak, atamak zorundayız. Böyle i şlemler çok sık kullanıldı ğı için, C kütüphanesi bazı karakter dizisi i şleme fonksiyonları sa ğlamaktadır. Örne ğin, strcpy(d, "bir dizi"); bizim i şimizi görecektir. Bu fonksiyon, ikinci argüman olarak geçirilen adresteki bütün karakterleri, en sonda gelen bo ş karakteri (\0) ile birlikte, d tarafından gösterilen yere aktaracaktır. Bu durumda, bu 9 karakterdir. Bu fonksiyon, hedef dizinin bu kadar çok karakteri alacak geni şlikte olup olmadı ğını kontrol etmez. (Zaten edemez.) Benzer bir durum karakter dizileri kar şıla ştırması yaparken ortaya çıkar. if (s=="Bu dizi") ... testi her zaman yanlı ş sonucunu verecektir. Ku şkusuz bunun nedeni gösterge e şitli ğini test etmemizdir. s ya bir gösterge yada bir dizi ismi olabilir (her iki durumda da bir gösterge 52 GÖSTERGELER VE B İT İŞLEME BÖLÜM 3 ifadesidir); de ği şmez karakter dizisi ise onu saklamak için kullanılan bellek öbe ğinin ba şına i şaret eden bir göstergedir. Do ğal olarak, bunlar farklı adreslerdir, böylece bu test hiçbir zaman “do ğru” sonucunu vermeyecektir. Bunun yerine, s1 ve s2 şeklinde verilen iki karakter dizisini kar şıla ştırıp, sözlük sıralamasına göre s1’in s2’den küçük, s2’ye e şit veya s2’den büyük olmasına ba ğlı olarak, sırasıyla olumsuz bir tamsayı, sıfır veya olumlu bir tamsayı veren strcmp(s1,s2) fonksiyonunu kullanmalıyız. strcat(d,s) fonksiyonu s dizisini d’nin arkasına aktarır. Ku şkusuz d dizisinin hem eski hem de yeni karakter dizisini kapsayacak kadar geni ş olması gerekir. strlen(s) s karakter dizisinin uzunlu ğunu verir; bunu yaparken en sondaki bo ş karakteri saymaz. strchr(s,c) c karakterinin s karakter dizisinin içinde ilk ortaya çıktı ğı yerin adresini bir karakter göstergesi olarak döndürür; c dizi içinde yoksa NULL verir. strrchr(s,c) strchr(s,c) gibidir, sadece tarama i şlemini sa ğdan sola doğru yapılır. Yukarıdaki fonksiyonlardan bazıları için i şlemi sınırlayan ba şka bir argüman, n, kabul eden bazı uyarlamalar bulunmaktadır. strncmp(s1,s2,n) en fazla n karakteri kar şıla ştırır; strncat(s1,s2,n) en fazla n bo ş olmayan karakter ekler; strncpy(s1,s2,n) tam olarak n karakter aktarır (e ğer s2’nin uzunlu ğu daha kısa ise, bo ş karakterler eklenir). Yararlı bir de ğer döndürmüyor gibi gözüken fonksiyonlar aslında karakter göstergesi döndürmektedir. Genelde, geri döndürülen gösterge hedef dizisinin ba şına i şaret eder. Bir sonraki bölümde de görece ğimiz gibi, fonksiyonları kullanmadan önce bildirimlerini yapmak zorundayız. Bu kısımda anlatılan fonksiyonların bildirimi string.h ba şlık dosyasında bulunmaktadır. Di ğer birçok fonksiyon yanında, C kütüphanesinde bazı veri dönü şüm fonksiyonları da mevcuttur. Bunlardan bazılarının bildirimi stdlib.h ba şlık dosyasında bulunmaktadır ve a şa ğıda açıklanmı ştır. Ayrıca fonksiyon ve argüman tipleri de gösterilmi ştir. double atof(char *) karakter dizisi argümanını çift duyarlıklı kayan noktalı sayıya çevirir; hata durumunda 0.0 döndürür. int atoi(char *) karakter dizisi argümanını tamsayıya çevirir; hata durumunda 0 döndürür. long atol(char *) karakter dizisi argümanını uzun tamsayıya çevirir; hata durumunda 0L döndürür. char * itoa(int, char *, int) ilk tamsayı argümanını karakter dizisine çevirir, sonucu ikinci argüman olarak verilen adrese koyar; üçüncü argüman tabanı belirtir. char * ltoa(long, char *, int) ilk uzun tamsayı argümanını karakter dizisine çevirir, sonucu ikinci argüman olarak verilen adrese koyar; üçüncü argüman tabanı belirtir. BÖLÜM 3 GÖSTERGELER VE B İT İŞLEME 53 int toupper(int) ve int tolower(int) sırasıyla karakter argümanının büyük harf ve küçük harf kar şılı ğını döndürür. 3.4. Bitsel İşleçler İşleçler C’nin önemli bir konusudur. Ancak, hepsinin birlikte anlatılacakları tek bir yer yoktur. En iyisi gerek duyuldu ğunda onları anlatmaktır. Bu bölümde, göstergelerle beraber kullanıldıkları için, iki tekli i şleç (& ve *) anlatılmı ştı. Bitsel i şleçler ba şka şeylerle pek ilgisi olmayan bir grup olu şturduklarından, hepsini bu kısımda anlatmaya karar verdik. İşleçlerin azalan önceliklerine göre anlatılmaları açısından bu kısım Kısım 2.2’ye benzemektedir. Bire tümler ve atama i şleçleri sa ğdan sola do ğru, di ğerleri soldan sa ğa do ğru birle şirler. Bu kısımda anlatılan tüm i şleçler sadece (çe şitli boylarda olabilen) tamsayı i şlenenleri kabul ederler ve i şlenenler üzerinde i şlem yapmadan önce Kısım 1.6’da anlatılan tip dönü şümlerini gerçekle ştirirler. Atama ile ilgili olanlar hariç, e ğer i şlenenler de ği şmez ifadeler ise, de ği şmez ifadeler olu ştururlar. Bu i şleçlerin isimleri ve kullanılan simgeler şöyledir: i şleç isim ~ bire tümler << sola kaydırma >> sa ğa kaydırma & bitsel VE ^ bitsel dı şlayan VEYA | bitsel VEYA <<= sola kaydırma ve atama >>= sa ğa kaydırma ve atama &= bitsel VE ve atama ^= bitsel dı şlayan VEYA ve atama |= bitsel VEYA ve atama Detaya girmeden önce, bitsel i şleçlerin mantıksal olarak ne yaptı ğını gösteren bir çizelge sunalım. A şa ğıda y ve z tek bitlerdir: yz ~yy &zy ^zy |z 001000 011011 100011 110101 Bitsel bir i şleç i şlenen(ler)in her bitine yukarıda anlatılan şekilde uygulanır. 54 GÖSTERGELER VE B İT İŞLEME BÖLÜM 3 Bire Tümler İşleci ~ ~ i şleci i şleneninin 1 olan bitlerini 0’a, 0 olan bitlerini de 1’e çevirir. Sonucun tipi i şlenenin tipiyle aynıdır. Kaydırma İşleçleri << Ve >> Bir kaydırma ifadesi ifade_ 1 << ifade_2 veya ifade_ 1 >> ifade_2 şeklindedir. Normalde ifade_ 1 bir de ği şken veya dizi elemanıdır. << i şleci durumunda, tip dönü şümlerinden sonra, ifade_2 int’e çevrilir ve ilk i şlenenin bitleri ifade_2’nin de ğeri kadar sola kaydırılır. İşlenenin solundan “dü şen” bitler kaybedilir. Sola kayan bitlerden arta kalan sa ğdaki bo ş yerler sıfırla doldurulur. Sonucun tipi soldaki i şlenenin tipidir. >> i şleci yukarıda anlatılanların sa ğa do ğru olan şeklini yerine getirir, tek bir farkla: E ğer soldaki ifade signed (i şaretli) ise bo ş kalan yerler, 0 yerine, i şaret bitiyle doldurulabilir. Buna aritmetik kaydırma denir ve sistemimiz bunu yapar. E ğer ilk ifade unsigned (i şaretsiz) ise solda bo şalan bitlerin sıfırla doldurulaca ğı garanti edilir ve bir mantıksal kaydırma söz konusudur. Bitsel VE İşleci & İkili & i şleci i şlenenlerinin bitlerinin VEsini verir. Yani e ğer her iki i şlenenin i’inci bitleri 1 ise, sonucun i’inci biti de 1 olur. Aksi takdirde 0’dır. Tabii ki, (a & b) & c ve a & (b & c) aynı de ğerlere sahiptirler (yani & i şlecinin birle şme özelli ği vardır). C bu gerçe ği kullanır ve derleyici, daha verimli olaca ğı gerekçesiyle, parantez içine alınmı ş olsa dahi, böyle ifadeleri (yani, * ve + gibi birle şme ve de ği şme özelli ği gösteren i şleçleri içeren ifadeleri) istedi ği şekilde yeniden düzenleyebilir. Bitsel Dı şlayan VEYA İşleci ^ ^ i şleci i şlenenlerinin dı şlayan VEYAsını verir. Yani e ğer i şlenenlerin i’inci bitleri farklı ise, sonucun i’inci biti 1 olur. Aksi takdirde 0’dır. ^ birle şme özelli ği gösteren bir i şleçtir ve bu i şleci içeren ifadeler, önceki altkısımda anlatıldı ğı gibi, yeniden düzenlenebilir. BÖLÜM 3 GÖSTERGELER VE B İT İŞLEME 55 Bitsel VEYA İşleci | | i şleci i şlenenlerinin kapsayan VEYAsını verir. Yani e ğer her iki i şlenenin i’inci bitleri 0 ise, sonucun i’inci biti de 0 olur. Aksi takdirde 1’dir. | da birle şme özelli ği gösteren bir i şleçtir ve yeniden düzenleme söz konusu olabilir. Atama İşleçleri <<=, >>=, &=, ^= Ve |= Yukarıda anlatılan i şleçler belirli ifadeler olu şturmalarına ra ğmen, i şlenenlerinin de ğerlerini de ği ştirmezler. Şimdi anlataca ğımız atama i şleçleri ise i şlemin sonucunu soldaki i şlenenlerine aktarırlar. Bölüm 1’deki +=, -=, *= vs i şleçlerini anımsayın. Her bir ikili bitsel i şlecin kar şılı ğında bir atama i şleci mevcuttur, << için <<=, >> için >>=, & için &=, ^ için ^= ve | için |=. Bu i şleçlerin i şlevselli ği di ğer atama i şleçlerine benzer. Bitsel İşleçler—Örnekler short, long gibi tiplerin uzunlukları derleyiciden derleyiciye de ği şti ğine göre, buradaki örnekler sadece bizim sistemimiz için geçerlidir. A şa ğıdaki bütün örneklerde ifadenin de ğeri sekizli tabanda verilecektir. Sonucun tipi de ayrıca belirtilecektir. Bütün de ği şkenlerin ilk de ğeri 5’tir. Tipler ise şöyledir: /* signed */ char c; short s; int i; long l; ifade de ğer tip ~c 0372 char ~s 0177772 int ~i 0177772 int ~l 037777777772 long c << 3 050 char s >> 2 01 int i << l 0240 int c & s 05 int -i & ~l 037777777772 long c ^ 3 06 int ~s ^ 2 0177770 int i ^ l & i 0 long ~c | 3 0177773 int s | s>>1 07 int i | l 05 long c <<= s 0240 char l >>= i 0 long s &= -i 01 short i ^= l+1 03 int c |= 16 025 char 56 GÖSTERGELER VE B İT İŞLEME BÖLÜM 3 Bir Örnek—Sayı Paketleme Bitsel i şleçlerin kullanımını göstermek için, üç sayıyı bir tamsayıya “paketleyen”, daha sonra ise “açan” a şa ğıdaki programı inceleyelim. 1. #include 2. #define GUN_UZ 5 3. #define AY_UZ 4 4. #define TABAN_YIL 1900 5. #define TAVAN_YIL (TABAN_YIL+(1<<16-GUN_UZ-AY_UZ)-1) 6. void main (void) 7. { 8. unsigned const ay_ortu = ~(~0<TAVAN_YIL || 15. ay<1 || ay>12 || gun<1 || gun>31); 16. yil -= TABAN_YIL; 17. tarih = (yil<>GUN_UZ) & ay_ortu; 23. yil = tarih>>(GUN_UZ+AY_UZ); 24. printf("Acma tamamlandi.\nTarih: %u %u %u", 25. yil+TABAN_YIL, ay, gun); 26. } /* main */ Program ba şladı ğında 1900 ile 2027 yılları arasında bir tarih kabul eder. (Satır 12- 15.) Sadece bazı basit kontroller yapılmı ştır; 13’üncü ayın 54’üncü günü giremezsiniz, ancak Şubat’ın 31’ini girebilirsiniz. Sadece 1900 yılından beri geçen yılları sakladı ğımız için, Satır 16’daki -= i şlemi yapılır. Paketleme Satır 17’de yapılır: yil içindeki geçen yıllar AY_UZ (yani 4) bit sola kaydırılır, ay yeni bo şalan yere VEYAlanır, sonra bunun tamamı GUN_UZ (5) bit sola kaydırılır ve gun içeriye VEYAlanır. Paketleme sonunda, tarihin en solundaki 7 bitinde geçen yıllar, en sa ğdaki 5 bitte gün ve geri kalanında ay bulunur. Bizim sistemimizde short bir tamsayı 16 bit kapladı ğına göre, tarihteki bütün bitler kullanılmı ş olur. do deyimindeki erim (yayılma aralı ğı) kontrolleri, bu sayıların hiçbirinin kendileri için ayrılan miktardan daha fazla bir yer iste ğinde bulunmayacaklarını sa ğlamak içindir. Satır 20 açma i şleminin gerçekten çalı şıp çalı şmadı ğı ku şkusunu bertaraf etmek içindir ve programın davranı şında herhangi bir de ği şikli ğe yol açmadan çıkarılabilir. Satır 21 tarihin gün bitlerini 1’le, geri kalanını da 0’la VEleyerek günü alır. Buna, belli nedenden dolayı, “örtme” denir. Satır 10’da ilklenen, gun_ortu de ği şkeni gerekli bit kalıbını içerir. (~0’ın bütün bitleri 1’dir.) Satır 22, önce ayın en sa ğdaki 4 bite gelece ği şekilde tarihi kaydırır, sonra da ay dı şındaki bitleri örterek ayı elde eder. Satır 23’te, tarih, sonuçta geçen yılların elde edilece ği şekilde, sa ğa kaydırılır. tarih unsigned oldu ğuna göre en solda hep 0 vardır. Program yeni açılan tarihi yazarak sona erer. BÖLÜM 3 GÖSTERGELER VE B İT İŞLEME 57 Bu arada, daha ileriki bir bölümde aynı paketlemeyi yapacak ba şka bir yöntem görece ğiz. 3.5. İşleç Önceli ği Ve Birle şme İşleç önceli ği ve birle şme çizelgesinin en son durumu Çizelge 3.1’de gösterilmi ştir. Bu çizelge yeni tanıtılan i şleçlerle daha ileriki bölümlerde tanıtılacak olan i şleçlerin tamamını içerir. Ç İZELGE 3. 1 C i şleç önceli ği ve birle şme () [] -> . › ~ ! ++ -- sizeof (tip) +(tekli) -(tekli) *(dolaylama) &(adres alma) ‹ * / % › + - › << >> › < <= > >= › == != › & › ^ › | › && › || › ? : ‹ = *= /= %= += -= <<= >>= &= ^= |= ‹ , › Şimdi bu çizelgenin ne anlama geldi ğini bir daha gözden geçirelim. Bu çizelge, C dilindeki bütün i şleçleri, azalan öncelik sıralarına göre liste halinde vermektedir. Aynı satırda verilmi ş olan i şleçler aynı önceli ğe sahiptirler. E ğer aynı önceli ğe sahip iki i şlecimiz varsa, o zaman çizelgenin sa ğ sütununda gösterilen birle şmeyi kullanırız. Sa ğa doğru ok (›) soldan sa ğa birle şmeyi ifade eder, örne ğin “x/y/z” ile “(x/y)/z” aynı anlamı ta şırlar. Sola do ğru ok (‹) sa ğdan sola birle şmeyi belirtir, örne ğin “x=y=z” ile “x=(y=z)” e şde ğer ifadelerdir. Tüm tekli i şleçler, üçlü (ko şullu) i şleç ve tüm atama i şleçleri sa ğdan sola do ğru gruplanırlar; geri kalanların soldan sa ğa do ğru birle şme özelli ği vardır. Bu çizelgede gösterilen bazı i şleçler henüz anlatılmamı ştır. Bunlar: (), ., -> ve sizeof’tur. 58 GÖSTERGELER VE B İT İŞLEME BÖLÜM 3 Problemler 1. Bizim sistemimizde #include void main (void) { int x; printf("%d %d %d\n",(int)&x,(int)(&x+1),(int)&x+1); } programı 8580 8582 8581 sonucunu görüntüler. Tahmin edebilece ğiniz gibi bunlar bellek adresleridir. Neden ilk durumda fark 2, ikinci durumda ise 1’dir? 2. E ğer makinenizde (i şaretli) bir tamsayı üzerinde yapılan bir sa ğa kaydırma (>>) i şlemi esnasında bo şalan yerler i şaret bitiyle dolduruluyorsa isaret-doldurma, aksi takdirde sifir-doldurma mesajını verecek bir program yazınız. Sisteminiz hakkında (sözcük uzunlu ğu gibi) herhangi bir varsayım yapmayın. 3. Girilen bir tamsayıda 1 olan bitleri sayan bir program yazınız. 4. A şa ğıdaki deyimler ne yapar? a ^= b; b ^= a; a ^= b; Açıklayınız. İpucu: Ba şlangıçta a’nın 0077, b’nin de 0707 içerdi ğini varsayın. Son de ğerleri ne olacaktır? 5. Zaman da bir sözcük içine a şa ğıdaki gibi paketlenebilir: 5 bit saat, 6 bit dakika, 5 bit saniye. Saniyeleri 5 bite sı ğdırmak için de ğeri 2 ile bölün, yani saniyenin en sa ğındaki biti atın. Bunu yerine getirecek bir program yazın. 6. A şa ğıdaki kodun ne i şe yaradı ğını açıklayın: int i; for (i=0; i<10; i++) printf("%d:%c\n",i,"QWERTYUIOP"[i]); 59 BÖLÜM 4: FONKS İYONLAR VE PROGRAM YAPISI Bir program bir görevi yerine getirmek için yazılır. E ğer yapılacak i ş pek kolay de ğilse, program oldukça uzun olabilir. Bazı programlar onbinlerce satır uzunlu ğunda olabilir. Böyle durumlarda, esas görevi daha küçük ve kolay idare edilebilir altgörevlere ayırmadan yerine getirmek hemen hemen olanaksızdır. C, böyle altgörevleri ifade etmek ve birbirinden ayırmak için bir yöntem öngörmektedir. Bu yöntem sayesinde “bilgi saklama” ilkeleri kullanılabilir. C sadece bir tek altprogram çe şidi sa ğlamaktadır, bu da fonksiyondur. Matematiksel olarak; bir fonksiyon, argümanlarını döndürdü ğü de ğere ili şkilendiren bir “kara kutu” gibidir. Aynı şey C için de geçerlidir, ancak bir fonksiyon birden fazla de ğer döndürecek, küresel veri yapılarında yan etkiler yapacak veya girdi/çıktı sa ğlayacak bir şekilde de tasarımlanabilir. Örne ğin, printf fonksiyonu, argümanlarının de ğerlerinin çıktısını yapmak için kullanılır. Geri döndürdü ğü de ğer, yazılan karakterlerin sayısıdır, ancak bu fazla ilgi çekici de ğildir. Çok “basit” bir fonksiyon tanımı a şa ğıda verilmi ştir: void f (void) { } Bu fonksiyon hiçbir şey yapmamasına ra ğmen, program geli ştirmesi esnasında yer tutucu olarak kullanılabilir. Bu bölümde fonksiyon tanımı ve kullanımı hakkında daha fazla şeyler ö ğrenece ğiz. Kitabın ba şından beri görmekte oldu ğumuz main tanıtıcı sözcü ğü, programın yerine getirmesi gereken görevi ifade eden fonksiyonun ismidir. Her makul C programı içinde main adı verilen bir fonksiyonun bulunması gerekir, çünkü program yürütülmeye ba şlandı ğında, program içinde ba ğlanmı ş bulunan bir ba şlangıç yordamı çalı şmaya ba şlar, bu da kontrolü sonuçta main fonksiyonuna geçirir. E ğer ba ğlama esnasında, ba ğlayıcı (linker) main adı verilen bir fonksiyon bulamazsa, sizin için yürütülebilir bir kod 60 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 olu şturamayacaktır. main’in bir anahtar sözcük olmadı ğına dikkat edin, yani isterseniz, main adında bir de ği şken de tanımlayabilirsiniz. Fonksiyonların gücü, bizim tekrarlanan kod yazmamızdan kaçınmamızı sa ğlamalarında yatar. Herhangi bir kodu, bir fonksiyon şeklinde, bir defa belirtiriz, ona bir isim veririz ve daha sonra, bu kodu çalı ştırma gereksinimi duydu ğumuzda, bu fonksiyonu “ça ğırırız”. Bu iyi, fakat yeterli de ğildir. Birçok durumda bu kod o anki gereksinmelerimize “uyarlanmalıdır”. Örne ğin, bir diziyi sıraya sokan bir kodumuz varsa, bu kodu her ça ğırdı ğımızda, de ği şik sayıda elemandan olu şan de ği şik bir dizi belirtecek şekilde bunu hazırlamamız daha iyi olur. Bu ise, fonksiyon argümanları kullanılarak yapılabilir. Her fonksiyon di ğerlerinden ba ğımsız oldu ğuna, yani bir fonksiyon içinde tanımlanmı ş de ği şkenler ba şka bir fonksiyonda kullanılamadı ğına göre, fonksiyonların birbirleriyle haberle şmelerini sa ğlayacak yöntemler geli ştirilmi ştir. Bir yöntem fonksiyonlara argüman geçirmektir. Ba şka bir yöntem küresel de ği şkenler kullanmaktır. Şimdiye kadar olan örneklerde gördü ğümüz bütün de ği şkenler fonksiyonlar (main fonksiyonu) içinde tanımlanmı şlardı. Bu bölümde görece ğimiz gibi; de ği şken bildirimleri veya tanımlamalarını fonksiyonlar dı şında yapmamız da olasıdır. Böyle de ği şkenlere küresel adını veririz, çünkü fonksiyon içinde tanımlanan yerel de ği şkenlerin aksine, bunlar, tanımlamadan sonra gelen program metni içindeki bütün fonksiyonlar tarafından kullanılabilirler. 4. 1. Fonksiyon Tanımlama Aslında bir fonksiyonu, yani main fonksiyonunu, nasıl tanımlayaca ğımızı zaten biliyoruz. Şimdi, bir fonksiyonun daha genel bir şeklini görelim: dönü ş_tipi opt fonksiyon_ismi (parametre_bildirimleri opt ) blok Dönü ş_tipi fonksiyon tarafından döndürülen de ğerin tipini belirtir. Bu, int, double gibi bir aritmetik tip veya gösterge olabilir. Bir dizi, ve bazı eski derleyicilerde bir yapı veya birlik olamayabilir, ancak bunlara bir gösterge olabilir. Bir fonksiyon için varsayılan dönü ş tipi int’tir, bu da geni ş bir alanı kapsar, çünkü genelde mantıksal de ğerler (do ğru/yanlı ş de ğerleri) ve karakterler için de int kullanırız. Dönü ş_tipi olarak void anahtar sözcü ğü kullanıldı ğında, fonksiyondan hiçbir de ğer döndürülmeyece ği belirtilmi ş olur. void fonksiyonlar FORTRAN’daki SUBROUTINE’ler veya Pascal’daki procedure’ların kar şılı ğıdır. Fonksiyon_ismi bir tanıtıcı sözcüktür. E ğer fonksiyon, ayrıca derlenen ba şka bir kaynak dosyadan ça ğrılacaksa, fonksiyon isminin sadece ilk 8 karakteri anlamlıdır, bu da ba ğlayıcı tarafından konulan sınırlamadan dolayıdır. BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 6 1 Parametre_bildirimleri virgülle ayrılmı ş ve önüne tipleri yazılmı ş biçimsel argüman veya parametre isimleri listesidir. Di ğer bir fonksiyon tarafından ça ğrıldı ğında bu fonksiyona geçirilecek olan argümanların sayısını, sırasını ve tipini belirtir. Aynı zamanda, parametrelere, sadece fonksiyonun gövdesini olu şturan blok’un içinde anlamlı olan, isimler verir. Hiç parametresi olmayan bir fonksiyon da olabilir. Bu durum, parantezler içine void yazılarak açıkça gösterilir. Örne ğin, rand (void) { fonksiyonun gövdesi } Blok, her biri iste ğe ba ğlı olan, iki kısımdan olu şan bile şik bir deyimdir: Bir de ği şken veya tip tanımlama veya bildirim kısmı ile onu izleyen deyimler. Kısım 1.8’e bakınız. Bildirim kısmı, fonksiyon gövdesi içinde yerel olarak kullanılacak olan nesnelerin tanımını veya bildirimini içerir. Deyimler, fonksiyon gövdesinin yürütülebilir kısmını olu ştururlar. Bir fonksiyon ba şka bir fonksiyon içinde tanımlanamaz. Di ğer bir de ği şle bir fonksiyon tanımı di ğer bir fonksiyon tanımının bitmesinden sonra ba şlar. Fonksiyon tanımlamalarının sırası önemsizdir, ancak bu bölümde daha ileride bahsedece ğimiz dikkat edilmesi gereken bazı küçük noktalar vardır. Şimdi, bir örnek. C’nin “mutlak de ğer alma i şleci” yoktur. Tamsayılar üzerinde çalı şan bir fonksiyon tanımlayalım. abs (int n) { if (n >= 0) return n; else return -n; } Burada return adında yeni bir deyim görmekteyiz. Bu genelde, return ; veya return ifade; şeklinde olur. Kontrolün ça ğırana geri dönmesini sa ğlar. return deyiminden sonra gelen deyimler yerine getirilmez ve fonksiyon hemen ça ğrıldı ğı yere “geri döner”. İlk şekilde kontrol geri döner, ancak yararlı hiç bir de ğer döndürülmez. Geri döndürülen de ğer tanımsız oldu ğu için, ça ğıran fonksiyon bunu kullanmaya çalı şmamalıdır. İkinci şekilde ifadenin de ğeri fonksiyonun de ğeri olarak geri döndürülür. E ğer ifadenin de ğerinin tipi fonksiyonun dönü ş tipiyle aynı de ğilse, otomatik tip dönü şümü yapılır. “Dönü ş tipi” void olan fonksiyonlar için ikinci şeklin kullanılamayaca ğı açıktır. 62 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 Sa ğ çengelli parantezin önünde bir return oldu ğu varsayılır; bundan dolayı belli bir de ğer döndürmek istemiyorsanız return yazmayabilirsiniz. Son deyim yerine getirildikten sonra, yararlı bir de ğer olmadan kontrol ça ğıran fonksiyona döndürülecektir. 4.2. Fonksiyon Ça ğrıları Bir fonksiyonu ça ğırmak için fonksiyon ismini ve virgülle ayrılıp parantez içine alınmı ş argümanların bir listesini belirtin. Fonksiyonun argümanları olmasa dahi parantezler bulunmalıdır, böylece derleyici ismin bir de ği şkeni de ğil de bir fonksiyonu gösterdi ğini anlayabilecektir. Fonksiyon tarafından geri döndürülen de ğer kullanılabilir veya kullanılmayabilir. Örne ğin, abs(-10); bir fonksiyon ça ğrısıdır. Bu noktada kontrol, ça ğıran fonksiyondan ça ğrılan fonksiyona aktarılır. -10 de ğeri abs fonksiyonunun n parametresine atanır. Ça ğrılan fonksiyon, ya bir return deyiminin yerine getirilmesi yada fonksiyon gövdesinin sa ğ çengelli parantezine ula şılması sonucu bitti ğinde, kontrol ça ğıran fonksiyondaki kaldı ğı yere geri döner. Fonksiyon tarafından bir de ğer döndürülüyorsa, bu de ğer ça ğrının yerini alır. Örne ğin, x = abs(-127); x’in de ğerini 127 yapacaktır; oysa daha yukarıda aynı fonksiyona yapılan ilk ça ğrıda geri döndürülen de ğer (10) kullanılmamı ştı, bu yüzden bu de ğer kaybolmu ştu. “Dönü ş tipi” void olan bir fonksiyonun bir ifade içinde kullanılmaması gerekti ği açıktır. Bir argüman istenildi ği kadar karma şık bir ifade olabilir. Argüman de ğerinin tipi fonksiyon tanımındaki kar şılık gelen parametre için beklenen tipe uymalıdır, aksi takdirde, a şa ğıda açıklanaca ğı gibi, bulunması zor olan bazı hatalar meydana çıkabilir. Dikkat: Fonksiyon argümanlarının hesaplanma sırası belirtilmemi ştir. Örne ğin, iki int argümanının toplamını veren topla isminde bir fonksiyonumuzun oldu ğunu varsayalım. Ayrıca, de ğeri 5 olan, i adında bir de ği şkenimiz olsun. toplam = topla(i--, i); yazdı ğımızda toplam’ın de ğeri ne olacaktır? 9 mu 10 mu? Bu, argümanların hesaplanma sırasına ba ğlıdır. De ği şik derleyiciler de ği şik şekilde yapabilirler. Bizim sistemimizde, argümanlar sa ğdan sola hesaplanır, böylece toplam’ın de ğeri 10 olacaktır. Bu tür şeylerden kaçınılması gerekti ğini söylemeye gerek yok tabii. Fonksiyonlar kullanılmadan önce bildirilmelidirler. Bu kural bazı hataların önlenmesi için titizlikle uygulanmalıdır. C derleyicisi, bildirimi yapılmayan bir fonksiyon kullanımı ile kar şıla ştı ğında dönü ş tipinin int oldu ğunu varsayar. Örne ğin, a şa ğıdaki gibi dabs adında bir fonksiyon tanımladı ğımızı BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 63 double dabs (double n) { return (n >= 0.0) ? n : -n; } ve onu deneme (void) { double d; ... d = dabs(-3.14159); ... } şeklinde ça ğırdı ğımızı dü şünün. Üç olasılık vardır: 1. dabs’ın tanımı aynı kaynak dosyada deneme’nin tanımından önce gelir. Bu durumda dabs’ın tanımı etkisini deneme’nin içinde de sürdürece ği için hiç bir sorun çıkmayacaktır. Derleyici, yukarıdaki ifadede dabs tarafından beklenen ve geri döndürülen de ğerin tipinin double oldu ğunu bilecek ve gerekli tip dönü şümlerini yapacaktır. 2. dabs’ın tanımı deneme’nin tanımından sonra gelir. Derleyici dabs’ın bir fonksiyon ça ğrısı oldu ğunu tanıyacak, ancak, henüz dönü ş tipinin ne oldu ğunu bilemeyece ği için, int döndüren bir fonksiyon oldu ğunu varsayacaktır. Daha sonra, dabs’ın gerçek tanımıyla kar şıla ştı ğında, bir sorun ortaya çıkacaktır, çünkü double döndüren bir fonksiyon olarak tekrar tanımlamaya çalı şacaktır. Bu durumda bir hata mesajı verilecektir. 3. En kötü durum, dabs’ın tanımı ayrı bir kaynak dosyada verildi ği zaman ortaya çıkacaktır. Ayrı ayrı derlemeden dolayı, derleyici uyu şmazlı ğı bulamayacaktır. Hatta ba ğlayıcı bile bir şey yapamayacaktır. Programın yürütülmesi esnasında anlamsız sonuçlar elde edilecektir. Bunun nedeni, yine, derleyicinin tanımı veya bildirimi yapılmamı ş olan fonksiyonun int döndürdü ğünü varsayması, böylece de dabs fonksiyonu tarafından döndürülen double de ğerin deneme tarafından int gibi yorumlanmasıdır. Birçok derleyici yapılan bu tip varsayımları, bir uyarı mesajı şeklinde kullanıcıya bildirirler. Bu tip uyarıları mutlaka dikkate alın, çünkü varsayımlar her zaman sizin dü şündüklerinizle uyu şmayabilir. Yukarıdaki 2 ve 3’teki sorunları çözmek için a şa ğıdaki şekil önerilmektedir: deneme (void) { double d, dabs(double); ... d = dabs(-3.14159); ... } 64 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 Yukarıdaki bildirim (buna ayrıca fonksiyon prototipi de denir) deneme fonksiyonun tanımının dı şında ve önünde de yazılabilir. Böyle fonksiyon prototiplerinin tamamını programın ba şlangıcında veya böyle fonksiyonları kullanan her kaynak dosya tarafından #include kullanılarak içerilecek ba şlık dosyalarına yazmak sıkça kullanılan bir yöntemdir. Standart kütüphane fonksiyonlarının bildirimlerini yapan standart ba şlık dosyaları buna iyi bir örnek olu ştururlar. Bunlar, derleyicilerin çe şitli hataları yakalamalarını veya gerekti ği zaman tip dönü şümleri yapmalarını sa ğlar. Örne ğin, yukarıdaki bildirimden sonra, derleyici, d = dabs(5); ifadesindeki 5 tamsayısını dabs’a geçirmeden önce double’a dönü ştürecektir. Ancak d = dabs("bes"); için bir hata mesajı verecektir, çünkü bu durumdaki karakter göstergesi double’a dönü ştürülemez. Argümanlar ça ğıran fonksiyondan ça ğrılan fonksiyona geçirildi ğinde, “do ğal” tiplerine (örne ğin short’tan int’e) dönü ştürürler. E ğer fonksiyon kısa bir tip bekliyorsa, bu argümanın kısa tipe dönü ştürülmesi gerekecektir. Böylece, e ğer özel bir neden yoksa, fonksiyon parametrelerinin bu do ğal tiplerden olması daha iyi olacaktır. Genelde, dönü ş tipleri için de aynı şey sözkonusudur. 4.2. 1. De ğer İle Ça ğrı FORTRAN’da ve bazı di ğer dillerde argümanlar referansla geçirilir. Yani, fonksiyona argümanın de ğeri yerine adresi verilir. Bu yolla, ça ğrılan fonksiyon ça ğıran fonksiyon tarafından argümanın saklandı ğı bölgeye eri şir ve de ğerini de ği ştirebilir. Böylece, bütün argümanlar hem fonksiyona bilgi iletirler, hem de fonksiyondan bilgi geri getirirler, yani, istemesek bile, fonksiyona hem girdi hem de çıktı için kullanılırlar. E ğer gerçek argüman, bir de ği şken de ğil de bir ifade veya de ği şmez ise ne olur? Bu durumda, ça ğıran fonksiyon ifadeyi hesaplar, de ğerini bir yerde saklar, sonra da bu adresi geçirir. E ğer ça ğrılan fonksiyon, mantıksal olarak yapmaması gerekti ği halde, argümanının de ğerini de ği ştirirse, bazı garip şeyler ortaya çıkabilir. Bir yordamın F FORTRAN fonksiyonunu bir de ği şmez olan 4 argümanı ile ça ğırdı ğını (yani “F(4)”), ancak F fonksiyonu içinde argümanın de ğerinin 5 yapıldı ğını varsayın. Bundan sonra, program içindeki 4 “de ği şmez”inin her kullanıldı ğı yerde (örne ğin “PRINT *,4”) 4’ün 5 oldu ğu “gerçe ği” ortaya çıkarılacaktır. Di ğer bir deyi şle, yukarıdaki deyimden 5 elde edilecektir! Yukarıdaki tartı şma, argüman geçirilmesi için ba şka bir yöntemin gerekli oldu ğunu ortaya çıkarmaktadır. Bu de ğer ile ça ğrıdır ve C tarafından desteklenmektedir. Bu durumda, argümanın adresi yerine de ğeri fonksiyona geçirilir. Bu de ğer, özel bir bölgede, tıpkı normal bir yerel de ği şken gibi saklanır. Biçimsel argümana yapılan her türlü de ği şiklik yerel kopyasında yapılacaktır ve ça ğıran fonksiyondaki argümanlara herhangi bir etkisi olmayacaktır. BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 65 Bazı diller argüman geçi şinin her iki yöntemine de izin verirler. Örne ğin, Pascal’da, önüne var anahtar sözcü ğü yazılarak tanımlanan parametreler için referansla ça ğrı yapılır, var yoksa de ğerle ça ğrı yapılır. Normalde C de ğerle ça ğrıyı destekledi ği halde, daha ileride görece ğimiz gibi, mantıklı bir adres ve gösterge kayna şması ile referansla ça ğrı yapılabilir. İlk önce de ğerle ça ğrıya bir örnek verelim: fakt (int n) { int i = n; while (--n) i *= n; return i; } Burada, önce i’ye n atanır, daha sonra n s ıfır oluncaya kadar a şa ğı do ğru sayılır, her sefer i yeni n ile çarpılır. Gördü ğünüz gibi n’nin de ğeri de ği şir, ancak ça ğıran fonksiyon tarafından geçirilen gerçek argüman üzerinde bunun bir etkisi yoktur. Örne ğin, sayi = 4; printf("%d! = %d\n", sayi, fakt(sayi)); deyimlerinden sonra sayi’nın de ğeri (0 de ğil) 4 olmaya devam edecektir. fakt’taki n parametresinin i gibi yerel bir de ği şken oldu ğuna dikkat edin. 4.2.2. Referans İle Ça ğrı Ça ğrıyı yapana bilgi döndürmek istedi ğimizde ne yapmamız gerekir? Bir yöntem fonksiyonun dönü ş de ğerini kullanmaktır. Şimdiye kadar olan örneklerimizde bu çok sık kullanılmı ştı. Fakat, birden fazla döndürülecek de ğer varsa o zaman ne yapaca ğız? Bu durumda, referansla argüman geçirmenin bir yolunu bulmamız gerekecektir. Aslında bunu nasıl yapaca ğımızı da biliyoruz. Daha önceki bölümlerde programa de ğer girmek için scanf fonksiyonunu kullanmı ştık. Bu fonksiyon argümanlarına yeni de ğerler atar. Bu fonksiyonu ilgilendirmedi ğine göre, argümanların eski de ğerlerini geçirmek yerine, adreslerini geçiririz. Bu amaçla da, adres alma (&) i şlecini kullanırız. Şimdi referans ile ça ğrı yöntemini göstermek için bir örnek vermenin zamanıdır. İki int argümanının de ğerlerini de ği ş toku ş eden bir fonksiyon yazmak istedi ğimizi varsayın. void degis (int x, int y) { int t; t = x; x = y; y = t; } fonksiyonu bu i şi yapacaktır, ancak sadece yerel olarak! Parametrelerin yeni de ğerleri ça ğıran fonksiyona geri iletilmeyecektir. De ğerleri geçirmek yerine, yukarıda anlatıldı ğı 66 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 gibi de ği şkenlerin adreslerini geçirmemiz gerekir. Böylece, a ve b’nin int de ği şken oldu ğu degis(&a, &b) şeklinde bir ça ğrı gerekecektir. Ancak degis fonksiyonu da bu göstergeleri kabul edecek şekilde yeniden düzenlenmelidir. Her şeyden önce, parametre bildirimleri de ği ştirilmelidir; yeni parametre de ği şkenleri de ğerler yerine adresleri saklamalıdır. Bildirim şöyledir: int *xg, *yg; ve, örne ğin, xg de ği şkeninin bir int göstergesi oldu ğu anlamına gelir. Şimdi bütün x ve y’leri sıra ile *xg ve *yg ile de ği ştirirsek degis’in do ğru tanımını elde ederiz: void degis (int *xg, int *yg) { int t; t = *xg; *xg = *yg; *yg = t; } Unutulmaması gereken bir nokta, dizi argümanlarının her zaman referans ile geçirildi ğidir. Örne ğin, argüman olarak verilen diziyi sıraya sokan sirala adında bir fonksiyonumuz oldu ğunu varsayalım. Fonsiyonun bildirimi şöyle bir şey olacaktır: void sirala (int a[], int n) /* n dizinin uzunlugudur */ { sıralama i şlemi } Bu durumda, sirala(dizi, eleman_sayisi); şeklinde bir ça ğrı, dizinin taban adresini fonksiyona geçirecektir. sirala’daki a geçirilen dizinin yerel bir kopyası de ğildir. a “dizisi”nin uzunlu ğunun belirtilmemesinden, dizi için bir yer ayrılmadı ğını anlayabilirsiniz. sirala fonksiyonu içinde a’ya yapılan bütün referanslar aslında dizi’ye yapılmaktadır, bundan dolayı de ği şiklikler de orada yapılmaktadır. Bunun nedeni dizi ile &dizi[0]’ın tamamen aynı şey olmasıdır. Bu iyi bir özelliktir, çünkü aksi takdirde bütün dizinin yerel bir diziye aktarılması gerekecekti; bu da hem bilgisayar zamanı hem de bellek harcayacaktı. Aslında, parametre_bildirimlerinde “int a[]” ile “int *a” aynı şeydir, yani a bir göstergedir. Örne ğin, bir dizinin elemanlarını toplayan bir fonksiyonumuz var diyelim. Bunu şu şekilde tanımlayabiliriz: BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 67 topla (int a[], int n) { int s = 0; while (n--) s += a[n]; return s; } ve dizi’nin bir tamsayı dizisi, uzunluk’un da toplanacak elemanların sayısı oldu ğu topla(dizi, uzunluk) şeklinde bir ça ğrı yapabiliriz. dizi isminin bir gösterge oldu ğu, bundan dolayı topla’nın a’da elde etti ği şeyin bir gösterge oldu ğuna dikkat edin. a’nın “int *a” şeklinde bildirilmesi daha iyi olacaktı. Aslında derleyici de aynı şeyi dü şünmekte ve fonksiyon parametreleri için iki bildirimi tamamen e şde ğer kabul etmektedir. Bunu görmek için a şa ğıdakini kar şıla ştırın: topla (int a[], int n) { int s = 0; while (n--) s += *a++; return s; } Atama deyiminde, *a++, *(a++) anlamına gelir, bu da (*a)++’dan tamamen farklıdır, çünkü bu sonuncusu dizinin ilk elemanını sürekli olarak artırmaya yarar, yani a[0]++. topla’nın bu yeni şeklinin ilk verilenle aynı i şi yaptı ğını, ancak daha verimli oldu ğunu gösterin. Ayrıca, topla’ya dizinin taban adresi yerine ba şka bir adresin de verilebilece ğini akıldan çıkarmayın. Örne ğin topla(&dizi[2], uzunluk-2) ve topla(dizi+2, uzunluk-2) topla’nın dizinin üçüncü elemanından ba şlayarak, yani ilk iki elemanı atlayarak, i şlemi yapmasını sa ğlayan iki e şde ğer ça ğrıdır. Bir fonksiyon parametresinin bildirimi yapılırken const tip niteleyicisi de kullanılabilir. Bir dizinin fonksiyon gövdesi içinde de ği ştirilmeyece ğini göstermesi açısından, dizi parametrelerinin bildirimlerinde yararlanılabilir. 4.2.3. main Fonksiyonunun Parametreleri main de bir fonksiyondur, fakat ilk bakı şta sanki herhangi biri onu ça ğırıyor gibi gözükmemektedir. Bu do ğru de ğildir, çünkü birisi onu gerçekten ça ğırmaktadır. İşletim 68 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 sistemi, programı çalı ştırmak için onu yükledikten sonra, bir ba şlatma yordamı kontrolü eline alır; bu da sonuçta main adında bir fonksiyonu ça ğırır—bundan dolayı bu isimde bir tane fonksiyon bulunması gerekir—ve ona üç tane argüman geçirir. En sık kullanılanlar ilk iki argümandır, bunlar da main fonksiyonunun komut satırı argümanlarına ula şmasını sa ğlar. main’in şu şekilde tanımlanmı ş oldu ğunu varsayın: #include void main (int argc, char *argv[]) { int i; printf("Merhaba, benim ismim %s.\n", argv[0]); printf("Argumanlarim sunlar"); for (i=1; iDNM BIR IKI UC Çıktı ise şöyle olacaktır: Merhaba, benim ismim A:\DNM.EXE. Argumanlarim sunlar, BIR, IKI, UC. main’in ilk parametresi (argc) bir sayıdır ve programı çalı ştırmak için verilen komut satırındaki toplam isim sayısına e şittir. Yukarıdaki denemede 4 idi: Bir tanesi .EXE dosya adı için, 3 tanesi de onun argümanları için. main’in ikinci parametresi (argv) char’a göstergelerden olu şan bir dizidir. Yine, main onun için yer ayırmadı ğından dolayı uzunlu ğu belirtilmemi ştir. “char *” bir karakter dizisini tanımlar. Bu tipten olan bir de ği şken, printf’in kontrol karakter dizisindeki %s dönü şüm tanımlaması kullanılarak basılabilir. argv bir karakter dizileri dizisidir ve argv[0], argv[1] elemanları, karakter dizilerini gösterir. Böylece yukarıdaki program argv’nin elemanlarını karakter dizileri olarak basar. Şekil 4.1’deki şema ba şlatma yordamının main için hazırladı ğı belle ğin durumunu gösterir. BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 69 . .A:\ .EXE\ 0 \ 0 \ 0 \ 0. . .. argc argv argv[0] ... argv[3] . ..... .4. .. DNM BIR IKI UC .. ŞEK İL 4. 1 main fonksiyonuna geçirilen komut satırı argümanları main’in üçüncü parametresi (envp) argv’ye benzer. SET i şletim sistemi komutuyla olu şturulan ortam karakter dizilerine göstergeler içeren bir dizidir. Bir program yazarak, bunları bastırmaya çalı şın. 4.3. Bellek Sınıfları De ği şken ve fonksiyonların bellek sınıfları onların ya şam sürelerini, etki alanlarını, saklandıkları bölgeleri ve ilklenme yolunu belirler. C dilinde dört tane bellek sınıfı vardır: Otomatik, yazmaç, dural ve dı şsal. A şa ğıda bunların herbiri detaylı olarak anlatılmaktadır. Bu kısım de ği şik bellek sınıfından de ği şkenlerin ilklenmeleriyle ilgili bir anlatımla sona ermektedir. Ba şlamadan önce, küresel de ği şkenden ne kastetti ğimizi açıklayalım: fonk_1 (...) { fonk_1’in gövdesi } double z; fonk_2 (...) { fonk_2’nin gövdesi } main (...) { main’in gövdesi } Yukarıdaki dosyada, z küresel bir de ği şkendir ve fonk_1 dı şındaki bütün fonksiyonlar sanki kendi blokları içinde tanımlanmı ş gibi onu kullanabilirler. (fonk_1 ve ba şka dosyalarda tanımlanan fonksiyonlar, bu kısımda daha ileride görece ğimiz bir yöntemle z’ye ula şabilirler.) E ğer daha ileriki bir blok içinde z adı verilen ba şka bir de ği şken tanımlanırsa, küresel z de ği şkeni, daha önce açıklandı ğı şekilde, geçici olarak “unutulacaktır”. Şimdiye kadar görmü ş oldu ğumuz yerel de ği şkenler, tanımlanmı ş oldukları blok sona erdi ğinde tamamen yok olurlar. E ğer aynı blok daha sonra tekrar ba şlarsa yerel de ği şkenlerin eski de ğerlerini almaları beklenemez. Öte yandan, küresel de ği şkenler de ğerlerini, program çalı ştı ğı sürece, yitirmezler. 70 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 4.3. 1. auto De ği şkenler Şimdiye kadar kar şıla şmı ş oldu ğumuz bütün de ği şkenlerin bellek sınıfı otomatiktir. Ö ğrenmi ş oldu ğunuz gibi, otomatik de ği şkenler, içinde bulundukları blok yürütüldü ğü sürece “ya şarlar” yani bloktan önce veya sonra mevcut olmazlar. De ği şkenlerin otomatik bellek sınıfından oldu ğunu belirtmek için tanımlarından önce auto anahtar sözcü ğünü yazabilirsiniz. Örne ğin, auto int i; auto char kar, x; (Genelde, bellek sınıfı belirten bütün anahtar sözcükler bu şekilde kullanılırlar; tanım veya bildirimin önüne yazılırlar.) auto kullanmanın aslında gerçek bir anlamı yoktur, çünkü bloklar içinde tanımlanmı ş de ği şkenler için bellek sınıfı belirtilmedi ği zaman, otomatik oldukları varsayılır. Yani, C’nin bile gereksiz bir anahtar sözcü ğü vardır. Do ğal olarak küresel de ği şkenler için auto kullanılamaz. Ayrıca, fonksiyonlar da otomatik olamaz. Fonksiyon parametrelerinin de otomatik oldu ğu varsayılır ve de ğerleri ça ğıran fonksiyon tarafından ilklenir. 4.3.2. register De ği şkenler register bellek sınıfı auto bellek sınıfı ile yakından ilgilidir. Bu iki sınıf için etki alanı ve ya şam süresi kuralları aynıdır, ve register, tıpkı auto gibi, fonksiyonlar dı şında anlamsızdır. E ğer bir de ği şken register s ınıfından tanımlanmı şsa, derleyici onu makinenin hızlı bellek yazmaçlarına yerle ştirmeye çalı şır. Bu tür yazmaçlardan sınırlı sayıda oldu ğu için, sadece ilk birkaç register de ği şkeni gerçekten yazmaçlarda saklanır, di ğerleri otomatik de ği şkenler gibi i şlem görürler. Yani, bir register bildirimi derleyiciye sadece bir öneri özelli ği ta şır. Böylece, e ğer bir önceki alt kısımda tanımlanmı ş de ği şkenlere gerçekten hızlı eri şmeyi istiyorsak register int i; register char kar, x; yazarız. Ana bellekte depolanmayabilecekleri için, register de ği şkenlerine tekli & i şleci uygulanamaz. Ayrıca, diziler gibi “karma şık” tipten bazı veriler register olamazlar; ancak bu sistemden sisteme de ği şebilir. register bellek sınıfından en iyi şekilde yararlanmak için, sadece birkaç de ği şkeni bu tipten tanımlamalısınız. Bunlar en çok kullanılanlar olmalıdır. (Örne ğin döngü sayaçları.) Mümkün oldu ğu kadar kullanıldıkları program koduna yakın tanımlanabilmeleri için de blok içine alın. Fonksiyon parametreleri de register bellek sınıfından tanımlanabilirler. Bu bölümün sonundaki örne ğe bakınız. BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 7 1 4.3.3. static De ği şkenler Ve Fonksiyonlar Kullanıldı ğı yere ba ğlı olarak static anahtar sözcü ğünün iki de ği şik anlamı vardır. Blok içinde, static “kalıcı” anlamına gelir. Yani, blok içinde de ği şkenlerin tanımlarının önüne static anahtar sözcü ğü kullanılırsa, bu de ği şkenlerin de ğerleri blok sona erdi ğinde yok olmazlar. Blok dı şına çıkıldı ğında de ği şkenler eri şilmez hale gelir, fakat blok tekrar i şletilirse, blok sona erdi ği zamanki de ğerleriyle programın yürütülmesine katılırlar. Di ğer bir deyi şle, bu ba ğlamda static auto’nun tersidir. Fonksiyon parametreleri olarak kullanılan de ği şkenler static olamaz. Örnek: void fark (void) { static int deger; int yeni_deger; scanf("%d", ¥i_deger); printf("Bu deger son seferden %d birim farklidir.\n", deger - yeni_deger); deger = yeni_deger; } Bu fonksiyon girilen de ğerle daha önce en son girilen de ğer arasındaki farkı yazar. İlk ça ğrıda eski de ğerin sıfır oldu ğunu varsayar. (Bütün static de ği şkenlerin sıfıra ilklendi ği varsayılır.) deger adı verilen de ği şken, kontrol ba şka fonksiyonlara dönüp tekrar buraya geldi ğinde de ğerini sürdürür. Bir fonksiyon veya küresel bir de ği şken tanımının önüne yazıldı ğı zaman, static “gizli” anlamına gelir. Yani, bu fonksiyon veya de ği şken (ayrıca derlenmi ş yada derlenecek) ba şka dosyalara tamamen yabancı olacaktır; di ğer bir deyi şle, bu dosyalar static de ği şken veya fonksiyona eri şemeyeceklerdir. Bu kısmın ba şındaki örnekte, z ve fonk_2’yi static yapalım: fonk_1 (...) { fonk_1’in gövdesi } static double z; static fonk_2 (...) { fonk_2’in gövdesi } main (...) { main’in gövdesi } Şimdi, eğer isterlerse, bu dosyadaki fonksiyonlar z ve fonk_2’ye eri şebilirler, ancak ba şka kaynak dosyalardaki fonksiyonlar için bu olanaksız olacaktır. 72 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 4.3.4. Fonksiyonlar Ve extern De ği şkenler Daha önce de bahsetti ğimiz gibi, küresel bir de ği şkenin etki alanı normalde tanımlanmı ş oldu ğu kaynak dosyanın sonuna kadar olan kısımdır. Ancak, ba şka dosyalarda veya aynı dosyada fakat daha ileride tanımlanmı ş bulunan küresel de ği şkenleri kullanmanın bir yolu vardır: Anlamlı bir yerde extern anahtar sözcü ğünü ve arkasına de ği şkenin bildirimini yazmanız gerekir. Bundan sonra, sanki orada de ği şkeni tanımlamı şsınız gibi onu istedi ğiniz gibi kullanabilirsiniz. Ancak, di ğer dosyalardan de ği şkenlere bu tür bir eri şim sa ğlamak için, de ği şkenin özgün tanımının static olmaması gerekir. Yukarıda anlatılan yöntemin kullanıldı ğı bir dosya toplulu ğunda static olmayan her küresel de ği şkenin tam bir tane extern olmayan tanımı ve birtakım extern bildirimleri vardır. extern kullanılmamı ş (“özgün”) tanım, de ği şken için bellekten bir bölgenin ayrıldı ğı tek yerdir. Di ğer bildirimler ise, bu de ği şkenin tanımının ba şka bir yerde bulundu ğunu, tipinin ise belirtildi ği gibi oldu ğunu derleyiciye anlatmak içindir. Di ğer bir deyi şle, extern bildirimi de ği şken için yer ayrılmasına neden olmaz. Do ğal olarak, bir de ği şkenin özgün tanımıyla extern bildirimlerinde farklı tiplerin belirtilmesi istenmeyen şeylerin olu şmasına neden olabilir, onun için dikkatli davranmak gerekir. E ğer hem tanım hem de bildirim aynı dosyada ise derleyici hatayı bulabilecektir, fakat e ğer farklı dosyalarda ise hata bulunamayacaktır. Fonksiyonlar kendi dosyalarında daha yukarıda kalan bölümler veya (e ğer static de ğillerse) ba şka dosyalar tarafından kullanılabilirler. Böyle bir durumda, kullanılmadan önce, kullanıldı ğı blo ğun (içinde veya) dı şında fonksiyonun bildirimi yapılmalıdır. Böyle bir bildirimde, fonksiyonun dönü ş tipi, adı, parantez içine alınarak virgülle ayrılmı ş parametre tipleri ve noktalı virgül bulunur. Fonksiyonun blo ğu yazılmaz. Örnek: #include double cikar(double,double); /* Bu fonksiyon daha ileride bir */ /* yerde tanimlanmaktadir. */ void main (void) { double a; a = 3.2; printf("%f\n", cikar(a,2)); } double cikar (double x, double y) { return x-y; } Yukarıdaki programda yazılan “double cikar(double,double);” bildirimi, ba şka bir dosyada veya bu dosyanın daha ileriki bölümlerinde iki double argüman kabul eden ve dönü ş tipi double olan cikar isminde bir fonksiyonun bulundu ğunu ve bu fonksiyon kullanılırken bu bilginin dikkate alınması gerekti ğini derleyiciye anlatır. E ğer BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 73 bu satır yazılmamı ş olsaydı, derleyici cikar’ın gerçek tanımına ula ştı ğında biri int biri de double olan iki cikar isminde fonksiyon bulundu ğunu dü şünecek, bu da büyük bir hata olacaktı. Ayrıca, bu bilgiyi kullanarak, derleyici 2 tamsayı argümanını fonksiyona geçirirken double’a dönü ştürür. 4.3.5. İlkleme Bu altkısma ba şlamadan önce, gelin bellek sınıflarını bir daha gözden geçirelim: Otomatik sınıfından olan de ği şkenler ait oldukları blokla beraber ortaya çıkarlar ve sonra yok olurlar. Yazmaç s ınıfı de ği şkenler otomatikler gibidir, sadece yazmaçlara yerle ştirilebilirler. Dural (static) yerel de ği şkenler de ğerlerini asla yitirmezler, oysa aynı s ınıftan olan küresel de ği şkenler ve fonksiyonlar kendi dosyalarında gizli kalırlar. static olmayan küresel de ği şkenler ve fonksiyonlar dördüncü ve son bellek sınıfını olu ştururlar, bunlara dı şsal adı verilir ve programın herhangi bir yerinden kullanılabilirler. Programcı tarafından, aksi belirtilmedi ği sürece dı şsal ve static bellek sınıfından olan de ği şkenler sıfıra ilklenir. auto ve register s ınıfından olan de ği şkenlerin ilk de ğerleri belirsizdir. Bildi ğiniz gibi, tanım esnasında bir ilkleme yapmak için, de ği şkenin arkasına = i şaretini koyup (çengelli parantez içine alarak veya almayarak) bir ifade yazarız. Böyle ifadeler için kurallar bellek sınıfına ba ğlı olarak de ği şir. Dı şsal veya static de ği şkenler durumunda, bu bir de ği şmez ifade olmalıdır ve şimdiye kadar gördü ğümüz de ği şmez ifadelerden farklı olarak (adreslerini belirtmek için) dizi ve fonksiyon isimleri ve dı şsal ile static de ği şkenler veya dizi elemanlarına uygulanan tekli & i şleciyle olu şturulmu ş ifadeler de içerebilir. Bütün bunların anlamı, böyle bir ifadenin de ğerinin (a) bir adres artı veya eksi bir de ği şmez veya (b) sadece bir de ği şmez olabilece ğidir. Örnek: float t = (900.9-888.1)*1.1; E ğer ilklenecek de ği şken auto veya register ise ilkleme ifadesi daha önce tanımlanmı ş sözcükler içerebilen her çe şit geçerli C ifadesi olabilir. Örnek: { double v = x/a()%77; /* x ve a bu blok */ /* icinde bilinmektedir. */ blo ğun geri kalanı } Gelin bu kuralların arkasındaki nedeni ara ştıralım: Dı şsal ve static de ği şkenler derleme sırasında hesaplanabilecek ilkleme ifadeleri isterler, çünkü bu esnada ilklenmektedirler. Program çalı şmaya ba şlamadan, bu de ği şkenler ilk de ğerlerini almı ş olurlar. Bunun için, tanımında bir ilkleyeni olan yerel bir static de ği şken blo ğa her giri şte de ğil de sadece bir defa ilklenir (bu da do ğru bir şeydir, çünkü static bir de ği şken böyle davranmalıdır). 74 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 Di ğer taraftan, derleyici, bir auto veya register de ği şkeni için bir ilkleyen gördü ğünde, bunu o blo ğun tanım listesinden hemen sonra gelen ve ilgili de ği şkenlere atama yapan bir deyim gibi görür. Bu atamalar, yürütme sırasında, blo ğun ba şına ula şıldı ğı her sefer tekrarlanır. Bundan dolayı, auto ve register de ği şkenleri için ilkleme ifadeleri, ilgili de ği şken bir sol i şlenen olarak bir atama deyiminde kullanıldı ğı zaman sa ğ tarafta gelebilecek her tür geçerli ifade olabilir. Bu da, di ğer dillerde rastlanması zor olan, C’nin güzel özelliklerinden biridir. Artık, static olmayan de ği şkenlerin bir switch blo ğunda ilklenmelerinin neden anlamsız oldu ğu anla şılıyor: Her durumda, kontrol bu ilklemelerin üstünden geçer. İlklenecek de ği şken bir dizi ise o zaman ne olur? Artan indis sırasına göre çengelli parantezler içine ve virgülle ayırarak her dizi üyesinin de ğerini belirten ifadeler yazılır. Bu listede, dizinin boyundan daha fazla sayıda ifadenin bulunması hata olur. Fakat e ğer daha az sayıda ifade varsa, kalan dizi elemanları sıfıra ilklenir. Örne ğin: int g[5] = { 1, -2, 0, 3 }; dizinin ilk dört elemanına belirtilen de ğerleri atar, be şinciye de sıfır yerle ştirir. Dizi ilklenmesinde bazı kestirmeler söz konusu olabilir. E ğer dizinin tanımlanması esnasında boyunu belirtmezseniz, derleyici (mutlaka var olması gereken) ilkleme listesine bakar ve listedeki eleman sayısına e şit boyda bir dizi yaratır. Örne ğin; float f[] = { 2.2, 0.3, 99.9, 1.1 }; dört elemanlı bir dizinin ayrılmasını ve yukarıdaki de ğerlerle ilklenmesini sa ğlar. Karakter dizileri liste yerine de ği şmez bir karakter dizisi yazarak da ilklenebilirler: char gercek[] = "C iyidir."; ile char gercek[] = { 'C', ' ', 'i', 'y', 'i', 'd', 'i', 'r', '.', '\0' }; aynı anlama gelirler. İlk durumda belirtilmemi ş olmasına ra ğmen derleyici tarafından otomatik olarak eklenen bo ş karaktere dikkat edin. E ğer böyle bir durumda dizinin uzunlu ğu belirtilmi ş olsa ve ilkleyen karakter dizisinin uzunlu ğuna (yukarıdaki örnekte 9’a) e şit olsaydı, bitirici bo ş karakter diziye dahil edilmeyecekti. Göstergeleri de ilkleyebilirsiniz. Otomatik veya register göstergeler için ilkleyen herhangi bir geçerli gösterge ifadesi olabilir. static veya dı şsal göstergeler için de ği şmez bir ifade olmalıdır. A şa ğıdaki örnekte, BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 75 #define N 10 test (int i) { int a[N], *ag = a+i; static b[N], *bg = &b[N], *bg1 = &b[0]+i, /* hata */ *bg2 = a; /* hata */ ... } ag ve bg için ilklemeler geçerlidir. Fakat bg1 için ilkleme geçersizdir, çünkü i bir de ği şmez de ğildir. Ayrıca bg2’de de bir sorun vardır: a otomatik bir dizidir; temel adresi yürütme esnasında belirlenir, oysa (ag’den farklı olarak) bg2’nin ilklemesi derleme esnasında yapılır, ancak bu durumda bu olanaksızdır. Dizilerle göstergeler arasında ilgi çekici bir kar şıla ştırma a şa ğıda görülebilir: char const msj1[] = "Sonraki lutfen? "; char const *msj2 = "Sonraki lutfen? "; Hem msj1 hem de msj2 karakter göstergeleri olarak de ğerlendirilebilirler ve birçok ba ğlamda birbirinin yerine kullanılabilirler. Fakat derleyici açısından bir fark sözkonusudur. İlk tanımda, dizi için 17 bayt kullanılır, bu da msj1 dizisi için ayrılan bellek miktarıdır. İkincisinde ise, dizinin derleyici tarafından, ba şka bir yerde saklanması (yine 17 bayt) ve bunun ba şlangıç adresinin msj2 için ayrılan yere (bizim sistemde 2 bayt) depolanması sa ğlanır. Yani ikinci tanım daha fazla yer kaplar. Bu de ği şken bir gösterge için ödememiz gereken bedeldir; oysa programın yürütülmesi esnasında belki de bu göstergenin de ğerini de ği ştirmeyece ğiz. Bu tür program de ği şmezleri için ilk seçene ği (yani de ği şmez bir göstergeyi) kullanmamız daha akıllıca olacaktır. 4.4. Özça ğrı Şimdiye kadar ba şka fonksiyonlar ça ğıran fonksiyonlara örnekler vermi ş bulunuyoruz. Peki, kendini ça ğıran bir fonksiyona ne dersiniz? Daha önce böyle bir şey görmeyenler için, bu oldukça garip gözükebilir. Her şeyden önce, bir fonksiyon niye kendisini ça ğırmak zorunda kalsın? İkinci olarak, sonsuz böyle özça ğrı sonucu ortaya çıkacak bir döngüden nasıl kaçınabiliriz? Üçüncü olarak da, aynı fonksiyondan birden fazla kopyanın i şlek durumda olaca ğı için, fonksiyonun yerel de ği şkenlerine ne olur? Kendini ça ğıran fonksiyonlara özça ğrılı adı verilir. Özça ğrılı bir fonksiyonun kendini dolaylı veya dolaysız olarak ça ğırabilece ğine dikkat edin. İkinci durumda, örne ğin, f adında bir fonksiyonun g adında ba şka bir fonksiyonu ça ğırması, onun da f’yi tekrar ça ğırması söz konusudur. Her durumda, bir fonksiyonun bir önceki etkinle ştirmesi sona ermeden aynı fonksiyonun tekrar ça ğrılması sözkonusudur. Bundan dolayı, özça ğrılı fonksiyonlar özel i şlem gerektirirler. Özça ğrılı fonksiyonları desteklemek için derleyicinin özel bir bellek düzeni kullanması; özça ğrılı fonksiyonlar yazmak için ise programcının biraz farklı bir dü şünme tarzına sahip olması gerekir. 76 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 Yine de, özça ğrılı fonksiyonlar o kadar garip de ğildir; ve bazı durumlarda, e şde ğer özça ğrılı olmayan fonksiyon yerine özça ğrılı olanı kodlamak daha kolaydır. İşte basit ve klasik bir örnek: Matematikte, faktöriyelin (!) tanımı şöyledir: n! = n × (n-1) ··· 2 × 1. Bu tanım, faktöriyel fonksiyonunun algoritmasını açıkça gösterir: fakt (int n) { int i = 1; while (n) i *= n--; return i; } Faktöriyelin ba şka bir e şde ğer tanımı da şöyledir: 0! = 1 n! = n × (n-1)! Bu bir özça ğrılı tanımdır. Özça ğrılı bir fonksiyonun tanımının temel unsurları şunlardır: 1. Fonksiyonun, bazı argümanlar için, de ğerini veren bir temel (veya “aksiyomlar” veya “sınır ko şulları”). Yukarıdaki tanımda ilk deyim buna bir örnektir. 2. Bilinen de ğerlerden fonksiyonun ba şka de ğerlerinin nasıl elde edilece ğini gösteren özça ğrılı yapı kuralı. Bu da yukarıdaki örne ğin ikinci deyiminde gösterilmektedir. Özça ğrılı tanımın, özça ğrılı yapı kuralının temel fonksiyon de ğerleri üzerinde sınırlı sayıda uygulama sonucu sona eren bir yöntem tarif etti ğine dikkat etmemiz gerekir. Her n?0 için yukarıdaki tanımın do ğru oldu ğu gösterilebilir. Örne ğin, 3! = 3 × 2! = 3 × (2 × 1!) = 3 × (2 × (1 × 0!)) = 3 × (2 × (1 × 1)) = 6 Bu kadar matematik yeter. Şimdi de bilgisayarlı gerçek ya şama dönelim. Faktöriyel fonksiyonunun özça ğrılı uyarlaması şöyledir: fakt (int n) { return (n==0) ? 1 : n*fakt(n-1); } Bu da tamamen matematik dilinden bilgisayar diline bir çeviridir. Ko şullu i şlece dikkat edin. Argümanın, temel deyimin gere ğine uyup uymadı ğı, yani sıfır olup olmadı ğı, kontrol edilir. E ğer öyle ise, temel fonksiyon de ğeri, yani 1, döndürülür. Aksi takdirde, özça ğrılı yapı kuralı uygulanır. Bu kural (3! örne ğinde oldu ğu gibi) sınırlı sayıda tekrarlanarak doğru de ğer hesaplanır. Böylece bu kısmın ba şında sorulan ikinci soruyu yanıtlamı ş bulunuyoruz: Temel deyim sonsuz sayıda özçağrıya engel olur. İlk soruya gelince: Bu bir zevk ve verimlilik sorunudur. Bazı programcılar fakt’ın ilk tanımını, bazıları ise ikinci tanımını be ğenebilir. Ancak, verimlilik programcılar için BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 77 önemli (ve nesnel) bir parametredir. Görece ğimiz gibi, özça ğrılı tanımlar özça ğrılı olmayan (yani yinelemeli olan) tanımlardan daha az verimlidir. Buna ra ğmen, gerçek programlarda (örne ğin bir derleyicinin kendisinde) özça ğrılı fonksiyonlar kullanılır, çünkü özça ğrılı bir tanım bazen daha zariftir ve anla şılıp izlenmesi daha kolay olur. Son sorumuz özça ğrılı fonksiyonların nasıl çalı ştı ğı ile ilgili idi. A şa ğıdaki atama deyiminin neyle sonuçlanaca ğını izleyelim. f2 = fakt(2); (fakt’ın ikinci uyarlamasını kullanmaktayız.) A şa ğıda adım adım ne oldu ğu verilmektedir: fakt 2 argümanıyla ça ğrılır.......................................................................................0 n = 2; ...............................................................................................................1 fakt n-1 (=1) argümanıyla ça ğrılır ...................................................................1 n = 1; ........................................................................................................2 fakt n-1 (=0) argümanıyla ça ğrılır............................................................2 n = 0; .................................................................................................3 return 1;..........................................................................................3 return n * 1; (=1 × 1 = 1) ...................................................................2 return n * 1; (= 2 × 1 = 2) .........................................................................1 f2 = 2; ....................................................................................................................0 Sa ğda yazılan sayılar fakt fonksiyonunun kaç tane i şlek kopyasının bulundu ğunu gösterir. Üçüncü seferki i şleme esnasında n yerel de ği şkeninin (parametrenin) de ğeri 0’dır, daha sonra ikinci i şlemeye döndü ğümüzde, n’nin de ğeri fonksiyonun o i şleme ba şladı ğı zamanki de ğer olur. Bu örnekten, üç n’nin aslında farklı de ği şken oldu ğu ortaya çıkar. Bunu sa ğlamak için, derleyici programa bir yı ğıt kullandırır. Bütün auto ve register de ği şkenleri yı ğıtta yer alır. Yı ğıt, bir bayt dizisi şeklinde biti şik bir bellek bölümü ve bununla birlikte bir yı ğıt göstergesi şeklinde dü şünülebilir. Yı ğıt göstergesi ba şlangıçta yı ğıtın ba şına i şaret eder; yı ğıtın geri kalanı serbest (yani bo ş) kabul edilir. Özça ğrılı olsun olmasın, herhangi bir fonksiyona giri ş yapıldı ğında, o fonksiyonun (static ve dı şsal olanlar hariç) yerel de ği şkenlerinin tamamını tutacak miktarda bayt için yı ğıtta yer ayrılır; yı ğıt göstergesi yı ğıtın geri kalan bo şlu ğunun ba şını gösterece ği şekilde ileriye götürülür. Fonksiyonun bütün (“dinamik”) yerel de ği şkenlerine yapılan referanslar yı ğıtın ayrılmı ş bu kesimine yapılır. Fonksiyon bitip geri döndü ğünde, yerel de ği şkenler yok olur, çünkü yı ğıt göstergesi fonksiyon ça ğrılmadan önce gösterdi ği yeri tekrar gösterecek şekilde geriye kaydırılır. E ğer aynı fonksiyondan iki ça ğrı yapılırsa, yerel de ği şkenler için iki defa yer ayrılır; üç defa ça ğrılırsa, yı ğıtta yerel de ği şkenlerin üç kopyası yaratılır vs. Aynı fonksiyona birden fazla ça ğrı yapılmı şsa, yerel de ği şkenlerin sadece son kopyası eri şilir olmaktadır. Fonksiyon geri döndü ğünde eski de ği şkenler etkili olmaya ba şlarlar vs. Bir fonksiyon ça ğrısı oldu ğu esnada yürütmenin sürdü ğü yer olan dönü ş adresi de yı ğıta “itilir”. Özça ğrılı fonksiyonları desteklemek için bütün bunlar gereklidir. FORTRAN gibi, bazı diller bunu yapmazlar, bundan dolayı bu dillerde 78 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 özça ğrılı fonksiyonlara izin verilmez. Di ğer taraftan, C ve Pascal gibi bazı diller özça ğrıyı destekler. Özça ğrılı fonksiyonlar yı ğıttan çok yer harcarlar. Bir int de ği şkenin iki bayt, dönü ş adresinin de dört bayt kapladı ğını varsayalım. Bu durumda, “fakt(i)” şeklinde bir ça ğrı y ı ğıtta 6×(i+1) bayt kullanacaktır. Örne ğin, “fakt(6)” için 42 bayta gereksinimimiz olacaktır. Di ğer taraftan, fakt’ın yinelemeli (yani ilk verilen) uyarlaması yı ğıttan 4 (dönü ş adresi için) + 2 (n için) + 2 (i için) = 8 bayt kullanacaktır. Özça ğrılı fonksiyonun bellek üzerinde daha fazla talepte bulundu ğu açıktır. Ayrıca, yerel de ği şkenlerin ve dönü ş adresinin yı ğıta itilip geri alınması i şlemci zamanı da harcar. Yinelemenin özça ğrıdan daha verimli oldu ğu sonucunu elde edebiliriz. Verimlilikteki bu farkın o kadar fazla olmadı ğı gerçek örnekler de verebiliriz, bundan dolayı e şde ğer bir yinelemeli algoritma bulamadı ğınız zaman özça ğrı kullanmaya tereddüt etmeyin. 4.5. Fonksiyonlara Göstergeler C dilinde, tıpkı bir de ği şkenin adresi gibi, bir fonksiyonun adresini de bir gösterge de ği şkeninde depolayabilir veya ba şka bir fonksiyona argüman olarak geçirebiliriz. Bu kısımda, di ğer fonksiyonlara fonksiyon göstergelerini nasıl geçirebilece ğimiz konusuyla ilgilenece ğiz. Derleyici tarafından, bir tanıtıcı sözcü ğün bir fonksiyonu gösterdi ği, ya daha önce bir fonksiyon olarak tanımlandı ğı veya bildirimi yapıldı ğı için, yada tanıtıcı sözcü ğün arkasında sol parantez oldu ğu için (yani ba ğlamdan) derleyici tarafından yapılan otomatik bildirim sonucu bilinir. E ğer bu tanıtıcı sözcük daha sonra bir parantezle birlikte kullanılmazsa, derleyici bu fonksiyonu ça ğırmaya kalkmayacak, onun yerine fonksiyonun adresini kullanacaktır. (C dilinde sık yapılan bir yanlı ş ta argümanı olmayan bir fonksiyonu parantezleri belirtmeden ça ğırmaya çalı şmaktır. Yani f(); yerine f; şeklinde bir deyim kullanmaktır. İkinci deyim, “f” yerine fonksiyonun adresini koyma dı şında bir şey yapmayacaktır.) Bazı de ğerler ile bu de ğerler üzerinde uygulanacak herhangi bir fonksiyondan geri döndürülen de ğerlerin bir çizelgesini çıkaracak bir fonksiyon yazmak istedi ğimizi dü şünün. Bu, örne ğin, bir sinüs, karekök veya doğal logaritma çizelgesi olabilir: BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 79 #include #include void cizelge (double al, double ul, double art, double (*fg)(double), char *fi) { double x; printf("\n x\t%s(x)\n\n", fi); for (x = al; x <= ul; x += art) printf("%7.2f\t%7.2f\n", x, (*fg)(x)); } Buradaki double (*fg)(double); tanımına dikkat edin. Bunun ne oldu ğunu anlamak için i şleçlerin uygulanı ş sırasını göz önünde tutmamız gerekir. Bu bir double döndürüp argümanı da double olan fonksiyona bir göstergedir. İleride, bir ifade içinde “(*fg)(...)” yazdı ğımızda böyle bir fonksiyona ça ğrı yapmı ş oluyoruz. Şimdiye kadar inceledi ğimiz di ğer gösterge de ği şkenlerinin, örne ğin int göstergelerinin, hem tanım hem de kullanımındaki benzerli ğe dikkat edin. fg fonksiyona bir göstergedir, (*fg) ise fonksiyonun kendisidir. Gösterge ifadesini çevreleyen parantezler gereklidir, çünkü aksi takdirde double *fg(double); ifadesi double *(fg(double)); anlamına gelecekti, bu da double gösterge döndüren bir fonksiyon demektir ki bu bildirim parametre tanımlarında kullanılamayacak çok farklı bir şeydir. Bunun nedeni fg’den sonra gelen parantezlerin *’dan daha yüksek önceli ğe sahip bir i şleç olmasıdır. A şa ğıdaki program cizelge fonksiyonuna geçerli ça ğrılar yapmaktadır: #include void main (void) { double sin(double), sqrt(double), log(double); cizelge(0.0, 3.14, 0.1, sin, "sin"); cizelge(1.0, 100.0, 1.0, sqrt, "k.kok"); cizelge(1.0, 2.718, 0.05, log, "log"); } Dördüncü argümanın bir de ği şken de ğil de bir fonksiyon ismi oldu ğuna dikkat edin. Fonksiyon tarafımızdan tanımlanmı ş olabilece ği gibi bir kütüphane fonksiyonu da olabilir. Bu noktada bu fonksiyona bir ça ğrı sözkonusu de ğildir, çünkü argümanlar verilmemi ştir, hatta parantezler bile yoktur. Derleyici, sin, sqrt ve log’un fonksiyon oldu ğunu bilir, çünkü yukarıda bildirimleri yapılmı ştır; böylece bu fonksiyonların ba şlangıç adreslerini alıp cizelge fonksiyonuna geçirir. Dizilerde oldu ğu gibi burada da adres alma (&) 80 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 i şlecini kullanmamıza gerek yoktur. E ğer bir dizi isminin arkasında “[]” varsa, o zaman dizinin belirtilen elemanının de ğeri kullanılır; aksi takdirde dizinin temel adresi kullanılır. Aynı şekilde, bir fonksiyon isminden sonra e ğer “()” varsa (ça ğrı sonucu) fonksiyondan döndürülen de ğer kullanılır; aksi takdirde ifadenin de ğeri olarak fonksiyonun başlangıç adresi kullanılır. cizelge fonksiyonu, ona geçirilen adresi kullanarak asıl ça ğrıyı yapar. cizelge’ye geçirilen bütün fonksiyonların “benzer” olması gerekir, yani aynı sayıda ve tipte argüman kabul edip aynı tipi döndürmelidirler. Parametrenin tanımlanması esnasında bütün bunlar belirtilir. main içinde verilen fonksiyon bildirimleri gerekli de ğildir, çünkü #include edilen standart ba şlık dosyası math.h’de bu bildirimler zaten mevcuttur. 4.6. Bir Örnek—8 Vezir Problemi Bu kısımda, fonksiyonlar, bitsel i şleçler, küresel de ği şkenler, register bellek sınıfı ve özça ğrı gibi kavramları kullanan örnek bir program verece ğiz. Bu program bize klasikle şmi ş bir problemin çözümlerini bulacaktır: 8 çarpı 8’lik bir satranç tahtasına birbirini almayacak şekilde 8 vezirin yerle ştirilmesi. İki vezir aynı sıra, sütun veya çaprazda oldu ğunda birbirini alabilir. Yani bir çözümde aynı sıra, sütun veya çapraz hatta iki vezir bulunmamalıdır. Örne ğin, ·······V ···V···· V······· ··V····· ·····V·· ·V······ ······V· ····V··· bir çözümdür. Burada “V” bir veziri “·” ise bo ş bir kareyi gösterir. Bu problemi çözmede ilk yakla şım sistemli bir şekilde tüm yerle ştirmeleri inceleyip sadece geçerli olanları listelemektir. Bir bilgisayarımız oldu ğuna göre, bunu çabuk bir şekilde yapabiliriz. Aslında, o kadar da de ğil! Olası tüm de ği şik yerle ştirmelerin sayısı (8 × 8)! (8 × 8 - 8)! × 8! = 4,426,165,368’dir. Her yerle ştirme için bir milisaniye harcasak bile, hepsini teker teker denemek elli günden daha uzun bir süre alacaktır. Ara ştırma bölgemizi daraltmamız gerekir. A şa ğıdaki gözlemler yararlı olacaktır: BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 8 1 1. E ğer iki veziri yerle ştirdi ğimizde bunların birbirini aldı ğını görürsek, di ğerlerini de dikkate alan bütün olası yerle ştirmeleri denememize gerek yoktur. Bu, bütün vezirleri satranç tahtasına yerle ştirdikten sonra de ğil, bir vezir yerle ştirir yerleştirmez uyuşmazlıkları kontrol etmemiz gerekti ği anlamına gelir. 2. Aynı sıraya iki vezir yerle ştirmeye çalı şmamalıyız. Her veziri bir sıraya “atayarak” bunu gerçekle ştirebiliriz. Her vezir sadece kendi sırasındaki 8 kareden birisine yerle ştirilecektir. Bu iki gözlem ara ştırma bölgemizi çok daraltacaktır. Algoritma şöyledir: • En üst sıradan ba şlayarak, her veziri kendi sırasına, en sa ğdaki sütundan itibaren, yerle ştirin. • Bir vezir yerle ştirdi ğinizde, daha önce yerle ştirilmi ş vezirlerle bir uyu şmazlı ğın olup olmadı ğını kontrol edin. E ğer varsa, veziri bir sonraki (yani hemen solundaki) kareye kaydırın; e ğer yoksa, bir sonraki (yani hemen altındaki) sırayı de ğerlendirin. E ğer son vezir de ba şarılı bir şekilde yerle ştirilirse, bu bir çözümdür. • E ğer bir vezir, sırasındaki sekizinci sütunu da geçerse, o zaman veziri satranç tahtasından alın, bir önceki sıraya geriye dönü ş yapın ve bu sıradaki veziri bir sonraki (yani hemen solundaki) kareye kaydırın. • İlk sıradaki vezir son sütundaki kareden dı şarı çıkıncaya kadar buna devam edin. Algoritmayı belirledikten sonra, bu sefer i şlenecek bilgiyi saklayacak veri yapısı için karar vermemiz gerekecektir. Verimlilik en önemli tasamız olmalıdır. Veri yapısı fazla miktarda bilgisayar belle ği harcamamalı ve kolay, hızlı eri şim sa ğlamalıdır. Satranç tahtasını nasıl göstermemiz gerekir? En azından iki seçenek sözkonusudur: 1. Her kare bir bitle gösterilebilir. E ğer bit 1 ise bu karede bir vezir var, 0 ise, bo ş demektir. Böylece, mantıksal olarak 8’e 8’lik bir kare şeklinde düzenlenmi ş 64 bite gereksinimimiz vardır. 2. Her sırada en fazla bir vezir oldu ğuna göre; her elemanında o sıradaki vezir tarafından i şgal edilen sütun sayısının saklandı ğı do ğrusal bir dizi tutabiliriz. Bu örnekte ilk seçene ği kullanaca ğız. Her sıra 8 bite gereksinim duyar. Birçok bilgisayarda, bir int de ği şken en az 16 bittir. Böylece iki sıra tek bir int de ği şkenin içinde saklanabilir. Ama, her sıra için bir tamsayı ayırıp sadece sa ğdaki (dü şük) bitlerin kullanılması daha kolay olacaktır. Soldaki bitler ise kullanılmayabilir. Ayrıca, programı daha genel bir problem (yani n çarpı n’lik bir satranç tahtasına n adet vezirin yerle ştirilmesi) için tasarlarsak, aynı programı kullanarak, örne ğin, 15 vezir problemini de çözebiliriz. Programda kullanılan veri yapısı (a şa ğıdaki program listesine bakın) şöyledir: int tahta[8]; (Bu arada, int unsigned olarak #define edilmi ştir, böylece sa ğa kaydırma i şlemlerinin aritmetik, yani i şaret doldurma, de ğil de mantıksal, yani sıfır doldurma, 82 FONKS İYONLAR VE PROGRAM YAPISI BÖLÜM 4 olması temin edilmi ştir.) tahta ve sayi küresel de ği şkenler olarak tanımlanmı şlardır, böylece bütün fonksiyonlar bunlara eri şebilir. tahta[0] satranç tahtasının en üstteki sırasını, tahta[7] ise en alttaki sırayı gösterir. Bir dizi elemanının en dü şük (yani sa ğdaki) biti sıranın en sa ğdaki sütununu gösterir. Altıncı sıranın en sa ğındaki sütununa bir vezir koymak istedi ğimizde tahta[5] = 1; atama deyimini; bu veziri bir sola kaydırmak istedi ğimizde tahta[5] <<= 1; atama deyimini; en soldaki sütundan ileriye bir vezir geçip geçmedi ğini anlamak için tahta[sira] >= 1<<8 testini; iki farklı sıradaki iki vezirin aynı sütunda olup olmadı ğını anlamak için tahta[sira2] == tahta[sira1] testini; aynı çapraz hatta olup olmadı ğını anlamak için tahta[sira2] == tahta[sira1]<>sira1-sira2 testini kullanabiliriz. Yukarıdaki testleri kullanarak, tahtaTamam fonksiyonunu tasarlayabiliriz. Bu fonksiyon, sira’ya yeni bir vezir yerle ştirildi ğinde tahtanın tamam olup olmadı ğını kontrol eder. Bunu yapmak için 0’dan sira’ya kadar (sira hariç) olan bütün sıralarla sira arasındaki uyu şmazlıkları kontrol eder. E ğer sira 0 ise o zaman for döngüsüne hiç girilmeyecek tahtaTamam fonksiyonu hemen 1 (do ğru) döndürecektir: İlk sıra için satranç tahtası her zaman “tamam”dır. Bir çözüm bulundu ğunda cozumyaz fonksiyonu ça ğrılır. sayi (çözüm sayısı) de ği şkeni bir artırılır ve tahta’daki çözüm yazılır. Dı ş döngü sıralar, iç döngü de sütunlar içindir. Programın kalbi yerlestir fonksiyonudur. Algoritmadan da tahmin edebilece ğiniz gibi, bu özça ğrılı bir fonksiyon olarak tanımlanabilir. Bu fonksiyon, ba şta 0 (ilk sıra) argümanıyla ana programdan ça ğrılır. for döngüsü belirtilen sira’nın her sütununa veziri yerle ştirir. Her yerle ştirmeden sonra tahta kontrol edilir; e ğer tamamsa, bu sira için yerle ştirme i şlemi geçici olarak bekletilir ve bir sonraki sira denenir. Bir sonraki sira’yı kim deneyecektir? Tabii ki, aynı fonksiyon! Sonsuz özça ğrılara engel olmak için fonksiyonun ba şında bir test yapılır. E ğer yerlestir 8 argümanıyla ça ğrılmı şsa, bu, satranç tahtasına (ba şarılı bir şekilde) 8 vezirin yerle ştirildi ği anlamına gelir. Bu durumda yerlestir fonksiyonu çözümü yazdırır ve hemen döner. yerlestir fonksiyonunun her yeni ça ğrısında sira adı verilen yeni bir (yerel) de ği şken yaratılır. Bir önceki ça ğrıya geri döndü ğümüzde bir önceki sira de ği şkeni tekrar geri gelir; de ğeri ise bir eksi ği olur. BÖLÜM 4 FONKS İYONLAR VE PROGRAM YAPISI 83 1. #include 2. #define VEZIRLER 8 /* vezir sayisi ve tahta boyu */ 3. #define int unsigned /* isaretsiz tamsayi kullan */ 4. 5. int sayi = 0; /* cozum sayisi */ 6. int tahta [VEZIRLER]; /* her eleman bir sirayi gosterir */ 7. 8. int tahtaTamam /* tahtanin gecerliligini kontrol et */ 9. (register int sira) 10. { 11. register int r; 12. 13. for (r = 0; r < sira; r++) /* onceki tum siralari kontrol et */ 14. if (tahta[sira] == tahta[r] || 15. tahta[sira] == tahta[r] << sira-r || 16. tahta[sira] == tahta[r] >> sira-r) 17. return 0; /* uyusmazlik varsa */ 18. return 1; /* uyusmazlik yoksa */ 19. } 20. 21. void cozumyaz (void) /* cozumu goster; sayiyi artir */ 22. { 23. register int t, r; 24. 25. printf("\n\n\tCOZUM %u\n\n", ++sayi); 26. for (r = 0; r < VEZIRLER; r++) { /* sira */ 27. for (t = 1< 0; t >>= 1) 28. printf(" %c", tahta[r] == t ? 'V' : '.'); 29. printf("\n"); 30. } 31. } 32. 33. void yerlestir (int sira) /* bir sonraki siraya yerlestir */ 34. { 35. if (sira == VEZIRLER) /* tum siralar dolu ve kontrol edilmis */ 36. cozumyaz(); 37. else 38. for (tahta[sira]=1; tahta[sira]<1< void main (void) { { int y = 1993; } { int i; printf("%d\n", i); } } programı 1993 yazar. Bunu açıklayabilir misiniz? 4. Sistemimizde #include void main (void) { { int a1=111, a2=222, a3=333, a4=444; } { register r1, r2, r3, r4; printf("%d %d %d %d\n", r1, r2, r3, r4); } } programı 131 3982 333 444 yazar. Bu size register de ği şken tanımı konusunda neyi dü şündürür? r3 de ği şkeni bir yazmaçta mı saklanmaktadır? 5. Bölüm 0’ın ba şında verilen programın ne yaptı ğını anlatın. 6. Bir önceki bölümde anlatılan ve C kütüphanesinde bulunan strcpy, strcmp, strcat ve strlen fonksiyonlarının i şlevsel benzerlerini yazın. 7. 8 vezir programını, yerlestir özça ğrılı fonksiyonu içindeki sira de ği şkeninin küresel bir de ği şken olaca ğı şekilde tekrar düzenleyin. Şimdi program daha az yı ğıt yeri kullanacaktır. 8. 8 vezir programını özça ğrılı olmayana (yani yinelemeli olana) çevirin. 87 BÖLÜM 5: TÜRET İLM İŞ T İPLER VE VER İ YAPILARI C dilinin yapısı içinde var olan veri tipleri arasında int, float, double, char gibi basit tipler, diziler, göstergeler, sayım tipleri, yapılar ve birlikler bulunmaktadır. Veri tipleri özça ğrılı bir şekilde tanımlanabilirler, yani dizilerden olu şan diziler, yapılar içeren yapılar, göstergelere göstergeler vs sözkonusu olabilir. Böylece, gerçekte, tanımlanabilecek veri tipleri sonsuz sayıdadır. Bu bölümde, yeni veri tiplerini ve var olan veri tiplerinden nasıl yeni tipler tanımlayaca ğımızı görece ğiz. Şimdiye kadar, göstergeler ve dizileri tanımı ş olduk, ancak, sayım tipleri, yapılar ve birlikler nedir? Gelin, bunları tek tek inceleyelim. 5. 1. Sayım Tipleri C dilindeki temel veri tipleri arasında basamaklı sayı tipleri vardır (i şaretli veya i şaretsiz çe şitli boylarda tamsayılar). Bütün basamaklı tipler sınırlı ve do ğrusal olarak sıralanmı ş bir de ğerler kümesi olu ştururlar. C dili tarafından sa ğlananlar dı şında, kullanıcının kendi basamaklı sayı tiplerini tanımlama olana ğı vardır, bunlara sayım (veya sayılı) tipler denir. Böyle bir tipin tanımı, sırasıyla, bütün olası de ğerleri belirtir. Bunlar tanıtıcı sözcüklerle temsil edilir ve yeni tipin de ği şmezleri olurlar. Sayım tiplerini tanımlamanın genel sözdizimi a şa ğıda verilmi ştir: enum tanıtıcı_sözcük opt { sayım_listesi } opt bild_belirteçleri opt ; Tanıtıcı_sözcük’e sayım künyesi denir ve tanımlanmakta olan tipe verilen iste ğe ba ğlı bir isimdir. Daha ileride, aynı tipten ba şka de ği şken veya fonksiyon tanımlamaları yapmak gerekirse, bu isim kullanılabilir. 88 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI BÖLÜM 5 Sayım_listesi virgülle ayrılmı ş tanıtıcı sözcüklerden olu şan bir listedir. Bunlara sayıcı adı verilir. Bild_belirteçleri, olası ilkleyenlerle izlenen, de ği şkenlerden olu şan bir listedir. Birkaç örnek: enum islecler { arti, eksi, carpi, bolu } isl1 = arti, isl2 = carpi, islx; enum gunler { pa, pt, sa, ca, pe, cu, ct }; enum gunler ilk_gun = pa, bir_gun, son_gun = ct; enum { erkek, kadin } cinsiyetim = erkek, cinsiyetler[MAKSK]; İlk örnekte “enum islecler” tipini ve bu tipten isl1, isl2, islx de ği şkenlerini tanımlamaktayız. Bu de ği şkenler herhangi bir zamanda arti, eksi, carpi ve bolu de ğerlerinin sadece bir tanesini alabilirler. Ayrıca, isl1 ve isl2 de ği şkenleri sırasıyla arti ve carpi de ğerleriyle ilklenirler. İlkleme i şlemi tamsayı de ği şken ilklemesine çok benzer, kuralları da aynıdır. Üçüncü de ği şken, islx, ilklenmemi ştir, fakat, tıpkı di ğer de ği şkenler gibi yürütme esnasında buna da yukarıdakilerden bir de ğer atanabilir. İkinci ve üçüncü satırlarda da buna benzer bir tanımlama yapılmakta, ancak bu sefer iki adımda olmaktadır. Önce “enum gunler” tipini tanımlıyoruz—henüz de ği şken tanımı yok—sonra da ilk_gun gibi de ği şkenleri bu tipten tanımlıyoruz. Dördüncü satırda künyeyi atlamı ş bulunuyoruz, böylece bundan sonra bu tipten yeni de ği şken veya fonksiyon tanımlamak istesek sayım_listesini tekrar belirtmek zorunda kalaca ğız. Bu örnekte ayrıca sayım tipinden elemanlardan olu şmu ş bir dizi tanımlamasını da görmekteyiz. Bu tanımlardan sonra, de ği şkenleri a şa ğıdaki gibi deyimlerde kullanabiliriz: cinsiyetim = kadin; bir_gun = ca; islx = isl1; if (isl1==bolu) ... while (bir_gun!=ct) ... printf("%d %d %d\n", cinsiyetim, bolu, son_gun); cinsiyetim de ği şkeninin kadin, son_gun’ün de ct oldu ğunu varsayarsak, son deyim 1 3 6 yazacaktır. Bunun nedeni, sayım tipinden olan de ği şkenlerin aslında tamsayı de ğerleri sakladıkları ve de ği şmezlerin de aslında tamsayı olduklarıdır. Örne ğin, arti, pa ve erkek’in de ğerleri 0’dır, eksi 1, carpi 2, bolu 3’tür. Normalde sayım de ği şmezlerine sıfırdan ba şlayarak sırayla de ğerler verilir, ancak C dilinde programcının istedi ği de ği şmez tamsayıyı bir sayıcıya vermesine izin verilir. Bundan sonra gelen sayıcılar da sonraki de ğerleri alırlar. Örne ğin, BÖLÜM 5 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI 89 enum renk { siyah, mavi, yesil, kirmizi=4, sari=14, beyaz }; Burada, siyah’ın de ğeri 0, mavi’nin 1, yesil’in 2 ve beyaz’ın 15’tir. Bir enum tanımında, iki sayıcı aynı de ğeri alacak şekilde tanımlanabilirler. Bir sayıcı eksi bir de ğere sahip olabilir. Sayım tipinden olan de ği şkenler fonksiyonlara argüman olarak geçirilebilir ve bir fonksiyonun dönü ş tipi sayım tipinden olabilir. Buna örnek bir fonksiyon a şa ğıda verilmi ştir: enum gunler gun_ekle (enum gunler g, int n) { return (enum gunler) (((int) g + n) % 7); } Bu fonksiyon bir gün kabul edip n gün sonraki günü verir. bir_gun = gun_ekle(pe, 31); şeklindeki bir ça ğrı bir_gun’e pa atayacaktır. Sayım tiplerini kalıplarda da kullanabilece ğimize dikkat ediniz. Bu örnekte iki tane kalıp kullanmaktayız: Bir tanesi, hesap yapmak için günü tamsayıya dönü ştürmede, di ğeri de sonucu tekrar “enum gunler” tipine dönü ştürmede kullanılır. Sistemimizde, sayım tiplerinden olan de ği şkenlerin tamsayı oldu ğunu dü şünebilirsiniz, örneğin enum de ğerlerinin girdi ve çıktısını tamsayı biçiminde yapabilirsiniz. Tıpkı int de ği şkenleri gibi, sayıcıların (ve sonuçta sayım tipinden olan de ği şkenlerin) alacakları de ğerler 16 bit içinde kalmalıdır. 5.2. Yapılar Yapılar ve birlikler C programları için karma şık veri yapılarının tanımlanmasında anahtar rolü oynarlar. Bu kısımda yapılar anlatılmaktadır. Daha sonraki bir kısım ise birlikleri kapsamaktadır. Pascal’la tanı şıklı ğı olan okuyucularımız, herhalde C dilindeki yapıların Pascal’daki record’lara kar şılık oldu ğunu fark edeceklerdir. Aynı tipte belirli sayıdaki de ği şkenleri saklamak için bir dizi kullanılabilir. Di ğer taraftan, bir yapı, genelde de ği şik tipte olan bir veya daha fazla de ği şkeni toplamak için kullanılabilir. Niye, ayrı ayrı de ği şkenler kullanmak yerine bunları bir yapı içinde toplamaya gerek duyarız? Temel neden kolaylıktır. Örne ğin, bir fonksiyona çok sayıda argüman geçirmek yerine, bazılarını yapılar içinde gruplayıp yapıları geçirebiliriz. Şimdi yapıları nasıl tanımlayabilece ğimizi ve kullanaca ğımızı görelim. Yapı tanımlamasının genel şekli şöyledir: struct tanıtıcı_sözcük opt { yapı_bild_listesi } opt bild_belirteçleri opt ; 90 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI BÖLÜM 5 struct anahtar sözcü ğü bir yapının tanımlanmakta oldu ğunu göstermektedir. Her zaman oldu ğu gibi, tanımlanmakta olan de ği şken(ler)in bellek sınıfını göstermek için bu anahtar sözcü ğün önüne uygun herhangi bir bellek sınıfı belirteci (örne ğin, static, extern) konulabilir. İste ğe ba ğlı olan tanıtıcı_sözcük’e yapı künyesi adı verilir. Tanımlanmakta olan yapı tipine isim verir ve daha sonra benzer yapı de ği şkenleri tanımlamak için bir kısaltma i şlevi görür. E ğer bu yapı tipi bütün program içinde bir defa kullanılıyorsa, daha sonra kullanılmayaca ğı için yapı künyesini atlayabiliriz. Yapı_bild_listesi her bildirimin bir noktalı virgülle bitirildi ği bir dizi bildirim içerir. Bu bildirimler (ilkleyen içerememeleri dı şında) normal de ği şken tanımlamalarına benzer; fakat bu durumda de ği şkenler bildirimi yapılan yapı altında gruplanacaklar ve yapının üyeleri olacaklardır. Bir yapının üyeleri diziler veya yapılar gibi karma şık tipler olabilece ği için, C dilinde istedi ğimiz kadar karma şık veri yapıları tanımlayabiliriz. Bild_belirteçleri belirtilen yapı tipinden de ği şkenler tanımlayan iste ğe ba ğlı bir listedir. Bunlar basit (yapı) de ği şkenleri, yapılara göstergeler, yapılardan olu şan diziler, yapı döndüren fonksiyonlar veya bunların herhangi bir birle şimi olabilir. Bir örnek: struct yk { int i; float f; } yd; Burada, yk yapı künyesini ve “struct yk” tipinden yd de ği şkenini tanımlamı ş bulunuyoruz. “struct yk” tipi iki üye içerir, bir tamsayı, bir de gerçek sayı. yk yapı künyesi daha sonra aynı tipten ba şka de ği şkenlerin bildirimini yapmak için kullanılabilir. Örne ğin, struct yk yd1, *yg; (yd’ye benzeyen) bir yd1 de ği şkenini ve “struct yk” tipindeki bir yapının saklandı ğı bir yere bir gösterge tanımlayacaktır. Gelin birkaç örne ğe daha bakalım. Bu kısmın ba şında verilen sözdizimde üç tane iste ğe ba ğlı bölüm görmekteyiz. Herhangi bir zamanda bunlardan en çok bir tanesi belirtilmeyebilir. Böylece, struct { int i; float f; } yd2; tanımlamasında bir yapı de ği şkeni, yd2, tanımlanmakta, fakat yapı künyesi tanımlanmamaktadır; struct yk { int i; float f; }; tanımlamasında ise bir yapı künyesi, yk, tanımlanmakta, fakat de ği şken tanımlamaları bulunmamaktadır; yani sadece bir tip bildirimi vardır. Daha sonra, bu ismi kullanarak, a şa ğıda yapıldı ğı gibi de ği şkenler tanımlayabiliriz: struct yk ydz[5], yf(float), (*ydgf(int))[8]; Burada yapı_bild_listesi’ni tekrar belirtmeye gerek yoktur. ydz böyle 5 tane yapıdan olu şan bir dizidir; yf bir float argüman alan ve böyle bir yapı döndüren bir BÖLÜM 5 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI 9 1 fonksiyondur (bazı eski derleyiciler böyle bir bildirimi kabul etmeyebilirler, çünkü, eski “Standarda” göre, fonksiyonlar dizi veya yapı gibi “karma şık” tipler döndürmezler); ydgf böyle 8 yapıdan olu şan bir diziye bir gösterge döndüren ve bir int argüman alan bir fonksiyondur. Son örne ği anlamak için, i şleçleri, uygulandıkları sırayı dikkate alarak (tersten) okuyun: (), *, []; yani yapı dizisi göstergesi fonksiyonu. Şimdi de daha karma şık bir örnek: struct kisi { char *isim; int dogumtarihi; enum cinsiyet_tipi { erkek, kadin } cinsiyet; struct kisi *baba, *ana, *es, *cocuklar[MAKSCCK]; } kisiler[MAKSKS]; Yukarıdaki tanımda gördü ğünüz kadarıyla, tıpkı di ğer dillerde oldu ğu gibi, C dilinde de “karma şık” veri yapıları tanımlanabilir. Burada, basit de ği şkenler, göstergeler, sayım tipinden de ği şkenler, yapılara göstergelerden olu şan diziler vs olan üyeleri içeren bir yapı dizisi görmekteyiz. Yapının bazı üyelerini tanımlarken yapının kendi tanımını da kullanmakta oldu ğumuza dikkat edin; tanımlamakta oldu ğumuz üyeler gösterge oldukları için bu herhangi bir problem olu şturmaz. Aslında, gösterge tanımlarken daha ileride tanımlanmı ş yapıları da kullanabiliriz. Yukarıda tanımlanan kisiler de ği şkeni, kolayca eri şilip i şlenebilen en fazla MAKSKS kadar ki şinin bilgisini saklayabilir. Bir yapının üyelerine ula şmak için, bir nokta (“.”) ile gösterilen, yapı üyesi i şlecini kullanırız. Bu i şleç, yapı de ği şkeni ile üyesi arasına konur. Örne ğin, yd.i = (int) yd.f; yd yapı de ği şkeninin f üyesi içindeki tamsayıyı i üyesine atayacaktır. “.” i şleci en yüksek önceli ği olan i şleçlerden biridir, böylece, örne ğin yd.i genelde sanki tek bir de ği şkenmi ş gibi, etrafına parantez koymaya gerek duymadan kullanılabilir. Şimdi, bir yapı göstergesi de ği şkeninin üyesine eri şirken kar şıla şabilece ğimiz küçük bir problemi inceleyelim. Örne ğin, yg bir yapıya bir göstergedir; *yg yapıya eri şmek için kullanılır, ancak onun üyesine eri şmek için *yg.i kullanılamaz. Bunun nedeni önceliklerdir; “.”nin önceli ği *’dan yüksektir, böylece *yg.i aslında *(yg.i) anlamına gelir, bu da yg’nin bir üyesi olan i’nin bir gösterge oldu ğunu varsayar. Do ğru sonucu elde etmek için parantez kullanmak zorundayız: (*yg).i. Ancak bu da sıkıntılı olabilir. Bunun üstesinden gelmek için, C’ye ba şka bir i şleç (->) eklenmi ştir. yg->i tamamen (*yg).i ile e şde ğerdir ve daha kısa ve anlamlıdır. Dört i şleç, (), [], . ve ->, öncelik tablosunda en yüksek düzeyi olu ştururlar ve referans olu şturmak için kullanıldıklarından di ğer i şleçlerden farklıdırlar. Bazı eski C uygulamalarında, yapılarla yapabilece ğimiz şeyler, & kullanarak bir yapının adresini almak ve üyelerinden birisine eri şmekle sınırlıdır. Örne ğin, yapılar fonksiyonlara geçirilip geri döndürülemez; 92 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI BÖLÜM 5 yapi1 = yapi2; şeklinde her iki tarafında yapı de ği şkeni olan bir atama gerçekle ştirilemez. Bu sınırlamaların üstesinden gelmek için göstergeler kullanılabilir. Buna ra ğmen, ANSI Standardını izleyen yeni C derleyicilerinde böyle sınırlamalar yoktur. Örne ğin, bizim sistemde a şa ğıdaki program kabul edilmektedir: #include struct kunye { int i; char *c; /* y1 yapi degiskeninin */ } y1 = { 1, "bir" }; /* tanimlanmasi ve ilklenmesi */ struct kunye f /* parametresi ve donus tipi */ (struct kunye y) /* struct kunye olan fonksiyon */ { struct kunye z; z.i = y.i * 2; /* uyelere degerler ata */ z.c = "iki kere"; return z; /* bir yapi dondur */ } /* f */ void main (void) { struct kunye y2, f(struct kunye); y2 = f(y1); /* yapiyi baska bir yapiya ata */ printf("%d %s\n", y2.i, y2.c); } /* main */ ve çıktı şöyledir 2 iki kere Burada yapılarla yapılacak üç şeyi görmekteyiz: Bir yapıyı bir argüman olarak geçirmek, fonksiyondan bir yapı döndürmek ve bir yapıyı ba şka bir yapıya atamak. Yapı ataması, kaynak yapının her üyesinin hedef yapının ilgili üyesine atanması demektir ve yapının boyuna göre bir miktar zaman alabilir. Yukarıdaki örnekte, yapı de ği şkenlerini ilkleme yöntemini de görmekteyiz. Sözdizimi diziler için kullanılana benzemektedir. İlklenecek de ği şken, = atama simgesinden sonra virgülle ayrılıp çengelli parantezler içine alınmı ş de ği şmez ifadelerden olu şan bir liste ile izlenir. Her üye ilgili ifadenin de ğerine ilklenir. E ğer ifadelerden daha fazla üye varsa, geri kalan üyeler C dilindeki varsayılan de ğere, yani sıfıra ilklenir. 5.3. Yeni Tip Tanımlama Türetilmi ş veri tipleri üzerindeki tartı şmamıza devam etmeden önce, gelin, dilin içindeki basit tipler gibi görünen, ancak karma şık tip olan yeni, yani kullanıcı tarafından tanımlanmı ş, tiplere ve böyle tiplerin tanımlanması için kullanılan yönteme bakalım. Bu BÖLÜM 5 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI 93 amaçla, C dilinde, bir tipe bir tanıtıcı sözcük vererek yeni bir tip tanımlamaya yarayan typedef bildirimi bulunmaktadır. Bildirim, anlambilim açısından oldukça farklı olmasına ra ğmen, sözdizimsel olarak bir de ği şken tanımıyla aynıdır. Sadece ba şına typedef anahtar sözcü ğü getirilir. typedef anahtar sözcü ğünün bir bellek sınıfı belirteci oldu ğu kabul edilir, ve C dili bir bildirimde en fazla bir tane bellek sınıfı belirtecine izin verdi ği için typedef’in arkasına (veya önüne) auto, register, static veya extern konulamaz. Gelin birkaç örne ğe bakalım: typedef unsigned short int kisa; typedef char *kdizisi, *kdfonk(char *, char *); typedef struct { float ger, im; } kompleks; typedef int vektor[6], matriks[8][6]; typedef enum { yanlis, dogru } mantiksal; (kisa, kdizisi, kdfonk, kompleks, vektor, matriks ve mantiksal gibi) yeni tanımlanan tanıtıcı sözcüklerin kendileri de ği şken veya fonksiyon de ğillerdir (e ğer typedef anahtar sözcükleri olmasaydı öyle olacaklardı), ancak bu tür de ği şken veya fonksiyon tanımlamaya yarayacak tiplerdir. Böyle tip isimleri kalıplarda ve sizeof’un i şlenenleri olarak kullanılabilir. (sizeof bir sonraki kısımda anlatılmaktadır.) Örne ğin, a şa ğıdakiler birbirlerine e şde ğerdir: kisa i, j, k; ile unsigned short int i, j, k; kdizisi s1, s2; ile char *s1, *s2; kdfonk strcpy; ile char *strcpy(char *, char *); kompleks z[5]; ile struct {float ger, im;} z[5]; vektor a[8]; veya matriks a; ile int a[8][6]; mantiksal m1, ile enum { yanlis, dogru } m1, md=dogru, my=yanlis; md=dogru, my=yanlis; typedef kullanmanın temel nedeni uzun bildirimleri kısaltmasıdır. Fakat, mantıksal olarak, programcı C dilinin sa ğladı ğı tiplerin yanına sanki yeni bir tip ekliyormu ş gibi dü şünebilir. Bu kolaylık programlama çabasını azaltır, programın okunaklılı ğını geli ştirir ve programlarımızı daha “yapısal” hale getirir. Ayrıca, önemli ve karma şık tip bildirimleri programın belirli bir yerinde toplandı ğında, programı belgelemek ve daha sonra onu anlayıp de ği ştirmek daha kolay olacaktır. typedef bildirimlerinin etki alanı de ği şkenlerde oldu ğu gibidir. Bir blok içinde tanımlanmı ş bir tip dı ş bloklara eri şilebilir de ğildir, fakat bir dı ş blokta tanımlanmı ş bir tip, tekrar tanımlanmadı ğı sürece, bir iç blokta kullanılabilir. Dı şsal düzeyde yapılmı ş bir typedef bildirimi kaynak dosyasının sonuna kadar etkisini sürdürecektir, fakat ayrı derlenen dosyalarda de ğil. struct, union ve sayım tipi bildirimlerinin etki alanı da aynıdır. 94 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI BÖLÜM 5 5.4. sizeof İşleci C dilinin bir di ğer anahtar sözcü ğü de sizeof’tur. sizeof C dilinde bir anahtar sözcük ile ifade edilen tek i şleçtir. Bir fonksiyon de ğildir; diğer tekli i şleçler ile aynı önceli ğe sahip olan ve sa ğdan sola birle şme özelli ği gösteren bir tekli i şleçtir. Genelde, ya bir de ği şkene yada bir tipe uygulanır. Bu i şleç i şlenenin tipinden olan bir de ği şkenin bellekte tutaca ğı bayt sayısını (bir de ği şmez) döndürür. Bir önceki kısmın de ği şken tanımlamalarını kullanan örnekler a şa ğıda verilmi ştir: printf("%ld %ld %ld %ld %ld\n", (long)sizeof i, (long)sizeof a, (long)sizeof s1, (long)sizeof z[3], (long)sizeof 1.0); printf("%ld %ld %ld %ld %ld\n", (long)sizeof(int), (long)sizeof(float), (long)sizeof(double), (long)sizeof(int *), (long)sizeof(kompleks[3])); printf("%ld %ld %ld %ld %ld\n", (long)sizeof(vektor), (long)sizeof(long[4]), (long)sizeof(struct { char *c; vektor v[5]; }), (long)sizeof *s1, (long)sizeof(a[1])); Bu deyimler farklı sistemlerde farklı ç ıktılar görüntüleyecektir. Sistemimizde çıktı şöyledir: 2 96 2 8 8 2 4 8 2 24 12 16 62 1 12 Bunun anlamı, int de ği şkenlerinin 2 bayt, float de ği şkenlerinin 4 bayt, double de ği şkenlerinin 8 bayt ve gösterge de ği şkenlerinin 2 bayt tuttu ğudur. Her gerçekle ştirmede sizeof(char)’ın 1 oldu ğu tanımlanmı ştır. Di ğer sayıları kendiniz doğrulamaya çalı şın. Bir long kaç bayttır? sizeof’un de ğerinin derleme zamanında belirlendi ğine dikkat edin, böylece sizeof bir de ği şmez ifadenin kullanılmasına izin verilen yerlerde kullanılabilir. Standarda göre sizeof i şlecinin verdi ği sayının int olması beklenmemelidir; gerçekle ştirmeye ba ğlı olarak long veya herhangi bir uygun tamsayı tipi olabilir. Bu (unsigned olan) tip standart ba şlık dosyası stddef.h’de size_t ismi ile tanımlanmı ştır. Bu sayıyı printf’e geçirmeden önce bir kalıpla long’a çevirecek ve long için olan dönü şüm tanımlamasını kullanacak kadar dikkatli davrandık. sizeof ile ilgili bir sözdizimsel ayrıntı da, bir ifade yerine bir tipe uygulandı ğında tipin parantezler içine alınması gerekti ğidir. BÖLÜM 5 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI 95 5.5. Birlikler Birlikler bir sözdizimsel, bir de anlambilimsel fark dı şında yapılara çok benzerler. Bir birli ğin sözdizimi aynıdır, sadece struct yerine union anahtar sözcü ğünü kullanırız. Yapılarda, üyeler belle ğe birbiri ardınca yerle ştirilirler (yani bir üyenin di ğerinin üstüne sarkması söz konusu de ğildir), böylece her üyeyi di ğerlerinden ba ğımsız i şleyebiliriz. Birliklerde üyeler aynı bellek bölgesini payla şırlar. Böylece, herhangi bir zamanda, üyelerden sadece bir tanesi ile ilgilenebiliriz. Derleyici, en büyük üyeyi içine alabilecek kadar geni ş bellek ayırır. Örne ğin, union cifdg { char c; int i; float f; double d; int * g; } bd = { 'A' }; 5 yerpayla şımlı üyeden olu şan bd birlik de ği şkenini tanımlar. sizeof bd 8’dir, bu da en büyük üye olan double de ği şkeninin boyudur. Üyelere yapılarda oldu ğu gibi aynı yolla ula şılır (yani “.” veya “->” i şlecini kullanarak). Örne ğin, bd . d = 9.8696044011; printf("%c\n", bd.c); Bu şekilde bu iki deyimi arka arkaya kullanmanın yanlı ş oldu ğuna dikkat edin, çünkü bir taraftan double bir de ğer koyup, di ğer taraftan bir char almaya çalı şmaktayız. Ayrıca, her üye için bir ilkleyenin bulundu ğu yapılara kar şılık, birliklerde en fazla bir tane ilkleyenin olabildi ğine dikkat edin. İlkleyen ilk üyeye uygulanır. Örne ğin, yukarıdaki tanımda bd.c’ye 'A' atanmaktadır; daha sonra, yukarıdaki iki deyim yerine getirildikten sonra, E çıktısını elde ederiz, bu da anlamsız bir de ğerdir, çünkü bd.d’ye atanan de ğer bd.c’deki de ğeri bozar. Herhangi bir zamanda üyelerinden en fazla bir tanesinin bir de ğer tutaca ğını bildi ğimiz zamanlarda, bellekten tasarruf etmek amacıyla genelde birlikler kullanılır. Bu özellik, daha önce verilmi ş olan bir örne ğin geni şletilmi ş uyarlaması olan, a şa ğıdaki örnekte kullanılmı ştır: struct kisi { char *isim; int dogumtarihi; enum cinsiyet_tipi { erkek, kadin } cinsiyet; union { int ahbtarihi; char *ksoyadi; } cbil; struct kisi *baba, *ana, *es, *cocuklar[MAKSCCK]; } kisiler[MAKSKS]; 96 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI BÖLÜM 5 Burada ki şinin cinsiyetine ba ğlı olan iki adet bilgi vardır: Erkekler için askerlik hizmetini bitirme, yani terhis tarihi (ahbtarihi), kadınlar için ise kızlık, yani evlenmeden önceki soyadı (ksoyadi). Aynı zamanda her iki üyenin anlamlı bir de ğer saklamayacaklarını bildi ğimiz için, bellekten tasarruf etmek amacıyla, bunları bir birli ğin içine alıyoruz. Hangi üyeyi (kisiler[birisi].cbil.ahbtarihi veya kisiler[birisi].cbil.ksoyadi) kulanmamız gerekti ğini belirlemek için kisiler[birisi].cinsiyet içindeki bilgiyi kullanabiliriz. 5.6. Alanlar Bazı durumlarda, dar bir yer içine (örne ğin bir tamsayı boyunda bir bölgeye) birçok bilgi sı ğdırmamız gerekebilir. Bunun nedeni bellek tasarrufu olabildi ği gibi, program dı şındaki bazı durumlardan (örne ğin donanım aygıtlarına olan arabirimlerden) kaynaklanabilir. Bunu yapmak için bir yapının üyelerini bit uzunluklarını da vererek tanımlarız. Bu tür üyelere alan adı verilir. Do ğal olarak, uzunluklar sıfırdan küçük olmayan de ği şmez ifadelerdir. Tanım yapılarda oldu ğu gibidir; sadece her üyenin arkasına iki nokta ile uzunluk verilebilir. Eri şim de yapılarda oldu ğu gibi “.” veya “->” i şleçleri ile yapılır. Bir örnek: struct tarih { unsigned yil : 7; unsigned ay : 4; unsigned gun : 5; }; Burada, tarihin iki bayt (sizeof(struct tarih) 2’dir) içine sı ğdırılabilece ği bir yapı tanımlanmaktadır. yil 7 bit kullanır (i şaretsiz oldu ğu için, de ğeri 0’dan 2 7 -1=127’e kadar de ği şebilir ve örne ğin 1900 ile 2027 arasındaki yılları ifade etmek için kullanılabilir), ay 4 bit (0’dan 2 4 -1=15’e kadar de ği şir), gun ise 5 bittir (0’dan 2 5 -1=31’e kadar de ği şir). E ğer uzunlukları belirtmemi ş olsaydık, her üye 2 bayt kullanacak, böylece tüm yapı 6 bayt kaplayacaktı. Alanlarla u ğra şan birisinin dikkat etmesi gereken kurallar şöyle özetlenebilir: 1. Alan tipi unsigned bir tamsayı olmalıdır. Standart, en azından unsigned int’in desteklenmesini gerektirir. 2. Bitlerin alanlara atanma tarzı (soldan sa ğa veya sa ğdan sola) derleyiciye ba ğlıdır. 3. E ğer bir alan sözcük sınırlarını (sistemimizde, short ve int için 16, long için 32 ve char için 8 bitlik sınırları) kesecek şekilde tanımlanırsa bir sonraki sözcükten ba şlatılır; kullanılmakta olan sözcükteki bitler kullanılmaz. Örne ğin, BÖLÜM 5 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI 97 struct dnm { unsigned a1 : 12; unsigned a2 : 5; unsigned a3 : 12; }; a şa ğıdaki biçimde 6 bayt kaplar: 12 bit a1, 4 bit kullanılmıyor (ilk sözcük, yani iki bayt), 5 bit a2, 11 bit kullanılmıyor (ikinci sözcük), 12 bit a3, 4 bit kullanılmıyor (üçüncü sözcük). E ğer unsigned yerine unsigned long kullanmı ş olsaydık, yapı a şa ğıdaki biçimde 4 bayt kaplayacaktı: 12 bit a1, 5 bit a2, 12 bit a3, 3 bit kullanılmıyor (bir long sözcük, yani 4 bayt). E ğer unsigned char kullanmı ş olsaydık, tanım kabul edilmeyecekti, çünkü alan a1 12 bit uzunlu ğundadır, oysa bir char en fazla 8 bit tutabilir. Bu, bir alanın kendi tipinden daha geni ş olamayaca ğı anlamına gelir. E ğer bir alan için bit sayısı belirtilmemi şse, o tip için en büyük de ğer kullanılır. 4. Alanlardan olu şan diziler tanımlanamaz. 5. Adres alma i şleci (&) alanlara uygulanamaz, böylece alanlar gösterge kullanarak doğrudan do ğruya adreslenemezler. 6. Alan isimleri iste ğe ba ğlıdır. E ğer bir alanı kullanmayı dü şünmüyorsanız—örne ğin yukarıdaki örnekte a2’yi—tipi ve alan ismini atlayın. Örne ğin, struct dnm { unsigned a1 : 12; : 5; unsigned a3 : 12; }; 7. E ğer bir sonraki sözcü ğün ba şına atlamak istiyorsanız, araya 0 geni şli ğinde bir bo ş alan koyun. Örne ğin, sistemimizde struct dnm { unsigned a1 : 12; : 0; unsigned a3 : 12; }; ile struct dnm { unsigned a1 : 12; : 4; unsigned a3 : 12; }; 98 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI BÖLÜM 5 e şde ğerdir. Neden? 8. Alanlar da tıpkı yapı üyeleri gibi ilklenebilirler, fakat alan için çok büyük olan bir de ğer vermemeye dikkat etmek gerekir. 5.7. Bellek Ayırma Bazı durumlarda, programcı program için gereken ana bellek miktarını önceden belirleyemez. Örne ğin, bu, büyük oranda program girdisine ba ğlı olabilir. Bir dosyayı sıraya sokan bir program, bütün dosyayı alacak kadar ana belle ğe gereksinim duyabilir. Bir dosya istenildi ği kadar uzun olabildi ğine göre, yürütme esnasında, sistemin bize sa ğlayabilece ği kadar daha fazla bellek elde edebilme yöntemine gereksinimimiz vardır. Standart kütüphane, buna izin verecek bir fonksiyon, calloc(n,boy) içerir. İki argümanı size_t tipinden tamsayılar olmalıdır. boy boyunda n tane de ği şken tutabilecek sıfıra ilklenmi ş bir bellek blo ğuna bir gösterge döndürür. Daha basit ba şka bir fonksiyon malloc(bayts)’tır ve bayts kadar bayttan olu şan bir bellek blo ğuna bir gösterge döndürür. Argümanın tipi yine size_t’dir. size_t gerçekle ştirmeye ba ğlı olan ve en büyük bellek boyunu saklayabilecek kadar büyük olan bir tamsayıdır. free(g) fonksiyonu daha önce calloc veya malloc ile ayrılmı ş bulunan ve g ile gösterilen bellek blo ğunu serbest bırakacaktır. malloc ve calloc’un dönü ş tipi ve free’nin argüman tipi genel gösterge tipi olan “void *”’dır. “void *” tipi bekleyen bir fonksiyona bir gösterge argümanı geçirdi ğinizde, bir kalıp kullanarak, bunu “void *” tipine dönü ştürmeniz gerekir. Aynı şekilde, bir fonksiyon “void *” döndürüyorsa, bunu uygun gösterge tipine dönü ştürmeniz gerekir. Her tip gösterge, herhangi bir bilgi yitimine u ğramadan, “void *” tipine ve daha sonra eski tipine dönü ştürülebilir. stdlib.h ba şlık dosyası bu fonksiyonlar için gerekli bildirimleri içerir ve bu bölümün sonunda bu fonksiyonları kullanan örnek bir program bulunmaktadır. 5.8. Karma şık Tipler Bu kısımda, dizi dizileri, dizilere göstergeler, gösterge dizileri ve göstergelere göstergeler gibi daha karma şık veri tiplerini inceleyece ğiz. Bir tanımı istedi ğimiz kadar karma şıkla ştırabilece ğimize dikkat edin; örne ğin, tamsayı dizilerine göstergeler içeren diziye bir gösterge. Biz ise burada yalnızca, yukarıda sıraladı ğımız gibi, “iki-düzeyli” karma şık veri tiplerine bakaca ğız. BÖLÜM 5 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI 99 5.8. 1. Dizi Dizileri Bir dizi benzer elemanlardan olu şan bir topluluktur. Eleman sayısı derleme sırasında belirlenir, böylece C dilinde devingen dizilere izin verilmez. Bir dizinin elemanları (alan veya fonksiyon dı şında) her şey olabilir; ayrıca dizi de olabilir, böylece çok-boyutlu diziler tanımlanabilir. Bir dizinin elemanlarına ula şmak için indisler kullanılır. İndisler tamsayı ifadelerdir ve, dizinin n tane elemanı varsa, de ğerleri 0 ile n-1 arasında de ği şebilir. Tek-boyutlu dizileri nasıl kullanaca ğımızı biliyoruz. Şimdi çok boyutlu bir dizi tanımına bakalım: int a[3][4] = { {1, 2, 3, 2+2}, {5, 6, 7, 1<<3}, {3*3, 10, 11, 0xF&~03} }; Burada çok-boyutlu bir dizinin (bir dizi dizisinin) tanımının bütün boyutlarda boyların ayrı ayrı kö şeli parantezler içine alınarak verildi ği görüyoruz. Yukarıdaki tanımda dizinin, her biri 4 elemanlı 3 “vektör” şeklinde düzenlenmi ş 12 elemanı vardır. Di ğer bir deyi şle, diziler satır şeklinde saklanırlar, yani son indis en hızlı de ği şendir. İlkleme beklendi ği gibi yapılır, dizinin her elemanı için üç madde bulunmaktadır, bunlar da virgülle ayrılmı ş vektörlerdir. Bu maddelerin her biri birbirinden virgülle ayrılıp çengelli parantezler içine alınmı ş 4 de ği şmez ifadeden olu şurlar. Bütün (12) de ğerleri de belirtmemize gerek yoktur. Örne ğin, int b[3][4] = { {1, 2, 3}, {5, 6} }; ile int b[3][4] = { {1, 2, 3, 0}, {5, 6, 0, 0}, {0, 0, 0, 0} }; aynıdır. E ğer bütün de ğerleri belirtirsek içteki çengelli parantezlere gerek yoktur: int a[3][4] = { 1, 2, 3, 2+2, 5, 6, 7, 1<<3, 3*3, 10, 11, 0xF&~03 }; E ğer derleyici dizinin boyunu ilkleyenden çıkarabilirse, o zaman boyu belirtmeye gerek yoktur. Örne ğin, int a[][4] = { {1, 2, 3, 2+2}, {5, 6, 7, 1<<3}, {3*3, 10, 11, 0xF&~03} }; 100 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI BÖLÜM 5 a için ilk verilen tanıma e şde ğerdir. Bildirimdeki ilk (yani belirtilmeyebilen) indisin sadece dizi tarafından gerek duyulan bellek miktarını belirlemede kullanıldı ğına dikkat edin; indis hesaplamalarında kullanılmamaktadır. Bir dizi elemanına ula şmak için “[]” i şlecini kullanırız. E ğer n-boyutlu bir dizimiz varsa, n tane böyle i şleç kullanılmalıdır. Örne ğin, a[1][2] de ğeri 7 olan dizi elemanını göstermektedir. Pascal programlama dilinden farklı olarak a[1,2]—veya a[(1,2)]— a[2]’ye e şde ğerdir ve bir int’in beklendi ği bir yerde kullanılamaz. 5.8.2. Dizilere Göstergeler Daha önce de açıklandı ğı gibi, bir fonksiyon parametresi olarak tanımlanmı ş tek boyutlu bir dizinin boyunun belirtilmesine gerek yoktur, çünkü bu bir dizi de ğil, gerçekte bir göstergedir. Çok-boyutlu bir dizide ne olur? Kural şöyledir: İlki dı şında bütün boyutların boyunu belirtmeniz gerekir. Örne ğin, f (int uc_b[][5][7]) { ... } Gelin bunun nedenine bakalım. uc_b[0]’ın 5×7 boyunda iki-boyutlu bir dizi oldu ğuna dikkat edin, uc_b[1] ilkinden 35 int ileride olan bir sonraki iki-boyutlu dizidir. Yani, uc_b[1] veya *(uc_b+1)—bir gösterge ifadesi—uc_b[0]’ın 35 int ilerisini göstermelidir. Bu, uc_b’nin 5 çarpı 7 (yani 35) elemanlık bir diziye gösterge oldu ğu anlamına gelir. Yukarıdaki parametre bildirimi şöyle de yazılabilirdi: int (*uc_b)[5][7]; bu da yukarıdaki ile tamamen aynıdır. Parantezlere dikkat edin. E ğer yazılmasalardı, int *(uc_b[5][7]); anlamına gelecek, bu da int göstergelerden olu şan iki-boyutlu bir dizi anlamına gelecekti; bir sonraki altkısmın konusu. A şa ğıdaki örnek çok-boyutlu dizilerin kullanımını özetlemeye çalı şmaktadır. Programı inceleyip, onu izleyen çıktıyı do ğrulamaya çalı şın. #include int x[3][5][7]; /* uc-boyutlu bir dizi */ void f (int a[][5][7]) /* iki-boyutlu diziye gösterge */ { printf("%d\t%d\n", a[0][0][0], (int)sizeof a[0][0][0]); printf("%d\t%d\n", a[0][0], (int)sizeof a[0][0]); printf("%d\t%d\n", a[0], (int)sizeof a[0]); printf("%d\t%d\n", a, (int)sizeof a); printf("\n%d\t%d\n", x[0][0][0], (int)sizeof x[0][0][0]); BÖLÜM 5 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI 10 1 printf("%d\t%d\n", x[0][0], (int)sizeof x[0][0]); printf("%d\t%d\n", x[0], (int)sizeof x[0]); printf("%d\t%d\n", x, (int)sizeof x); printf("\n%d\t%d\t%d", (int)a[0], (int)a[1], ((int)a[1]-(int)a[0]) / (int)sizeof(int)); printf("\n%d\t%d\t%d", (int)x[0], (int)x[1], ((int)x[1]-(int)x[0]) / (int)sizeof(int)); printf("\n%d\t%d\t%d", (int)a[0][0], (int)a[0][1], ((int)a[0][1]-(int)a[0][0]) / (int)sizeof(int)); printf("\n%d\t%d\t%d", (int)x[0][0], (int)x[0][1], ((int)x[0][1]-(int)x[0][0]) / (int)sizeof(int)); } void main (void) { f(x); } Çıktı şöyledir: 0 2 3384 14 3384 70 3384 2 0 2 3384 14 3384 70 3384 210 3384 3454 35 3384 3454 35 3384 3398 7 3384 3398 7 5.8.3. Gösterge Dizileri Daha önceki bir bölümde, geleneksel olarak argv adı verilen, main’in ikinci parametresinin bir karakter göstergeleri dizisi oldu ğunu görmü ştük. Aslında bunu anlamak ta o kadar zor de ğildir; e ğer belirli bir sayıda göstergemiz varsa, di ğer tipteki de ği şkenler için yaptı ğımız gibi, bunları da bir dizi içinde saklayabiliriz. Bir örnek görelim, char *msj[] = { "Tamam", "Disk dolu", "Sozdizim hatasi", ... "Dosya bulunamadi" }; Burada, ilkleyen içinde verilen karakter dizilerinin sayısı kadar boyda bir dizimiz vardır. Her karakter dizisinin temel adresi msj dizisi içinde arka arkaya gelen gösterge 102 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI BÖLÜM 5 elemanları içinde saklanmaktadır. Bu msj’yi iki-boyutlu bir karakter dizisi olarak tanımlamaktan iyidir. Bellek kullanımı dikkate alarak bunun nedenini açıklamaya çalı şın. Bu diziyi kullanabilecek bir hata yordamı şöyledir: void hata (int hk) { printf("<%d>: %s.\n", hk, msj[hk]); exit(hk); } Burada exit, programı bitiren bir kütüphane fonksiyonudur. stdlib.h ba şlık dosyasında bildirilmi ştir. int tipinden olan argümanı da, ça ğıran sürece—tipik olarak i şletim sistemine—döndürülen bir durum kodudur. Geleneksel olarak, 0 normal sonuçlanmayı, sıfırdan farklı bir sayı da farklı bir durumu göstermek için kullanılır. Ba şka bir örne ğe bakalım: int cikis(void), ekleme(void), silme(void), degistirme(void); int (*fonkt[])(void) = { cikis, ekleme, silme, degistirme }; Bu, fonksiyonlara göstergelerden olu şan bir dizidir. Tekrar, i şleç önceliklerini anımsayın. İlk olarak fonksiyon tiplerini tanımlıyoruz. Fonksiyonların hepsinin parametresiz ve dönü ş tiplerinin de hep aynı oldu ğuna dikkat edin. Daha sonra bu fonksiyonlara göstergelerle diziyi ilkliyoruz. Bildi ğiniz gibi, e ğer bir fonksiyon ismi arkasında parantez bulunmuyorsa, bu o fonksiyona bir göstergedir. Bu dizideki bir fonksiyonu ça ğırmak için, (*fonkt[secenek])() kullanırız; secenek burada bir tamsayıdır. E ğer secenek 0’sa cikis, 1 ise ekleme ça ğrılır vs. 5.8.4. Göstergelere Göstergeler Göstergeler de ği şken olduklarına göre, onlara da gösterge tanımlanabilir. Pratik bir durum, bir fonksiyona geçirilen bir gösterge dizisidir. main’in ikinci parametresi böyle bir örnektir, argv char göstergelerine bir gösterge olarak dü şünülebilir. Böylece, void main (int argc, char *argv[]) ve void main (int argc, char **argv) tanımları e şde ğerdir. A şa ğıda, Altkısım 4.2.3’te verilen programın bir ba şka şekli verilmi ştir: BÖLÜM 5 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI 103 #include void main (int argc, char *argv[]) { printf("Merhaba, benim ismim %s.\n", *argv); printf("Argumanlarim sunlar"); while (*++argv) printf(", %s", *argv); printf(".\n"); } argv’nin en sonunda bir NULL göstergenin bulundu ğuna dikkat edin. Bir sonraki kısımda bir göstergeye gösterge örne ği vardır. 5.9. Bir Örnek—Dosya Sıralama Bu kısımda, malloc ve free kütüphane fonksiyonlarını kullanan ve bu bölümde ö ğrenilmi ş bazı kavramları gösteren bir örne ğe bakaca ğız. Problem bir metin dosyasındaki satırları sıraya sokmaktır. Sıraya sokma düzeni, sistem tarafından sa ğlanan sıraya göre olacaktır. Bu, bizim sistem için, artan ASCII karakterleri sırasıdır. (Ek A’ya bakınız.) Bu program MS-DOS’un SORT komutuna benzemektedir. Yöntemimiz ikili bir a ğaç kullanmak olacaktır. A ğacın her dü ğümünde bir bilgi alanı ve iki gösterge vardır: biri sola, biri sa ğa. Algoritma şöyledir: • Bo ş bir a ğaçla ba şla. • Bir satır oku; bir dü ğüm olu ştur; bilgi bölümünü satırla doldurup iki göstergeye BO Ş (NULL) koy. Bu, kök dü ğümü olacaktır. • Bir sonraki satırı oku; bu satır için yukarıdaki gibi bir dü ğüm olu ştur. Şimdi bu dü ğümün a ğaç içine konulacak yeri ara ştır. Kök dü ğümüne olan göstergeden ba şlayarak ve BO Ş bir gösterge elde edilmedi ği sürece göstergeleri şu şekilde izle: E ğer yeni satır, eldeki gösterge tarafından i şaret edilen dü ğümdeki satırdan sözlük sırası açısından küçükse, göstergeye o dü ğümün sol göstergesini aktar; aksi takdirde sa ğ göstergeyi aktar; bu i şlemi tekrarla. Sonunda BO Ş bir göstergeye ula şılacaktır; bu göstergeyi yeni dü ğümü gösterecek şekilde de ği ştir. • Girilen bütün satırlar için önceki adımı tekrarla. Sonunda—ille de dengeli olmasına gerek olmayan—bir ikili a ğaç elde edilecektir. Sayısal de ğerler kullanılarak elde edilen örnek bir ikili a ğaç Şekil 5.1’de gösterilmi ştir. 104 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI BÖLÜM 5 15 15, 9, 3, 5, 17, 10, 4, 7, 13 3, 4, 5, 7, 9, 10, 13, 15, 17. 91 7 31 0 51 3 47 Sayılar şu sırada girilmi ştir: ve çıkı ş sırası şöyledir: i şareti BO Ş gösterge anlamına gelir. ŞEK İL 5. 1 Bir örnek ikili a ğaç A ğacı bastırmak için a şa ğıdaki özça ğrılı algoritmayı kullanaca ğız: Kök dü ğüme olan göstergeden ba şla. E ğer gösterge BO Ş de ğilse, soldaki alta ğacı bastır; eldeki dü ğümün bilgisini bastır; sağdaki alta ğacı bastır. “Alta ğaç”ların basım i şi aynı tümcede anlatılan algoritma kullanılarak yapılacaktır. Bu algoritma eninde sonunda bitecektir; çünkü tümce ba şında “e ğer” ko şulu vardır. Dikkat ederseniz, bir a ğaçtaki göstergelerin yarısından fazlası BO Ştur. Neden? Bu algoritmayı bir program şeklinde uygulamaya sokmak için dü ğüm için ne tür bir veri yapısı kullanaca ğımıza karar vermemiz gerekir. Do ğal olarak, bu, üç üyeden olu şan bir yapı (struct) olacaktır: satir, sol ve sag; bu son ikisi de aynı yapıya olan gösterge tipinden olacaktır. Yani, bir öz-referanslı yapımız olacaktır. İlk üye (satir), belirli bir üst limite (örne ğin 80 karaktere) kadar olabilecek bir satırı saklayabilecek büyüklükte bir karakter dizisi şeklinde tanımlanabilir. Fakat bütün satırlar bu kadar uzun olamayacaklarına göre, dizi içindeki alanın büyük bir bölümü kullanılmayabilecektir, yani bellek israfı olacaktır. Bundan dolayı satir bir karakter göstergesi şeklinde tanımlanmı ştır ve satırın boyu kadar, yürütme esnasında istenen, bellek bölgesinin ba şına i şaret edecektir. Şimdi de program: 1. #include 2. #include 3. #include 4. #include 5. #define MAKSSU 80 /* en buyuk satir uzunlugu */ 6. BÖLÜM 5 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI 105 7. typedef struct dugum { /* struct dugum'un tanimi */ 8. char *satir; /* bilgi */ 9. struct dugum *sol, *sag; 10. } *dugumg; /* dugumg tipinin tanimi*/ 11. 12. void *yeni (size_t d) /* bellek ayirma */ 13. { 14. void *g; 15. 16. if ((g=malloc(d))!=NULL) 17. return g; /* tamam */ 18. fprintf(stderr, "SIRALA: Yetersiz bellek"); 19. exit(1); /* programi kes */ 20. } /* yeni */ 21. 22. size_t satiroku /* satir uzunlugu dondur; 0 dosya sonu */ 23. (char *d, int u) 24. { 25. register char *g = d; 26. register int c; 27. 28. while ((c=getchar())!='\n' && c!=EOF) 29. if (u-->1) 30. *g++ = (char)c; /* daha uzun satirlari kes */ 31. if (c==EOF && g==d) 32. return 0; /* bir sey okunamadi */ 33. *g++ = '\0'; 34. return g-d; /* asil uzunluk arti bir ('\0' icin) */ 35. } /* satiroku */ 36. 37. void satirlaribas /* agacin ozcagrili taranmasi */ 38. (dugumg g) 39. { 40. if (g!=NULL) { 41. satirlaribas(g->sol); 42. printf("%s\n", g->satir); 43. satirlaribas(g->sag); 44. free((void *)g->satir); 45. free((void *)g); 46. } 47. } /* satirlaribas */ 48. 49. void main (void) 50. { 51. char satir[MAKSSU+1]; /* MAKSSU arti bir ('\0' icin) */ 52. size_t su; /* simdiki satir uzunlugu */ 53. dugumg kok = NULL, *g; 54. 55. while ((su=satiroku(satir,(int)sizeof satir)) > 0) { 56. g = &kok; 57. while (*g!=NULL) 58. g = (strcmp(satir,(*g)->satir) < 0) 59. ? &(*g)->sol : &(*g)->sag; 60. *g = (dugumg) yeni(sizeof(struct dugum)); 61. strcpy((*g)->satir = (char *)yeni(su), satir); 62. (*g)->sol = (*g)->sag = NULL; 63. } 64. satirlaribas(kok); 65. } /* main */ 106 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI BÖLÜM 5 Programın ba şında, yapı ( struct dugum) ve böyle bir yapıya bir gösterge (dugumg) için tipler tanımlamı ş bulunuyoruz. main yordamı, her okunan satır için bir defa yürütülen büyük bir while döngüsünden olu şmaktadır. satiroku fonksiyonu satir karakter dizisinin içine bir satır okur ve okunan karakter sayısı artı bir (en sona konan '\0' için) verir. Dosya sonu (EOF) durumunda ise 0 döndürür. main içinde iki önemli de ği şkenimiz vardır: kok, dü ğüme bir göstergedir ve her zaman kök dü ğümüne i şaret eder, g ise bir dü ğüme olan göstergeye göstergedir; bir dü ğümün sol yada sag göstergelerine i şaret eder. Bir defa bir satır okundu mu, g kök dü ğüm göstergesine i şaret edecek şekilde getirilir. Sonra, g tarafından i şaret edilen yerde NULL (BO Ş) bir gösterge olmadı ğı sürece, g’nin i şaret etti ği gösterge tarafından i şaret edilen dü ğümde şimdi okunan satırdan sözlük sırasına göre daha büyük bir satırın olup olmadı ğını kontrol ederiz. E ğer öyle ise g’nin sol, aksi takdirde sag göstergeye i şaret etmesini sa ğlarız. while döngüsü g tarafından i şaret edilen (sol ve sag) gösterge bir dü ğüme i şaret etti ği (yani NULL olmadı ğı) sürece tekrarlanır. Bir NULL göstergeye ula ştı ğımızda, g’nin bu göstergeye i şaret etti ğini bilerek, döngüden çıkarız. Şimdi yeni bir dü ğüm olu şturmanın zamanıdır. malloc kütüphane fonksiyonunu kullanan yeni fonksiyonu, bu dü ğüm için yeterli miktarda bellek bölümü ayırmak için ça ğrılır. Döndürdü ğü gösterge g tarafından i şaret edilen göstergeye aktarılır. Daha sonra, okunmu ş olan satırı alacak büyüklükte bir bellek bölgesi ayrılır; satır bu bölgeye aktarılır ve bu bölgeye olan gösterge, g’nin i şaret etti ği gösterge tarafından gösterilen dü ğüm, yani yeni dü ğüm, içindeki satir göstergesine atanır. Ayrıca, bu dü ğümün sol ve sag göstergelerine de NULL konur. Yukarıda anlatılanlar, ilk bakı şta, çok karma şık gelebilir. E ğer açıklamayı tam olarak izleyemediyseniz, tamamen haklısınız. Birkaç tekrar yararlı olacaktır. Yapılacak son şey a ğacı basmaktır. Burada özça ğrı bize çok yardımcı olacaktır. Ana program, kok göstergesini vererek satirlaribas adlı özça ğrılı fonksiyonu ça ğırır. Bu fonksiyon, “E ğer gösterge NULL de ğilse, sol alta ğacı bas; şimdiki dü ğümün bilgisini bas; sa ğ alta ğacı bas” cümlesinde denileni yapar ve ayrıca “bu dü ğüm tarafından kullanılan belle ği serbest bırak” i şini de yapar. Bellek serbest bırakıldıktan sonra, tekrar bellek ayırma söz konusu olmadı ğı için free fonksiyonu ça ğrılarının bu program için gereksiz oldu ğuna dikkat edin. Programımız girdisini standart girdi aygıtından alır ve çıktısını da standart çıktı aygıtına gönderir. Daha sonraki bir bölümde görece ğimiz gibi, programlarımızda girdi/çıktı için dosyalar da kullanabiliriz, ama daha basit bir yol vardır. Birçok i şletim sistemi, girdi/çıktının yeniden yönlendirilmesi adı verilen ve tekrar derleme yapmadan, standart girdi ve çıktı dosyaları yerine ba şka dosyaların kullanılmasına izin veren bir yöntem sa ğlarlar. MS-DOS’ta, bu, şu şekilde yapılabilir: Programınızın SIRALA adlı yürütülebilir dosya içinde derlendi ğini varsayın. A>SIRALA SIRALI BÖLÜM 5 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI 107 komutunu kullanarak programın girdiyi SIRASIZ adlı disk dosyasından almasını ve çıktıyı SIRALI adlı dosyaya koymasını sa ğlayabilirsiniz. Bu “argümanların” bir tanesini belirtmedi ğinizde ne oldu ğunu deneyip kendiniz bulmaya çalı şın. Program için bu “argümanların” tamamen görünmez oldu ğuna dikkat edin; yani (main fonksiyonunun ikinci parametresi olan) argv dizisinde gözükmeyeceklerdir; gerekli i şlemleri i şletim sistemi yapar. Ba şka bir özellik küme komut i şlemedir. A>DIR | SIRALA şeklindeki MS-DOS komutunu deneyip çıktıyı açıklayın. Daha fazla bilgi için i şletim sisteminizin elkitabına danı şın. Problemler 1. İlklenmemi ş “enum gunler” tipinden bir de ği şken (a) e ğer static veya dı şsalsa ve (b) e ğer auto veya register ise hangi de ğere sahip olacaktır. 2. Kısım 5.2’de sözü edilen yapılarla ilgili sınırlamaları olan bir derleyiciniz oldu ğunu varsayın. Argüman olarak aynı tipten iki yapının adreslerini alıp ikinci yapıyı ilk yapıya aktaran yapi_ata adında bir fonksiyon yazın. 3. Yeni yapı tipleri tanımlamanın iki yöntemi vardır: yapı künyesi kullanarak ve typedef kullanarak. A şa ğıdakini typedef kullanan bir bildirime dönü ştürün. aylar de ği şkeni için yazılmı ş tanımı da uygun şekilde de ği ştirin. struct ay { char *ayadi; int ayuzunlugu; }; ... struct ay aylar[12]; 4. İki yerde (yani kalıplarda ve sizeof’un i şlenenleri olarak), bir veri tipi verilmesi gerekir. Bu basit bir tip ismi olabilece ği gibi daha karma şık bir ifade de olabilir. Böyle bir ba ğlamda a şa ğıdakilerin ne anlama geldi ğini bulmaya çalı şın: int * int *[3] int (*)[3] int *(float) int (*)(void) 5. Altkısım 5.8.1’in ba şında tanımlanmı ş bulunan a dizisinin içindekileri görüntülemek için a şa ğıdakini deneyin: 108 TÜRET İLM İŞ T İPLER VE VER İ YAPILARI BÖLÜM 5 #include void main (void) { int i, j; for (i=0; i<3; i++) for (j=0; j<4; j++) printf("%2d%c",a[i,j], j==3 ? '\n' : ' '); } Neden do ğru çıktıyı elde edemiyoruz? Görüntülenen sayılar nelerdir? Beklenen çıktıyı elde edecek şekilde programı de ği ştirin. 6. Altkısım 5.8.2’de verilen örnekte neden sizeof(x) 210’dur da sizeof(a) 2’dir? 7. E ğer MS-DOS kullanmakta iseniz, MS-DOS elkitabında SORT komutu için belirtilenleri okuyup, bu bölümün sonunda verilen örnek programı, bunları da yapacak şekilde geli ştirin. Örne ğin, büyük-küçük harf ayırımı yapmadan sıralama yapmayı veya sıralama yaparken belirli bir kolondan itibaren dikkate almayı sa ğlayın. 8. A şa ğıdaki örneklerde const ve volatile anahtar sözcüklerinin ne i şe yaradı ğını anlamaya çalı şın: int const x = 11; int y = 22; int * const a = &y; const volatile * const b = &x; 109 BÖLÜM 6: ÖN İŞLEMC İ 1. #include 2. #define PI 3.14159265358979323846 3. #define DEGIS(x,y,tip) { tip t; t = x; x = y; \ 4. y = t; } 5. #ifdef EOF 6. # define SON EOF 7. #else 8. # define SON (-1) 9. #endif 10. #ifndef MAKS 11. # define MAKS(p,q) ((p)>(q) ? (p) : (q)) 12. #endif 13. #define OZEL static ... 14. #undef OZEL 15. #if (HDUZ & 0x40) != 0 16. printf("satir = %d\n", __LINE__); 17. #endif Bu bölümde hemen her zaman C derleyicisi ile birlikte kullanılan ayrı bir “i şlemci”ye göz ataca ğız. Bu; derlenmeden önce kaynak dosyalarımızı metin yönünden öni şlemeye tabi tuttu ğu için bu şekilde adlandırılan, C öni şlemcisidir. Öni şlemciyi, kaynak dosyalarımızı alıp, verilen öni şlemci emirlerine göre yeni bir dosya olu şturan bir düzenleyici şeklinde dü şünebiliriz. Kabaca durum şöyledir: stdio.h benim.h prog.c › › › amaç kod. Öni şlemci aslında derleyici ile bütünle şmi ştir, yani genelde ayrı bir sistem programı de ğildir. Bir öni şlemci emrini ile sıradan bir C deyimini ne ayırır? İlk olarak, farklı sözdizimi. İkinci olarak ta, satırın başındaki sayı i şareti (#). Genelde, emirler bir satır tutarlar; ancak bir satır, sonuna bir ters bölü i şareti (\) konularak, bir sonraki satıra devam ettirilebilir. Ayrıca emrin sonunda noktalı virgül olmadı ğına dikkat edin. 110Ö N İŞLEMC İ BÖLÜM 6 Emirler hiçbir zaman derleyici tarafından görünmezler. Öni şlemci, emirleri çıkarıp yerlerine istenen i şlemleri yapar. Örne ğin, bir #include emri içeren satır yerine emirde belirtilen dosyanın içeri ği konur. Öni şlemci emirleri herhangi bir satıra konabilirler, ancak öni şlemci açıklamaları atladı ğı için, açıklamaların içine konulamazlar. Bu bölümün geri kalan kısımlarında, öni şlemci emirlerini ayrıntılı olarak açıklayaca ğız. 6. 1. #define Ve #undef Emirleri #define emri belirli karakter dizileri için (“makro” adı da verilen) takma isimler tanımlamaya yarar. Sözdizimi şöyledir: #define tanıtıcı_sözcük de ği ştirme_dizisi Örne ğin, #define BLOKBASI { #define BLOKSONU } #define YORDAM static void Tanımlanmakta olan tanıtıcı_sözcük’ün önünde ve arkasında en az bir tane bo şluk karakteri bulunmalıdır. Normal C tanıtıcı sözcüklerinden ayırt etmek için, bu tür isimlerde büyük harflerin kullanılması alı şılagelmi ştir. Bu isimlerin tanımı #undef ile iptal edilmedi ği sürece, kaynak dosyanın geri kalan kısmında, tanımında ondan sonra gelen karakter dizisi (yani de ği ştirme_dizisi) ile de ği ştirilirler. Tanımlanmı ş bulunan bir tanıtıcı_sözcük için ikinci bir #define ancak de ği ştirme_dizisi aynı ise kabul edilebilecektir. Örne ğin, YORDAM hepsini_goster (...) BLOKBASI ... BLOKSONU program parçası, derlenmeden önce, öni şlemci tarafından static void hepsini_goster (...) { ... } şeklinde de ği ştirilecektir. Bir istisna: E ğer isim tırnak içinde yer alıyorsa, makro de ği şikli ği yapılmayacaktır. Örne ğin, printf("BU YORDAM..."); deyimi de ği ştirilmeden, aynı şekilde kalacaktır. BÖLÜM 6 ÖNİŞLEMC İ 111 Tipik olarak, #define emri program için sayı, karakter dizisi vs de ği şmezleri tanımlamak için kullanılır, ancak de ği ştirme_dizisi, daha önce veya sonra tanımlanan makrolar da dahil, her şeyi içerebilir. Daha önce tanımlanmı ş bir makronun tanımını kaldırmak için #undef emrini, arkasına makro ismini belirterek, kullanabilirsiniz. (Bu bölümün ba şındaki ilk örnekte Satır 13 ve 14’e bakınız.) Yani #undef tanıtıcı_sözcük Makrolara argüman da verilebilir. (Bölümün ba şında Satır 3 ve 11’e bakınız.) Genel şekil şöyledir: #define tanıtıcı_sözcük(tanıtıcı_sözcük opt , ...) de ği ştirme_dizisi Makro ismi ile “biçimsel argüman listesi” içindeki ilk parametreden önce gelen sol parantez arasında herhangi bir bo şluk bulunmamalıdır. Bir fonksiyona benzemesine ra ğmen, bazı farklar vardır. Makrolar “satıriçi kod” olu ştururlar, yani makronun kullanıldı ğı her sefer, biçimsel argümanlar yerine gerçek argümanlar konularak, ilgili de ği ştirme_dizisi onun yerini alır. Makro ça ğrısındaki argümanların sayısı, bildirimde belirtilmi ş bulunan biçimsel argümanların sayısı ile aynı olmalı ve virgüllerle ayrılmalıdırlar. Tırnak i şaretleri içinde veya bir çift parantez arasında bulunan virgüller gerçek argüman ayırıcıları olarak sayılmazlar. Örne ğin, Satır 11’de tanımlanmı ş makroya bir ça ğrı içeren m = MAKS(x=10, c?y:z) + 5; ifadesi öni şlemci tarafından, m = ((x=10)>(c?y:z) ? (x=10) : (c?y:z)) + 5; şeklinde “açılacaktır”. Şimdi makro tanımında parametreler etrafında neden parantez kullanmı ş oldu ğumuzu görüyorsunuz. Hepsi gereklidir. Aksi takdirde, istenen sonuç elde edilemeyecektir. E ğer inanmıyorsanız, bir de parantezler olmadan deneyin. ( İşleç önceliklerini unutmayın!) Böyle durumlar için kural şöyledir: • İlk olarak, de ği ştirme_dizisini sol parantezle ba şlatıp sa ğ parantezle bitirin. Az önceki örnekte oldu ğu gibi, genelde, bir makro, ifadenin bir bölümünü olu şturur. Bu aynı zamanda Satır 8’deki tanımda da gerekli idi. [Neden? “if (kar SON)” durumunu inceleyin.] • İkinci olarak, de ği ştirme_dizisindeki bütün parametreleri parantez içine alın. Çünkü gerçek argümanların karma şık ifadeler olabileceğini unutmayın. Bir önceki örnekte oldu ğu gibi, dikkat ettiyseniz, makro açılımından sonra bazı hesaplamalar birden fazla kez yapılabilir. Örne ğin, “x=10” atama deyimi. Bu durum verimsiz olması d ı şında, bazı beklenmeyen sonuçların çıkmasına da neden olabilir. Örne ğin i’nin de ğerinin 6 oldu ğunu varsayın. “MAKS(6,i++)”nin de ğeri ne olacaktır? 6 mı? Bakalım. Öni şlemci “((6)>(i++) ? (6) : (i++))” şeklinde açacaktır. Böylece de ğeri 7 olacaktır. Ayrıca, i’nin yeni de ğeri 7 de ğil de 8 olacaktır. 112Ö N İŞLEMC İ BÖLÜM 6 E ğer de ği ştirme_dizisinde bir parametrenin önüne # konursa, makro açılımından sonra çift tırnak içine alınacaktır, yani argüman bir karakter dizisine dönü ştürülecektir. Ayrıca böyle bir argümanın içinde bulunan " ve \ karakterlerinin önüne \ eklenecektir. E ğer de ği ştirme_dizisi içinde bir ## simgesi varsa, bu i şlecin önünde ve arkasında bulunan isimlerin birbirine yapı ştırılaca ğı şekilde, ## ve etrafındaki her türlü beyaz boşluk karakteri çıkarılacaktır. Örne ğin #define cagir(x) yord ## x() tanımını ele alalım. Bu makroyu cagir(1); şeklinde kullandı ğımızda yord1(); şeklinde açılacaktır. 6.2. #include Emri #include "dosya_adı" #include veya #include karakter_dizisi şeklindeki bir satır, öni şlemcinin bu satır yerine belirtilen dosyanın içindekilerini koymasını sa ğlar. Dosyanın içinde uygun C kodunun bulunması gerekti ği açıktır. İlk şekil, öni şlemcinin dosya_adı için önce varsayılan altdizine, yani derlenmekte olan kaynak dosyanın bulundu ğu altdizine, daha sonra “standart yerler”e bakmasını sa ğlayacaktır. İkinci şekil sadece standart yerlerde aramaya neden olur. “Standart yerler” derken, bu tür dosyaların bulundu ğu, öni şlemci tarafından bilinen, altdizinlerden sözetmekteyiz. Dosya_adına bazen başlık dosyası adı da verilir. Üçüncü şekilde ise, öni şlemci tarafından #define ile tanımlanmı ş karakter_dizisi açıldı ğında ilk iki şekilden birisinin elde edilmesi beklenir. Sistemimizde, standart yerler, “INCLUDE” adındaki MS-DOS ortam de ği şkeninde belirtilir. Örne ğin, SET INCLUDE=a:\ktphnm;a:\include MS-DOS komutu, öni şlemcinin dosyayı bulması için, belirtilen iki altdizine bakmasını sa ğlayacaktır. E ğer #include’un çift tırnaklı olanı kullanılırsa, önce varsayılan aldizine bakılacaktır. Ayrıca, isterseniz #include emrindeki dosya_adında dosya isminin önüne altdizin ismini de belirtebilirsiniz. BÖLÜM 6 ÖNİŞLEMCİ1 1 3 Son bir nokta: #include emirleri (8 düzeye kadar) içiçe yazılabilir; bu, #include edilen bir dosyanın içinde ba şka #include emirleri de bulunabilir anlamına gelir. 6.3. Ko şullu Derleme #if, #ifdef, #ifndef, #else, #elif ve #endif emirleri, bazı ko şullara ba ğlı olarak derlemeyi kontrol ermek için kullanılırlar. #if de ği şmez_ifade emri, e ğer de ği şmez_ifadenin de ğeri do ğru (sıfırdan farklı) ise bir sonraki #endif veya #else (veya #elif) emrine kadar olan satırların derlemeye dahil edilmesini sa ğlar. İlk durumda, derleme #endif’ten sonra, normal olarak devam eder; ikinci durumda ise, #else’den sonra ilgili #endif’e kadar olan satırlar öni şlemci tarafından atlanır (yani derleyiciye gönderilmez). E ğer de ği şmez_ifadeni de ğeri yanlı ş (0L) ise, #if ile #endif veya #else (hangisi önce geliyorsa) arasındaki metin atlanır. #if emirlerinin içiçe yazılabildi ğine dikkat edin, bunun için hangi #else’in hangi #if’e ait oldu ğunu bilmemiz gerekir: #else bir #endif ile ba ğlantısı olmayan, yukarıdaki en yakın #if’e aittir. De ği şmez_ifade, öni şlemcinin “öni şlem zamanında” hesaplayabilece ği herhangi bir C ifadesidir; sizeof ve kalıp i şleçleriyle sayım ve kayan noktalı sayı de ği şmezleri burada kullanılamazlar. Daha önce öni şlemciye tanımlanmı ş makrolar ise kullanılabilirler; ancak, tanımsız isimlerin yerine 0L konur. De ği şmez_ifade her zaman long duyarlıkta hesaplanır. Bir emir satırında defined tanıtıcı_sözcük şeklindeki bir ifade, e ğer tanıtıcı_sözcük öni şlemci tarafından biliniyorsa 1L ile de ği ştirilir, aksi takdirde 0L konur. Bir örnek olarak, iki mü şteri için hazırlanmı ş bir programı ele alalım. Program içinde belirli bir mü şteri için gerekli bölümler olabilir. Derlemeyi kontrol etmek için, şu anki derlemenin hangi mü şteri için yapıldı ğını gösteren bir tanıtıcı sözcük tanımlayabiliriz. Örne ğin, #define MUSTERI 1 /* diger must. icin baska bir deger */ ... #if MUSTERI == 1 /* ilk musteri icin kod */ ... #else /* ikinci musteri icin kod */ ... #endif Bu arada 114Ö N İŞLEMC İ BÖLÜM 6 #ifdef tanıtıcı_sözcük ve #ifndef tanıtıcı_sözcük emirleri, sırasıyla, tanıtıcı_sözcük’ün öni şlemci tarafından #define ile tanımlanmı ş olup olmadı ğını test ederler. Bunlar, sırasıyla, #if defined tanıtıcı_sözcük ve #if !defined tanıtıcı_sözcük emirleriyle e şde ğerdirler. #elif de ği şmez_ifade emri #else #if de ği şmez_ifade için bir kısaltma şeklinde dü şünülebilir, ancak #elif kullanıldı ğında yeni bir #endif’e gerek kalmaz; önceki #if’in #endif’i kullanılır. Ba şka bir örnek olarak, hataların düzeltilmekte oldu ğu bir program dü şünün; böylece bu programda htkntrl adlı bir fonksiyona bazı yerlerde ça ğrılar olmaktadır. (Bu fonksiyon, örne ğin, bazı de ği şkenlerin o anki de ğerlerini basıyor olabilir.) Ancak, program geli ştirilmesi sonunda programı “normal” bir şekilde derlememiz gerekecektir. Bunu yapmanın kolay bir yolu da şöyledir: ... #ifndef HATASIZ /* hata duzeltme yardimci fonksiyonu */ /* iceren baslik dosyasi */ # include "htkntrl.h" #else # define htkntrl() #endif ... E ğer HATASIZ adlı tanıtıcı sözcük #define ile tanımlanmamı şsa, o zaman #include emri öni şlemeye girecek ve htkntrl fonksiyonu da dahil, hata düzeltme yardımcı programları içeren “htkntrl.h” dosyasının içindekileri derlenecektir. Ancak, e ğer HATASIZ #define ile tanımlanırsa, o zaman, bo ş bir de ği ştirme dizisine sahip olan htkntrl makrosu #define ile tanımlanmı ş olacaktır. Bu durumda, htkntrl’e yapılan ça ğrılar, öni şlemci tarafından, bo şlukla de ği ştirilecektir. Buna benzer #if emirleri programın ba şka bölümlerinde de konulabilir. HATASIZ tanıtıcı sözcü ğü programın ba şında tanımlanabilece ği gibi, UNIX veya sistemimizde oldu ğu gibi C (öni şlemcisi ve) derleyicisinin ça ğrıldı ğı komut satırında belirtilebilir. Ek B’ye bakınız. BÖLÜM 6 ÖNİŞLEMCİ1 1 5 6.4. Di ğer Emirler Pek kullanılmayan bir emir de a şa ğıdakidir: #line de ği şmez "dosya_adı" opt Burada de ği şmez, bir de ği şmez ifade değil, 1 ile 32767 arasında bir tamsayı de ği şmezidir. Dosya_adı ise bir karakter dizisidir. Bu emir, derleyicinin şu anki satır sayısını unutup derlemekte oldu ğu satırın sayısının sanki de ği şmez ile ifade edilen sayı imi ş gibi davranmasını sa ğlar. Yani emirden sonraki be şinci satırda bir hata olursa “de ği şmez+4 nolu satırda hata var” şeklinde bir hata mesajı ortaya çıkacaktır. İste ğe ba ğlı olan ikinci argüman ise, derleyicinin şu anda derlenmekte olan dosyanın adının sanki dosya_adı imi ş gibi bir varsayımda bulunmasına neden olur. Dosya_adının içinde altdizin de belirtilmi şse, bu #include dosyaları için taranacak olan varsayılan altdizini de etkileyebilir. (Kısım 6.2’deki tartı şmaya bakınız.) #error karakter_dizisi şeklindeki bir satır, öni şlemcinin karakter_dizisini de içeren bir mesaj yazmasını sa ğlayacaktır. #pragma karakter_dizisi şeklindeki bir öni şlemci emri, öni şlemci ve/veya derleyicinin karakter_dizisi içinde belirtilen bir i şlem yapmasına neden olacaktır. Karakter_dizisi için kabul edilebilecek de ğerler C Standardında belirtilmemi ştir. Onun için bu tamamen uygulamaya ba ğlı bir özelliktir ve dikkate de alınmayabilir. En son olarak; görünen tek karakteri # olan bir satır dikkate alınmaz ve atlanır. 6.5. Önceden Tanımlanmı ş İsimler Öni şlemci, ayrıca bazı tanıtıcı sözcükleri önceden #define ile tanımlamı ştır. Bunların tanımının #undef ile kaldırılması veya #define ile yeniden tanımlanmaları mümkün de ğildir. Bunlar şunlardır: __FILE__ Derlenmekte olan dosyanın adı (karakter dizisi), __LINE__ Şu anki kaynak satır numarası (ondalık sayı), __DATE__ Tarih (“Aaa gg yyyy” şeklinde karakter dizisi), __TIME__ Saat (“ss:dd:ss” şeklinde karakter dizisi), __STDC__ Standarda uyan derlemeler için 1 de ği şmezi. 116Ö N İŞLEMC İ BÖLÜM 6 6.6. Bir Örnek—ctype.h Ba şlık Dosyası A şa ğıda ctype.h ba şlık dosyasının basitle ştirilmi ş ve Türkçele ştirilmi ş bir uyarlaması verilmektedir: 1. /*** 2. *ctype.h - karakter donusum makrolari ve ctype makrolari 3. * 4. * Copyright (c) 1985-1992, Microsoft Corp. Her hakki saklidir. 5. * 6. *Amac: 7. * Karakter siniflandirmasi ve donusumu icin makrolar tanimlar. 8. * [ANSI/Sistem V] 9. * 10. ****/ 11. 12. #ifndef _INC_CTYPE 13. 14. /* ... */ 15. 16. /* Asagidaki tanim, kullanicinin, ctype.obj'da 17. * tanimlanmis bulunan _ctype adli karakter tipi 18. * dizisine erisimini saglar. 19. */ 20. 21. extern unsigned char /* ... */ _ctype[]; 22. 23. /* olasi karakter tipleri icin bit ortulerinin tanimlanmasi */ 24. 25. #define _UPPER 0x1 /* buyuk harf */ 26. #define _LOWER 0x2 /* kucuk harf */ 27. #define _DIGIT 0x4 /* rakam[0-9] */ 28. #define _SPACE 0x8 /* durak, satir basi, yeni satir, */ 29. /* dikey durak veya sayfa ilerletme */ 30. #define _PUNCT 0x10 /* noktalama karakteri */ 31. #define _CONTROL 0x20 /* kontrol karakteri */ 32. #define _BLANK 0x40 /* bosluk karakteri */ 33. #define _HEX 0x80 /* onaltili rakam */ 34. 35. /* ... */ 36. 37. /* karakter siniflandirilmasi ile ilgili makro tanimlari */ 38. 39. #define isalpha(_c) ( (_ctype+1)[_c] & (_UPPER|_LOWER) ) 40. #define isupper(_c) ( (_ctype+1)[_c] & _UPPER ) 41. #define islower(_c) ( (_ctype+1)[_c] & _LOWER ) 42. #define isdigit(_c) ( (_ctype+1)[_c] & _DIGIT ) 43. #define isxdigit(_c) ( (_ctype+1)[_c] & _HEX ) 44. #define isspace(_c) ( (_ctype+1)[_c] & _SPACE ) 45. #define ispunct(_c) ( (_ctype+1)[_c] & _PUNCT ) 46. #define isalnum(_c) ( (_ctype+1)[_c] & (_UPPER|_LOWER|_DIGIT) ) 47. #define isprint(_c) ( (_ctype+1)[_c] & (_BLANK|_PUNCT| \ 48. _UPPER|_LOWER|_DIGIT)) 49. #define isgraph(_c) ( (_ctype+1)[_c] & (_PUNCT|_UPPER| \ 50. _LOWER|_DIGIT) ) 51. #define iscntrl(_c) ( (_ctype+1)[_c] & _CONTROL ) 52. #ifndef __STDC__ 53. #define toupper(_c) ( (islower(_c)) ? _toupper(_c) : (_c) ) BÖLÜM 6 ÖNİŞLEMCİ1 1 7 54. #define tolower(_c) ( (isupper(_c)) ? _tolower(_c) : (_c) ) 55. #endif 56. #define _tolower(_c) ( (_c)-'A'+'a' ) 57. #define _toupper(_c) ( (_c)-'a'+'A' ) 58. #define __isascii(_c) ( (unsigned)(_c) < 0x80 ) 59. #define __toascii(_c) ( (_c) & 0x7f ) 60. 61. /* genisletilmis ctype makrolari */ 62. 63. #define __iscsymf(_c) (isalpha(_c) || ((_c) == '_')) 64. #define __iscsym(_c) (isalnum(_c) || ((_c) == '_')) 65. 66. /* ... */ 67. 68. #define _INC_TYPE 69. #endif Bu dosyanın ba şında (_ctype) extern dizisinin bildirimi yapılmaktadır. Bu 129 elemanlık bir dizidir. İlk elemanının de ğeri 0’dır, böylece ikinci elemandan ba şlamamız gerekir. İlk elemanını atlamak için, dizi şu şekilde indislenebilir: (_ctype+1)[indis] Her eleman, indis olarak kullanılan karaktere kar şılık gelen bir kod içerir. Örne ğin: (_ctype+1)[' ']’in de ğeri 0x48’dir (_ctype+1)['A']’in de ğeri 0x81’dir Bu sayılar, herbirinin özel bir anlamı olan, 8 bitten olu şmaktadır. Bu bitlerin anlamları 25’ten 33’e kadar olan satırlarda verilmi ştir. Örne ğin, 0x48 _BLANK (bo şluk) ve _SPACE (görünmeyen karakter) anlamına gelir, 0x81 _HEX (onaltılı rakam) ve _UPPER (büyük harf) demektir. Bu bilgi ile, “is...” (...dır) makrolarının nasıl çalı ştı ğını açıklamak zor olmayacaktır. __isascii (ASCII karakteri) olup olmadı ğını test eder. Di ğer makroların açıklaması kolaydır ve okuyucuya bırakılmı ştır. Problemler 1. Yeni tipler tanımlamak için en az iki yolunuz vardır. Bir, öni şlem esnasında #define kullanarak; iki, derleme sırasında typedef anahtar sözcü ğünü kullanarak. #define’ın typedef yerine kullanılamayaca ğı bir örnek verin. 2. Makrolar, karakter dizileri, yani çift tırnak içinde ise açılmazlar. Ancak makro parametreleri, makro tanımında tırnak içinde olsalar bile de ği ştirilebilirler. Standart açıkça bunu yasaklamaktadır ve bizim öni şlemcimiz de bunu yapmamaktadır. Sizinkinin de aynı şeyi yapıp yapmadı ğını deneyerek görün ve bu “özelli ği” kullanan yararlı bir örnek verin. 3. _ctype dizisini kullanmadan ctype.h dosyasında tanımlanmı ş bulunan “is...” (...dır) makrolarına e şde ğer uyarlamalar tanımlayın. Bir örnek a şa ğıda verilmi ştir: 118Ö N İŞLEMC İ BÖLÜM 6 #define isalpha(_c) (((_c)>='A' && (_c)<='Z') || \ ((_c)>='a' && (_c)<='z')) 4. Anahtar sözcükleri Türkçe, Almanca, İtalyanca veya ba şka bir dilde olan C programları yazmanızı sa ğlayacak #define’lar yazın. 119 BÖLÜM 7: DOSYALAR VE G İRD İ/ÇIKTI Alı ştı ğımız de ği şkenlerden farklı olarak, bir dosya, programın yürütülmesinden önce ve/veya sonra da var olan bir nesnedir. “Kalıcı olma” özelli ği dosyaları çok yararlı kılar. Şimdiye kadar gördü ğümüz programlarda oldu ğu gibi, dosyalar sayesinde, programlar kullanıcılarıyla veya birbirleriyle haberle şebilirler. C dilinde dosyalar, istenildi ği kadar uzun olabilen karakter (bayt) sıraları şeklinde görülürler. Ancak daha karma şık bir yapı, kullanıcı tarafından, uygulamaya göre, verilebilir. Bu bölümün büyük bir kısmı, dosyalarla ilgili çe şitli i şlemler ve girdi/çıktı yapmak için bize yardımcı olacak standart kütüphaneyi anlatacaktır. Bu bölümde anlatılan fonksiyonlar, birçok C ortamında sa ğlananların sadece küçük bir kısmıdır. Daha fazla bilgi için ilgili ba şvuru elkitaplarına danı şın. Kullanıcı programları, i şletim sistemi adı verilen, karma şık bir sistem programının gözetimi altında çalı ştırılırlar. Programların i şletim sistemine çe şitli i şlemler yaptırması için, C kütüphanesi bazı yordamlar içerir. C farklı sistemlerde uygulandı ğı için kütüphanenin bu bölümü pek standart de ğildir. Bu bölümde tartı şılacak ba şka bir konu da, bizim sistemin C ile nasıl etkile şti ğidir. Kısım 7.1’den 7.4’e kadar anlatılan fonksiyonlar Standardın bir parçasıdır ve stdio.h ba şlık dosyasında bildirilmi ştir. Kısım 7.5’teki fonksiyonların bildirimi stdlib.h standart ba şlık dosyasında bulunmaktadır. Ancak Kısım 7.6’dakiler Standardın bir parçası de ğildir, buna ra ğmen birçok ortamda desteklenmektedir. 7. 1. Dosya Esasları Program bir dosya üzerinde herhangi bir i şlem yapmadan önce, dosyanın açılması gerekmektedir. fopen standart fonksiyonu bunu yapar ve iki karakter dizisi argüman alır: açılacak olan dosyanın adı ve eri şim modu. İlk argüman herhangi geçerli bir dosya 120 DOSYALAR VE G İRD İ/ÇIKTI BÖLÜM 7 adı içerebilir; dosya adının önüne sürücü ve altdizinler de belirtilebilir. İkinci argümanın alabilece ği de ğerler ve anlamları a şa ğıdaki çizelgede gösterilmi ştir: de ğer eri şim modu "r" okuma "w" yeniden yazma "a" sona ekleme "r+" okuma ve yazma (de ği ştirme) "w+" okuma ve yeniden yazma (de ği ştirme) "a+" okuma ve ekleme Varolmayan bir dosyadan okumaya kalkmak hatadır. Yeni bir dosya yaratmanın yolu varolmayan bir dosya adı verip "a..." veya "w..." belirtmektir. E ğer eri şim modunun sonuna b harfi eklenirse—örne ğin "rb"—ikili (ham) modda girdi/çıktı yapılacaktır, aksi takdirde metin girdi/çıktısı yapılır. E ğer açma i şlemi ba şarılı ise fopen açtı ğı dosyaya bir dosya göstergesi döndürür, yoksa, standart kütüphanede de bulunan, NULL yani bo ş gösterge döndürür. Dosya göstergeleri şu şekilde tanımlanmalıdır: FILE * dosya_gostergesi; FILE bütün dosyaların tipidir; kütüphanede tanımı bulunan bir yapıdır ve bu tanımın detayları normal kullanıcıları ilgilendirmez. Gelin bir dosya olu şturalım: dosya_gostergesi = fopen("DOSYA.YEN", "w") Bundan sonra, DOSYA.YEN ile ilgili i şlemlerde dosya_gostergesi kullanılacaktır. Bir program ekrana bilgi görüntüledi ği zaman, aslında standart çıktı dosyasına karakter yazmaktadır. Programınıza klavyeden bilgi girdi ğinizde, aslında bunları standart girdi dosyasına yazmaktasınız ve program bu dosyayı okumaktadır. “Standart dosyalar” programcı tarafından fopen kullanılarak açılmazlar, yürütme ba şlamadan önce, otomatik olarak açılıp, normalde, kullandı ğınız ekran ve klavyeye atanırlar. Kütüphane, bu iki dosya için de dosya göstergeleri içermektedir: standart girdi dosyası için stdin, standart çıktı dosyası için de stdout. Bazı durumlarda, hata mesajları için ayrı bir çıktı akı şının olması uygun olabilir. C bir standart hata dosyası sa ğlamaktadır; bu dosyaya olan göstergenin adı stderr’dir. Normalde, stderr’e giden çıktı stdout’ınkiyle birlikte aynı aygıta yapılır, ancak bunu de ği ştirmenin yolları vardır. stdin, stdout ve stderr de ği şmez göstergelerdir; onları kullanırken bunu unutmayın. Şimdi, bir dosyayı nasıl açaca ğımızı bildi ğimize göre, gelin ona nasıl yazaca ğımıza bakalım. dosya_gostergesi tarafından i şaret edilen dosyaya kar karakterini yazmak için putc fonksiyonunu kullanırız: putc(kar, dosya_gostergesi) BÖLÜM 7 DOSYALAR VE G İRD İ/ÇIKTI 12 1 putc aslında karakterleri bir tampon bölgeye koymakta ve bu bölge doldu ğunda içindekileri dosyaya aktarmaktadır. E ğer dosyaya, tamponun boyundan daha az miktarda, birkaç karakter yazmak isterseniz ne olacaktır? Tamponu “bo şaltmak” için bir yol gereklidir. fclose fonksiyonu, di ğer i şlerin yanında bunu yapmaktadır. fclose’un, dosya göstergesi olan, bir argümanı vardır. fclose(dosya_gostergesi) çalı ştırıldıktan sonra, dosya kapatılır ve dosya_gostergesi artık ona i şaret etmez. fclose fopen’in “tersi”dir. fopen ile açtı ğınız her dosyayı fclose ile kapatmanız gerekir. Sistemden sisteme fark etmekle beraber, herhangi bir zamanda açık olan dosya sayısında bir sınırlama oldu ğu için, bu ayrıca gerekli de olabilir. Program normal olarak sona erdi ğinde, bütün açık dosyalar fclose ile kapatılır. Okuma için açılmı ş ve dosya_gostergesi tarafından i şaret edilen bir dosyadan bir karakter okumak için getc kullanılır: kar = getc(dosya_gostergesi) E ğer okuyaca ğı karakter kalmazsa getc ne yapar? Dosya sonuna ula ştı ğını göstermek için özel bir de ğer döndürmesi gerekti ği açıktır. Bu de ğer bir karakter olmamalıdır, çünkü aksi takdirde, getc’nin dosyadan bir karakter mi okudu ğunu, yoksa dosya sonunu mu i şaret etmek istedi ğini anlıyamayaca ğız. Böyle bir durumda, getc, EOF de ği şmezini döndürür. Kütüphane, genelde EOF’u (-1) olarak tanımlar. Bu de ğeri de tutmak için, yukarıda kullanılan kar “karakteri”nin bir char de ğil de, bir int olarak tanımlanması gerekti ğine dikkat edin. Böylece, her seferinde dosyadan bir karakter okuyup, o karakter için bir şey yapan ve dosyada karakter kalmadı ğı zaman sona eren bir program parçası şu şekilde olacaktır: if ((kar=getc(dosya_gostergesi))!=EOF) { kar’a göre i şlem yap } else programı bitir 7.2. Dosya Eri şimi—Ba şka Yöntemler fopen, fclose, putc ve getc ile çok yararlı şeyler yapılabilir, fakat C, kolaylık için, ba şka, “daha geli şmi ş” dosya eri şim yöntemleri de sa ğlar. Zaten bildi ğiniz, getchar ve putchar böyle iki örnektir. Sistemimizde, stdio.h dosyasında şu şekilde tanımlanmı şlardır: #define getchar() getc(stdin) #define putchar(c) putc((c),stdout) Do ğal olarak, programcılar, bir seferde birden fazla karakter yazabilen fonksiyonlara gereksinim duyarlar. İşte bunu yapan fputs fonksiyonu: fputs(kar_dizisi, dosya_gostergesi) 122 DOSYALAR VE G İRD İ/ÇIKTI BÖLÜM 7 Bu, kar_dizisi adlı karakter dizisinin dosya_gostergesi tarafından i şaret edilen dosyaya yazılmasını sa ğlar. Dizinin sonundaki bo ş karakter yazılmaz. Bu fonksiyonun da puts adında “standart dosya” uyarlaması bulunmaktadır. puts(kar_dizisi) kar_dizisi’ni stdout’a yazar ve fputs’tan farklı olarak yeni satır karakteri yazıp yeni bir satıra geçer. Kütüphanede, ayrıca, bir seferde bir satır okuyan fgets adında bir fonksiyon bulunmaktadır. fgets(kar_dizisi, maks_uzunluk, dosya_gostergesi) dosya_gostergesi tarafından i şaret edilen dosyanın bir sonraki satırından en fazla maks_uzunluk-1 sayıda karakteri kar_dizisi içine okuyup, e ğer dosya sonu de ğilse, kar_dizisi’ni (bir gösterge), aksi takdirde NULL döndürür. (Bir satır sadece sonunda yeni satır karakterinin bulundu ğu bir karakter sırasıdır.) kar_dizisi içine aktarılan satırın sonuna bo ş karakter eklenir. Standart girdi fonksiyonu gets biraz fgets’e benzer. gets(kar_dizisi) stdin’den bir satır okuyup kar_dizisi ile ba şlayan yere koyar. fgets’ten farklı olarak, gets kar_dizisi’ne yeni satır karakterini koymaz. Kolaylık isteyen programcılar, karakter dizisi-sayı dönü şümlerinin fonksiyon tarafından yerine getirildi ği, herhangi bir tipten sayıların dosyaya yazılmasını veya oradan okunmasını isterler. Bu gereksinimler, fprintf ve fscanf fonksiyonları tarafından yerine getirilirler. fprintf(dosya_gostergesi, kontrol_karakter_dizisi, argüman_listesi) ça ğrısı kontrol_karakter_dizisi içindeki sıradan karakterlerle, argüman_listesinden aldı ğı argümanları uygun bir şekilde biçimlendirerek dosya_gostergesi tarafından i şaret edilen dosyaya yazar. Kontrol_karakter_dizisi ve argüman_listesi için kurallar printf’teki gibidir. fscanf(dosya_gostergesi, kontrol_karakter_dizisi, argüman_listesi) ça ğrısı dosya_gostergesi tarafından i şaret edilen dosyadan bir karakter dizisi okur, kontrol_karakter_dizisine göre dönü şümleri yapıp, de ğerleri, argüman_listesindeki argümanlar tarafından gösterilen yerlere koyar. Kurallar scanf’teki gibidir. Argümanlar için do ğru biçimleri ve doğru sayıda argüman sayısını vermek kullanıcının sorumlulu ğundadır. printf ve scanf fonksiyonları fprintf ve fscanf’in özel uyarlamalarıdır. İlk argüman olarak dosya göstergesi yoktur; bunlar, sırasıyla, stdout ve stdin’i kullanırlar. BÖLÜM 7 DOSYALAR VE G İRD İ/ÇIKTI 123 Bu fonksiyon ailesinin ba şka iki üyesi de sprintf ve sscanf’tir. Bunlar dosyaya eri şmezler; onun yerine, ilk argüman olarak belirtilen bir karakter dizisi üstünde çalı şırlar. sprintf(kar_dizisi, kontrol_karakter_dizisi, argüman_listesi) ça ğrısı, tıpkı fprintf gibi, kontrol_karakter_dizisi ve argüman_listesi ile normal biçim dönü şümlerini yapar; sonucu fprintf’ten farklı olarak kar_dizisi’ne koyar. Buna benzer olarak, sscanf(kar_dizisi, kontrol_karakter_dizisi, argüman_listesi) ça ğrısı, scanf’in stdin’i taradı ğı şekilde kar_dizisi’nin taranıp de ğerlerin, normalde oldu ğu gibi, argüman_listesinin elemanları tarafından gösterilen yerlere konmasını sa ğlar. Örne ğin sprintf(kar_dizisi, "abc%dcba", 100); deyimi kar_dizisi’nin içine "abc100cba" koyar; e ğer ondan sonra sscanf(kar_dizisi, "abc%d", &int_deg); deyimi i şletilirse, beklendi ği gibi int_deg’in içine 100 konur. 7.3. Rastgele Eri şim Normalde, bir dosya açıldıktan sonra, ilk okuma veya yazma i şlemi dosyanın hemen ba şından yapılır. Bir sonraki i şlem ise, en son i şlem tarafından etkilenen son baytı izleyen bayttan ba şlayarak yapılır. Bundan dolayı, buna sıralı eri şim denir. Bunu yapmadan, yani önceki baytları okuyup veya yazmadan, istedi ğimiz bir bayta ula şmak (yani rastgele eri şim yapmak) için fseek kullanırız: fseek(dosya_gostergesi, uzun_sayi, nereden) Yukarıdaki ça ğrıda ilk iki argümanın tipleri isimlerinden anla şılabilir. nereden ise ya SEEK_SET (dosyanın ba şından), ya SEEK_CUR ( şu anki konumundan) yada SEEK_END (dosyanın sonundan) olabilir. fseek i şletildikten sonra dosya_gostergesi tarafından i şaret edilen dosya üzerindeki okuma veya yazma nereden ile belirtilmi ş yerden uzun_sayi mesafedeki bayttan ba şlıyacaktır. E ğer herhangi bir hata olursa, fseek sıfırdan farklı bir sayı döndürür, aksi takdirde 0 verir. Bir metin dosyasında bir karakterin konumunun hesaplanmasının anlamlı yada en azından ta şınabilir bir özellik olmadı ğına dikkat edin; fseek tamamen ikili (ham) girdi/çıktı içindir. E ğer, birtakım i şlemlerden sonra, dosyanın ba şından kaç bayt ileride oldu ğunuzu ö ğrenmek isterseniz ftell kullanın: uzun_sayi = ftell(dosya_gostergesi) uzun_sayi’ya miktarı koyacaktır; e ğer bir hata olursa -1L verecektir. 124 DOSYALAR VE G İRD İ/ÇIKTI BÖLÜM 7 Sık sık dosyayı “geri sarmak”, yani ba şına fseek yapmak isteyebilirsiniz. rewind(dosya_gostergesi) bunu yapmanın kısa bir yoludur. 7.4. Dosyalarla İlgili Ba şka Bilgiler “Okuma” fonksiyonları veya makrolarının okudu ğu şey ungetc tarafından etkilenebilir. ungetc(kar, dosya_gostergesi) ça ğrısı, dosya_gostergesi ile i şaret edilen dosyadan yapılacak bir sonraki okuma i şlemi (getc, fgets, fscanf vs) tarafından dosyada var olan karakterlerden önce kar’da verilen karakterin okunmasını sa ğlar. ungetc ile okuma i şlemi arasında fseek yapılırsa, ungetc ile saklanan karakter unutulacaktır. ungetc isminin aslında biraz yanıltıcı olmasına ra ğmen, ungetc genelde okunmaması gerekirken okunmu ş bir karakterin sanki okunmamı ş gibi geri alınmasını sa ğlar. Her dosya için, en fazla bir karakter bu şekilde geri konabilir. ungetc i şlemi ba şarısız olursa EOF döndürülür. Dosyaları olu şturdu ğunuz gibi onları silebilirsiniz de. Dosyanın ismi dosya_adi ise, o zaman remove(dosya_adi) yazın. Dosya bu altdizinden silinmi ş olacaktır. E ğer dosyanın ait oldu ğu tek altdizin bu ise dosya sistemden tamamen silinecektir. (Bir altdizin ba şka altdizin veya dosya isimleri içerebilen bir rehber olarak dü şünülebilir.) E ğer i şlem ba şarılı ise remove 0 döndürecektir. Buna benzer olarak bir dosyanın adını de ği ştirmek istiyorsanız. rename(eski_dosya_adi, yeni_dosya_adi) kullanın. Bilgi öbekleri okumak veya yazmak için iki yararlı fonksiyon vardır: fread(gosterge, boy, sayi, dosya_gostergesi) ve fwrite(gosterge, boy, sayi, dosya_gostergesi) fread, dosya_gostergesi tarafından i şaret edilen dosyadan gosterge ile i şaret edilen diziye boy uzunlu ğunda sayi kadar nesne aktaracaktır. fwrite ise bu i şlemi ters yönde yapacaktır. Bu fonksiyonlar aktarılan nesne sayısını döndürürler; e ğer bir hata olmu şsa, bu sayı sayi’dan az olacaktır. Çok girdi/çıktı, örne ğin bir aktarma i şlemi yapan bir program dosyalar için büyük tampon bölgeleri kullanırsa kazançlı çıkacaktır. Tamponlu girdi/çıktı yapmak için standart kütüphane iki fonksiyon sa ğlamaktadır. Bunlar fopen’dan hemen sonra ça ğrılmalıdır. BÖLÜM 7 DOSYALAR VE G İRD İ/ÇIKTI 125 setbuf(dosya_gostergesi, tampon) fonksiyonu, normalde char tampon [BUFSIZ]; olarak tanımlanması gereken tampon dizisini dosya için tampon bölge haline getirir. BUFSIZ stdio.h dosyasında tanımlanmı ş olan uygun bir de ği şmezdir. E ğer tampon yerine NULL verirsek, tamponlama ortadan kalkar. Tampon boyunun kullanıcı tarafından belirlendi ği daha iyi bir fonksiyon ise şöyledir: setvbuf(dosya_gostergesi, tampon, mod, tampon_boyu) Burada, mod ya _IOFBF (tam tamponlama), ya _IOLBF (metin dosyaları için satır tamponlama) yada _IONBF (tamponlamanın kaldırılması) olabilir. E ğer tampon NULL ise tampon_boyu boyundan bir tampon bölgesi setvbuf tarafından ayrılacaktır. İşlem ba şarılı ise, bu fonksiyon 0 döndürür. Son olarak, fflush(dosya_gostergesi) fonksiyonu, tamponda bilgi varsa, bunun dosyaya aktarılmasını sa ğlar. Sadece bir çıktı dosyası için kullanılabilir ve bir hata durumunda EOF, aksi durumda 0 döndürür. 7.5. Sistem İle İlgili Fonksiyonlar İlginç bir fonksiyon olan system, bir C programı içinden, i şletim sisteminizin kabul edebilece ği herhangi bir komutu çalı ştırmanızı sa ğlar. system(kar_dizisi) ça ğrısı yapıldı ğında, kar_dizisi içindeki i şletim sistemi komutu çalı ştırılır; bu komut tamamlandıktan sonra ise program normal bir şekilde devam eder. Örne ğin, system("DIR C:\\MSVC\\INCLUDE\\*.H") ifadesi c:\msvc\include altdizini içinde dosya tipi h olan bütün dosyaların ekranda görüntülenmesini sa ğlar. Şimdiye kadar görmü ş oldu ğumuz programlar (herhangi bir sorun çıkmazsa), kontrol main blo ğunun sonuna ula ştı ğında biterler. exit fonksiyonu ise, konuldu ğu yerde programın sona ermesini sa ğlar. exit(durum) ça ğrısı, açık olan tüm dosyalar için fclose’un, daha sonra da _exit kütüphane fonksiyonunun ça ğrılmasını sa ğlar. _exit ba şka bir şey yapmadan programı bitirir. (Programlarınızda kütüphanede tanımlanmı ş bulunan ve “_” ile ba şlayan bir şey kullanmanız tavsiye edilmez; normal programcılar için bunlar biraz dü şük düzeyde kalırlar ve Standarda girmezler.) Bir tamsayı olan durum’un de ğeri, bu programın 126 DOSYALAR VE G İRD İ/ÇIKTI BÖLÜM 7 çalı şmasını sa ğlayan sürece geçirilir ve bu süreç tarafından bazı kararlar vermek için kullanılabilir. Geleneksel olarak, sıfırdan farklı durum de ğerleri çe şitli hatalı durumları gösterirler, 0 ise ba şarılı bir sonuçlanmayı gösterir. stdlib.h ba şlık dosyasında tanımlanmı ş EXIT_SUCCESS (ba şarılı sonuçlanma) ve EXIT_FAILURE (hatalı sonuçlanma) de ğerleri bu kodları standartla ştırmaktadırlar. Birbirleriyle ili şkili iki fonksiyon da şunlardır: rand() ve srand(tohum) İlki 0 ile RAND_MAX (?32767) arasında bir sözde rastgele tamsayı verir. İkincisi ise, rand tarafından üretilecek yeni bir sözde rastgele sayı sırası için tohumu (i şaretsiz bir tamsayı) belirtmek için kullanılır. E ğer srand ça ğrılmazsa, program ba şlarken tohum’un de ğeri 1’dir. 7.6. Dosya Tanımlayıcıları Ve İlgili Fonksiyonlar Dosya göstergelerine bir alternatif de dosya tanımlayıcılarıdır. Her dosya tanımlayıcısı (sistemimizde tutamak da denir), programın yürütülmesi esnasında dosyayı gösteren, sıfırdan küçük olmayan bir tamsayıdır. Kısım 7.1’den 7.4’e kadar anlatılan dosya eri şim fonksiyonlarının dosya tanımlayıcıları için ayrı uyarlamaları bulunmaktadır. Dikkat: Önceki kısımdakilerden farklı olarak, bu kısımda anlatılan fonksiyonlar standartla şmı ş de ğillerdir; sadece bizim sistem tarafından bunların desteklendi ğini söyleyebiliriz. Bundan ba şka, dosya tanımlayıcısı fonksiyonları ile dosya gösterge fonksiyonları birbirinden tamamen farklı ve uyumsuzdurlar; bir program içinde ikisi birlikte kullanılmamalıdır. Aslında, bu kısımda anlatılan fonksiyonları hiç kullanmamak en iyi yoldur! Bu kısımda anlatılanlarla ilgili bilgiler, Standarda dahil olmayan, fcntl.h, sys\types.h, sys\stat.h ve io.h adlı ba şlık dosyalarında bulunur. A şa ğıda anlatılan isimlerin önünde, standart olmadıklarını göstermek için, altçizgi (_) karakteri bulunmaktadır; birçok sistemde bu karakter bulunmayabilir. Standart girdi, çıktı ve hata dosyalarının sırasıyla 0, 1 ve 2 şeklinde dosya tanımlayıcıları vardır. Bir dosya olu şturmanın yolu dosya_tanimlayicisi = _creat(kar_dizisi, izin) yazmaktır. _creat ile ilgili yeni bir şey de her dosya için bir izin belirtebilmeyi sa ğlamasıdır. kar_dizisi adında bir dosya önceden bulunmuyorsa, _creat böyle bir dosya yaratır ve yazma için açar. Daha sonra, dosya ilk defa kapatıldı ğında, _creat’in ikinci argümanı olarak belirtilen izin dosyaya atanır. izin, _S_IWRITE ve _S_IREAD kütüphane de ği şmezlerinin bir tanesine e şit olması gereken bir tamsayı ifadesidir. BÖLÜM 7 DOSYALAR VE G İRD İ/ÇIKTI 127 _S_IREAD sadece okumaya izin verilmi ştir, _S_IWRITE yazılmaya izin verilmi ştir anlamına gelir. Hem yazma hem de okumaya izin vermek için _S_IREAD|_S_IWRITE kullanın. E ğer kar_dizisi adında bir dosya daha önceden bulunuyorsa, _creat içindekileri silip, yazma için açmaya çalı şır. Dosyanın eski izin durumu etkisini sürdürür. Normalde, _creat dosya için bir tanımlayıcı döndürür. E ğer ba şarısızsa, örne ğin dosya daha önceden var olan salt okunabilen bir dosya ise veya çok fazla açık dosya varsa, -1 döndürür. kar_dizisi adında bir dosyayı açmak için a şa ğıdaki yazılır: dosya_tanimlayicisi = _open(kar_dizisi, bayrak, izin) E ğer her şey iyi giderse dosya_tanimlayicisi’nın içine bir tutamak de ğeri konur; aksi takdirde -1 döndürülür. bayrak dosya ile ilgili yapılacak i şlemi gösterir; örne ğin dosyayı okumak için _O_RDONLY kullanın. izin yukarıdaki gibi _S_IWRITE ve _S_IREAD kütüphane de ği şmezlerinden biri olmalıdır ve sadece bayrak için _O_CREAT (dosyayı yarat) kullanıldı ğında anlam ta şır. _close fonksiyonu daha önce açık bulunan bir dosyayı kapatmak için kullanılır ve _close(dosya_tanimlayicisi) şeklindedir. Dosyayı kapatabilirse 0, aksi takdirde -1 döndürür. Dosya tanımlayıcıları kullanarak girdi-çıktı yapmak istiyorsanız, okunacak veya yazılacak baytlar için önceden yeterli büyüklükte bir (tampon) bölge tanımlamanız gerekir. A şa ğıda, tampon’un yeterince büyük bir char dizisi oldu ğunu varsayın. dosya_tanimlayicisi tarafından belirtilmi ş bulunan dosyaya sayi kadar bayt yazmak isterseniz s = _write(dosya_tanimlayicisi, tampon, sayi) kullanın. Yazmayı dü şündü ğünüz baytları, tampon ile ba şlayan bölgeye daha önceden yerle ştirmi ş olmanız gerekir. s’ye ya -1 (hatayı göstermek için) veya gerçekte yazılmı ş bulunan bayt sayısı konur. _write i şleminden sonra e ğer s!=sayi ise bir hata olmu ş demektir; fonksiyonu kullandıktan sonra bu testi yapmayı unutmayın. s = _read(dosya_tanimlayicisi, tampon, sayi) ifadesi dosya_tanimlayicisi ile belirtilen dosyanın okunup tampon ile ba şlayan bölgeye baytların konulmasını sa ğlar. Dosya sonuna ula şıldı ğında okuma biter. Her durumda en fazla sayi kadar bayt okunur. s okunmu ş bulunan bayt sayısını veya okuma yapılamazsa -1 içerecektir. fseek’in dosya tanımlayıcısı kar şılı ğı _lseek’tir. uzun_yeni_yer = _lseek(dosya_tanimlayicisi, uzun_sayi, nereden) 128 DOSYALAR VE G İRD İ/ÇIKTI BÖLÜM 7 ça ğrısında son iki argüman fseek’te oldu ğu gibi aynı anlam ta şırlar ve aynı i ş yapılmı ş olur. _lseek, dosyanın ba şından şimdiki konuma kadar olan uzaklı ğı bayt cinsinden döndürür. 7.7. Bir Örnek—Ö ğrenci Veritabanı Ö ğrenci kayıtlarını tutup bunlar üzerinde ekleme, silme ve görüntüleme i şlemlerini yapan bir program yazalım. Program kullanıcıya bir menü sunacak ve kullanıcının seçimine göre ilgili seçene ği çalı ştıracaktır. C’nin bu tür uygulama için en uygun dil oldu ğunu veya bunun en iyi ve kısa program oldu ğunu savunmuyoruz; amacımız sadece, bu bölümde anlatılmı ş olan C ile ilgili bazı konuları göstermektir. Programın listesinden sonra, kodun detaylı bir açıklaması verilmektedir. Devam etmeden önce, programı bilgisayara girip çalı ştırmanız önerilir. 1. #include 2. #include 3. #include 4. #include 5. 6. /* Degismezler */ 7. char const DOSYA_ADI[] = "OGRENCI.DAT"; 8. char const BOS[] = "\r\r\r\r\r\r\r"; 9. #define ANHTR_UZ 7 10. char const AKD[] = "%7s"; 11. #define ISIM_UZ 15 12. #define KAYIT_BOYU ((long)(ANHTR_UZ+ISIM_UZ+4)) 13. char const KKD[] = "%7s%15s%4d"; 14. 15. struct kayit { 16. char anhtr[ANHTR_UZ+1], isim[ISIM_UZ+1]; 17. int yil; 18. }; 19. 20. /* Her fonksiyonda bastan tanimlamak yerine bu 21. * degiskenler burada tanimlanmislardir. 22. */ 23. char satir[128]; 24. FILE *dg; 25. 26. void dizioku /* d icine en fazla u karakter oku */ 27. (char d[], int u) 28. { 29. gets(satir); 30. strncpy(d, satir, u); 31. d[u] = '\0'; 32. } /* dizioku */ 33. 34. long bul /* Dosya icindeki ANHTR'in yerini; */ 35. (char const anhtr[]) /* aksi takdirde -1L dondur. */ 36. { 37. int drm, kar = 1; 38. long dns; 39. char d1[ANHTR_UZ+1], d2[ANHTR_UZ+1]; 40. BÖLÜM 7 DOSYALAR VE G İRD İ/ÇIKTI 129 41. sprintf(d2, AKD, anhtr); /* soldan bosluk doldur */ 42. dg = fopen(DOSYA_ADI, "rb"); 43. if (dg == NULL) 44. return -1L; 45. drm = fseek(dg, -KAYIT_BOYU, SEEK_END); 46. while (drm == 0 && fgets(d1, ANHTR_UZ+1, dg) != NULL && 47. (kar=strcmp(d2,d1)) != 0) 48. drm = fseek(dg, -KAYIT_BOYU-ANHTR_UZ, SEEK_CUR); 49. if (kar == 0) 50. dns = ftell(dg)-ANHTR_UZ; 51. else 52. dns = -1L; 53. fclose(dg); 54. return dns; 55. } /* bul */ 56. 57. void ekleme (void) 58. { 59. long konum; 60. struct kayit k; 61. int scd; 62. 63. puts("Eklenecek ogrenci numarasini girin:"); 64. dizioku(k.anhtr, ANHTR_UZ); 65. if (bul(k.anhtr) == -1L) { 66. puts("Ogrenci adini girin:"); 67. dizioku(k.isim, ISIM_UZ); 68. do { 69. puts("Kayit yilini girin:"); 70. scd = scanf("%d", &k.yil); 71. gets(satir); 72. } while (1!=scd || k.yil<1980 || k.yil>9999); 73. konum = bul(BOS); 74. dg = fopen(DOSYA_ADI, "ab"); /* dosyayi olustur */ 75. fclose(dg); 76. dg = fopen(DOSYA_ADI, "r+b"); 77. if (konum == -1L) 78. fseek(dg, 0L, SEEK_END); /* dosya sonuna git */ 79. else 80. fseek(dg, konum, SEEK_SET); /* bos kayida git */ 81. fprintf(dg, KKD, k.anhtr, k.isim, k.yil); 82. fclose(dg); 83. puts("Ekleme islemi tamamlandi."); 84. } 85. else 86. fprintf(stderr, "Cift anahtar!\n\a"); 87. } /* ekleme */ 88. 89. void silme (void) 90. { 91. long konum; 92. char anhtr[ANHTR_UZ+1]; 93. 130 DOSYALAR VE G İRD İ/ÇIKTI BÖLÜM 7 94. puts("Silinecek ogrenci numarasini girin:"); 95. dizioku(anhtr, ANHTR_UZ); 96. if ((konum = bul(anhtr)) != -1L) { 97. dg = fopen(DOSYA_ADI, "r+b"); 98. fseek(dg, konum, SEEK_SET); 99. fprintf(dg, AKD, BOS); 100. fclose(dg); 101. puts("Silme islemi tamamlandi."); 102. } 103. else 104. fprintf(stderr, "Boyle anahtar yok!\n\a"); 105. } /* silme */ 106. 107. void goruntuleme (void) 108. { 109. long konum; 110. struct kayit k; 111. 112. puts("Goruntulenecek ogrenci numarasini girin:"); 113. dizioku(k.anhtr, ANHTR_UZ); 114. if ((konum = bul(k.anhtr)) != -1L) { 115. dg = fopen(DOSYA_ADI, "rb"); 116. fseek(dg, konum+ANHTR_UZ, SEEK_SET); 117. printf("Ogrenci adi: %s\n", fgets(k.isim,ISIM_UZ+1,dg)); 118. fscanf(dg, "%d", &k.yil); 119. fclose(dg); 120. printf("Kayit yili : %d\n", k.yil); 121. } 122. else 123. fprintf(stderr, "Boyle anahtar yok!\n\a"); 124. } /* goruntuleme */ 125. 126. int menu (void) 127. { 128. int secenek; 129. 130. do { 131. puts("\n\t1.EKLEME\n\t2.SILME\n\t3.GORUNTULEME\n\t0.CIKIS"); 132. printf("Seciminizi yapin:"); 133. } while ((secenek=_getche()) < '0' || secenek > '3'); 134. putchar('\n'); 135. return secenek - '0'; 136. } /* menu */ 137. 138. void main (void) 139. { 140. static void (*fd[])(void) = 141. { (void (*)(void)) exit, ekleme, silme, goruntuleme }; 142. 143. while (1) (*fd[menu()])(); 144. } /* main */ Programda, her ö ğrenci için bir sayı, isim ve kayıt yılı saklanır. Bu bilgiyi birle ştirmek için Satır 15’te kayit yapısı tanımlanmı ştır. Ö ğrenci numarası “anahtar”dır, yani her ö ğrencinin ayrı numarası vardır ve ö ğrencinin bilgisine ula şmak için bu numarayı kullanırız. menu fonksiyonu (Satır 126-136) kullanıcıya seçimleri sunar ve neyi seçti ğini gösteren bir sayı (aslında bir char) girmesini ister. 0’dan küçük veya 3’ten büyük BÖLÜM 7 DOSYALAR VE G İRD İ/ÇIKTI 13 1 seçimler kabul edilmez. Geçerli bir seçenek girildi ğinde, fonksiyon tarafından secenek de ği şkeninin tamsayı e şde ğeri döndürülür. Bu fonksiyonda puts kullanımına dikkat edin. Herhangi bir de ği şkenin de ğerinin basılmasına gerek olmadı ğından, printf kullanmanıza gerek yoktur. Programda, böyle durumlar için puts kullandık. main’deki while deyimi biraz karma şık gözükebilir. Satır 140-141’de exit, ekleme, silme ve goruntuleme fonksiyonlarına göstergeler içerecek şekilde ilklenmi ş bulunan, fd dizisinin menu’ncü elemanını ça ğırır. Gördü ğünüz gibi, fonksiyonlara göstergeler için bir dizi gibi, karma şık veri yapılarının kullanımı küçük bir yerde çok şey yapabilecek kod yazmamızı sa ğlar. Dikkat: stdlib.h’de tanımlanmı ş olan exit fonksiyonu bir int argüman beklemektedir; di ğer fonksiyonlara uyması için, bir kalıp aracılı ğı ile, bu fonksiyonu argümansız hale çevirdik. ekleme, silme ve goruntuleme fonksiyonları, argüman olarak verilmi ş anahtarı içeren kaydı taramak için bul adı verilen bir fonksiyonu ça ğırırlar. bul (Satır 34-55) kaydın dosyanın ba şına göre konumunu bir long sayı şeklinde verir; herhangi bir hata olursa -1L döndürür. bul’un ba şındaki sprintf, anhtr’ın sa ğa dayanmı ş bir uyarlamasını d2’ye koyar. Daha sonra, ö ğrenci dosyasını okumak için dosyayı açmaya çalı şırız. E ğer açılamazsa, hata döndürülür. E ğer dosya açılırsa, dosyadaki son kaydın ba şına konumlanırız. Satır 46-48’deki while şu anda konumlandırılan kaydın anahtarını d2 ile kar şıla ştırır ve e ğer e şitseler veya dosyanın ba şına ula ştıysak, sona erer. Satır 48 dosyayı bir önceki kaydın ba şına konumlandırır. Dosya taramasını geriye do ğru yapmamızın nedeni, fseek fonksiyonunun, dosyanın sonundan ileri do ğru gitmeyi bir hata şeklinde de ğerlendirmemesinden kaynaklanır. Satır 53’te dosyayı kapattıktan sonra, bul’un sonunda, (Satır 50’de ftell kullanılarak uygun de ğer verilen) dns döndürülür. Üç “büyük” fonksiyon tarafından çokça kullanılan ba şka bir fonksiyon da dizioku’dur. Bu “kolaylık” fonksiyonu iki argüman kabul eder: İçine bir şey okunacak karakter dizisi ile okunacak dizinin uzunlu ğunu gösteren bir tamsayı. Ba ştaki gets girdiden bir satır okur. Geri kalan deyimler, gerekli sayıda karakteri d’ye aktarıp sonuna bir bo ş karakter koyarlar. ekleme fonksiyonu dosyaya yeni bir ö ğrenci kaydı yerle ştirmeye çalı şır. Yeni ö ğrencinin numarasını okur ve bu anahtarla bul’u ça ğırır. E ğer bul -1L’den farklı bir şey döndürürse, dosya içinde bu numaradan bir ö ğrenci kaydı vardır demektir, onun için ekleme uygun bir uyarı mesajı ile sona erer. E ğer bu numara dosyada yeni ise, ö ğrencinin ismi ve kayıt yılı sorulur. Yıl için dört rakamlı bir sayı girinceye kadar devam etmeyi engelleyen do deyimine dikkat ediniz. scanf’in gerçekle ştirilen ba şarılı dönü şüm sayısını döndürdü ğünü anımsayın. Ö ğrenci hakkında bütün bilgileri elde etti ğimize göre, onu dosyaya yazmamız gerekir. Satır 73’te BOS anahtarı içeren bir kayıt ararız. BOS, bir ö ğrenci numarası olarak, kullanıcı ne kadar çalı şırsa çalı şsın, giremeyece ği özel bir karakter dizisidir. (Satır 8’deki BOS’un tanımına bakıp bunun neden böyle oldu ğunu söyleyiniz.) BOS anahtarı daha önce eklenmi ş, fakat sonra silinmi ş kayıtları gösterir. Satır 74-75, dosya yoksa, yeni bir dosya açar; aksi takdirde bir de ği şiklik yapmaz. Satır 76, okuma-yazma eri şimi için dosyayı 132 DOSYALAR VE G İRD İ/ÇIKTI BÖLÜM 7 açar. E ğer BOS bir kayıt yoksa, yeni kayıt dosyanın sonuna eklenir (Satır 78). Aksi takdirde, adresi konum içinde bulunan BOS kayda yazılır (Satır 80). Asıl yazma i şlemi Satır 81’de fprintf ile yapılır. Dosyayı kapattıktan sonra ekleme sona erer. silme silinecek ö ğrenci numarasını okuyarak ba şlar. Böyle bir ö ğrencinin dosya içinde olup olmadı ğını ara ştırmak için bul ça ğrılır. E ğer kayıt varsa, anahtarına BOS yazılır ve silme biter. E ğer yoksa, dönmeden önce, uygun bir hata mesajı basılır. Hata mesajlarının stderr’e gönderildi ğinde dikkat edin. goruntuleme, ö ğrenci numarasını okur ve silme’ye benzer bir şekilde kaydın bulunup bulunmadı ğını kontrol eder. Kayıt bulunursa, anahtar dı şındaki bilgiler görüntülenir. Problemler 1. stdio.h dosyasında getc() ve putc()’nin tanımlarına bakıp ne oldu ğunu açıklamaya çalı şın. 2. Kısım 7.7’deki örnek programa degistirme adında yeni bir seçenek ekleyin. Seçildi ğinde, ö ğrenci numarası okunur ve ö ğrencinin şu anki bilgileri görüntülenir. Kullanıcı, isterse, anahtar dı şındaki bilgileri de ği ştirebilir ve yeni bilgiler eski bilgilerin yerini dosyada alır. Varlık testleri ve uygun hata mesajları bulunmalıdır. 3. Sözdizimsel açıdan do ğru olan bir C programından bütün açıklama ve görünmeyen gereksiz karakterleri çıkaran bir program yazın. 4. Komut satırında argüman olarak verilen dosyaları birle ştirip stdout’a yazan (ve UNIX komutu cat’e benzeyen) bir program yazın. 5. Büyük bir dosyayı birkaç küçük dosyaya ayıran bir program yazın. İlk argüman dosya adını; ikincisi (e ğer verilmezse 1000 varsayılacak) parça ba şına satır sayısını gösterir. Parçaların dosya isimleri parca.1, parca.2 vs olacaktır. 6. Argüman olarak verilen iki dosyayı kar şıla ştırıp farklı olan baytları sekizli gösterimde görüntüleyecek (ve UNIX komutu cmp’e benzeyen) bir program yazın. 7. Bir satır editörü yazın. Çalı şma dosyasının adı komut satırı argümanı olarak verilecektir. Program a şa ğıdaki komutların herhangi birini girdi olarak kabul edebilecektir: E numara Bu komuttan sonra, standart girdiden bir satır okunup numara’ıncı satırdan önce yerle ştirilir. S numara Numara’ıncı satır silinir. G numara BÖLÜM 7 DOSYALAR VE G İRD İ/ÇIKTI 133 Numara’ıncı satır görüntülenir. C Program sona erer. 8. Bir metin dosyasındaki satırları tersten basacak bir program yazın; yani son satır ilk olarak basılacak vs. Dosya boyuna herhangi bir sınırlama getirmeyin. 9. Ekranı temizleyen bir fonksiyon yazın. 10. Sözdizimsel açıdan do ğru ve tam olan bir C programını içeren bir dosyayı alıp, aynı programı daha iyi bir biçimde ba şka bir dosyaya yazan bir program hazırlayın. “Daha iyi bir biçim” derken, şunu anlatmak istiyoruz: Bütün fonksiyon ba şlıkları aynı sütunda ba şlar ve ba şka deyimlerin parçaları olan blokların sol ve sa ğ çengelli parantezlerin yeri Bölüm 2’de önerilen şekildedir. 11. Metin okuyup a şa ğıdaki şekilde biçimlendirilmi ş olarak bir dosyaya koyan bir program yazın: Solda 7 karakterlik bo şluk bulunur, doküman her biri 55 satır olan sayfalardan olu şur, her satır en fazla 65 karakterdir, her sayfanın son satırında sayfa numarası bulunur ve noktadan sonra gelen ilk harf büyü ğe dönü ştürülür. Program, tek bir yeni satır ('\n') karakterini bo şlu ğa çevirecek; arka arkaya iki tane yeni satır karakteri varsa, bunlar paragraf sonu olarak de ğerlendirilecek ve aynen bırakılacaktır. Gereksinimlerinize göre programı geli ştirin. (Bazı biçimleme komutları ekleyin: Örne ğin, özel bir karakterle ba şlayan satırlar emir olarak de ğerlendirilebilir.) 135 EK A: KARAKTER KODLARI Ç İZELGES İ Bizim kullandı ğımız sistemde oldu ğu gibi, birçok sistemde karakterleri göstermek için ASCII (American Standard Code for Information Interchange—Bilgi De ği şimi için Standart Amerikan Kodu) karakter kodları kullanılır. ASCII karakter kümesi 128 tane (7 bitlik) koddan olu şur ve 33 kontrol karakteri, bir bo şluk ve 94 görüntülenebilen (grafik) karakteri tanımlar. Bir kontrol karakteri çıktı aygıtında de ği şik etkilere neden olabildi ği gibi, bazen grafik bir şekil de olu şturabilir. Bir karakterlik bilginin saklanması için 8 bitlik baytların kullanıldı ğı makineler genelde 128 tane daha karakter içeren “geni şletilmi ş” bir karakter kümesi sa ğlarlar. Bu karakterlerin kodları 128’den 255’e kadardır ve aygıttan aygıta veya sistemden sisteme de ği şebilir. Bundan sonraki dört sayfa, standart ASCII karakter kümesinin bir listesini vermektedir. Bu listede kontrol karakterleri ^tu ş şeklinde gösterilirler; bu da CONTROL tu şu basılı iken tu şa basarak bu karakterin elde edilebilece ği anlamına gelmektedir. IBM uyumlu ki şisel bilgisayarlarda (PC’lerde) ALT tu şu basılı iken klavyenin sa ğındaki sayısal tu şlar kullanılarak girilecek olan ASCII ondalık kod aracılı ğıyla ilgili karakter olu şturulabilir. Örne ğin, ‘A’ harfini elde etmek için ALT tu şu basılı iken, sırayla önce 6’ya sonra da 5’e basın. Daha sonraki dört sayfada ise 128’den 255’e kadar kodlara sahip olan karakterler için PC’lerde kullanılan iki ayrı karakter standardı gösterilmi ştir: • ASCII (geni şletilmi ş): Bu, daha çok MS-DOS ortamında kullanılmaktadır. MS-DOS ortamında, bu karakterlerin klavyeden girilmesi için ALT tu şu basılı iken klavyenin sa ğındaki sayısal tu şlar kullanılarak, ilgili karakterin ondalık kodu girilmelidir. Örne ğin, ‘Ç’ için ALT+128. Windows ortamında da kullanılan yöntem aynıdır, ancak bu i şlemi yaparken NUM LOCK ı şı ğının yakılı olması gerekmektedir. 136 KARAKTER KODLARI Ç İZELGES İ EK A • ANSI: Windows ortamında kullanılmaktadır. Bu karakterlerin klavyeden girilmesi için yukarıdaki yöntem kullanılır; sadece girilen kodun ANSI oldu ğunu belirtmek için kodun önüne ‘0’ eklenir. Örne ğin, ‘Ç’ için ALT+0199. Türkçe karakterler için en az üç ayrı standart bulunmaktadır. Herbirinde, belirli karakter kodları için, uluslararası tanımlanmı ş karakterin yerini Türkçe karakter almaktadır. Bunlar, listede, yerini aldıkları karakterlerin yanında, parantez içinde verilmi ştir. • 7 bitlik ASCII standardı: Bu sadece 128 de ği şik karakter kodunu destekleyen aygıtlarda kullanılmaktadır. Günümüzde 256 de ği şik karakter kullanan PC’lerin yaygınla şmasıyla, bu standart daha az kullanılmaya ba şlanmı ştır. • 8 bitlik geni şletilmi ş ASCII standardı: Genelde MS-DOS ortamında kullanılmaktadır. • 8 bitlik ANSI standardı: Windows gibi grafik ortamlarda kullanılmaktadır. EK A KARAKTER KODLARI Ç İZELGESİ1 37 Ond. Sekizli Onaltılı Karakter Anlamı 0 0000 0x00 ^@ NUL Bo ş—zaman doldurmak için kull. tamamı sıfır karakter 1 0001 0x01 ^A SOH Ba şlık ba şı 2 0002 0x02 ^B STX Metin ba şı 3 0003 0x03 ^C ETX Metin sonu 4 0004 0x04 ^D EOT İletim sonu 5 0005 0x05 ^E ENQ Sorgu—“Kimsiniz?” 6 0006 0x06 ^F ACK Olumlu yanıt—“Evet” 7 0007 0x07 ^G BEL Zil— İnsan dikkati gerekiyor 8 0010 0x08 ^H BS Geriye alma (biçim etkileyicisi) 9 0011 0x09 ^I HT Yatay durak (biçim etkileyicisi) 10 0012 0x0A ^J LF Satır ilerletme (biçim etkileyicisi) 11 0013 0x0B ^K VT Dikey durak (biçim etkileyicisi) 12 0014 0x0C ^L FF Sayfa ilerletme (biçim etkileyicisi) 13 0015 0x0D ^M CR Satırba şı (biçim etkileyicisi) 14 0016 0x0E ^N SO Dı şarı kayma—standart olmayan kod geliyor 15 0017 0x0F ^O SI İçeri kayma—standart koda geri dönü ş 16 0020 0x10 ^P DLE Veri ba ğl. kaçı şı—sınırlı veri ileti şimi kontr. de ği şikli ği 17 0021 0x11 ^Q DC1 Yardımcı aygıtları açıp kapamak için aygıt kontrolü 18 0022 0x12 ^R DC2 Yardımcı aygıtları açıp kapamak için aygıt kontrolü 19 0023 0x13 ^S DC3 Yardımcı aygıtları açıp kapamak için aygıt kontrolü 20 0024 0x14 ^T DC4 Yardımcı aygıtları açıp kapamak için aygıt kontrolü 21 0025 0x15 ^U NAK Olumsuz yanıt—“Hayır” 22 0026 0x16 ^V SYN E şzamanlı bo şa i şleme—e şzamanlama sa ğlamak için 23 0027 0x17 ^W ETB İletim öbe ği sonu—fiziksel ileti şim öbekleri ile ilintili 24 0030 0x18 ^X CAN Önceki bilginin iptali 25 0031 0x19 ^Y EM Ortam sonu—kullanılan/istenen bilgi bölümünün sonu 26 0032 0x1A ^Z SUB Hatalı karakterin yerine gelen karakter 27 0033 0x1B ^[ ESC Kaçı ş—kod geni şlemesi için 28 0034 0x1C ^\ FS Dosya ayırıcısı 29 0035 0x1D ^] GS Grup ayırıcısı 30 0036 0x1E ^^ RS Kayıt ayırıcısı 31 0037 0x1F ^_ US Birim ayırıcısı 138 KARAKTER KODLARI Ç İZELGES İ EK A Ond. Sekizli Onaltılı Karakter Anlamı 32 0040 0x20 BOSLUK Basılmayan karakter—sözcük ayırıcısı 33 0041 0x21 ! Ünlem i şareti 34 0042 0x22 " (Çift) tırnak i şareti 35 0043 0x23 #( Ğ) Sayı i şareti 36 0044 0x24 $ Dolar 37 0045 0x25 % Yüzde 38 0046 0x26 & Ve i şareti 39 0047 0x27 ' Kesme i şareti (tek tırnak) 40 0050 0x28 ( Sol parantez 41 0051 0x29 ) Sa ğ parantez 42 0052 0x2A * Yıldız 43 0053 0x2B + Artı 44 0054 0x2C , Virgül 45 0055 0x2D - Çizgi i şareti 46 0056 0x2E . Nokta 47 0057 0x2F / Bölü 48 0060 0x30 0 49 0061 0x31 1 50 0062 0x32 2 51 0063 0x33 3 52 0064 0x34 4 53 0065 0x35 5 54 0066 0x36 6 55 0067 0x37 7 56 0070 0x38 8 57 0071 0x39 9 58 0072 0x3A : İki nokta 59 0073 0x3B ; Noktalı virgül 60 0074 0x3C < Küçüktür 61 0075 0x3D = E şittir 62 0076 0x3E > Büyüktür 63 0077 0x3F ? Soru i şareti EK A KARAKTER KODLARI Ç İZELGESİ1 39 Ond. Sekizli Onaltılı Karakter Anlamı 64 0100 0x40 @(Ç) -de i şareti 65 0101 0x41 A 66 0102 0x42 B 67 0103 0x43 C 68 0104 0x44 D 69 0105 0x45 E 70 0106 0x46 F 71 0107 0x47 G 72 0110 0x48 H 73 0111 0x49 I 74 0112 0x4A J 75 0113 0x4B K 76 0114 0x4C L 77 0115 0x4D M 78 0116 0x4E N 79 0117 0x4F O 80 0120 0x50 P 81 0121 0x51 Q 82 0122 0x52 R 83 0123 0x53 S 84 0124 0x54 T 85 0125 0x55 U 86 0126 0x56 V 87 0127 0x57 W 88 0130 0x58 X 89 0131 0x59 Y 90 0132 0x5A Z 91 0133 0x5B [( Ş) Sol kö şeli parantez 92 0134 0x5C \( İ) Ters bölü 93 0135 0x5D ](Ö) Sa ğ kö şeli parantez 94 0136 0x5E ^(Ü) Uzatma i şareti 95 0137 0x5F _ Alt çizgi 140 KARAKTER KODLARI Ç İZELGES İ EK A Ond. Sekizli Onaltılı Karakter Anlamı 96 0140 0x60 `(ç) A ğır vurgu 97 0141 0x61 a 98 0142 0x62 b 99 0143 0x63 c 100 0144 0x64 d 101 0145 0x65 e 102 0146 0x66 f 103 0147 0x67 g 104 0150 0x68 h 105 0151 0x69 i 106 0152 0x6A j 107 0153 0x6B k 108 0154 0x6C l 109 0155 0x6D m 110 0156 0x6E n 111 0157 0x6F o 112 0160 0x70 p 113 0161 0x71 q( ğ) 114 0162 0x72 r 115 0163 0x73 s 116 0164 0x74 t 117 0165 0x75 u 118 0166 0x76 v 119 0167 0x77 w 120 0170 0x78 x 121 0171 0x79 y 122 0172 0x7A z 123 0173 0x7B {( ş) Sol çengelli parantez 124 0174 0x7C |(ı) Dikey çizgi 125 0175 0x7D }(ö) Sa ğ çengelli parantez 126 0176 0x7E ~(ü) İnceltme i şareti 127 0177 0x7F DEL Ortam doldurma EK A KARAKTER KODLARI Ç İZELGESİ1 4 1 Ond. Sekizli Onaltılı ASCII karakter ANSI karakter 128 0200 0x80 Ç € 129 0201 0x81 ü 130 0202 0x82 é ‚ 131 0203 0x83 â ƒ 132 0204 0x84 ä „ 133 0205 0x85 à … 134 0206 0x86 å † 135 0207 0x87 ç ‡ 136 0210 0x88 ê ˆ 137 0211 0x89 ë ‰ 138 0212 0x8A è Š 139 0213 0x8B ï ‹ 140 0214 0x8C î Œ 141 0215 0x8D ì(ı) 142 0216 0x8E Ä 143 0217 0x8F Å 144 0220 0x90 É 145 0221 0x91 æ ‘ 146 0222 0x92 Æ ’ 147 0223 0x93 ô “ 148 0224 0x94 ö ” 149 0225 0x95 ò • 150 0226 0x96 û – 151 0227 0x97 ù — 152 0230 0x98 ÿ( İ)˜ 153 0231 0x99 Ö ™ 154 0232 0x9A Ü š 155 0233 0x9B ¢ › 156 0234 0x9C £ œ 157 0235 0x9D ¥ 158 0236 0x9E ?( Ş) 159 0237 0x9F ƒ( ş)Ÿ 142 KARAKTER KODLARI Ç İZELGES İ EK A Ond. Sekizli Onaltılı ASCII karakter ANSI karakter 160 0240 0xA0 á 161 0241 0xA1 í ¡ 162 0242 0xA2 ó ¢ 163 0243 0xA3 ú £ 164 0244 0xA4 ñ ¤ 165 0245 0xA5 Ñ ¥ 166 0246 0xA6 ª( Ğ)¦ 167 0247 0xA7 °( ğ)§ 168 0250 0xA8 ¿ ¨ 169 0251 0xA9 ? © 170 0252 0xAA ¬ ª 171 0253 0xAB ½ « 172 0254 0xAC ¼ ¬ 173 0255 0xAD ¡ - 174 0256 0xAE « ® 175 0257 0xAF » ¯ 176 0260 0xB0 - ° 177 0261 0xB1 - ± 178 0262 0xB2 - ² 179 0263 0xB3 - ³ 180 0264 0xB4 + ´ 181 0265 0xB5 ? µ 182 0266 0xB6 ? ¶ 183 0267 0xB7 ? · 184 0270 0xB8 ? ¸ 185 0271 0xB9 ¦ ¹ 186 0272 0xBA ¦ º 187 0273 0xBB ¬ » 188 0274 0xBC - ¼ 189 0275 0xBD ? ½ 190 0276 0xBE ? ¾ 191 0277 0xBF ¬ ¿ EK A KARAKTER KODLARI Ç İZELGESİ1 43 Ond. Sekizli Onaltılı ASCII karakter ANSI karakter 192 0300 0xC0 L À 193 0301 0xC1 + Á 194 0302 0xC2 T  195 0303 0xC3 + à 196 0304 0xC4 ¦Ä 197 0305 0xC5 + Å 198 0306 0xC6 ? Æ 199 0307 0xC7 ? Ç 200 0310 0xC8 L È 201 0311 0xC9 - É 202 0312 0xCA ¦ Ê 203 0313 0xCB T Ë 204 0314 0xCC ¦ Ì 205 0315 0xCD = Í 206 0316 0xCE + Î 207 0317 0xCF ? Ï 208 0320 0xD0 ? ?( Ğ) 209 0321 0xD1 ? Ñ 210 0322 0xD2 ? Ò 211 0323 0xD3 ? Ó 212 0324 0xD4 ? Ô 213 0325 0xD5 ? Õ 214 0326 0xD6 ? Ö 215 0327 0xD7 ? × 216 0330 0xD8 ? Ø 217 0331 0xD9 - Ù 218 0332 0xDA - Ú 219 0333 0xDB - Û 220 0334 0xDC - Ü 221 0335 0xDD ? Y( İ) 222 0336 0xDE ? ?( Ş) 223 0337 0xDF - ß 144 KARAKTER KODLARI Ç İZELGES İ EK A Ond. Sekizli Onaltılı ASCII karakter ANSI karakter 224 0340 0xE0 ? à 225 0341 0xE1 ß á 226 0342 0xE2 ? â 227 0343 0xE3 ? ã 228 0344 0xE4 ? ä 229 0345 0xE5 ? å 230 0346 0xE6 µ æ 231 0347 0xE7 ? ç 232 0350 0xE8 ? è 233 0351 0xE9 ? é 234 0352 0xEA ? ê 235 0353 0xEB ? ë 236 0354 0xEC ? ì 237 0355 0xED Ø í 238 0356 0xEE ? î 239 0357 0xEF ? ï 240 0360 0xF0 ? ?( ğ) 241 0361 0xF1 ± ñ 242 0362 0xF2 ? ò 243 0363 0xF3 ? ó 244 0364 0xF4 ? ô 245 0365 0xF5 ? õ 246 0366 0xF6 ÷ ö 247 0367 0xF7 ? ÷ 248 0370 0xF8 ° ø 249 0371 0xF9 ? ù 250 0372 0xFA ? ú 251 0373 0xFB ? û 252 0374 0xFC ? ü 253 0375 0xFD ² y(ı) 254 0376 0xFE • ?( ş) 25503770xFF ÿ 145 EK B: MICROSOFT C DERLEY İC İS İ HAKKINDA TEMEL B İLG İLER Bu ekte, Microsoft C derleyicileri hakkında bazı bilgiler verilecektir. Bir C programının Microsoft C Eniyile ştirici Derleyicisi kullanılarak nasıl derlenece ğine geçmeden önce, C bellek modellerini bilmek ve anlamak gerekir. B. 1. Bellek Modelleri 80x88 ve 80x86 i şlemcilerinin yapısından dolayı, bir bellek adresi 16 bitlik kesim adresi ile kesim içinde 16 bitlik bir uzaklıktan olu şur. Böyle bir adres normalde kesim:uzaklık (segment:offset) şeklinde gösterilir. Verimlilik açısından, bir programın aynı kesim içinde kalan adresler üretmesi daha iyidir, çünkü adresleme sadece uzaklık olu şturularak sa ğlanabilir. Sadece uzaklık bölümünden olu şan bir adrese yakın adres adı verilir. Bazen, program, ba şka kesimlerde bulunan nesneleri adreslemek durumunda kalabilir; böyle adreslere uzak adres adı verilir. Uzak bir adres 32 bittir ve kesim temel adresi ile uzaklıktan olu şur. Bir kesimden, yani 64 Kbayttan daha büyük olan bir veri yapısı, örne ğin bir dizi, uzak adres kullanılarak adreslenemez. Bu amaç için, dev adres adı verilen ba şka bir adres tipi kullanılır. Dev adreslerin uzak adreslerden farkı göstergelerde ortaya çıkar; uzak adreslerde göstergeler 16 bit olmalarına ra ğmen, dev adreslerde 32 bittir. Bir C programı derlendikten sonra, en az bir veri kesimi ve bir kod kesiminden olu şur. Bu, olası en küçük C programı için bile geçerlidir. Büyük C programları birkaç veri kesimi, yani çok fazla ve büyük veri yapıları ve/veya birkaç kod kesimi, yani birçok yürütülebilir deyim şeklinde olu şabilirler. Büyük programların do ğru bir şekilde derlenip 146 MICROSOFT C DERLEY İC İS İ HAKKINDA TEMEL B İLG İLER EK B yürütülebilmeleri için, Microsoft C’ye bellek modelleri konmu ştur. A şa ğıdaki çizelge bellek modelleri arasındaki farkları göstermektedir: Kod Kesimi Veri Kesimi Kullanılan Model Sayısı Sayısı Kütüphane minik (tiny) kod ile veri toplam 1 kesim SLIBCE.LIB küçük (small) 1 1 SLIBCE.LIB kısa (compact) 1 çok CLIBCE.LIB orta (medium) çok 1 MLIBCE.LIB büyük (large) çok çok LLIBCE.LIB dev (huge) çok çok LLIBCE.LIB Microsoft C Eniyile ştirici Derleyicisi (MS-CL) için varsayılan model küçük olandır; Microsoft QuickC (MS-QC) ise her zaman orta modelde çalı şır. B. 1. QC Kütüphanesi MS-QC derleyici ortamı içinde bulunan fonksiyonlar çekirdek kütüphaneyi olu ştururlar; ancak QuickC çekirdek kütüphanesi Standart C kütüphanesi içindeki bütün fonksiyonları içermez. Örne ğin, rand standart fonksiyonu QC ile birlikte yüklenmez. Bu fonksiyonu ça ğıran bir program çalı ştırmaya kalkarsanız, “çözümlenmemi ş dı şsal referans” şeklinde bir hata mesajı alırsınız. Bir amaç dosya olu şturmanız ve daha sonra yürütülebilir bir dosya elde etmek için bunu LINK ile ba ğlamanız gerekecektir. Programınızı her de ği ştirdi ğinizde, bunu yapmaktan kurtulmak için, bir QuickC kütüphanesi olu şturmanız ve QC’yi çalı ştırdı ğınızda bu kütüphaneyi de yüklemeniz gerekir. Bunu yapmak için a şa ğıdaki yöntemi kullanın: • Gerekti ği kadar dı şsal referans yapan, örne ğin ql.c adında, bir program yazın. Derleme esnasındaki uyarı mesajlarını dikkate almayın. Örne ğin: #include void main (void) { rand(); srand(); bsearch(); qsort(); } • QC’yi kullanarak bir amaç dosya, örne ğin ql.obj, olu şturun. • Bu dosyayı MS-QC tarafından sa ğlanan QUICKLIB.OBJ adlı amaç modülle beraber ba ğlayıp bir Quick kütüphane olu şturun. Örne ğin: LINK /Q QUICKLIB.OBJ+ql.obj,ql.qlb; • QC’yi çalı ştırırken bu kütüphaneyi belirtin. Örne ğin: QC /l ql EK B MICROSOFT C DERLEY İC İS İ HAKKINDA TEMEL B İLG İLER 147 Dikkat: QC kütüphanelerinin içerilmesi QC çalı şırken bellek-içi derleme için ayrılmı ş bulunan serbest bellek miktarının azalmasına yol açar. En iyisi, birden fazla küçük Quick kütüphane olu şturup, gerekti ği zaman bunları yüklemektir. B.3. CL Eniyile ştirici Derleyicisi Microsoft C Eniyile ştirici Derleyicisinin (MS-CL) 5.10 uyarlaması, 80x8x i şlemcileri ile MS-DOS ve OS/2 i şletim sistemleri için amaç kod üretmede kullanılan geli şmi ş bir eniyile ştirici derleyicidir. 5.10 uyarlamasının 5.00 uyarlamasından tek farkı 80386 i şlemcisi ile OS/2 i şletim sistemini desteklemesidir. Microsoft Visual C++ paketi içinde bulunan Microsoft C Eniyile ştirici Derleyicisinin 8.00 uyarlaması ise Windows ortamı ve C++ için ek olanaklar tanır. Ancak, temel olarak, CL derleyici/ba ğlayıcısının kullanımı, komut satırından birtakım seçim anahtarları ile dosya isimleri belirtilmek suretiyle CL komutunun ça ğrılması şeklindedir. Seçeneklerin bir özeti ve ça ğrı örnekleri şöyledir: C>CL /HELP CL seçeneklerinin bir özeti görüntülenir. C>CL F1.C F1.C C kaynak dosyası derlenip SLIBCE.LIB adlı varsayılan kütüphane ile ba ğlanır. F1.OBJ amaç dosyası ve F1.EXE yürütülebilir program olu şturulur. C>CL F1.C F2.C Yukarıda oldu ğu gibi, fakat ayrıca F2.C dosyası F2.OBJ içine derlenir. Yürütülebilir program F1.EXE içinde ba ğlanır. C>CL /c F1.C Derleme yapılır, ama ba ğlama yapılmaz. C>CL F1.OBJ Daha önce derlenmi ş bulunan F1.OBJ dosyası F1.EXE içine ba ğlanır. C>CL F1 Varsayılan dosya tipi .OBJ oldu ğu için, yukarıdaki ile aynı. C>CL F1.C F2.C F3.OBJ F4 F1.C ve F2.C derlenip, F1.OBJ, F2.OBJ, F3.OBJ ve F4.OBJ ba ğlandıktan sonra F1.EXE olu şturulur. C>CL *.C Bulunulan altdizin içindeki tüm C kaynak dosyaları derlenip tek bir program şeklinde ba ğlanır. C>CL * Bulunulan altdizin içindeki tüm .OBJ amaç dosyaları ba ğlanır. C>CL /Zi /Od F1.C Eniyilemenin engellendi ği ve Codeview hata düzelticisinin kullanılabilece ği şekilde F1.EXE olu şturulur. 148 MICROSOFT C DERLEY İC İS İ HAKKINDA TEMEL B İLG İLER EK B A şa ğıda derleyici seçeneklerinden bazılarının özet bir listesi bulunmaktadır: Bellek Modeli Seçenekleri /AS Küçük bellek modeli (varsayılan). /AC Kısa bellek modeli. /AM Orta bellek modeli. /AL Büyük bellek modeli. /AH Dev bellek modeli. /AT Minik bellek modeli (.COM dosyası olu şur). Eniyileme Seçenekleri /O Eniyilemeye izin ver (/Ot ile aynı). /Oa Ba şka ad vermeyi dikkate alma. /Od Eniyilemeleri engelle (varsayılan). /Oi Yapıiçi fonksiyonların kullanılmasına izin ver. /Ol Döngü eniyilemelerine izin ver. /On “Güvenilmez” eniyilemeleri engelle. /Op Duyarlık eniyilemelerine izin ver. /Or Satıriçi dönü şleri engelle. /Os Kod için eniyileme yap. /Ot Hız için eniyileme yap. /Ox En yüksek eniyileme (/Oailt /Gs). Kod Olu şturma Seçenekleri /G0 8088/8086 kodu olu ştur (varsayılan). /G1 186 kodu olu ştur. /G2 286 kodu olu ştur. /G3 386 kodu olu ştur. /Gc Pascal tarzında fonksiyon ça ğrıları olu ştur. /Gs Yı ğıt kontrolü yapma. /Gtsayı Veri boyu e şi ği. Listeleme Seçenekleri /Fadosyaadı opt MASM için girdi olarak kullanılabilecek birle ştirici dil listesi (.ASM). /Fcdosyaadı opt Birle ştirilmi ş kaynak ve birle ştirici dil listesi (.COD). /Fedosyaadı Yürütülebilir dosya adı (.EXE). /Fldosyaadı opt Amaç ve birle ştirici dil listesi (.COD). /Fmdosyaadı opt Ba ğlayıcı planı (.MAP). /Fodosyaadı Amaç dosya adı (.OBJ). /Fsdosyaadı opt Kaynak listesi (.LST). EK B MICROSOFT C DERLEY İC İS İ HAKKINDA TEMEL B İLG İLER 149 /Sl satırgeni şli ği Listenin geni şli ğini satırgeni şli ğine ayarla; varsayılan de ğer 79’dur. /Sp sayfaboyu Listede sayfa ba şına satır sayısı; varsayılan de ğer 63’tür. /Ss "altba şlık" Bir liste altba şlı ğı görüntüle. /St "başlık" Bir liste ba şlı ğı görüntüle. Öni şlemci Seçenekleri /C Açıklamaları çıkarma. /Disim=metin opt Kaynak programda “#define isim metin”e e şde ğerdir. /E Öni şlemci çıktısını stdout’a gönder. /EP Öni şlemci çıktısını stdout’a, “#line” emirleri olmadan, gönder. /Iisim #include i şlemi için ek altdizin. /P Öni şlemci çıktısını dosyaya gönder; dosya tipi .I’dir. /Uisim Önceden tanımlanmı ş makronun tanımını kaldır. /u Önceden tanımlanmı ş bütün makroların tanımını kaldır. /X “Standart yerleri” dikkate alma. Dil Seçenekleri /Za Dildeki geni şletmeleri engelle (sadece ANSI Standardını kullan). /Zd Satır numarası bilgisi. /Ze Dildeki geni şletmelere izin ver (varsayılan). /Zg Fonksiyon prototipleri olu ştur. /Zi Simgesel hata düzeltme bilgileri. /Zl .OBJ içindeki varsayılan kütüphane bilgisini kaldır. /Zpn Yapıları n-baytlık sınırlar içine paketle. /Zs Sadece sözdizim kontrolü yap. Ba ğlama Seçenekleri /Fonaltılı_sayı Yı ğıt boyu (onaltılı gösterimde bayt sayısı). /linkbağ_seç_ve_kütüp Ba ğlayıcı seçenekleri belirle. Kayan Noktalı İşlemler İçin Kod Üretme Seçenekleri /FPa Kar şılıklı matematik kodu için ça ğrılar olu ştur. /FPc 80x87 benzetme kodu için ça ğrılar olu ştur. /FPc87 80x87 kodu için ça ğrılar olu ştur. 150 MICROSOFT C DERLEY İC İS İ HAKKINDA TEMEL B İLG İLER EK B /FPi Satıriçi 80x87 benzetme kodu üret (varsayılan). /FPi87 80x87 komutları üret. Çe şitli Seçenekler /c Sadece derle, ba ğlama. /Huzunluk Dı şsal isim uzunlu ğu. /J Varsayılan karakter tipi unsigned olsun. /Tcdosya .C’si olmayan dosyayı derle. /Vkar_dizisi Uyarlama kar_dizisini ver. /Wdüzey Uyarı düzeyi (0CL /c /Zi /Od F1.C C>LINK /CO F1 veya, C>CL /Zi /Od F1.C Bu yolla F1.EXE dosyası olu şturulduktan sonra, hata düzelticisini ça ğırmak için C>CV seçenekler exedosyası argümanlar yazmak gerekir. Burada, exedosyası derlenip ba ğlanmı ş olan programı içeren dosyanın adı, argümanlar hataları düzeltilecek olan programa geçirilecek olan argümanlar ve seçenekler de Codeview seçeneklerinden olu şan bir listedir. Bu seçeneklerden en önemli birkaç tanesi şöyledir: /2 İki monitör kullan; bir tanesi hata düzelticisi çıktısı di ğeri de program çıktısı için. /B Renkli bir adaptör ve monitörde siyah/beyaz renkler kullan. /M Olsa bile, fareyi kullanma. Codeview’a girildi ğinde, seçilebilir menü maddeleri, bir görüntüleme penceresi, bir diyalog penceresi ve iste ğe ba ğlı olarak bir yazmaç içerikleri görüntüleme bölgesinden olu şan bir ekran kullanıcıya sunulur. Hatası düzeltilecek programın ilk birkaç satırı otomatik olarak görüntüleme penceresine konur. Codeview komutları fare ve/veya klavye aracılı ğıyla girilebilir. Girdilerin ço ğu için fare kullanımı kolay oldu ğu için, sadece klavye 152 MICROSOFT CODEVIEW HATA DÜZELT İC İS İNE GENEL B İR BAKI Ş EK C komutları burada anlatılmaktadır. Bazı klavye komutları tek tu şa dayanır; diyalog komutları gibi, bazılarının ise diyalog penceresinden girilmesi gerekir. A şa ğıda bazı komutların özet bir listesi verilmi ştir. PAGE UP, PAGE DOWN, oklar vs gibi düzenleme tu şları her zamanki anlamlarını ta şırlar. CONTROL+HOME Programın ilk satırını görüntüle. CONTROL+END Programın son satırını görüntüle. F1Y a r d ım. F2 Yazmaç penceresi görüntüleme anahtarı. F3 Kaynak kodu, birle ştirici kodu veya her ikisini görüntüle. F4P r o g r a m ç ıktı ekranını görüntüle. F5E ğer varsa, bir sonraki kesilme noktasına kadar, programı yürüt. F6D e ği şik pencereler arasında dola şma anahtarı. F7 İmlecin bulundu ğu yere kadar programı çalı ştır. F8 Bir izleme (trace) komutu çalı ştır. F9 Kesilme noktası (breakpoint) ver/sil. F10 Bir sonraki kaynak satırını çalı ştır (program adım [step] modu). Diyalog komutları “komut i şlenenler” şeklindedir. İşlenenler olarak her tür geçerli C ifadesi kullanılabilir. Diyalog komutlarında kullanılan di ğer i şlenenler a şa ğıda örneklerle tanıtılmaktadır: .100 100 numaralı satır. (Öndeki noktaya dikkat edin.) .X.C:100 X.C dosyasındaki 100 numaralı satır. 1000:2000 kesim:uzaklık şeklinde bir adres. Kesim iste ğe ba ğlıdır. Rakam gösterimi o andaki sayı sistemine ba ğlıdır, fakat varsayılan sistem onaltılıdır. AH BH CH DH Yazmaçların yüksek baytları. AL BL CL DL Yazmaçların dü şük baytları. AX BX CX DX 16-bit yazmaçlar. CS DS SS ES 16-bit kesim yazmaçları. SP BP IP 16-bit gösterge yazmaçları. SI DI 16-bit indis yazmaçları. EAX EBX ECX EDX 32-bit yazmaçlar. ESP EBP 32-bit gösterge yazmaçları. ESI EDI 32-bit indis yazmaçları. adr 1 adr2 Adr 1’den adr2’ye bir adres aralı ğı. BY adres Adresteki bayt. WO adres Adresteki sözcük. DW adres Adresteki çift sözcük. Sıkça kullanılan diyalog komutları, komutun genel şeklinden sonra gelen örneklerle birlikte a şa ğıda liste şeklinde verilmi ştir: EK C MICROSOFT CODEVIEW HATA DÜZELT İC İS İNE GENEL B İR BAKIŞ1 53 V .100 Satır 100’ü göster. ?ifade,biçim Belirtilen biçimde ifadenin de ğerini göster. ?A+B,d Ondalık olarak A+B’nin de ğerini göster. ?WO SP,x SP ile gösterilen sözcü ğü onaltılı gösterimde göster. XP simge Simgenin adresini göster. X* Bütün simgelerin adreslerini göster. R Bütün yazmaçları göster. MDbiçim adres Biçim seçimine göre adresten ba şlayarak 128 bayt dök. MDbiçim adr 1 adr2 Biçim seçimine göre adr 1’den adr2’ye kadar dök. Biçim seçimi şöyledir: A ASCII karakter B Bayt C Program kodu I Tamsayı (2 bayt) IU İşaretsiz tamsayı L Uzun tamsayı (4 bayt) R Kısa kayan noktalı sayı (4 bayt) RL Uzun kayan noktalı sayı (8 bayt) RT 10-baytlık kayan noktalı sayı MC adr 1 adr2 adr3 Adr 1’den adr2’ye kadar olan baytları adr3’ten ba şlayan baytlarla kar şıla ştırıp farkları göster. MS adr 1 adr2 de ğer Adres aralı ğı içinde de ğeri ara ştır. MS 100 1000 "isim" 100-1000 aralı ğı içinde “isim”i ara ştır. MS 100 1000 0A 100-1000 aralı ğı içinde onaltılı gösterimde 0A’yı ara ştır. BP adr_listesi Kesilme noktası koy. BC adr_listesi Kesilme noktasını sil. BP .29 Satır 29’a kesilme noktası koy. BC 0 8 22 0, 8 ve 22 adreslerindeki kesilme noktalarını sil. BC * Tüm kesilme noktalarını sil. BL Tüm kesilme noktalarını göster. W?ifade,biçim İfadenin de ğerini gözle ve biçimde göster. W Tüm gözetlemeleri göster. WC * Tüm gözetlemeleri sil. 155 EK D: MICROSOFT LIB VE NMAKE YARDIMCI PROGRAMLARINA GENEL B İR BAKI Ş Bu ekte iki Microsoft yardımcı programlarına kısaca göz atılacaktır. Daha kesin bilgi için kullandı ğınız paketin elkitaplarına danı şın. D. 1. LIB Yardımcı Programı LIB, amaç program kütüphaneleri olu şturmak ve bakımını yapmak için kullanılan yardımcı bir programdır. LIB’i ça ğırmak için kullanılacak komutun genel şekli şöyledir: C>LIB eskikütüphane komutlar opt ,listedosyası opt ,yenikütüphane opt Burada, eskikütüphane Yaratılacak yeni kütüphane veya de ği ştirilecek eski kütüphanenin dosya adı. komutlar LIB’e komutlar: +amaçdosya Eski kütüphaneye yeni amaç modülü ekle. +kütüphanedosyası Kütüphanedosyasındaki tüm amaç modüllerini eski kütüphaneye ekle. (Kütüphaneleri birle ştir.) -+amaçdosya Eski kütüphane içindeki amaç modülün yerine yenisini koy. 156 MICROSOFT LIB VE MAKE YARDIMCI PROGRAMLARINA GENEL B İR BAKI ŞEK D *modülismi Kütüphanedeki bir modülü (modülismi.OBJ adlı) dosyaya aktar. -*modülismi Kütüphanedeki bir modülü bir dosyaya ta şı, yani aktarıp kütüphaneden sil. listedosyası Çapraz referans için liste. yenikütüphane De ği şikliklerden sonra olu şturulan yeni kütüphanenin dosya ismi. E ğer belirtilmezse, eski kütüphanenin tipi .BAK’a dönü ştürülüp, eskikütüphane isminde saklanır. Örnekler: LIB KH1 +MOD1; MOD1.OBJ’daki amaç modülü KH1.LIB kütüphanesine ekle. LIB KH1 -+MOD1; KH1.LIB kütüphanesindeki amaç modülü MOD1.OBJ’daki amaç modülle de ği ştir. LIB komutunda ayrıca birtakım seçenekler de bulunmaktadır. D.2. NMAKE Yardımcı Programı NMAKE—veya MAKE—farklı kaynak dosyalarda bulunan çok sayıda modülden olu şan büyük programların otomatik olarak derlenmesi ve ba ğlanması için kullanılan bir yardımcı programdır. NMAKE programını çalı ştıracak komutun genel şekli şöyledir: C>NMAKE seçimler opt makrotanımları opt seçimler A şa ğıdakiler olabilir: /Fdosyaadı NMAKE yardımcı programı komutları içeren tanımlayıcı dosyanın adı. (Dosya tipi .MAK’tır.) /D NMAKE tarafından i şlenen her dosyanın son de ği ştirilme tarihini görüntüle. /I Tanımlayıcı dosyadaki programlardan döndürülen kodları dikkate alma ve daha sonraki satırları yürütmeyi sürdür. /N Tanımlayıcı dosyadaki komutları i şletme, sadece görüntüle. /S Sessiz mod, hiçbir şey görüntüleme. /Xdosyaadı Hata mesajlarını bir dosyaya yönlendir. /X- Hata mesajlarını standart çıktı aygıtına yönlendir. makrotanımları İste ğe ba ğlı olarak, isim=metin şeklinde, bir veya daha fazla sayıda karakter dizisi. Bir tanımlayıcı dosya bir veya daha fazla sayıda tanımlayıcı bloktan olu şur. Bo ş satırlar tanımlayıcı blokları ayırırlar. Bir tanımlayıcı bloktaki maddelerin sözdizimi ve anlambilimi a şa ğıda özetlenmi ştir: EK DMICROSOFT LIB VE MAKE YARDIMCI PROGRAMLARINA GENEL B İR BAKIŞ1 57 çıkdosya : girdosya ... #açıklama #açıklama komutlar Çıkdosya iki noktadan sonra gelen dosyalara ba ğımlıdır. Komutlar, satırı çıkdosya üzerinde yapılacak i şlemleri belirtir. Örne ğin, XYZ.MAK tanımlayıcı dosyasında XYZ.EXE : XYZ.C F1.C F2.C # XYZ'yi derleyip bagla. CL XYZ.C F1.C F2.C yazılı ise C>NMAKE /F XYZ şeklinde bir ça ğrı, e ğer XYZ.C, F1.C ve F2.C dosyalarından herhangi biri XYZ.EXE olu şturulduktan sonra de ği ştirilmi şse, bu dosyaların tekrar derlenmesini sa ğlayacaktır. 159 EK E: D İLLERARASI ÇA ĞRILAR Yazılım ayrı ayrı modüller şeklinde geli ştirildi ğinde, modülleri ayrı programlama dilleri kullanarak gerçekle ştirmek olasıdır. Bu, hem o modül için belli bir dilin daha uygun olmasından, hem de programcının o dili daha iyi bilmesinden dolayı belli bir dili seçmi ş olmasından kaynaklanabilir. Örne ğin, C’de yazılmı ş bir programın bazı modüleri için sık sık birle ştirici dil kullanılır. Bu ekte bir C programından bir birle ştirici dil yordamı ça ğırmak veya bir birle ştirici dil programından bir C fonksiyonu ça ğırmak için ça ğırma ve argüman geçirme yöntemlerini kısaca inceleyece ğiz. BASIC, Pascal ve FORTRAN’dan C yordamları veya C’den bu dillerde yazılmı ş yordamları nasıl ça ğırabilece ğinizi ö ğrenmek için Microsoft C Version 5.00 Mixed Language Programming Guide (Karma Dil Programlama Kılavuzu) veya Microsoft Visual C++ Programming Techniques (Programlama Teknikleri) elkitaplarına bakınız. E. 1. Birle ştirici İle Ba ğlayıcının Kullanılması Bir C programında, fonksiyon isimleri dı şsal simgelermi ş gibi i şlem görürler ve ba ğlayıcı tarafından kullanılmaları için, amaç program dosyasına kaydedilirler. Fakat bir farkla: C derleyicisi her fonksiyon isminin önüne bir altçizgi ekler. Örne ğin: xyz (...) { ... } fonksiyon tanımında, fonksiyon ismi amaç programda _xyz şeklinde kaydedilir. Standarda göre, dı şsal tanıtıcı sözcüklerde, anlamlı karakter sayısı en az 8’dir. Ayrıca, küçük büyük harf ayırımı yapılmayabilir. Bir C fonksiyonu ba şka bir C fonksiyonunu ça ğırdı ğında, ça ğrıdaki argümanlar ve dönü ş adresi, yı ğıt adı verilen bir veri yapısı içinde ça ğrılan fonksiyona geçirilir ve 160 D İLLERARASI ÇA ĞRILAR EK E ça ğrılan fonksiyon de ği şiklikleri bu yı ğıt içinde yapar. Bundan dolayı, ça ğıran ile ça ğrılan fonksiyonun bu yı ğıtı nasıl de ği ştirdi ğini anlamak çok önemlidir. Yı ğıt, belle ğin büyük adreslerinden küçük adreslerine do ğru büyür. C derleyicisi, ça ğrıdaki argümanları argüman listesindeki sıralarına göre fakat sa ğdan ba şlayarak yı ğıta yerle ştirir. Böylece, yı ğıta en son itilen ve bundan dolayı en dü şük adreste bulunan argüman en soldaki, yani argüman listesindeki ilk argümandır. Ça ğıran yordam tarafından yı ğıta en son itilen şey ise dönü ş adresidir. Ça ğrılan yordam Taban Yazmaç BP’nin içeri ğini saklayarak, yerel verileri için yer ayırarak ve, SI ile DI gibi, içerikleri de ği şebilecek olan yazmaçların içeriklerini saklayarak yı ğıtta de ği şiklikler yapar. A şa ğıdaki çizelge yı ğıtın içeri ğini göstermektedir. n’inci argüman (büyük adres) ça ğıran fonksiyon n-1’inci argüman tarafından de ği ştirilen ... yı ğıt bölümü birinci argüman dönü ş adresi ça ğrılmı ş fonksiyon saklanmı ş BP ‹ BP tarafından de ği ştirilen yerel veriler yı ğıt bölümü saklanmı ş yazmaçlar ‹ SP (küçük adres) Her argüman için kullanılan bayt sayısı argümanın tipi ve, de ğerle veya referansla ça ğrı gibi, argümanı geçirmek için kullanılan yönteme ba ğlıdır. Referansla ça ğrı durumunda, bir adres geçirildi ğine göre, bu sayı adresin yakın/uzak niteli ğine de ba ğlıdır. Aynı durum dönü ş adresi için de sözkonusudur. Her biri için kullanılan bayt sayısı şöyledir: Yöntem Tip Bayt de ğerle short, int 2 de ğerle long 4 de ğerle float 4 de ğerle double 8 referansla yakın2 referansla uzak 4 dönü ş adresi yakın2 dönü ş adresi uzak 4 Program minik, küçük veya kısa bellek modelinde derlenmi şse dönü ş adresi yakın, aksi takdirde uzaktır. Uzak adresler kesim:uzaklık şeklinde olurlar. C’de dizi dı şındaki tüm veri yapılarının de ğerle, dizilerin ise referansla geçirildi ğini anımsayın. E ğer bir dizinin de ğerle geçirilmesi isteniyorsa, o zaman de ğerle geçirilen bir yapının tek üyesi olarak tanımlanmalıdır. Ça ğrılan yordam, i şini bitirdikten sonra, hesapladı ğı de ğeri şu şekilde döndürür: EK E D İLLERARASI ÇA ĞRILAR 16 1 Döndürülen De ğer Yazmaç 1 bayt AL 2 bayt AX 4 bayt yüksek baytlar DX’te, dü şük baytlar AX’te > 4 bayt de ğerin adresi DX:AX’te A şa ğıdaki örnekte, birle ştirici dilde yazılmı ş xyz adındaki fonksiyonu ça ğıran bir C main fonksiyonu gösterilmektedir: extern int xyz (int, int); main (...) { ... xyz(3,5); ... } .MODEL SMALL .CODE PUBLIC _xyz _xyz PROC push bp ; Taban gosterge yazmacini sakla mov bp,sp ; Yigitta ... boyunda yeni sub sp,... ; bir taban bolge ac push si ; SI ve DI yazmaclarini sakla push di ; pushf ; Bayrak yazmacini sakla mov ax,[bp+4] ; Ilk argumani AX'e tasi mov cx,[bp+6] ; Ikinci argumani CX'e tasi ... ; xyz'nin hesaplamasi ... ; gereken seyi hesapla mov ax,... ; Donus degerini koy popf ; Bayrak yazmacini geri al pop di ; DI ve SI yazmaclarini geri al pop si mov sp,bp ; Yigiti temizle pop bp ; Eski BP'yi geri al ret ; Cagirana don _xyz ENDP END Programları ayrı ayrı amaç dosyaları içine derleyin ve birle ştirin; daha sonra bu iki dosyayı tek bir yürütülebilir dosya şeklinde ba ğlayın. 162 D İLLERARASI ÇA ĞRILAR EK E E.2. Satıriçi Birle ştiricisinin Kullanılması Microsoft C Derleyicisinin 8.00 uyarlamasını kullanıyorsanız, bir önceki kısımda anlatıldı ğı şekilde MASM gibi ayrı bir birle ştirici kullanmanıza gerek kalmayabilir. Derleyici içine dahil edilmi ş satıriçi birle ştiricisini kullanabilirsiniz. Bu durumda, amaç dosyaların LINK i şlemiyle de u ğra şmanıza gerek kalmaz. Satıriçi birle ştiricisinin birçok avantajları vardır: tek bir kaynak dosya içinde hem C hem de birle ştirici kodunu yazma; C de ği şmez, de ği şken, fonksiyon ve etiket isimlerine birle ştirici kod içinden ula şma; C deyimleri arasına istenilen yere birle ştirici kodu ekleme gibi. Ancak, birle ştirici kodun kullanılması ta şınabilirlik sorunları ortaya çıkarabilir; bunun için birle ştirici kodlarının, kaynak dosya içinde, ayrı bir yerde tutulması yararlı olur. Satıriçi birle ştiricisini kullanmak için bir C fonksiyonu içinde uygun yerlere __asm { ... } şeklinde özel bir deyim kullanmanız gerekir. Örne ğin __asm { mov ah,2 mov dl,7 int 21h } deyimi ekrana zil karakterinin yazılmasını sa ğlar. Satıriçi birle ştiricisinde birçok MASM ifadesi ve 80286 ile 80287 i şlemci komutları kullanılabilir. İfadeler içinde kaynak dosyada tanımlanmı ş C isimleri de kullanılabilir. Açıklamalar, normal olarak satırın sonuna noktalı virgülün arkasına yazılır. Birle ştirici kodu içinde _emit sözde komutu kullanılarak tek bir bayt tanımlanabilir. Örne ğin: _emit 0x66 _emit 0x98 sözde komut sırası, satıriçi birle ştiricisinin anlamadı ğı, 80386 CWDE komutunun yerine kullanılabilir. Satıriçi birle ştiricisi kodu içinde AX, BX, CX, DX, ES ve bayrak yazmaçlarını istedi ğiniz gibi kullanabilirsiniz. Ancak, DI, SI, DS, SS, SP ve BP yazmaçlarıyla (STD ve CLD komutuyla de ği ştirilebilen) yön bayra ğını eski halinde bırakmanız gerekir. EK E D İLLERARASI ÇA ĞRILAR 163 E.3. Bir Örnek—Disket Saklama Bu kısımda, bir disketi oldu ğu gibi diske kopyalayıp geri alabilen veya disketle disk dosyasını kar şıla ştırabilen bir programı inceleyece ğiz. Program bir disketi blok blok okuyup diskteki tek bir dosya içine kopyalamakta veya bu i şin tam tersini yapmaktadır. Bu amaçla diskette istedi ğimiz bir sektörü okuyup yazabilen bir yönteme gereksinimimiz vardır. MS-DOS kesintilerinden 0x25 ve 0x26 bu i şi yaparlar, ancak bir sorunları vardır: Olası bir hata durumunu bayrak yazmacının elde (carry) bitinde, hata kodunu ise AX yazmacında döndürürler. Bu arada, bayrak yazmacının eski durumunu da yı ğıtta saklarlar. Bu durumda, bu kesintilerden dönüldü ğü zaman yı ğıtta fazla bir sözcük bulunmaktadır. Programa devam etmeden önce bunun geri alınması gerekir. Bu yüzden, bu kesintileri dos.h ba şlık dosyasında tanımlanmı ş _int86 fonksiyonunu kullanarak ça ğıramayız; birle ştirici kodu yazmamız gerekir. A şa ğıdaki programda mdisk fonksiyonu bu i şi yapar. 1. /* Disk uzerinde dosya seklinde disket saklama. Uyarlama 2.00. 2. * (C) Fedon Kadifeli 1989-1993. 3. * Derleyici: Microsoft C. Uyarlama 8.00. 4. */ 5. 6. #include 7. #include 8. #include /* MS-CL */ 9. 10. #define M_OKU (0x25) /* mutlak disk okuma kesinti kodu */ 11. #define M_YAZ (0x26) /* mutlak disk yazma kesinti kodu */ 12. #define SEKTOR ((size_t)512) /* sektor boyu */ 13. #define IOS ((size_t)48) /* bellek tampon boyu (sektor) */ 14. #define BBS (1024/SEKTOR) /* 1K'lik bloklar */ 15. #define MAKS_DB (66) /* en uzun dosya ismi boyu */ 16. 17. typedef unsigned char BAYT; /* 8 bit */ 18. 19. BAYT tam1 [IOS*SEKTOR], tam2 [IOS*SEKTOR]; 20. 21. /* karsilastirma islemi */ 22. int esit (register BAYT * a, register BAYT * b, register size_t u) 23. { 24. while (u--) 25. if (*a++ != *b++) 26. return 0; /* uyusmuyor */ 27. return 1; /* uyusuyor */ 28. } /* esit */ 29. 164 D İLLERARASI ÇA ĞRILAR EK E 30. /* mutlak disk girdi/cikti */ 31. size_t mdisk (BAYT kesno, BAYT surno, size_t seksay, size_t sekno, 32. BAYT * aktadr) 33. { 34. size_t dondeg; 35. __asm { 36. push di ; yazmaclari 37. push si ; sakla 38. push bp 39. mov ah,kesno ; kesinti numarasi (M_OKU, M_YAZ) 40. mov al,surno ; disket surucu numarasi 41. sub al,'A' ; 'A' -> 0, 'B' -> 1 42. mov cx,seksay ; sektor sayisi 43. mov dx,sekno ; sektor numarasi 44. mov bx,aktadr ; aktarma adresi 45. cmp ah,M_OKU 46. jne else ; eger M_YAZ ise 47. int M_OKU 48. jmp SHORT devam 49. else: int M_YAZ 50. devam: pushf 51. pop ax ; bayraklari al 52. and ax,1 ; hata biti (kesinti donus degeri) 53. popf ; bayraklari geri al 54. pop bp ; yazmaclari 55. pop si ; geri al 56. pop di 57. mov dondeg,ax 58. } 59. return !dondeg; /* 0 hata; 1 tamam */ 60. } /* mdisk */ 61. 62. /* menu seceneklerini sor */ 63. int mensor (void) 64. { 65. int sec; 66. static char * scnklr [] = { 67. "\n", 68. " 1. Sakla\tDisket --> Disk", 69. " 2. Yukle\tDisket <-- Disk", 70. " 3. Karsilastir\tDisket <-> Disk" }; 71. 72. printf("\n\n\t%s\n\t%s\n\t%s\n\nSecenek:", 73. scnklr[1], scnklr[2], scnklr[3]); 74. if ((sec = _getch()) == '1' || sec == 'S' || sec == 's') 75. sec = 1; 76. else if (sec == '2' || sec == 'Y' || sec == 'y') 77. sec = 2; 78. else if (sec == '3' || sec == 'K' || sec == 'k') 79. sec = 3; 80. else 81. sec = 0; 82. puts(scnklr[sec]); 83. return sec; 84. } /* mensor */ 85. 86. /* kullanilacak disket surucusunu sor */ 87. int sursor (void) 88. { 89. int sur; 90. EK E D İLLERARASI ÇA ĞRILAR 165 91. printf("Disket surucusu (A/B): "); 92. if ((sur = toupper(_getch())) != 'A' && sur != 'B') 93. sur = 0; 94. printf(sur ? "%c:\n" : "\n", sur); 95. return sur; 96. } /* sursor */ 97. 98. /* kullanilacak disk dosyasinin adini sor */ 99. char * dossor (void) 100. { 101. static char da [MAKS_DB+3] = { MAKS_DB+1 }; 102. 103. printf("Disk dosya adi: "); 104. _cgets(da); 105. putchar('\n'); 106. return da[2] ? da+2 : NULL; 107. } /* dossor */ 108. 109. int main (void) 110. { 111. int secenek, surucu; 112. char * da; 113. FILE * dg; 114. int b; 115. size_t i, d1, d2; 116. 117. printf("Disk uzerinde dosya seklinde disket saklama." 118. " Uyarlama 2.00.\n(C) Fedon Kadifeli 1989-1993.\n"); 119. while ((secenek = mensor()) != 0) 120. while ((surucu = sursor()) != 0) 121. while ((da = dossor()) != NULL) { 122. i = 0; 123. d1 = 1; 124. b = 0; 125. /* 1 nolu secenek : Disket --> Disk */ 126. if (secenek == 1) { 127. if ((dg = fopen(da,"rb")) != NULL) { 128. fclose(dg); 129. printf("'%s' dosyasi zaten var!\n", da); 130. continue; 131. } 132. if ((dg = fopen(da,"wb")) == NULL) { 133. printf("'%s' dosyasi acilamiyor!\n", da); 134. continue; 135. } 136. while (mdisk(M_OKU, (BAYT)surucu, IOS, i, tam1) && 137. (d1=fwrite((void *)tam1, SEKTOR, IOS, dg)==IOS) != 0) 138. printf("\r%d", (i+=IOS)/BBS); 139. printf(d1 ? (i?" adet blok '%s' dosyasina aktarildi.\n" 140. :". Disket okunamadi!\a\n") 141. : ". '%s' dosyasinda yazma hatasi!\a\n", da); 142. } else { 143. /* 2 veya 3 nolu secenek */ 144. if ((dg = fopen(da,"rb")) == NULL) { 145. printf("'%s' dosyasi acilamiyor!\n", da); 146. continue; 147. } 166 D İLLERARASI ÇA ĞRILAR EK E 148. /* 2 nolu secenek : Disket <-- Disk */ 149. if (secenek == 2) { 150. while (fread((void *)tam1, SEKTOR, IOS, dg) == IOS && 151. (d1=mdisk(M_YAZ, (BAYT)surucu, IOS, i, tam1)) != 0) 152. printf("\r%d", (i+=IOS)/BBS); 153. printf(d1 ? " adet blok diskete aktarildi.\n" 154. : ". Diskette yazma hatasi!\a\n"); 155. } else { 156. /* 3 nolu secenek : Disket <-> Disk */ 157. while ((d1=mdisk(M_OKU, (BAYT)surucu, IOS, i, tam1)) & 158. (d2=fread((void *)tam2, SEKTOR, IOS, dg)==IOS) && 159. (b =esit(tam1, tam2, IOS*SEKTOR)) != 0) 160. printf("\r%d", (i+=IOS)/BBS); 161. printf( 162. !b ? ". Karsilastirma hatasi!\a\n" : 163. d1 ? ". Dosya disketten kisa!\a\n" : 164. d2 ? ". Disket dosyadan kisa!\a\n" : 165. " adet blok uyusuyor.\n"); 166. } 167. } /* if */ 168. fclose(dg); 169. } /* while */ 170. printf("\nIslem tamamlandi\n"); 171. return 0; 172. } /* main */ esit fonksiyonu (Satır 22-28) iki tampon bölgeyi kar şıla ştırır, e şitse 1 döndürür, aksi takdirde 0 döndürür. mdisk fonksiyonu (Satır 31-60) surnoda verilen sürücüdeki—bu programda, surno 'A' veya 'B' de ğerlerini alabilmektedir—sekno ba şlangıç sektör (kesim) numarasından seksay sektör sayısı kadar sektör üzerinde i şlem yapar. kesno M_OKU’ya e şitse disketten bu sektörleri okuyup aktadr tampon bölgesine aktarır; kesno M_YAZ’a e şitse aktadr tampon bölgesindeki baytları disketteki ilgili sektörlere yazar. Bu fonksiyon, yukarıda anlatıldı ğı gibi ilgili kesintiyi ça ğırdıktan sonra, yı ğıtta saklanmı ş bulunan bayrakları bayrak yazmacına geri alır (Satır 53). Menu seçeneklerini kullanıcıya mensor fonksiyonu (Satır 63-84) gösterir ve istenilen seçene ği kullanıcıdan alır. Bir numaralı seçenek, programın disketi sektör sektör okuyup, adı kullanıcıdan alınan, bir disk dosyası içine kopyalamasını sa ğlar. İki numaralı seçenek bu i şin tersini yapar; daha önce, bir numaralı seçenek kullanılarak, disk dosyası içine aktarılmı ş olan bir disket görüntüsünün sektör sektör okunup formatlanmı ş bir diskete aktarılmasını sa ğlar. Üç nolu seçenek diskteki dosya ile disketi kar şıla ştırır; bu seçenek, bir veya iki nolu seçenekler kullanılarak yapılan bir kopyalama i şleminden sonra, i şlemin do ğrulu ğunu sınamak için kullanılabilir. Kullanılacak disket sürücüsü (“A:” veya “B:”) sursor fonksiyonu (Satır 87-96) aracılı ğıyla kullanıcıdan alınır. Kullanılacak disk dosyasının adı ise dossor fonksiyonu (Satır 99-107) tarafından alınır. Burada, dosya adını okumak için standart olmayan _cgets fonksiyonu kullanılmı ştır. _cgets fonksiyonu kontrollü bir şekilde klavyeden bir satır okumak için kullanılabilir. Ana fonksiyon içiçe üç döngüden olu şur; bunlar, sırasıyla, kullanıcıdan menü seçene ğini, kullanılacak sürücüyü ve dosya adını alırlar. Her bir menü seçene ği için EK E D İLLERARASI ÇA ĞRILAR 167 yapılan i şlem temelde aynıdır: Bir döngü içinde disk dosyası ve/veya disketten bilgi okunup gerekli i şlem yapılır. (Kar şıla ştırma seçene ği kısmında, satır 157’nin sonunda neden && de ğil de & kullanılmı ştır?) Not: Bu program kullanılırken dikkat edilmesi gereken bir nokta disket kapasitesidir. İşlenen bilgi miktarı kilobayt cinsinden ekranda görüntülenir. Örne ğin 1.44 megabaytlık bir disket ile i şlem yapıldı ğında ekrandaki sayının son durumu 1440 olmalıdır. Programda kullanılan kesintinin gerçek disket kapasitesini anlaması olası de ğildir; MS- DOS ortamında iken en son yapılan disket i şlemindeki disket kapasitesi kullanılır. Bu yüzden, herhangi bir sorun çıkmaması için, program kullanılmadan önce, kullanılacak disket tipinden bir disket sürücüye takılıp, örne ğin “DIR A:” veya “CHKDSK A:” şeklinde bir MS-DOS komutu çalı ştırılmalıdır. Bundan sonra, program yürütülmesi esnasında, kullanılan disketlerin kapasitesi de ği şmedi ği sürece, herhangi bir sorun çıkmayacaktır. Dikkat edilmesi gereken bir di ğer nokta da, kullanılan disketlerin formatlı olması ve bozuk sektörlerin bulunmamasıdır. 169 EK F: STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLER İ Bu ekte, ANSI Standardında olmasına ra ğmen, henüz yaygın olarak bilinmeyen ve pek kullanılmayan bazı özelliklerden sözedilmektedir. Ayrıca kitapta sözü edilmi ş standart kütüphane fonksiyonları hakkında (dönü ş tipi ve argümanlarının tipi gibi) bazı detaylar için son kısma ba şvurulabilir. F. 1. C Dünyanın Her Yerinde—Yöreler Bilginin gösterim yolları ülkeden ülkeye de ği şir. Örne ğin, tarih yazılırken, Türkçe’de önce gün, sonra ay yazılır. Bazı batı ülkelerinde ise bunun tersi yapılır. İngilizce’de ondalık sayıları ayırmak için nokta kullanılırken, ba şka ülkelerde virgül kullanılır. Ve, en önemlisi de, her ülkenin kendine özgü harfleri vardır ve bütün dillerin bütün karakterlerini ifade edebilecek tek bir karakter takımı yoktur. Bu konuya bir çözüm getirmek için yöreler kavramı getirilmi ştir. Bir yöre, belirli bir ülke veya dil için yukarıdaki paragrafta sözü edilen türden bilgileri içeren bir bilgi paketidir. Yöreler, ctype fonksiyonlarını, yazı yazma yönünü, saat-tarih biçimlerini, karakterlerin sırasını ve ondalıkları ayırmak için kullanılan karakteri belirlerler. Yeni bir yöre belirterek, printf gibi, birçok standart fonksiyonu etkilemek olasıdır. Kullanılmakta olan yöre ile ilgili bilgileri lconv yapısı tutar ve buna bir gösterge elde etmek için localeconv adlı fonksiyonu ça ğırmak gerekir. Yürütme esnasında yöreyi belirtmek için, şu iki argümanı olan setlocale adlı fonksiyonu ça ğırırsınız: De ği ştirmek istedi ğiniz özelliklerden olu şan grup (LC_COLLATE [karakter sırası], LC_CTYPE [karakter tipi], LC_MONETARY [para], LC_NUMERIC [sayılar], LC_TIME [zaman], LC_ALL [hepsi]) ve yeni özelliklerin alınaca ğı yörenin adı. E ğer bütün diller 170 STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLER İ EK F için yöreler tanımlanmı şsa, programın ba şında kullanıcının milliyetini sorup ondan sonra bu ki şinin alı ştı ğı şekilde çalı şan bir program yazılabilir. Örne ğin, setlocale(LC_ALL, turkish) Standart sadece “C” yöresinin gerçekle ştirilmesini gerektirmektedir. Bu da, kitap boyunca anlatılan özelliklerden olu şmaktadır. F.2. Geni ş Karakterler Ve Çokbaytlı Karakterler char tipinin 256 farklı de ğer alabilmesi temin edilmi ştir. Japonca veya Çince gibi, bazı diller 256’dan fazla simge gerektirmektedir. Böyle dillerle çalı şabilmek için, geni ş karakterler ve çokbaytlı karakterler kavramı geli ştirilmi ştir. Bir geni ş karakter wchar_t adlı standart tipe aittir. Bu tamsayı tipi herhangi bir karakter takımındaki bütün de ğerleri gösterebilecek kadar büyük olan, normalde 16 bitlik bir tiptir. Geni ş karakterlerden olu şan diziler, ba şlangıçtaki "’ın hemen önüne bir L harfi konarak belirtilir. Karakter de ği şmezleri için de, benzer şekilde, '’ın önüne L konur. wchar_t gkd[] = L"Bir genis karakter dizisi"; wchar_t gk = L'h'; Bir çokbaytlı karakter, çevresel bir aygıta yazılabilecek, bir veya birden fazla bayttan olu şan, sıradan bir karakter sırasıdır. Çokbaytlı bir karakter dizisinin uzunlu ğunu elde etmek için mblen fonksiyonu kullanılır. Bu iki karakter türü birbirleriyle yakın ili şkili oldukları için, bunlar arasında dönü ştürme yapmayı isteriz. A şa ğıdaki fonksiyonlar bu i şi yaparlar: wctomb bir geni ş karakteri bir çokbaytlı karaktere, mbtowc bir çokbaytlı karakteri bir geni ş karaktere, wcstombs bir geni ş karakter dizisini bir çokbaytlı karakter dizisine, mbstowcs bir çokbaytlı karakter dizisini bir geni ş karakter dizisine dönü ştürür. F.3. Üçlü Karakterler Bazı klavyelerde C programlarında kullanılan bazı önemli karakterler yazılamayabilir. Böyle dokuz karakteri ifade etmek için dokuz özel karakter sırası kullanılır. Bütün bu sıralar üç karakterden olu ştu ğu için bunlara üçlü karakter denir. Öni şlemci bir üçlü karakter ile kar şıla ştı ğında yerine onun ifade etti ği karakteri koyar. Üçlü karakterler ve onların e şde ğerleri şunlardır: EK F STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLERİ1 7 1 Üçlü Karakter Karakter ??= # (sayı i şareti) ??( [ (sol kö şeli parantez) ??/ \ (ters bölü) ??) ] (sa ğ kö şeli parantez) ??' ^ (uzatma i şareti) ??< { (sol çengelli parantez) ??! | (dikey çizgi) ??> } (sa ğ çengelli parantez) ??- ~ (inceltme i şareti) Programın heryerinde üçlü karakter yerine ilgili karakterin konuldu ğuna dikkat edin. Yani, printf("Devam??(e/h)") fonksiyon ça ğrısı Devam[e/h) basacaktır. F.4. Zaman Fonksiyonları Zamanla ilgili dokuz tane standart fonksiyon bulunmaktadır. Gerekli bildirimler time.h adlı dosyada bulunmaktadır. Şu anki takvim zamanını elde etmek için time fonksiyonunu ça ğırın. Sonuç time_t tipindendir. E ğer zaman elde edilebilir de ğilse, bu fonksiyon -1 döndürür. difftime fonksiyonu iki time_t argümanı alır ve bunlar arasındaki zaman farkının saniye cinsinden verildi ği bir double döndürür. Takvim zamanını yerel zamana dönü ştürmek için, localtime fonksiyonunu kullanın. gmtime fonksiyonu takvim zamanını (eskiden Greenwich Ortalama Saati olarak bilinen) Düzenlenmi ş Evrensel Saate çevirmek için kullanılır. Zamanı görüntülemek için önce bir karakter dizisine çevirmeniz gerekir. Bu asctime fonksiyonu ile yerine getirilir. Argümanı tarafından i şaret edilen yapı içindeki zamanı bir karakter dizisine dönü ştürür. ctime(zg) ça ğrısı asctime(localtime(zg)) ça ğrısına e şde ğerdir. Yani yerel zamanı bir karakter dizisine dönü ştürür. 172 STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLER İ EK F mktime fonksiyonu argümanı tarafından i şaret edilen yapı içindeki yerel zamanı takvim zamanına dönü ştürür ve sonucu time_t şeklinde döndürür. E ğer sonuç ifade edilemezse, -1 döndürülür. Program çalı şmaya ba şladı ğından beri ne kadar i şlemci zamanı kullandı ğını ö ğrenmek için, clock_t tipinden sonuç döndüren, clock fonksiyonunu ça ğırın. En son olarak, şu anki yöreye uygun olarak tarih ve saatler içeren karakter dizileri hazırlamak için strftime fonksiyonu kullanılabilir. Dört tane argümanı vardır: Sonuçta uygun formatlanmı ş karakter dizisini içerecek bölgeye bir karakter göstergesi; bu karakter dizisine konulacak en fazla karakter sayısını gösteren size_t tipinde bir sayı; printf’tekine benzeyen bir kontrol karakter dizisi ve zaman bilgisini içeren yapıya bir gösterge. Normalde oldu ğu gibi önüne % konan, kontrol karakter dizisindeki dönü şüm tanımlamaları zaman unsurlarını belirtirler ve sonuçtaki karakter dizisinde kullanılmakta olan yöreye uygun olarak biçimlendirilmi ş ilgili zaman bilgileri ile de ği ştirilirler. Di ğer karakterler, tıpkı printf gibi, de ği ştirilmeden bırakılırlar. Dönü şüm tanımlamaları ve anlamları şöyledir: Dönü şüm Karakteri Anlamı a kısaltılmı ş gün adı A tam gün adı b kısaltılmı ş ay adı B tam ay adı c yerel tarih ve saat gösterimi d ay içindeki gün H saat (24 saatlik) I saat (12 saatlik) j yıl içindeki gün m ay M dakika pA M (ö ğleden önce) veya PM (ö ğleden sonra) ifadelerinin yerel e şde ğeri S saniye U (Pazar gününden ba şlamak ko şuluyla) yıl içindeki hafta sayısı w hafta içindeki gün W (Pazartesi gününden ba şlamak ko şuluyla) yıl içindeki hafta sayısı x yerel tarih gösterimi X yerel saat gösterimi y yılın son iki rakamı Y yıl Z saat dilimi adı %% EK F STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLERİ1 73 strftime, en sondaki \0 hariç, olu şturulan karakter sayısını döndürür. E ğer bu sayı ikinci argümandan büyükse, 0 döndürülür. F.5. Standart Ba şlık Dosyaları ANSI Standardı, de ği şmez, makro ve tip tanımlayan; de ği şken bildiren ve tüm standart kütüphane fonksiyonlarının prototiplerini içeren 15 tane ba şlık dosyası tanımlar. Bir ANSI fonksiyonu ça ğırmadan önce ilgili ba şlık dosyası #include emri ile programa dahil edilmelidir. Bazı gerçekle ştirmelerde, bazı “fonksiyonlar” öni şlemci makroları şeklinde tanımlanmı şlardır. Kullanıcı açısından bir fonksiyonun gerçekten fonksiyon şeklinde mi yoksa makro şeklinde mi tanımlanmı ş oldu ğu, bir istisna dı şında, farketmez: Makro argümanları, parametre makro içinde kaç defa kullanılırsa, o kadar kere hesaplanırlar. E ğer argümanlarda yan etkili i şleç veya fonksiyonlar kullanılırsa, bu sorun yaratabilir. Örne ğin, bazı uygulamalarda tolower ve toupper makro şeklinde ctype.h içinde tanımlanırken, stdlib.h içinde ilgili fonksiyonların bildirimi yapılmaktadır. E ğer yan etkisi olmayan i şleçler içeren argümanlar verecekseniz, daha hızlı olaca ğı için, makroları kullanmak daha akılcıdır; ancak argümanlar olası yan etkileri olan karma şık ifadeler ise, argümanların bir defa hesaplanacakları ilgili fonksiyonları ça ğırın. assert.h—Diyagnostikler Bu dosyada, yürütme esnasında bir savı (mantıksal ifadeyi) kontrol edip, e ğer yanlı şsa bir diyagnostik görüntüleyen bir “fonksiyon” tanımı vardır: void assert(int) E ğer bu dosya programa içerilmeden önce NDEBUG #define ile tanımlanmı şsa, assert ça ğrısı dikkate alınmaz; aksi takdirde a şa ğıdakine benzer bir durum gerçekle şir: #define assert(exp) { \ if (!(exp)) { \ fprintf(stderr,"Assertion failed: %s, file %s, line %d\n",\ #exp, __FILE__, __LINE__); \ abort(); \ } \ } ctype.h—Karakter Kontrolleri Ve Dönü şümleri Bu dosya karakterleri kontrol eden veya de ği ştiren fonksiyonlar ve/veya makrolar bildirir. Test fonksiyonları veya makroları, do ğru için sıfırdan farklı herhangi bir tamsayı, aksi takdirde sıfır döndürürler. int isalnum(int) int isalpha(int) int iscntrl(int) 174 STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLER İ EK F int isdigit(int) int isgraph(int) int islower(int) int isprint(int) int ispunct(int) int isspace(int) int isupper(int) int isxdigit(int) int tolower(int) int toupper(int) errno.h—Hatalar Bu dosya errno de ği şkeni için bir bildirim içerir. Ayrıca çe şitli kütüphane fonksiyonları tarafından bir hata durumunu göstermek için, EDOM, ERANGE gibi, bu de ği şkene verilebilecek bazı sıfırdan farklı de ği şmezler tanımlar. float.h—Kayan Noktalı De ğerler İçin Sınırlar Bu dosya, kayan noktalı (yani float, double ve long double) de ğerler için bazı de ği şmezler tanımlar. Standart tarafından kabul edilebilen en küçük de ğerler parantez içinde gösterilmi ştir. FLT_DIG duyarlı ondalık rakam sayısı (6) FLT_EPSILON 1.0+FLT_EPSILON!=1.0 şekilde en küçük sayı (1E-5) FLT_MANT_DIG FLT_RADIX tabanına göre mantisteki rakam sayısı FLT_MAX en büyük de ğer (1E+37) FLT_MAX_10_EXP en büyük ondalık üs FLT_MAX_EXP en büyük üs FLT_MIN en küçük düzgünlenmi ş pozitif de ğer (1E-37) FLT_MIN_10_EXP en küçük ondalık üs FLT_MIN_EXP en küçük üs FLT_RADIX üssün taban rakamı (2) FLT_ROUNDS toplamada yuvarlama DBL_DIG duyarlı ondalık rakam sayısı (10) DBL_EPSILON 1.0+DBL_EPSILON!=1.0 şekilde en küçük sayı (1E-9) DBL_MANT_DIG DBL_RADIX tabanına göre mantisteki rakam sayısı DBL_MAX en büyük de ğer (1E+37) DBL_MAX_10_EXP en büyük ondalık üs DBL_MAX_EXP en büyük üs DBL_MIN en küçük düzgünlenmi ş pozitif de ğer (1E-37) DBL_MIN_10_EXP en küçük ondalık üs DBL_MIN_EXP en küçük üs DBL_RADIX üssün taban rakamı DBL_ROUNDS toplamada yuvarlama EK F STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLERİ1 75 LDBL_DIG duyarlı ondalık rakam sayısı LDBL_EPSILON 1.0+LDBL_EPSILON!=1.0 şekilde en küçük sayı LDBL_MANT_DIG LDBL_RADIX tabanına göre mantisteki rakam sayısı LDBL_MAX en büyük de ğer LDBL_MAX_10_EXP en büyük ondalık üs LDBL_MAX_EXP en büyük üs LDBL_MIN en küçük düzgünlenmi ş pozitif de ğer LDBL_MIN_10_EXP en küçük ondalık üs LDBL_MIN_EXP en küçük üs LDBL_RADIX üssün taban rakamı LDBL_ROUNDS toplamada yuvarlama limits.h—Tamsayı De ğerleri İçin Sınırlar Bu dosya, çe şitli boylardaki tamsayılar için bazı üst ve alt sınırlarla ilgili de ği şmezler tanımlar. Kabul edilebilir en dü şük de ğerler parantez içinde gösterilmi ştir. Yani, bir derleyici için INT_MAX 32767’den büyük olabilir, fakat Standarda uygun hiçbir derleyicinin bu sayıdan küçük bir INT_MAX sa ğlamasına izin verilmez. CHAR_BIT bir char’daki bit sayısı (8) CHAR_MAX en büyük char de ğeri (UCHAR_MAX veya SCHAR_MAX) CHAR_MIN en küçük char de ğeri (0 veya SCHAR_MIN) INT_MAX en büyük (signed) int de ğeri (+32767) INT_MIN en küçük (signed) int de ğeri (-32767) LONG_MAX en büyük (signed) long de ğeri (+2147483647) LONG_MIN en küçük (signed) long de ğeri (-2147483647) SCHAR_MAX en büyük signed char de ğeri (+127) SCHAR_MIN en küçük signed char de ğeri (-127) SHRT_MAX en büyük (signed) short de ğeri (+32767) SHRT_MIN en küçük (signed) short de ğeri (-32767) UCHAR_MAX en büyük unsigned char de ğeri (255U) UINT_MAX en büyük unsigned int de ğeri (0xFFFF) ULONG_MAX en büyük unsigned long de ğeri (0xFFFFFFFF) USHRT_MAX en büyük unsigned short de ğeri (0xFFFF) MB_LEN_MAX bir çokbaytlı karakter içindeki en büyük bayt sayısı locale.h—Yöre Fonksiyonları Bu dosya, “struct lconv” için bir tip tanımlaması, LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME de ği şmezlerinin tanımlarını ve a şa ğıdaki fonksiyon prototiplerini içerir: struct lconv * localeconv(void) char * setlocale(int, const char *) 176 STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLER İ EK F math.h—Matematiksel Yordamlar Bu dosya, birtakım kayan noktalı matematik yordamları tarafından hata durumunda döndürülen bir de ğeri tutmak için HUGE_VAL adlı double de ği şkenini bildirir. Ayrıca, alan hatası veya ta şma durumlarını göstermek için sırasıyla EDOM veya ERANGE de ğeri errno de ği şkenine atanır. Fonksiyon prototipleri şöyledir: double acos(double) double asin(double) double atan(double) double atan2(double, double) double ceil(double) double cos(double) double cosh(double) double exp(double) double fabs(double) double floor(double) double fmod(double, double) double frexp(double, int *) double ldexp(double, int) double log(double) double log10(double) double modf(double, double *) double pow(double, double) double sin(double) double sinh(double) double sqrt(double) double tan(double) double tanh(double) setjmp.h—Yerel Olmayan Atlamalar Bu dosya, program durumunu saklamak ve tekrar yüklemek için setjmp makrosu ile longjmp fonksiyonunun kullandı ğı jmp_buf adlı, makineye ba ğlı, bir tampon bölge için bir tip tanımlar ve ayrıca bu yordamların bildirimini içerir. void longjmp(jmp_buf, int) int setjmp(jmp_buf) signal.h—Sinyaller Bu dosya, yürütme esnasında kesintileri veya hataları i şlemek için kullanılan fonksiyonlar bildirir. EK F STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLERİ1 77 Sinyal tipleri: SIGABRT abort ça ğrısı ile tetiklenen düzensiz sonuçlanma SIGFPE kayan noktalı i şlem hatası SIGILL hatalı komut—geçersiz fonksiyon imgesi SIGINT CONTROL+C kesintisi—etkile şimli dikkat SIGSEGV bellek sınırları dı şında eri şim SIGTERM öldürme sonucu yazılım sonlandırma sinyali Sinyal i şleyi ş kodları: SIG_DFL varsayılan signal i şleyi şi SIG_IGN dikkate almama Hata durumunda signal ça ğrısı tarafından döndürülen sinyal hata de ğeri: SIG_ERR signal hata de ğeri Fonksiyon prototipleri: int raise(int) void (* signal(int, void (*)(int)))(int) stdarg.h—De ği şken Argüman Listeleri Bu dosya, de ği şken sayıda argüman alabilen fonksiyonların argümanlarına eri şebilmesi için standart yöntemler tanımlar. va_list tipi bir gösterge olarak tanımlanmı ştır. tip va_arg(va_list, tip) void va_end(va_list) void va_start(va_list, son_argüman) stddef.h—Standart Sistem Tanımları Bu dosya, NULL gösterge de ğeri, errno dı şsal de ği şkenine bir referans ve uygulamaya ba ğlı olarak de ği şen ptrdiff_t (iki göstergenin farkı alındı ğında elde edilen i şaretli de ğerin tipi), size_t (sizeof i şleci tarafından döndürülen i şaretsiz de ğerin tipi) ve wchar_t (geni ş bir karakterin tipi) için tanımlar içermektedir. stdio.h—Standart Girdi Ve Çıktı Bu dosya, standart girdi/çıktı yordamları tarafından kullanılan yapılar, de ğerler, makrolar ve fonksiyonlar tanımlar. size_t, va_list, fpos_t ve FILE adlı tipler; BUFSIZ, EOF, NULL, FILENAME_MAX (dosya isimlerinde en büyük karakter sayısı), FOPEN_MAX (aynı anda açık olabilecek en çok dosya sayısı), P_tmpnam (geçici dosyaların açılabilece ği altdizin), L_tmpnam (geçici dosya isimlerinin uzunlu ğu), TMP_MAX (açılabilecek en çok farklı geçici dosya isimleri sayısı), SEEK_CUR, SEEK_END, SEEK_SET, stdin, stdout, stderr, _IOFBF, _IOLBF ve _IONBF de ği şmezleri bu dosyada tanımlanmı şlardır. Fonksiyon prototipleri: 178 STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLER İ EK F void clearerr(FILE *) int fclose(FILE *) int feof(FILE *) int ferror(FILE *) int fflush(FILE *) int fgetc(FILE *) int fgetpos(FILE *, fpos_t *) char * fgets(char *, int, FILE *) FILE * fopen(const char *, const char *) int fprintf(FILE *, const char *, ...) int fputc(int, FILE *) int fputs(const char *, FILE *) size_t fread(void *, size_t, size_t, FILE *) FILE * freopen(const char *, const char *, FILE *) int fscanf(FILE *, const char *, ...) int fseek(FILE *, long, int) int fsetpos(FILE *, const fpos_t *) long ftell(FILE *) size_t fwrite(const void *, size_t, size_t, FILE *) int getc(FILE *) int getchar(void) char * gets(char *) void perror(const char *) int printf(const char *, ...) int putc(int, FILE *) int putchar(int) int puts(const char *) int remove(const char *) int rename(const char *, const char *) void rewind(FILE *) int scanf(const char *, ...) void setbuf(FILE *, char *) int setvbuf(FILE *, char *, int, size_t) int sprintf(char *, const char *, ...) int sscanf(const char *, const char *, ...) FILE * tmpfile(void) char * tmpnam(char *) int ungetc(int, FILE *) int vfprintf(FILE *, const char *, va_list) int vprintf(const char *, va_list) int vsprintf(char *, const char *, va_list) stdlib.h—Sıkça Kullanılan Kütüphane Fonksiyonları Bu dosyada, size_t, wchar_t, div_t (div’den döndürülen yapı) ve ldiv_t (ldiv’den döndürülen yapı) tipleri ve NULL, RAND_MAX ( rand fonksiyonundan EK F STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLERİ1 79 döndürülen en büyük de ğer), EXIT_SUCCESS (programın ba şarılı exit kodu) ve EXIT_FAILURE (programın ba şarısız exit kodu) de ği şmezleri için tanımlarla MB_CUR_MAX ( şu anki yöreye göre bir çokbaytlı karakter içindeki en büyük bayt sayısı) ve errno de ği şkenleri için bildirimler bulunmaktadır. Fonksiyon prototipleri: void abort(void) int abs(int) int atexit(void (*)(void)) double atof(const char *) int atoi(const char *) long atol(const char *) void * bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *)) void * calloc(size_t, size_t) div_t div(int, int) void exit(int) void free(void *) char * getenv(const char *) long labs(long) ldiv_t ldiv(long, long) void * malloc(size_t) int mblen(const char *, size_t) size_t mbstowcs(wchar_t *, const char *, size_t) int mbtowc(wchar_t *, const char *, size_t) void perror(const char *) void qsort(void *, size_t, size_t, int (*)(const void *, const void *)) int rand(void) void * realloc(void *, size_t) void srand(unsigned int) double strtod(const char *, char **) long strtol(const char *, char **, int) unsigned long strtoul(const char *, char **, int) int system(const char *) size_t wcstombs(char *, const wchar_t *, size_t) int wctomb(char *, wchar_t) E ğer tolower makrosu #define ile tanımlanmamı şsa, int tolower(int) E ğer toupper makrosu #define ile tanımlanmamı şsa, int toupper(int) string.h—Karakter Dizileri İşleyen Fonksiyonlar Bu dosya NULL de ği şmezi ile size_t için bir tip tanımı ve a şa ğıdaki fonksiyon prototiplerini içerir: 180 STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLER İ EK F void * memchr(const void *, int, size_t) int memcmp(const void *, const void *, size_t) void * memcpy(void *, const void *, size_t) void * memmove(void *, const void *, size_t) void * memset(void *, int, size_t) char * strcat(char *, const char *) char * strchr(const char *, int) int strcmp(const char *, const char *) int strcoll(const char *, const char *) char * strcpy(char *, const char *) size_t strcspn(const char *, const char *) char * strerror(int) size_t strlen(const char *) char * strncat(char *, const char *, size_t) int strncmp(const char *, const char *, size_t) char * strncpy(char *, const char *, size_t) char * strpbrk(const char *, const char *) char * strrchr(const char *, int) size_t strspn(const char *, const char *) char * strstr(const char *, const char *) char * strtok(char *, const char *) size_t strxfrm(char *, const char *, size_t) time.h—Tarih Ve Saat Fonksiyonları Bu dosya, zaman yordamları için bildirimler ile, size_t ve sırasıyla clock ve time fonksiyonları tarafından döndürülen, uygulamaya ba ğlı clock_t ve time_t tiplerinin tanımlarını içerir. Ayrıca, localtime ve gmtime yordamları tarafından döndürülüp asctime tarafından kullanılan yapı şöyle tanımlanmaktadır: struct tm { int tm_sec; /* dakikadan sonraki saniyeler: [0,60] */ int tm_min; /* saatten sonraki dakikalar: [0,59] */ int tm_hour; /* geceyarisindan beri saatler: [0,23] */ int tm_mday; /* ayin gunu: [1,31] */ int tm_mon; /* Ocak'tan beri aylar: [0,11] */ int tm_year; /* 1900'dan beri yillar */ int tm_wday; /* Pazar'dan beri gunler: [0,6] */ int tm_yday; /* Ocak 1'den beri gunler: [0,365] */ int tm_isdst; /* Yaz Saati Uygulamasi bayragi */ } CLOCKS_PER_SEC makrosu, “clock()/CLOCKS_PER_SEC” ifadesi aracılı ğıyla, saniye cinsinden i şlemci zamanını elde etmek için kullanılabilir. Bu dosyada, ayrıca, ctime ailesinden yordamlar tarafından kullanılan küresel de ği şkenler için extern bildirimleri de bulunmaktadır: EK F STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLERİ1 8 1 int _daylight; /* eger Yaz Saati Uygulamasi kullani- * liyorsa, sifirdan farkli bir deger */ long _timezone; /* saniye cinsinden Duzenlenmis Evrensel * Saat ile yerel saat arasindaki fark */ char * _tzname[2]; /* Standart/Yaz Saati dilim isimleri */ Fonksiyon prototipleri: char * asctime(const struct tm *) clock_t clock(void) char * ctime(const time_t *) double difftime(time_t, time_t) struct tm * gmtime(const time_t *) struct tm * localtime(const time_t *) time_t mktime(struct tm *) size_t strftime(char *, size_t, const char *, const struct tm *) time_t time(time_t *) F.6. Çevirme Sınırları ANSI Standardı, Standart C uyumlu her derleyici tarafından kar şılanması gereken birtakım sınırlar tanımlamı ştır. Örne ğin, tanımlanan bir nesne için izin verilen en büyük boy 32 767 bayttır; ancak belli bir derleyici, 40 000 karakterlik bir dizi gibi daha büyük bir nesneye izin verebilir. Her durumda, ta şınabilirli ği garantilemek için programınızın a şa ğıda belirtilmi ş “en küçük büyük” sınırlar içinde kalmasını sa ğlayın: Bir fonksiyon ça ğrısındaki argümanlar.................................................31 Bir nesnedeki baytlar.................................................................... 32 767 Bir switch deyimindeki case etiketleri .........................................257 Mantıksal bir kaynak kod satırındaki karakterler ...............................509 Bir karakter dizisi de ği şmezindeki karakterler ...................................509 Bile şik deyimler, içiçe yazma...............................................................15 bir enum’daki de ği şmezler.................................................................127 do, for ve while, içiçe yazma .........................................................15 Tam bir ifade içindeki ifadeler, içiçe yazma.........................................32 Bir çevirme birimi içindeki dı şsal tanıtıcı sözcükler ..........................511 Ba şlık dosyaları, içiçe yazma .................................................................8 Bir blok içindeki, etki alanı blok olan, tanıtıcı sözcükler ...................127 if ve switch deyimleri, içiçe yazma ................................................15 #if, #ifdef ve #ifndef, içiçe yazma .............................................8 Bir çevirme birimi içindeki makro tanıtıcı sözcükleri .................... 1 024 Bir struct veya union içindeki üyeler .........................................127 Bir fonksiyon tanımındaki parametreler ...............................................31 Bir makro içindeki parametreler...........................................................31 Bir dı şsal tanıtıcı sözcük içindeki anlamlı karakterler ............................8 182 STANDART C PROGRAMLAMA D İL İN İN DİĞER ÖZELL İKLER İ EK F Bir içsel tanıtıcı sözcük içindeki anlamlı karakterler............................31 struct veya union tanımları, içiçe yazma ......................................15 183 EK G: SEÇ İLM İŞ PROBLEMLERE YANITLAR Bu ekte, her bölümün sonunda verilen problemlerden bazıları için yanıtlar verilmi ştir. Bazı problemler için de ği şik çözümler de sözkonusu olabilir. Burada ilk sayı bölümü, ikinci sayı ise problemi belirtir. 1. 1. Şunu deneyin void main (void) { int entry; } 1.4. Evet, x=5; deyimine e şde ğerdir. 1.5. Evet, bo ş bir blok deyimidir. 1.6. ... scanf("%f", &x); printf("%d", (int)x); ... 2.2.switch (yas) case 16 : printf("..."); 2.4.#include void main (void) { unsigned i, n; scanf("%u", &n); for (i=1; i<=n; i++) printf("%u\t%g\n", i*i, 1.0/i); } 184 SEÇ İLM İŞ PROBLEMLERE YANITLAR EK G 2.6.#include void main (void) { int p, c, i; c = p = getchar(); i = 1; while (c!=EOF) { c = getchar(); if (c==p) i++; else { if (i==3) printf("%c ", p); p = c; i = 1; } /* else */ } /* while */ } 2.8. Satır 32’deki do’yu uygun bir şekilde while’a çevirin. 3. 1. Gösterge aritmeti ğine kar şılık tamsayı aritmeti ği. 3.2.#include void main (void) { printf("%s-doldurma\n", (-10>>1<0)?"isaret":"sifir"); } 3.3.#include void main (void) { unsigned n, b; scanf("%d", &n); for (b=0; n!=0; n>>=1) b += n&1; printf("%d bit\n", b); } 3.4. E ğer a ve b aynı tipten ise içeriklerini de ği ştirir. 4. 1. Hayır! Bundan emin olamayız, çünkü bu, fonksiyon argümanlarının hesaplanma sıralarına ba ğlıdır. 4.2.int maks (int x, ...) { int maks, *xg; for (maks = *(xg=&x); *xg != 0; xg++) if (maks < *xg) maks = *xg; return maks; } EK G SEÇ İLM İŞ PROBLEMLERE YANITLAR 185 Tanımda “...” (üç nokta) geri kalan parametrelerin sayılarının (ve tiplerinin) belirlenmedi ği anlamına gelir. Ancak, böyle de ği şken sayıda argümanlı fonksiyon yazmanın ta şınabilir yolu bu de ğildir. Bunun yerine, a şa ğıda gösterildi ği gibi, stdarg.h standart ba şlık dosyasında tanımlanmı ş bulunan va_start, va_arg ve va_end makroları kullanılmalıdır. #include int maks (int x, ...) { int m; va_list xg; /* geri kalan argumanlara gosterge */ va_start(xg, x); /* ilk isimlendirilmemis argumana * isaret et */ for (m = x; x != 0; x = va_arg(xg,int)) if (x > m) m = x; /* yeni enbuyuk */ va_end(xg); /* donmeden once temizlik yap */ return m; } 4.3. İlklenmemi ş otomatik de ği şkenler belirsiz de ğerler ta şır. Bu, daha önce aynı adreste saklanmı ş olan bir otomatik de ği şkenin de ğeri olabilir. 4.4. Sadece ilk iki register bildirimi dikkate alınır, geri kalanlar auto gibi i şlem görürler. Aynı zamanda bir önceki alı ştırmaya bakın. 4.5. Girilen satırdaki karakterleri tersten basar. 5. 1. (a) sıfır, yani ilk sayıcı ve (b) belirsiz bir de ğer. 5.4.int * tamsayıya gösterge, int *[3] tamsayıya 3 göstergeden olu şan dizi, int (*)[3] 3 tamsayıdan olu şan diziye gösterge, int *(float) argümanı float olan ve int’e gösterge döndüren fonksiyon, int (*)(void) argümanı olmayan ve int döndüren fonksiyona gösterge. 5.5.a[i,j] ile a[(i,j)] e şde ğerdir, bu da a[j]’ye, yani bir göstergeye e şde ğerdir. 5.6.x dizi olmasına kar şın, a bir göstergedir. 5.8.a de ği şmez bir göstergedir; bundan sonra hep &y’yi göstermek zorundadır. Fakat gösterdi ği yer, yani y içindeki bilgi de ği ştirilebilir. b de de ği şmez bir göstergedir, bunun yanında gösterdi ği yer, yani x de program tarafından de ği ştirilemez. Buna ra ğmen, bu yer program dı şındaki bir süreç tarafından de ği ştirilmektedir. Yani b’nin gösterdi ği yeri program de ği ştiremez, sadece okuyabilir. 6. 1.typedef int * gosterge; ile 186 SEÇ İLM İŞ PROBLEMLERE YANITLAR EK G #define gosterge int * birbirine benzemektedir, ama typedef int dizi[N]; #define ile ifade edilemez, onun için typedef tercih edilir. 6.2.#define dok(x) printf("x = %d\n", x) E ğer Standarda uygun bir öni şlemciniz varsa, o zaman a şa ğıdakini kullanın: #define dok(x) printf(#x " = %d\n", x) 7.9.#include void temizle (void) { system("CLS"); } 187 EK H: TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ Bu kitapta, olanaklar ölçüsünde, İngilizce terimlerden kaçınılmaya çalı şılmı ştır. Onun yerine Türkçe’de yaygın olarak kullanılan bilgisayar terimleri veya—C’nin özel terimleri için—yeni Türkçe kar şılıklar bulunmu ştur. Okuyucuların terminoloji konusunda faklı dü şüncelerde olması doğaldır. Ancak bir metnin akıcılı ğını yitirmemesi ve hiç İngilizce bilmeyen ki şilerin de zorlanmadan bilgisayar konusundaki kitapları okuyabilmeleri için ulusal bir bilgisayar terminolojisinin olu şturulması ve geli ştirilmesi gerekmektedir. Bu terminoloji içinde Türkçe’ye girip türkçele şmi ş sözcükler pekala bulunabilir; ancak belli bir standardın bulunması esastır. Örne ğin, “çevirici” sözcü ğünden birisinin translator, ba şkasının assembler anlamaması gerekir. Bu ek böyle bir dü şüncenin sonucunda ortaya çıkan ve bu kitapta da kullanılan bir çalı şmanın sonucunu vermektedir. İlk kısımda, okuyucularımızın kitap içinde kar şıla ştıkları Türkçe terimlerin İngilizce kar şılıklarını bulabilecekleri bir Türkçe- İngilizce sözlük bulunmaktadır. İkinci kısımdaki İngilizce-Türkçe sözlük ise, İngilizce terimlerin kar şılı ğı olarak hangi Türkçe terimlerin kullanıldı ğını göstermesi açısından okuyucularımıza yardımcı olacaktır. H. 1. Türkçe- İngilizce Sözlük açıklama..................................................comment açılı parantez, <> ....................................angular bracket açma........................................................unpack adres .......................................................address adres alma...............................................address of adresleme................................................addressing 188 TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ EK H a ğ ............................................................network a ğa köle...................................................master slave a ğaç.........................................................tree akım........................................................current akı ş çizene ği ...........................................flowchart aktarma ...................................................copy, transfer alan .........................................................field; domain, range alfasayısal ...............................................alphanumeric algoritma.................................................algorithm altçizgi, _ ................................................underscore altdizin....................................................directory altprogram ..............................................subprogram altta şma...................................................underflow altyordam................................................subroutine amaç program .........................................object program ana bellek................................................main memory ana bilgisayar..........................................mainframe, host computer anahtar ....................................................key; switch; toggle anahtar sözcük ........................................keyword anlambilim..............................................semantics anlambilimsel..........................................semantic anlamlı rakam .........................................significant digit anlamsal..................................................semantic arabirim ..................................................interface arama ......................................................search, seek argüman ..................................................argument aritmetik mantık birimi ...........................arithmetic and logic unit (ALU) artım........................................................increment artırma ....................................................increment atama deyimi...........................................assignment statement aygıt........................................................device ayırıcı......................................................separator ayırma.....................................................allocation; partitioning ayraç .......................................................parenthesis ayrılmı ş sözcük.......................................reserved word ayrı ştırıcı.................................................parser azaltma....................................................decrement ba ğıntısal ................................................relational ba ğlam ....................................................context ba ğlama ..................................................link ba ğlayıcı .................................................linker bakım......................................................maintenance basamaklı................................................scalar basılmayan karakter................................nonprint character ba şlık ......................................................header EK H TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ 189 bayrak .....................................................flag bayt .........................................................byte belgeleme................................................documentation belirsiz ....................................................undefined belirteç....................................................specifier bellek ......................................................memory bellek ayırma ..........................................storage allocation bellek sınıfı .............................................storage class bellenir....................................................mnemonic benzetim .................................................simulation benzetme.................................................emulation biçim(lendirme) ......................................format biçimsel ..................................................formal bildirim...................................................declaration bildirme ..................................................declare bile şik deyim...........................................compound statement bilgi.........................................................information bilgisayar ................................................computer bilgisayar destekli tasarım ......................computer aided design (CAD) birikeç.....................................................accumulator birim .......................................................unit birle şme ..................................................associativity birle ştirici................................................assembler birle ştirici dil ..........................................assembly language birle ştirme...............................................merge birlik .......................................................union bit............................................................bit biti şme ....................................................join bitsel .......................................................bitwise blok.........................................................block Boole cebiri ............................................Boolean algebra boş ..........................................................blank boş dizgi .................................................null string boş karakter ............................................null character boşluk karakteri ......................................space character boy..........................................................size boyut.......................................................dimension bölü.........................................................slash bulu şsal...................................................heuristic ça ğırma ...................................................call ça ğrı........................................................call çengelli parantez, {} ...............................brace çevirici....................................................translator çevresel...................................................peripheral çevrimdı şı ...............................................offline 190 TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ EK H çevrimiçi.................................................online çıktı.........................................................output çift duyarlık ............................................double precision çizelge.....................................................table çizici .......................................................plotter çok i ş düzeni...........................................multitasking çok kullanıcılı .........................................multiuser çoklama ..................................................multiplexing çoklu.......................................................multiple çözümleme..............................................analysis çözünülürlük...........................................resolution dal...........................................................branch dallanma .................................................branching de ğer ile ça ğrı .........................................call by value de ğil........................................................not de ği şken..................................................variable de ği şmez.................................................constant denetim ...................................................control denetleme................................................verify derleme ...................................................compile derleyici..................................................compiler devingen .................................................dynamic devre.......................................................circuit deyim......................................................statement dı şsal.......................................................external dikey.......................................................vertical dil............................................................language disk .........................................................disk dizgi........................................................string dizi..........................................................array dizin........................................................directory; index doğrudan eri şim......................................direct access doğrulama...............................................validate doğruluk tablosu .....................................truth table doğruluk-de ğerli .....................................truth-valued dolaylama i şleci ......................................indirection operator dolaylı adresleme....................................indirect addressing donanım..................................................hardware dosya.......................................................file dosya sonu ..............................................end of file (EOF) dosya tipi ................................................extension döküm.....................................................dump döngü......................................................loop dönü ş ......................................................return dönü ştürme .............................................convert EK H TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ 19 1 dönü şüm .................................................conversion dönü şüm tanımlaması .............................conversion specification dura ğan ...................................................static durak.......................................................tab dural........................................................static durma......................................................halt duyarlık...................................................precision dü ğüm.....................................................node dü şük düzeyli dil.....................................low level language dü şürme ..................................................abort düzen ......................................................order, scheme ekran.......................................................screen elkitabı....................................................manual emir.........................................................directive enbüyük ..................................................maximum eniyi........................................................optimal eniyile ştirici ............................................optimizing enküçük...................................................minimum erim.........................................................range eri şim......................................................access, retrieval eri şim modu............................................access mode e ş(le şme).................................................match e şanlamlı.................................................synonym e şik .........................................................threshold e şitlik ......................................................equality e şlik ........................................................parity e şmerkezli...............................................coaxial e şzamanlı ................................................synchronous etiket .......................................................label etki alanı .................................................scope etkile şimli ...............................................interactive fare..........................................................mouse fonksiyon ................................................function geçi ş........................................................pass, run geçi ş süresi..............................................run time geni şleme................................................extension gerçek adres............................................actual address gerçek zaman..........................................real time gerçekle ştirme.........................................implementation geri alma .................................................backspace geriye dönü ş (yapma) .............................backtrack getirme....................................................fetch girdi ........................................................input girdi/çıktı (G/Ç)......................................input/output (I/O) göreli adres .............................................relative address 192 TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ EK H görev.......................................................task görüntü bellek.........................................virtual memory görüntü noktası .......................................pixel görünüm..................................................configuration gösterge ..................................................pointer gösterim..................................................notation güncelle ştirme.........................................update güvenilirlik .............................................reliability hareket ....................................................transaction hata .........................................................bug, error hata düzelticisi........................................debugger hata düzeltme..........................................debug hedef.......................................................destination hesaplama ...............................................evaluate içerik.......................................................content içiçe ........................................................nested içsel.........................................................internal ifade........................................................expression ikil...........................................................bit ikili .........................................................binary ikili dü ğümlenmi ş onlu yazım.................binary coded decimal (BCD) ikiye tümler.............................................twos complement ileti..........................................................prompt ileti şim....................................................communication ili şki........................................................relation ili şkisel....................................................relational ilk de ğer atama .......................................initialize ilkleme ....................................................initialize ilkleyen ...................................................initializer imleç .......................................................cursor indis ........................................................subscript; index indisleme.................................................indexing iptal.........................................................cancel iste ğe ba ğlı..............................................optional i ş .............................................................job i şaret .......................................................mark; sign i şaret biti.................................................sign bit i şaretsiz...................................................unsigned i şleç.........................................................operator i şleklik ....................................................activity i şlem .......................................................operation i şlem kodu ..............................................opcode i şlem operatörü .......................................operator i şlemci ....................................................operator i şleme......................................................processing EK H TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ 193 i şlenen.....................................................operand i şletilebilir...............................................executable i şletim sistemi .........................................operating system i şletme ....................................................execution iz.............................................................track izleme .....................................................trace kabuk ......................................................shell kaçı ş sırası ..............................................escape seqence kaçı ş tu şu ................................................escape key kalıp........................................................cast; pattern kalıtım.....................................................inheritance karakter...................................................character karakter dizisi .........................................string karakter sırası..........................................character sequence karar........................................................decision kayan noktalı...........................................floating point kaydırma.................................................shift kayıt........................................................record kayma .....................................................scroll kaynak program ......................................source program kesilme noktası .......................................breakpoint kesim ......................................................sector; segment kesinti .....................................................interrupt kısaad......................................................acronym kısım .......................................................section ki şisel bilgisayar .....................................personal computer (PC) kitaplık....................................................library klavye .....................................................keyboard kod..........................................................code kod çözme...............................................decode kodlama ..................................................coding, encode komut......................................................command, instruction kontrol ....................................................control kontrol akı şı............................................control flow kontrol karakteri .....................................control character konum.....................................................position; offset kopyalama...............................................copy ko şullu dallanma.....................................conditional branch ko şulsuz dallanma...................................unconditional branch kök..........................................................radix kö şeli parantez, [] ...................................bracket kullanıcı ..................................................user kullanıcı-tanımlı......................................user-defined kullanma .................................................reference kurgu.......................................................setup 194 TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ EK H kurulu ş ....................................................installation kuşak.......................................................generation kuyruk.....................................................queue, tail küme .......................................................set küme komut i şleme.................................pipelining, piping künye ......................................................tag küresel ....................................................global kütüphane ...............................................library liste .........................................................list makine dili..............................................machine language makro......................................................macro mantık.....................................................logic mantıksal kaydırma.................................logical shift menü .......................................................menu merkezi i şlem birimi (M İB)....................central processing unit (CPU) mesaj.......................................................message metin.......................................................text metin düzenleme.....................................editing metin düzenleyici....................................editor mikroi şlemci ...........................................microprocessor mimari.....................................................architecture mod.........................................................mode modüler...................................................modular monitör ...................................................monitor mutlak adres............................................absolute address nesne.......................................................object nesneye dayalı.........................................object oriented niteleyici .................................................qualifier nitelik......................................................attribute okunaklılık..............................................readability olumlu sayı .............................................positive number olumsuz sayı ...........................................negative number olumsuzlama...........................................negation onaltılı gösterim......................................hexadecimal notation ondalık....................................................decimal ortam.......................................................environment, medium otomasyon...............................................automation otomatik..................................................automatic öbek ........................................................block ön bellek .................................................cache memory öncelik ....................................................priority, precedence önek ........................................................prefix öni şlemci.................................................preprocessor önyükleme ..............................................bootstrapping örneksel ..................................................analog EK H TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ 195 örtü .........................................................mask özça ğrı ....................................................recursion özça ğrılı..................................................recursive özdevimli ................................................automatic özdevinim ...............................................automation özel karakter ...........................................special character özellik.....................................................property paketleme................................................packing parametre................................................parameter parantez ..................................................parenthesis pencere ...................................................window plan.........................................................schema program ..................................................program program sayacı........................................program counter programcı................................................programmer programlama dili.....................................programming language rakam......................................................digit rastgele eri şimli bellek............................random access memory (RAM) rastgele sayı ............................................random number referans ...................................................reference referans ile ça ğrı .....................................call by reference saat..........................................................clock sabit ........................................................constant sa ğa yana ştırma.......................................right justify saklama...................................................save, store salt okunur bellek....................................read only memory (ROM) satır ilerletme..........................................line feed satırba şı...................................................carriage return satıriçi .....................................................inline sayaç .......................................................counter sayfa ilerletme.........................................form feed sayı gösterimi..........................................number representation sayıcı.......................................................enumerator sayılı .......................................................enumerated sayım.......................................................enumeration sayısal .....................................................digital, numeric sayısal tu şlar ...........................................numerical keypad seçme......................................................select sekizli......................................................octal sıfır doldurma .........................................zerofill sıfırlama..................................................reset sıfırların kaldırılması ..............................zero suppression sı ğa .........................................................capacity sıkı ştırma ................................................compression sınama.....................................................test 196 TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ EK H sınıf.........................................................class sınıflandırma...........................................taxonomy sınırlayıcı ................................................delimiter sıra ..........................................................order, sequence sıralama ..................................................sort sıralı eri şim.............................................sequential access silme .......................................................clear simge ......................................................symbol sistem......................................................system sola yana şık ............................................left justified sonek.......................................................postfix sorgu(lama).............................................query soyut .......................................................abstract sözcük.....................................................word sözcük i şleme..........................................word processing sözcük uzunlu ğu .....................................word length sözde kod................................................pseudo code sözde komut............................................pseudo instruction sözdizim..................................................syntax sözdizimsel .............................................syntactic süreç .......................................................process sürücü .....................................................driver; drive şifre.........................................................password şimdiki ....................................................current taban .......................................................base tahteravalli ..............................................flip flop tampon....................................................buffer tamsayı....................................................integer tanım.......................................................definition tanımlama ...............................................define tanımlayıcı ..............................................descriptor tanımsız...................................................undefined tanıtıcı sözcük.........................................identifier tarama .....................................................scan tasarım ....................................................design ta şınabilir................................................portable ta şma.......................................................overflow tekli.........................................................unary temel adres..............................................base address ters bölü..................................................backslash tez sıralama.............................................quick sort tikel.........................................................partial tip............................................................type toplama ...................................................add tutamak ...................................................handle EK H TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ 197 tuzak .......................................................trap tümle şik ..................................................integrated türetilmi ş tip............................................derived type uç ............................................................terminal uyarı mesajı ............................................warning message uyarlama .................................................version uygulama ................................................application uyumlu....................................................compatible uzaklık ....................................................offset üç nokta, ... .............................................ellipsis üçlü.........................................................ternary üçlü harf..................................................trigraph üs ............................................................exponent; superscript üye ..........................................................member varsayılan de ğer......................................default value vazgeçme ................................................abort ve ............................................................and veri..........................................................data veritabanı................................................database versiyon ..................................................version veya ........................................................or yama .......................................................patch yan etki ...................................................side-effect yana ştırma...............................................justify yanıt süresi..............................................response time yapay anlayı ş ..........................................artificial intelligence yapı .........................................................structure yapı adı ...................................................structure tag yapıiçi .....................................................intrinsic yapısal.....................................................structured yardımcı program ...................................utility yayılma aralı ğı ........................................range yazıcı ......................................................printer yazılım....................................................software yazım ......................................................notation yazma-koruma ........................................write-protect yazmaç....................................................register yedek(leme) ............................................backup yeni satır .................................................newline yeniden yönlendirme...............................redirection yeniden yükleme.....................................restore yerde ği şir ................................................relocatable yerel........................................................local yerle şen (- şik) .........................................resident yerpayla şım.............................................overlay 198 TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ EK H yı ğıt.........................................................stack yıldız.......................................................asterisk yineleme .................................................iteration yinelemeli ...............................................iterative yol...........................................................path yonga ......................................................chip yordam....................................................procedure, routine yorumlayıcı.............................................interpreter yöntem....................................................method yöre.........................................................locale yumu şak disk ..........................................floppy disk, diskette yükleme ..................................................load yükleyici .................................................loader yüksek düzeyli dil...................................high level language yürütme...................................................execution yürütülebilir ............................................executable zaman uyumsuz.......................................asynchronous zamanpayla şım .......................................timesharing zil............................................................bell H.2. İngilizce-Türkçe Sözlük abort........................................................dü şürme, vazgeçme absolute address......................................mutlak adres abstract ...................................................soyut access......................................................eri şim access mode............................................eri şim modu accumulator ............................................birikeç acronym..................................................kısaad activity....................................................i şleklik actual address .........................................gerçek adres add ..........................................................toplama address....................................................adres address of................................................adres alma addressing...............................................adresleme algorithm.................................................algoritma allocation ................................................ayırma alphanumeric ..........................................alfasayısal analog .....................................................örneksel analysis ...................................................çözümleme and ..........................................................ve angular bracket, <>.................................açılı parantez application ..............................................uygulama argument.................................................argüman EK H TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ 199 architecture .............................................mimari arithmetic and logic unit (ALU) .............aritmetik mantık birimi array........................................................dizi artificial intelligence ...............................yapay anlayı ş assembler ................................................birle ştirici assembly language ..................................birle ştirici dil assignment statement ..............................atama deyimi associativity ............................................birle şme asterisk....................................................yıldız asynchronous ..........................................zaman uyumsuz attribute...................................................nitelik automatic ................................................özdevimli, otomatik automation ..............................................özdevinim, otomasyon backslash ................................................ters bölü backspace................................................geri alma backtrack ................................................geriye dönü ş (yapma) backup ....................................................yedek(leme) base.........................................................taban base address............................................temel adres bell..........................................................zil binary......................................................ikili binary coded decimal (BCD)..................ikili dü ğümlenmi ş onlu yazım bit............................................................bit, ikil bitwise ....................................................bitsel blank.......................................................bo ş block.......................................................blok, öbek Boolean algebra......................................Boole cebiri bootstrapping..........................................önyükleme brace, {} .................................................çengelli parantez bracket, [] ...............................................kö şeli parantez branch.....................................................dal branching................................................dallanma breakpoint...............................................kesilme noktası buffer ......................................................tampon bug..........................................................hata byte .........................................................bayt cache memory.........................................ön bellek call ..........................................................ça ğırma, ça ğrı call by reference .....................................referans ile ça ğrı call by value............................................de ğer ile ça ğrı cancel......................................................iptal capacity...................................................sı ğa carriage return.........................................satırba şı cast..........................................................kalıp central processing unit (CPU).................merkezi i şlem birimi (M İB) 200 TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ EK H character .................................................karakter character sequence..................................karakter sırası chip.........................................................yonga circuit......................................................devre class ........................................................sınıf clear ........................................................silme clock .......................................................saat coaxial ....................................................e şmerkezli code ........................................................kod coding.....................................................kodlama command ................................................komut comment .................................................açıklama communication .......................................ileti şim compatible ..............................................uyumlu compile ...................................................derleme compiler..................................................derleyici compound statement ...............................bile şik deyim compression............................................sıkı ştırma computer.................................................bilgisayar computer aided design (CAD) ................bilgisayar destekli tasarım conditional branch ..................................ko şullu dallanma configuration...........................................görünüm constant...................................................de ği şmez, sabit content ....................................................içerik context ....................................................ba ğlam control.....................................................kontrol, denetim control character .....................................kontrol karakteri control flow ............................................kontrol akı şı conversion ..............................................dönü şüm conversion specification .........................dönü şüm tanımlaması convert....................................................dönü ştürme copy ........................................................aktarma, kopyalama counter....................................................sayaç current..................................................... şimdiki; akım cursor......................................................imleç data .........................................................veri database ..................................................veritabanı debug ......................................................hata düzeltme debugger .................................................hata düzelticisi decimal ...................................................ondalık decision...................................................karar declaration ..............................................bildirim declare ....................................................bildirme decode.....................................................kod çözme decrement ...............................................azaltma EK H TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ2 0 1 default value ...........................................varsayılan de ğer define......................................................tanımlama definition ................................................tanım delimiter..................................................sınırlayıcı derived type ............................................türetilmi ş tip descriptor................................................tanımlayıcı design......................................................tasarım destination ..............................................hedef device .....................................................aygıt digit.........................................................rakam digital......................................................sayısal dimension ...............................................boyut direct access............................................do ğrudan eri şim directive..................................................emir directory..................................................(alt)dizin disk .........................................................disk documentation ........................................belgeleme domain....................................................alan double precision .....................................çift duyarlık drive........................................................sürücü driver ......................................................sürücü dump.......................................................döküm dynamic ..................................................devingen editing.....................................................metin düzenleme editor.......................................................metin düzenleyici ellipsis, ...................................................üç nokta emulation ................................................benzetme encode.....................................................kodlama end of file (EOF) ....................................dosya sonu enumerated .............................................sayılı enumeration ............................................sayım enumerator..............................................sayıcı environment............................................ortam equality ...................................................e şitlik error ........................................................hata escape key...............................................kaçı ş tu şu escape seqence........................................kaçı ş sırası evaluate...................................................hesaplama executable...............................................i şletilebilir, yürütülebilir execution ................................................i şletme, yürütme exponent .................................................üs expression...............................................ifade extension.................................................geni şleme; dosya tipi external ...................................................dı şsal fetch........................................................getirme 202 TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ EK H field.........................................................alan file...........................................................dosya flag..........................................................bayrak flip flop...................................................tahteravalli floating point ..........................................kayan noktalı floppy disk..............................................yumu şak disk (disket) flowchart.................................................akı ş çizene ği form feed ................................................sayfa ilerletme formal .....................................................biçimsel format .....................................................biçim(lendirme) function...................................................fonksiyon generation ...............................................ku şak global......................................................küresel halt..........................................................durma handle .....................................................tutamak hardware .................................................donanım header .....................................................ba şlık heuristic ..................................................bulu şsal hexadecimal notation..............................onaltılı gösterim high level language.................................yüksek düzeyli dil host computer .........................................ana bilgisayar identifier .................................................tanıtıcı sözcük implementation .......................................gerçekle ştirme increment ................................................artım, artırma index.......................................................indis; dizin indexing..................................................indisleme indirect addressing..................................dolaylı adresleme indirection operator ................................dolaylama i şleci information .............................................bilgi inheritance ..............................................kalıtım initialize..................................................ilkleme, ilk de ğer atama initializer.................................................ilkleyen inline.......................................................satıriçi input........................................................girdi input/output (I/O)....................................girdi/çıktı (G/Ç) installation ..............................................kurulu ş instruction...............................................komut integer.....................................................tamsayı integrated................................................tümle şik interactive ...............................................etkile şimli interface..................................................arabirim internal....................................................içsel interpreter ...............................................yorumlayıcı interrupt ..................................................kesinti intrinsic...................................................yapıiçi EK H TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ 203 iteration...................................................yineleme iterative...................................................yinelemeli job...........................................................i ş join..........................................................biti şme justify......................................................yana ştırma key ..........................................................anahtar keyboard .................................................klavye keyword ..................................................anahtar sözcük label ........................................................etiket language..................................................dil left justified.............................................sola yana şık library .....................................................kütüphane, kitaplık line feed ..................................................satır ilerletme link..........................................................ba ğlama linker.......................................................ba ğlayıcı list...........................................................liste load.........................................................yükleme loader......................................................yükleyici local ........................................................yerel locale ......................................................yöre logic........................................................mantık logical shift .............................................mantıksal kaydırma loop.........................................................döngü low level language ..................................dü şük düzeyli dil machine language ...................................makine dili macro......................................................makro main memory..........................................ana bellek mainframe...............................................ana bilgisayar maintenance............................................bakım manual ....................................................elkitabı mark........................................................i şaret mask........................................................örtü master slave ............................................a ğa köle match ......................................................e ş(le şme) maximum................................................enbüyük medium...................................................ortam member...................................................üye memory...................................................bellek menu .......................................................menü merge......................................................birle ştirme message...................................................mesaj method....................................................yöntem microprocessor .......................................mikroi şlemci minimum.................................................enküçük mnemonic ...............................................bellenir 204 TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ EK H mode .......................................................mod modular...................................................modüler monitor ...................................................monitör mouse......................................................fare multiple...................................................çoklu multiplexing............................................çoklama multiuser.................................................çok kullanıcılı multitasking ............................................çok i ş düzeni negation ..................................................olumsuzlama negative number .....................................olumsuz sayı nested......................................................içiçe network...................................................a ğ newline ...................................................yeni satır node ........................................................dü ğüm nonprint character...................................basılmayan karakter not...........................................................de ğil notation...................................................gösterim, yazım null character ..........................................bo ş karakter null string................................................bo ş dizgi number representation ............................sayı gösterimi numeric...................................................sayısal numerical keypad....................................sayısal tu şlar object ......................................................nesne object oriented ........................................nesneye dayalı object program........................................amaç program octal ........................................................sekizli offline .....................................................çevrimdı şı offset.......................................................konum, uzaklık online......................................................çevrimiçi opcode ....................................................i şlem kodu operand...................................................i şlenen operating system.....................................i şletim sistemi operation.................................................i şlem operator...................................................i şleç, i şlemci, i şlem operatörü optimal....................................................eniyi optimizing...............................................eniyile ştirici optional...................................................iste ğe ba ğlı or ............................................................veya order .......................................................düzen, sıra output......................................................çıktı overflow..................................................ta şma overlay....................................................yerpayla şım packing ...................................................paketleme parameter................................................parametre parenthesis..............................................parantez, ayraç EK H TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ 205 parity.......................................................e şlik parser ......................................................ayrı ştırıcı partial......................................................tikel partitioning .............................................ayırma pass.........................................................geçi ş password................................................. şifre patch .......................................................yama path.........................................................yol pattern.....................................................kalıp peripheral................................................çevresel personal computer (PC)..........................ki şisel bilgisayar pipelining................................................küme komut i şleme piping......................................................küme komut i şleme pixel........................................................görüntü noktası plotter .....................................................çizici pointer.....................................................gösterge portable...................................................ta şınabilir position...................................................konum positive number ......................................olumlu sayı postfix.....................................................sonek precedence..............................................öncelik precision .................................................duyarlık prefix ......................................................önek preprocessor ...........................................öni şlemci printer .....................................................yazıcı priority....................................................öncelik procedure................................................yordam process....................................................süreç processing...............................................i şleme program ..................................................program program counter......................................program sayacı programmer ............................................programcı programming language ...........................programlama dili prompt ....................................................ileti property ..................................................özellik pseudo code ............................................sözde kod pseudo instruction...................................sözde komut qualifier ..................................................niteleyici query.......................................................sorgu(lama) queue ......................................................kuyruk quick sort ................................................tez sıralama radix........................................................kök random access memory (RAM) ..............rastgele eri şimli bellek random number.......................................rastgele sayı range .......................................................erim, alan, yayılma aralı ğı 206 TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ EK H read only memory (ROM) ......................salt okunur bellek readability...............................................okunaklılık real time..................................................gerçek zaman record......................................................kayıt recursion .................................................özça ğrı recursive .................................................özça ğrılı redirection...............................................yeniden yönlendirme reference .................................................referans, kullanma register....................................................yazmaç relation....................................................ili şki relational.................................................ba ğıntısal, ili şkisel relative address.......................................göreli adres reliability ................................................güvenilirlik relocatable ..............................................yerde ği şir reserved word .........................................ayrılmı ş sözcük reset ........................................................sıfırlama resident ...................................................yerle şen, yerle şik resolution................................................çözünülürlük response time..........................................yanıt süresi restore.....................................................yeniden yükleme retrieval...................................................eri şim return ......................................................dönü ş right justify .............................................sa ğa yana ştırma routine.....................................................yordam run...........................................................geçi ş run time...................................................geçi ş süresi save.........................................................saklama scalar.......................................................basamaklı scan.........................................................tarama schema ....................................................plan scheme ....................................................düzen scope.......................................................etki alanı screen......................................................ekran scroll.......................................................kayma search......................................................arama section.....................................................kısım sector ......................................................kesim seek.........................................................arama segment...................................................kesim select.......................................................seçme semantic..................................................anlambilimsel, anlamsal semantics ................................................anlambilim separator .................................................ayırıcı sequence .................................................sıra sequential access.....................................sıralı eri şim EK H TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ 207 set ...........................................................küme setup .......................................................kurgu shell ........................................................kabuk shift.........................................................kaydırma side-effect ...............................................yan etki sign .........................................................i şaret sign bit ....................................................i şaret biti significant digit.......................................anlamlı rakam simulation ...............................................benzetim size..........................................................boy slash........................................................bölü software ..................................................yazılım sort..........................................................sıralama source program.......................................kaynak program space character .......................................bo şluk karakteri special character .....................................özel karakter specifier ..................................................belirteç stack........................................................yı ğıt statement.................................................deyim static .......................................................dural, dura ğan storage allocation....................................bellek ayırma storage class............................................bellek sınıfı store ........................................................saklama string.......................................................karakter dizisi, dizgi structure..................................................yapı structure tag ............................................yapı adı structured................................................yapısal subprogram.............................................altprogram subroutine ...............................................altyordam subscript..................................................indis superscript ..............................................üs switch......................................................anahtar symbol ....................................................simge synchronous............................................e şzamanlı synonym..................................................e şanlamlı syntactic..................................................sözdizimsel syntax......................................................sözdizim system.....................................................sistem tab...........................................................durak table ........................................................çizelge tag...........................................................künye tail...........................................................kuyruk task .........................................................görev taxonomy ................................................sınıflandırma terminal...................................................uç 208 TÜRKÇE- İNG İL İZCE VE İNG İL İZCE-TÜRKÇE TER İMLER SÖZLÜ ĞÜ EK H ternary.....................................................üçlü test ..........................................................sınama text..........................................................metin threshold .................................................e şik timesharing .............................................zamanpayla şım toggle......................................................anahtar trace ........................................................izleme track........................................................iz transaction ..............................................hareket transfer....................................................aktarma translator.................................................çevirici trap..........................................................tuzak tree..........................................................a ğaç trigraph ...................................................üçlü harf truth table................................................do ğruluk tablosu truth-valued.............................................do ğruluk-de ğerli twos complement....................................ikiye tümler type .........................................................tip unary.......................................................tekli unconditional branch ..............................ko şulsuz dallanma undefined ................................................belirsiz, tanımsız underflow................................................altta şma underscore, _ ..........................................altçizgi union.......................................................birlik unit..........................................................birim unpack ....................................................açma unsigned..................................................i şaretsiz update .....................................................güncelle ştirme user .........................................................kullanıcı user-defined ............................................kullanıcı-tanımlı utility ......................................................yardımcı program validate ...................................................do ğrulama variable ...................................................de ği şken verify ......................................................denetleme version ....................................................uyarlama, versiyon vertical....................................................dikey virtual memory........................................görüntü bellek warning message.....................................uyarı mesajı window ...................................................pencere word........................................................sözcük word length.............................................sözcük uzunlu ğu word processing......................................sözcük i şleme write-protect ...........................................yazma-koruma zero suppression .....................................sıfırların kaldırılması zerofill ....................................................sıfır doldurma 209 B İBL İYOGRAFYA Bach, Maurice J. The Design of the UNIX Operating System. Englewood Cliffs, NJ: Prentice-Hall, 1986. Bolon, C. Mastering C. Berkeley, CA: Sybex, 1986. Bolsky, Morris I. The C Programmer’s Handbook. Englewood Cliffs, NJ: Prentice-Hall, 1985. Brown, D. L. From Pascal to C. Belmont, CA: Wadsworth, 1985. Butzen, Fred, “Porting to ANSI C,” UNIX World, May-June 1989. BYTE. McGraw-Hill Inc., August 1983. BYTE. McGraw-Hill Inc., August 1988. Campbell, Joe. Crafting C Tools for the IBM PCs. Englewood Cliffs, NJ: Prentice-Hall, 1986. Costales, Bryan. C: From A to Z. Englewood Cliffs, NJ: Prentice-Hall, 1985. Curry, David A. Using C on the UNIX System: A Guide to System Programming. Sebastopol, CA: O’Reilly & Associates, 1991. Feuer, Alan R. The C Puzzle Book. Englewood Cliffs, NJ: Prentice-Hall, 1982. Gehani, N. Advanced C: Food for the Educated Palate. Rockville, Md.: Computer Science Press, 1985. Hancock, Les and Morris Krieger. The C Primer. 2nd ed. New York, NY: McGraw-Hill, 1986. Harbison, Samuel P. and Guy L. Steele, Jr. C: A Reference Manual. Englewood Cliffs, NJ: Prentice-Hall, 1984. Holub, Allen. The C Companion. Englewood Cliffs, NJ: Prentice-Hall, 1987. 2 10B İBL İYOGRAFYA Holzner, Steven. PS/2-PC Assembly Language. New York, NY: Brady, 1989. Jaeschke, Rex, “Standard C: A status report,” Dr. Dobb’s Journal, August 1991. Kelley, A. and I. Pohl. An Introduction to Programming in C. Menlo Park, CA: Benjamin/Cummings, 1984. Kernighan, Brian W. and Dennis M. Ritchie. The C Programming Language. Englewood Cliffs, NJ: Prentice-Hall, 1978. Kernighan, Brian W. and Dennis M. Ritchie. The C Programming Language. 2nd ed. Englewood Cliffs, NJ: Prentice-Hall, 1988. Ladd, Scott Robert. C++ Techniques and Applications. Redwood City, CA: M&T Books, 1990. Lippman, Stanley B. C++ Primer. 2nd ed. Reading, MA: Addison-Wesley, 1993. Microsoft® C for the MS-DOS® Operating System, Version 5.00, Run-time Library Reference. Microsoft Corporation, 1987. Microsoft® C for the MS-DOS® Operating System, Version 5.00, Mixed Language Programming Guide. Microsoft Corporation, 1987. Microsoft® Macro Assembler for the MS-DOS® Operating System, User’s Guide. Microsoft Corporation, 1985. Microsoft ® QuickC™ Compiler for IBM ® Personal Computers and Compatibles, Microsoft Corporation, 1987. Microsoft® Visual C++™ Development System for Windows™, Introduction (Presenting Visual C++). Redmond, WA: Microsoft Corporation, 1993. Microsoft® Visual C++™ Development System for Windows™, User’s Guides (Visual Workbench User’s Guide, App Studio User’s Guide). Redmond, WA: Microsoft Corporation, 1993. Microsoft® Visual C++™ Development System for Windows™, Programmer’s Guides (C++ Tutorial, Class Library User’s Guide, Programming Techniques). Redmond, WA: Microsoft Corporation, 1993. Microsoft® Visual C++™ Development System for Windows™, Professional Tools User’s Guides (Programming Tools for Windows, CodeView Debugger User’s Guide, Command-line Utilities User’s Guide, Source Profiler User’s Guide). Redmond, WA: Microsoft Corporation, 1993. Microsoft® Visual C++™ Development System for Windows™, Reference, Vol. 1-3 (Class Library Reference; C Language Reference, C++ Language Reference; Run- time Library Reference, iostream Class Library Reference). Redmond, WA: Microsoft Corporation, 1993. Microsoft® Visual C++™ Development System for Windows™, Comprehensive Index. Redmond, WA: Microsoft Corporation, 1993. B İBL İYOGRAFYA 2 11 Microsoft® Visual C++™ Development System for Windows™, C/C++ Version 7.0 Update. Redmond, WA: Microsoft Corporation, 1993. Oualline, Steve. Practical C Programming. Sebastopol, CA: O’Reilly & Associates, 1993. Plauger, P. J. and Jim Brodie. Standard C. Plum, Thomas. C Programming Guidelines. Englewood Cliffs, NJ: Prentice-Hall, 1984. Plum, Thomas. Learning to Program in C. Englewood Cliffs, NJ: Prentice-Hall, 1983. Plum, Thomas. Notes on the Draft C Standard. Cardiff, NJ: 1988. Prosser, David F. Draft proposed American National Standard for Information Systems— Programming Language C X3 Secretariat, CBEMA, Washington. Schildt, Herbert. Windows NT Programming Handbook. Berkeley, CA: Osborne McGraw-Hill, 1993. Stroustrup, Bjarne. The C++ Programming Language. Reading, MA: Addison-Wesley, 1986. Stroustrup, Bjarne. The C++ Programming Language. 2nd ed. Reading, MA: Addison- Wesley, 1993. Tanenbaum, Aaron M., Yedidyah Langsam, and Moshe J. Augenstein. Data Structures Using C. Englewood Cliffs, NJ: Prentice-Hall, 1990. Tanenbaum, Andrew S. Operating Systems: Design and Implementation. Englewood Cliffs, NJ: Prentice-Hall, 1987. The Waite Group. Advanced C Programming. Englewood Cliffs, NJ: Prentice-Hall, 1986. Tondo, Clovis L. and Scott E. Gimpel. The C Answer Book. 1st ed. Englewood Cliffs, NJ: Prentice-Hall, 1985. Tondo, Clovis L. and Scott E. Gimpel. The C Answer Book. 2nd ed. Englewood Cliffs, NJ: Prentice-Hall, 1988. Varhol, Peter D. Object-Oriented Programming: The Software Development Revolution. Charleston, South Carolina: Computer Technology Research Corp., 1993. Waite, M., S. Prata, and D. Martin. C Primer Plus. Indianapolis, IN: Howard W. Sams & Co., 1984. Wiener, Richard S. and Lewis J. Pinson. An Introduction to Object-Oriented Programming and C++. Reading, MA: Addison-Wesley, 1988. Williams, Mark. ANSI C Lexical Guide. Englewood Cliffs, NJ: Prentice-Hall, 1988. Wortman, Leon A. and Thomas O. Sidebottom. The C Programming Tutor. Englewood Cliffs, NJ: Prentice-Hall, 1984. 2 13 D İZ İN # #define, 12, 110 #elif, 113 #else, 113 #endif, 113 #error, 115 #if, 113 #ifdef, 113 #ifndef, 113 #include, 12, 112 #line, 115 #pragma, 115 #undef, 111 _ __asm, 162 __DATE__, 115 __FILE__, 115 __LINE__, 115 __STDC__, 115 __TIME__, 115 _cgets, 166 _close, 127 _creat, 126 _daylight, 181 _emit, 162 _exit, 125 _getch, 21 _getche, 21 _IOFBF, 125, 177 _IOLBF, 125, 177 _IONBF, 125, 177 _int86, 163 _lseek, 127 _O_CREAT, 127 _O_RDONLY, 127 _open, 127 _read, 127 _S_IREAD, 126 _S_IWRITE, 126 _timezone, 181 _tzname, 181 _write, 127 A abort, 177, 179 abs, 179 acos, 176 açıklama, 5 adım modu, 152 alan, 96 altdizin, 124 anahtar, 130 anahtar sözcük, 6 ANSI, 2 ANSI karakter kümesi, 136 ANSI Standardı, 3, 25, 92, 149, 169, 173, 181 argc, 68 argüman, 62 argv, 68 aritmetik kaydırma, 54 ASCII karakter kümesi, 135 asctime, 171, 181 2 14D İZ İN asin, 176 assert, 173 assert.h, 173 atama, 13 atan, 176 atan2, 176 atexit, 179 atof, 52, 179 atoi, 52, 179 atol, 52, 179 auto, 70 B ba ğlama, 59, 68, 146, 149 ba ğlayıcı, 59, 60, 63, 148, 159 ba şlangıç adresi, 80 ba şlık dosyaları, 12 ba şlık dosyası, 112 bayt, 46 bellek modeli, 146 bellek sınıfı, 69 bellek sınıfı belirteci, 93 beyaz karakter, 20 biçimsel argüman, 61, 111 bildirim, 72 bile şik deyim, 21 bire tümler i şleci, 54 birle şme, 14, 57 birle ştirici dil, 159 birlik, 95 bit, 46 bitsel i şleç, 53 blok, 21, 61 bo ş deyim, 30, 34, 37 bo ş karakter, 8, 9 break, 39 bsearch, 179 BUFSIZ, 125, 177 büyük model, 146 C C, 1 C++, 2 calloc, 98, 179 case, 41 ceil, 176 char, 10 CHAR_BIT, 175 CHAR_MAX, 175 CHAR_MIN, 175 clearerr, 178 clock, 172, 181 clock_t, 172, 180 CLOCKS_PER_SEC, 180 Codeview, 151 const, 10, 67 continue, 38 cos, 176 cosh, 176 ctime, 171, 181 ctype.h, 116, 173 C ça ğrı de ğer ile, 64, 160 referans ile, 64, 160 çevirme sınırları, 181 çıktı, 17 çokbaytlı karakter, 170 D DBL_DIG, 44, 174 DBL_EPSILON, 174 DBL_MANT_DIG, 174 DBL_MAX, 174 DBL_MAX_10_EXP, 174 DBL_MAX_EXP, 174 DBL_MIN, 174 DBL_MIN_10_EXP, 174 DBL_MIN_EXP, 174 DBL_RADIX, 174 DBL_ROUNDS, 174 default, 41 defined, 113 de ğer ile ça ğrı, 64, 160 de ği şken, 9 dı şsal, 72 dural, 71 otomatik, 70 yazmaç, 70 de ği şken gösterge, 50, 75 de ği şmez, 7 çift duyarlıklı, 8 dörtlü duyarlıklı, 8 karakter, 8 karakter dizisi, 9 kayan noktalı, 7 kısa tamsayı, 7 D İZ İN2 15 onaltılı, 7 sekizli, 7 tamsayı, 7 tek duyarlıklı, 8 uzun çift duyarlıklı, 8 uzun tamsayı, 7 de ği şmez gösterge, 50, 75 de ği şmez ifade, 35, 53, 73, 92, 94, 99, 113 dev adres, 145 dev model, 146 devam etme, satır, 9, 109 devingen dizi, 99 deyim, 29 difftime, 171, 181 div, 179 div_t, 178 dizi, 10, 99 do, 36 dos.h, 163 dosya, 119 dosya göstergesi, 120 dosya sonu, 21 dosya tanımlayıcısı, 126 dosya tutama ğı, 126 double, 10 dönü ş adresi, 77 dönü şüm tanımlaması, 18 E EDOM, 174, 176 else, 33 entry, 26 enum, 87 envp, 69 EOF, 21, 121, 124, 177 ERANGE, 174, 176 errno, 174, 176, 177, 179 errno.h, 174 etiket, 39 etiketli deyim, 39 etki alanı de ği şken, 69 tip bildirimi, 93 EXIT_FAILURE, 126, 179 EXIT_SUCCESS, 126, 179 exit, 102, 125, 179 exp, 176 extern, 72 F fabs, 176 fclose, 121, 125, 178 fcntl.h, 126 feof, 178 ferror, 178 fflush, 125, 178 fgetc, 178 fgetpos, 178 fgets, 122, 178 FILE, 120, 177 FILENAME_MAX, 177 float, 10 float.h, 12, 174 floor, 176 FLT_DIG, 174 FLT_EPSILON, 174 FLT_MANT_DIG, 174 FLT_MAX, 174 FLT_MAX_10_EXP, 174 FLT_MAX_EXP, 174 FLT_MIN, 174 FLT_MIN_10_EXP, 174 FLT_MIN_EXP, 174 FLT_RADIX, 174 FLT_ROUNDS, 174 fmod, 176 fonksiyon, 59 fonksiyon argümanı, 60 fonksiyon bildirimi, 64 fonksiyon göstergesi, 78 fonksiyon prototipi, 64 fonksiyon tanımı, 60 fopen, 119, 178 FOPEN_MAX, 177 for, 37 fpos_t, 177 fprintf, 122, 178 fputc, 178 fputs, 121, 178 fread, 124, 178 free, 98, 103, 179 freopen, 178 frexp, 176 fscanf, 122, 178 fseek, 123, 178 fsetpos, 178 ftell, 123, 178 fwrite, 124, 178 2 16D İZ İN G genel gösterge, 98 geni ş karakter, 170 geni şletilmi ş ASCII karakter kümesi, 135 gerçek argüman, 62 geriye dönü ş, 81 getc, 121, 178 getchar, 20, 121, 178 getenv, 179 gets, 122, 178 girdi, 17 girdi/çıktının yeniden yönlendirilmesi, 106 gmtime, 171, 181 goto, 39 gösterge, 45 gösterge aritmeti ği, 48 gözcü, 42 H harf ayırımı, 6 HUGE_VAL, 176 I INT_MAX, 175 INT_MIN, 175 if, 33 ifade, 13 de ği şmez, 10, 16 do ğruluk-de ğerli, 32 karı şık-tip, 16 ifade deyimi, 21 ifadelerin yeniden düzenlenmesi, 16, 54 ikili a ğaç, 103 ikili girdi/çıktı, 120 ikili i şleç, 46 ikili sistem, 7 ilk de ğer atama, 10 ilkleme, 10, 73 int, 10 io.h, 126 isalnum, 173 isalpha, 173 iscntrl, 173 isdigit, 174 isgraph, 174 isim, 6 islower, 174 isprint, 174 ispunct, 174 isspace, 174 isupper, 174 isxdigit, 174 i şleç, 13 addres alma, 46 adres alma, 20, 65, 79, 97 aritmetik, 13 artırma, 14 atama, 14, 55 azaltma, 14 ba ğıntısal, 30 bitsel dı şlayan VEYA, 54 bitsel VE, 54 bitsel VEYA, 55 do ğruluk-de ğerli, 30 dolaylama, 46 e şitlik, 31 kaydırma, 54 ko şullu, 34 mantıksal olumsuzlama, 30 mantıksal VE, 31 mantıksal VEYA, 32 üçlü, 35 virgül, 38 yapı üyesi, 91 i şlem operatörü, 13 i şlenen, 13 i şletim sistemi, 119 itoa, 52 izleme, 24, 152 J jmp_buf, 176 K kaçı ş sırası, 8 kalıp, 17, 89, 93 karakter dizisi, 51 karakter dizisi i şleme fonksiyonu, 51 kesilme, 152 kesilme noktası, 24 kesim, 145, 152, 160 kesinti, 163, 176 kısa model, 146 kod kesimi, 145 komut satırı argümanı, 68 kullanım, 11 küçük büyük harf ayırımı, 6 küçük model, 146 küme komut i şleme, 107 D İZ İN2 17 küresel de ği şken, 60, 69 kütüphane, 119 kütüphane fonksiyonu, 79 L L_tmpnam, 177 labs, 179 LC_ALL, 169, 175 LC_COLLATE, 169, 175 LC_CTYPE, 169, 175 LC_MONETARY, 169, 175 LC_NUMERIC, 169, 175 LC_TIME, 169, 175 lconv, 169, 175 LDBL_DIG, 175 LDBL_EPSILON, 175 LDBL_MANT_DIG, 175 LDBL_MAX, 175 LDBL_MAX_10_EXP, 175 LDBL_MAX_EXP, 175 LDBL_MIN, 175 LDBL_MIN_10_EXP, 175 LDBL_MIN_EXP, 175 LDBL_RADIX, 175 LDBL_ROUNDS, 175 ldexp, 176 ldiv, 179 ldiv_t, 178 LIB, 155 limits.h, 12, 175 locale.h, 175 localeconv, 169, 175 localtime, 171, 181 log, 176 log10, 176 long, 10 LONG_MAX, 175 LONG_MIN, 175 longjmp, 176 ltoa, 52 M MAKE, 156 makro, 110 malloc, 98, 103, 179 mantıksal kaydırma, 54 math.h, 80, 176 MB_CUR_MAX, 179 MB_LEN_MAX, 175 mblen, 170, 179 mbstowcs, 170, 179 mbtowc, 170, 179 memchr, 180 memcmp, 180 memcpy, 180 memmove, 180 memset, 180 Microsoft C Derleyicisi, 147 minik model, 146 mktime, 172, 181 modf, 176 N NDEBUG, 173 NMAKE, 156 NULL, 49, 120, 177, 178, 179 O orta model, 146 otomatik tip dönü şümü, 16, 61, 73 Ö önceden tanımlanmı ş isimler, 115 öncelik, 14, 57 öni şlemci, 12, 109 örtme, 56 özça ğrı, 75, 82, 106 özça ğrılı fonksiyon, 75 öz-referanslı yapı, 104 P P_tmpnam, 177 parametre, 61 perror, 178, 179 pow, 176 printf, 18, 59, 122, 178 program açıklaması, 5 ptrdiff_t, 49, 177 putc, 120, 178 putchar, 20, 121, 178 puts, 122, 178 Q qsort, 179 QuickC çekirdek kütüphanesi, 146 QuickC kütüphanesi, 146 2 18D İZ İN R raise, 177 rand, 126, 179 RAND_MAX, 126, 178 rastgele eri şim, 123 realloc, 179 referans, 11 referans ile ça ğrı, 64, 160 register, 70 remove, 124, 178 rename, 124, 178 return, 61 rewind, 124, 178 S satır devam etme, 9, 109 satıriçi birle ştiricisi, 162 satıriçi kod, 111 sayıcı, 88 sayım künyesi, 87 sayım tipi, 87 scanf, 19, 122, 178 SCHAR_MAX, 175 SCHAR_MIN, 175 SEEK_CUR, 123, 177 SEEK_END, 123, 177 SEEK_SET, 123, 177 setbuf, 125, 178 setjmp, 176 setjmp.h, 176 setlocale, 169, 175 setvbuf, 125, 178 short, 10 SHRT_MAX, 175 SHRT_MIN, 175 SIG_DFL, 177 SIG_ERR, 177 SIG_IGN, 177 SIGABRT, 177 SIGFPE, 177 SIGILL, 177 SIGINT, 177 SIGSEGV, 177 SIGTERM, 177 sıralı eri şim, 123 signal, 177 signal.h, 176 signed, 10 sin, 176 sinh, 176 size_t, 94, 98, 177, 178, 179, 180 sizeof, 93, 94 sözcük, 46 sözcük sınırı, 96 sprintf, 123, 178 sqrt, 176 srand, 126, 179 sscanf, 123, 178 static, 71 stdarg.h, 177, 185 stddef.h, 49, 94, 177 stderr, 18, 120, 177 stdin, 18, 120, 177 stdio.h, 18, 119, 121, 177 stdlib.h, 52, 98, 102, 119, 178 stdout, 18, 120, 177 strcat, 52, 180 strchr, 52, 180 strcmp, 52, 180 strcoll, 180 strcpy, 51, 180 strcspn, 180 strerror, 180 strftime, 172, 181 string.h, 52, 179 strlen, 52, 180 strncat, 52, 180 strncmp, 52, 180 strncpy, 52, 180 strpbrk, 180 strrchr, 52, 180 strspn, 180 strstr, 180 strtod, 179 strtok, 180 strtol, 179 strtoul, 179 struct, 89 struct tm, 180 strxfrm, 180 switch, 40 sys\\stat.h, 126 sys\\types.h, 126 system, 125, 179 T tan, 176 tanh, 176 D İZ İN2 19 tanım, 72 tanıtıcı sözcük, 6 ta şınabilirlik, 3, 84 tekli i şleç, 46 temel adres, 47, 80 time, 171, 181 time.h, 171, 180 time_t, 172, 180 tip dönü şümü, 16, 53 otomatik, 16, 61, 73 tip niteleyicisi, 10, 67 tm, 180 TMP_MAX, 177 tmpfile, 178 tmpnam, 178 tolower, 53, 174, 179 toupper, 53, 174, 179 tutamak, 126 typedef, 93 U UCHAR_MAX, 175 UINT_MAX, 175 ULONG_MAX, 175 ungetc, 124, 178 UNIX, 1 unsigned, 10 USHRT_MAX, 175 uzak adres, 145, 160 uzaklık, 145, 152, 160 Ü üç nokta, 185 üçlü karakter, 170 üye, 90 V va_arg, 177, 185 va_end, 177, 185 va_list, 177, 185 va_start, 177, 185 varsayılan altdizin, 112, 115 veri dönü şüm fonksiyonu, 52 veri kesimi, 145 veri yapısı, 81, 104 vfprintf, 178 void, 60 void *, 98 volatile, 10 vprintf, 178 vsprintf, 178 W wchar_t, 170, 177, 178 wcstombs, 170, 179 wctomb, 170, 179 while, 35 Y yakın adres, 145, 160 yan etkisi, 14 yapı, 89 yapı künyesi, 90 yeniden yönlendirme, 106 yerel de ği şken, 60 yı ğıt, 77, 159 yı ğıt göstergesi, 77 yineleme, 78 yön bayra ğı, 162 yöre, 169