![]() |
C# Hakkında Herşey.
|
Cevap: C# Hakkında Herşey. C# Programlama Sanatı Programlama Sanatı Programcılar modern çağın ressamları, heykeltıraşları yani sanatçılarıdır. Programlama da sanatın ta kendisi. Bir başka açıdan baktığımızda da programlama bir bilim, programcı da bilim adamıdır. Bence her ikisi de doğru. Şöyle ki, programcı da sanatçının esin kaynağına yani ilhama dayanarak program yazar, aklına ilginç bir fikir gelir, bu fikri kendi araçlarını kullanarak başlar program halinde vücuda getirmeye. Programcının en büyük görevi, insanlar ile bilgi arasındaki iletişimi ve bağlantıyı sağlamaktır. İnsan yaşamını kolaylaştıran bu kutsal görev programcı olmayanlarca pek de önemsenmez. Geleceğin sanal şehirlerini kuranlar programcı dediğimiz gizli kahramanlardır. Yeni yazdığı programın kullanıldığını ve yararlı olduğun görmek ona her şeyi unutturur, programcı olmayanların asla anlayamayacağı bir haz verir. Bilgisayar kullanıcısı sayısı gün geçtikçe geometrik olarak artıyor ama bu tür bir haz bilgisayar kullanıcılarının büyük bir çoğunluğu tarafından asla yaşanmaz. Çünkü bilgisayar kullanıcılarının büyük bir çoğunluğu programcı değildir ve asla da olmayacaklar. Onlar sadece yazılan programları ve içerisinde yazılım gömülü akıllı cihazları kullanırlar. BİR PROGRAMLAMA DİLİ ÖĞRENMEK Programlama dili öğrenmeyi yabancı dil öğrenemeye benzetebilirsiniz. Mesela her ikinde de öğrenilmesi gereken, o dile özgü bir grup kelime var. Anahtar kelime diye adlandırdığımız bu kelimelerin c# dilindeki sayısı 77 tanedir. C dilinin geleneğini sürdürdüğü için de bu kelimeler küçük harflerle yazılır. Yabancı dil öğrenirken bir takım yazım ve dil bilgisi kuralları öğrenmek zorundayız. Programlama dilinin yazım ve dil bilgisi kuralları konuşulan dillerin kurallarına göre daha katıdır. Programlama dili ile yabancı dil öğrenme arasındaki en büyük benzerlik bence her ikisinin de okuyarak öğrenilememesidir. Pratik yapmak zorundayız. Bir müzik aletini çalmayı öğrenirken olduğu kadar çok pratik yapmalıyız hem de. Bir programcı gibi düşünmeye ve kendi kodumuzu kendimiz yazmaya alışmalıyız. Programlama bir problem çözme etkinliğidir. Programcının tek en önemli kalite göstergesi problemleri bileşenlerine ayırma ve daha küçük parçalara bölerek çözebilme yeteneğidir. Programcının sorumluluğu bu küçük parçaları bir araya getirip çözümü oluşturmaktır. Bu beceri de bence sadece pratik yaparak gelişir. PROGRAMLAMA NEREDEN NEREYE Charles Petzold, bilgisayar devrimini iki evreye ayırır: Birinci evre bilgisayarların tasarlandığı ve yapıldığı zaman, ikinci evre ise onlarca yıl sonra bilgisayarların programcı olmayan kimseler tarafından da kullanılabilir olmasıdır. İlk programlanabilir bilgisayar 1930'lu yıllarda yapıldı. Uzun bir süre programlama işlemi delikli kartlar gibi mekanizmalar kullanılarak sağlandı. Bilgisayarın kendisine donanım, üzerinde çalışan kodlara da yazılım adı verildi. Bir kaç dekad boyunca donanım ve yazılım birbirine bitişikti. Her makinanın kendine özgü bir komut seti vardı ve bu komutlar başka makinalarda çalışmazdı. Sayısal tümleşik devreler kullanıldığı dönemlerde de bu durum devam etti. 1950'lerin başında mimariden bağımsız bilgisayar dilleri geliştirilmeye başlandı. Bu diller Makine kodu ile karşılaştırıldığında yüksek seviyeli diller olarak aklandırıldı. COBOL, BASIC, FORTRAN gibi diller hala farklı sürümleri ile hayattadır. Derlemek, Yorumlamak Bilgisayar sadece Makine kodunu çalıştırabilir. Öyleyse yüksek seviyeli dillerle yazılan program kodları Makine konuda dönüştürülmelidir. Derleyici, bir programı tamamen Makine koduna çevirirken yorumlayıcı bu işlemi eş zamanlı olarak yapar. Bilinen en eski programlama dillerinden birisi de ALGOL dilidir. 1950'li yıllarda uluslar arası bir komite tarafından geliştirildi ve uzun yıllar değişiklikler yapılarak kullanıldı. Hâlâ Pascal, PL/I ve C gibi dillerin temelini oluşturduğu için yaşamını sürdürmektedir. C Dilinin Serüveni Bell Laboratuarlarının etkisi olmadan çağdaş dünyayı düşünmek imkansızdır. 1947 yılında transistor orada icat edildi. 1970’lerde UNIX işletim sistemi orada geliştirildi.Uzun yıllar, büyük bir kısmı Dennis Ritchie tarafından geliştirilen C dili, UNIX işletim sistemi ile ilişkilendirilir. C dili tek harfle temsil edildiğinden bu adın nereden geldiği merak edilebilir: İlk olarak CPL (Combined Programming Language) dili vardı. BCPL (Basic CPL) dili daha sonra CPL dilinden esinlenerek geliştirildi. Sonraları BCPL dilinin basitleştirilmiş bir hali olan B dili ortaya çıktı. C dili de bu B dilinden türetildi. C ismi oradan gelir. ALGOL ve onun türevi olan dillerde, program parçaları BEGIN ve END kelimeleri arasına yazılır. C ise bu işi küme parantezlerini kullanak yapar. C’de yazılmış programların en belirgin farkı hızlı olmalarıdır. Çünkü C işaretçiler dediğimiz, bellek bölgelerine doğrudan erişmeye yarayan yapılara izin verir. Bazıları C’ye yüksek seviyeli assembly dili der. Çünkü C; bit, byte ve bellek düzeyinde çok iyi çalışır. Aslında bu yaklaşımın tehlikeli tarafı da var. Yüksek seviyeli dillerin derleyicileri program kodları derlenirken programın çökmemesi ve veri kayıplarına neden olmaması için fazladan kodlar eklerler. C derleyicisi ise hızlı program ortaya koyma adına, fazladan kod eklemez. Bu yüzden, dikkatli davranılmadığında hata oluşturmaya daha elverişlidir. Hatasız program olmaz ise de, C’de bu durum daha yaygındır. Hataların çoğunluğu işaretçi kullanmanın yol açtığı hatalardır. C, hala çok yaygındır ama bazı açılardan tarih olmuştur. Geleneksel prosedürel diller grubuna dahil edilmektedir. Program içerisinde belirli bir işi yapan ya da algoritmayı gerçekleştiren program parçasına prosedür denir. Bir C programı da, bir grup prosedür ya da fonksiyondan oluşur. Fonksiyonlar, devamlı veriler ile çalışır. Prosedürel yapıda bu veriler ile program kodu iç içe bulunur. Nesne yönelimli programlama terimini çok sık duymaya başladık. Nesne yönelimli programlama dillerinin (OOP) ilki Palo Alto Araştırma Merkezinde (PARC) geliştirilen SmallTalk dilidir. PARC, Microsoft Windows ve Apple Machintosh’ta da kullanılan grafiksel kullanıcı arayüzü kavramlarını geliştiren Xerox tarafından kurulan araştırma laboratuarıdır. Nesne yönelimli dilde, programcılar prosedürler yerine sınıflar oluştururlar, kodların ve verilerin birleşiminden oluşan nesneler de bu sınıflardan türetilir. Programlamadaki bu bakış açısı değişimi, çeşitli programlama işlerinde tekrar tekrar kullanılabilecek kodlar yazmaya olanağı sağladı. C dilinin de nesne yönelimli sürümünü yazmak isteyenler oldu. 1980lerin başında Bjarne Stroustrup tarafından Bell laboratuarlarında C++ (Si plas plas okunur) geliştirildi. C++ dilinin adında geçen ++, C dilinde bir sayıya 1 eklemek için kullanılır, yani sayının değeri 1 artar. C++ dili, C’nin tüm özelliklerine sahip ama nesne yönelimli olması için bir takım ek özellikler katılmış hali diye özetlenebilir. Ama bu yapı biraz hantal bir yapı oldu. Çünkü C’de olan her şeyi destekleme kaygısı ile garip bir notasyon ortaya çıktı. Bu hantal yapının yanında, baş edilmesi gereken bir sorun daha vardı. Bilgisayar donanımı hızla gelişiyor. Gereğinden fazla hızlı işlemciler ve gereğinden fazla bellek var. Bir program yazılırken dikkat edilen temel kriterler değişti. Eskiden performans ve ekonomik kaynak kullanımı iken şimdilerde yerini daha hızlı ve hatadan arınmış kod yazmaya bıraktı. Bu da alçak seviyeli yapıdan hızla uzaklaşma ve işaretçi kullanımının azalması demekti. Artık programcılar işaretçi kullanmaktan kaçınıyorlar. 1990’larda Sun Microsystems, C++ dilinden daha esnek bir notasyona sahip olan, daha güvenli kod yazmayı olanaklı kılan bir yapı ortaya koydu, yani Java dilini geliştirdi. C#’ın Doğuşu Borland firmasından ayrılan Anders Hejlsberg, 20002li yılların başında Microsoft için C# (Si Şarp okunur) dilini geliştirdi. C#’taki diyez işareti (şarp), C++ taki ++ ın 2 tanesinin üst üste koyulmuş halidir. C# Java gibi, C# da C’nin tehlikeli özelliklerini almadı. Ama işaretçiler C#’tan tamamıyla çıkarılmadı. Java ile C# arasındaki diğer bir benzerlik, derleyicinin rolündedir. Geleneksel olarak, derleyici kaynak kodu (yüksek seviyeli dil metin dosyası) makina koduna çevirir. Makina kodu, bilgisayar tarafından çalıştırılabilir bir formdadır. Bu da Microsoft Windows ile Apple Machintosh üzerinde aynı programın çalıştırılamayacağı anlamına geliyor. C# derleyicisi, kaynak kodu bir ara dile (IL) çevirir. Program çalıştırılacağında ise IL makina koduna dönüştürülür. Bunu kullanıcı fark etmez. Teorik olarak, bu iki adımlı işlem, aynı IL kodunun farklı makinalarda da çalışabilmesine olanak tanır. Ayrıca IL formundaki bir programda bulunan kötü ve zararlı kod işletim sistemi tarafından kolaylıkla tetkik edilebilir. |
Cevap: C# Hakkında Herşey. .Net Framwork .net Framework Bu bölümde .net Framework nedir sorusuna cevap verip .NET Framework Redistributable ile .NET Framework SDK uygulamaları arasındaki farklardan bahsedeceğiz. Sonra da .NET Framework Redistributable uygulamasını adım adım kurmayı öğreneceğiz. .net Framework Nedir? Bir çok uygulama geliştirme dili var. Bu dillerle yazılmış uygulamaları çalıştırmak için ise farklı platformlar var. .net Framework, windows tabanlı uygulamalar geliştirebilmek için farklı programlama dillerinin birlikte çalışabileceği ortak bir geliştirme ortamıdır. Bu ortam hem yazılımları geliştirmek hem de çalıştırmak için gereklidir. .net Framework aşağıdaki bileşenlerden oluşur:
|
Cevap: C# Hakkında Herşey. C# Atama İşlemleri C# ile program yazmaya ilk adım: Atama İşlemleri Programlamaya başlarken, ilk olarak onu matematiğe benzetebiliriz. Mesela ilk yazacağımız programlardan biri de iki tane sayıyı toplayıp sonucunu ekrana yazdırmak olabilir. Ama tabiki matematikteki her şey programlamada da olduğu gibi var anlamına gelmiyor. Bu farkları başlarda iyi anlarsak programlama mantığını kavramakta zorluk çekmeyiz. Şimdi matematiksel bir ifade görelim: 1 A = 1 2 B = 2 3 C = A + B Oldukça anlaşılır ifadeler. Şimdi bu işlemi C# dilinde yazalım: 1 A = 1; 2 B = 2; 3 C = A + B; Yukarıda görülen program parçasında A, B ve C ifadeleri değişken olarak adlandırılır. Değişkenler basitçe kendilerine atanan değerleri saklayan bellek bölgelerini sembolize eder diye tanımlanabilir. Görüldüğü gibi C# kodu ile matematiksel ifade arasında sadece sonlara konulan noktalı virgül farkı var. Ama bu benzerlik aldatıcıdır. 1 A = 1; 2 C = A + B; 3 B=2; Yukarıdaki program parçası matematiksel olarak anlamlı olsa da programlama açısından anlamsızdır. Matematikte eşittir işareti eşitlik bildirmek için kullanılır. Bu yüzden matematiksel olarak bu ifadeyi gördüğümüzde C’nin 5 olacağını rahatlıkla söyleyebiliriz. C#’ta eşittir ifadesi atama operatörüdür. Program kodları satır satır sırayla derlenir. İlk satır derlendiğinde A değişkenine 1 değeri atanır. C# derleyicisi, daha henüz değeri belli olmayan B ifadesini kullanan 2. satıra geldiğinde ne yapacağını bilemez ve hata olduğunu bildirir. Operatörler, bilgisayarın bir işlemi gerçekleştirmesini sağlayan semboller ya da kısa kelimelerdir. Mesela yukarıdaki program kodlarındaki eşittir ifadesi atama operatörüdür. Operatörlerin sağındaki ve solundaki ifadelere ise operand denir. Atama operatörünün de 2 tane operandı vardır. Atama operatörünün solundaki ifade mutlaka bir değişken olmalıdır. Sağındaki ifadelerin hesaplanması sonucu oluşacak değer solundaki değişkene atanır. Artı işareti de aritmetik operatörlerden biridir. Operatörlerin tamamı ileride geniş bir şekilde işlenecektir. Burada kısaca bahsettik. Atama işlemi sadece yukarıda verdiğimiz örnekteki gibi değildir. Aşağıda gördüğünüz atamaların hepsi C#’ta geçerlidir: 1 C = A + 3; 2 C = 27 + A + B; 3 C = B + A + A + B + A + B + 14; 4 C = 45 + 27; A=A+1 MESELESİ Matematiksel olarak hiçbir anlamı olmayan ama programlamada kullanılan bir ifade var. Bunu ilk defa öğrenirken doğru anlarsanız, daha sonra zorluk çekmezsiniz. 1 A = 11; 2 A = A + 1; Atama yaparken göz önüne alınacak en önemli kural atamaların daima sağdan sola doğru olduğudur. Yukarıdaki örneğin 1. satırında A değişkenine 11 değeri atandı. Daha sonraki satırda ise A değişkeninin değeri olan 11 ile 1 toplanıp hesaplanan değer A değişkenine atandı. Kısacası A’nın yeni değeri 12 oldu. Negatif sayıları da bir eksi işareti ile gösteririz. 1 A = -11; Aşağıdaki ifade matematikte geçerli olmasına rağmen programlamada geçersizdir. 1 A + 2 = 4; Değişkenlere değerleri değişebildiği için değişken denmiştir. Aşağıdaki örneği inceleyelim. 1 A = 10; 2 B = -2; 3 C = A + B; 4 B = 5; 5 C = A + B; Yukarıdaki örneğin 3. satırında C 8’e eşit oluyor. 4. satırda B’nin değeri değişerek 5 oluyor. 5. satırda ise C’nin değeri 15 oluyor. C#’ta program yazarken satır kavramı yoktur. ALGOL dilinden türeyen diğer dillerde olduğu gibi C#’ta da her ifadenin sonuna noktalı virgül konur. İfadenin bittiği yerden hemen bir yenisi başlayabilir, bir ifade birden çok satıra bölünebilir. 1 A=3;B=2;C=A+B; 2 3 A = 10; 4 B 5 = -2; 6 C = A 7 + B; Yukarıda verilen örneklerden her ikisi de doğrudur. C#’ta her ikisine de izin verilir. Programlamada boşluklar ve boş satırlar, alfabe dışı karakter olarak bilinir. Programcılar alfabe dışı karakterleri programlarını daha okunur yapabilmek için kullanırlar. Mesela ben, atama ve aritmetik operatörlerde operatörün sağında ve solunda 1 karakterlik boşluk bırakmayı severim: 1 C = 3; 2 B = 27; 3 A = B + C; C# büyük- küçük harfe duyarlı bir programlama dilidir, değişken isimlendirirken küçük harf ve büyük harf kullanabilirsiniz. Aşağıdaki örnekte her üç değişken de diğerinden farklıdır. Ama yine de program yazarken karışıklığa mahal vermemek için birbirine sadece bir harfin büyük ya da küçük olması kadar benzeyen değişken isimleri kullanılmaz. 1 Antalya = 38; 2 antalya = 36; 3 ANTALYA = Antalya + antalya; İSİMLENDİRME KURALLARI Değişkenleri isimlendirirken dikkat edilecek kurallar vardır ama bu kurallar son derece basittir:
Birden çok kelime içeren değişkenlerin isimlendirilmesi için yaygın olan iki yaklaşım çok sık görülür. Birincisi her kelimeler arasına alt çizgi koyarak küçük harflerle yazmaktır. Diğeri ise her kelimenin baş harfini büyük yazarak bitişik yazmaktır. Bu konuyu daha sonra isimlendirme notasyonlarını işlediğimiz ünitede geniş bir şekilde işleyeceğiz. 1 okuldaki_ogrenci_sayisi = 500; 2 Deney41 = 36; 3 OgretmenlerinSayisi = 46; 4 _sonuc = 12; Değişken ismi olarak kullanılamayacak kelimeler vardır. Bunlara anahtar kelime denir, bunlar C# tarafından ayrılmış kelimelerdir. 77 tanedir. Bunların listesini inceleyiniz. Değişkenlere isim verirken X, A, B gibi isimler verebilirsiniz. Ama sizin yazdığınız programa birisi devam edecekse, siz daha sonra dönüp bakacaksanız anlamlı isimler vermeniz gerekiyor. 1 OgrenciNumarasi = 36; 2 BirinciYaziliSonucu = 85; 3 SozluNotu = 90; 4 YazililarinOrtalamasi = 86; Ama değişkenlere uzun isimler vermek de sıkıcı olabilir. Onun yerine anlamlı kısaltmalar yapmak daha mantıklıdır. 1 OgrNo = 36; 2 Yazili1 = 85; 3 Sozlu = 90; 4 Ort = 86; |
Cevap: C# Hakkında Herşey. C# Türlerinin Belirlenmesi Türlerin Tanımlanması 05 Ocak 2006 C#’ta bir değişkeni kullanmadan önce onun türünü tanımlamak zorundayız. Bir değişken program içerisinde yalnızca bir kere tanımlanabilir. Bir sayı C#’ta üç farklı türde olabilir. Canlıların sayısını yazıyorsak tamsayıları kullanmak isteyebiliriz. Eğer yazdığımız programda para miktarı bulunuyorsa bunun için desimal sayılar gerekecektir. Mesela 2 YTL 50 YKr gibi. Eğer bilimsel rakamlar içeren bir program yazıyorsak bilimsel notasyonu kullanmalıyız. Programlamada bu tür sayılara kayar noktalı sayılar denir. Bir programın içinde her üç türden de sayılar bulunabilir. Şimdilik sadece tamsayı türünden örnekler yapalım. Daha sonra her bir türü ayrı bir ünite olarak işleyeceğiz. Şimdi bir tamsayı tanımlayalım. 1 int Elma; Aşağıdaki örnekte değişkenler tanımlanacak ve değer ataması yapılacaktır. 1 int Elma; 2 int Armut; 3 int Toplam; 4 5 Elma = 2; 6 Armut = 3; 7 Toplam = Elma + Armut; Aşağıdaki örnekte olduğu gibi bir satırda birden çok tür tanımlaması yapılabilir. 1 int Elma, Armut, Toplam; 2 3 Elma = 2; 4 Armut = 3; 5 Toplam = Elma + Armut; Bazı değişkenleri birlikte bazılarını da ayrı tanımlayabiliriz. 1 int Elma, Armut; 2 int Toplam; 3 4 Elma = 2; 5 Armut = 3; 6 Toplam = Elma + Armut; Tür tanımlamasını hep bir arada yapmak zorunda değiliz. Tek önemli kural değişkenelrin kullanılmadan önce tanımlanması gerektiğidir. 1 int Elma; 2 Elma = 2; 3 4 int Armut; 5 Armut = 3; 6 7 int Toplam; 7 Toplam = Elma + Armut; Bir değişkenin tür tanımlaması ve değer atama işlemi aynı ifade içinde yapılabilir. 1 int Elma = 2; 2 3 int Armut = 3; 4 5 int Toplam = Elma + Armut; Bir satırda birden çok değişkenin tanımlanması ve değer atanması aynı anda yapılabilir. 1 int Elma = 2, Armut = 3, Toplam = Elma + Armut; Ama bir satırda tanımlanan bütün değişkenlere değer ataması yapma zorunluluğu yoktur. Bazılarına değer ataması yapmayabiliriz. 1 int Elma, Armut = 3, Toplam; 2 Elma = 2; 3 Toplam = Elma + Armut; Bir tek satırda çok fazla değişken tanımlanması programın okunurluğunu ve hata ayıklamayı zorlaştırabilir. Kısa ve anlaşılır olmak iyi kodlanmış bir programda olması gereken özelliklerdendir. Aşağıdaki örnekte değişkenlerin tanımlanması ve değer atama işlemleri oldukça güzel yapılmıştır. 1 int Elma = 2; 2 3 int Armut = 3; 4 5 int Toplam = Elma + Armut; |
Cevap: C# Hakkında Herşey. C# ile ilk Program C# ile ilk Program Şimdiye kadar yaptığımz örneklerin hiç biri çalışır bir program değildi. Şimdi çalışabilecek komple bir program yazalım. C#’ta programlar yöntemlerden ve birbiri ile alakalı olan yöntemlerin gruplanarak oluşturduğu sınıflardan oluşur. Yöntem, belirli bir işi yapan program kodlarının bir araya gelerek oluşturduğu program bloğudur. Sonra bu yöntemleri gruplayarak sınıfları oluştururuz. En basit C# programı bir sınıftan ve o sınıfa üye bir yöntemden oluşur. Bir sınıfın içinde birden çok yöntem bulunabileceğine göre birisinin giriş noktası olması gerekir. Program çalıştığında ilk olarak hangi yöntem devreye girecek? Bu sorunun cevabı Main yöntemidir. Bilgisayar, sınıfın içindeki Main isimli yöntemi ilk olarak çalıştır. Daha sonra programcının belirlediği yönergeleri izleyerek diğer yöntemleri de çalıştırır. C# programında özel bir role sahip olan Main, bir anahtar kelime değildir. Eğer isterseniz Main isminde bir değişken de tanımlayabilirsiniz. Yöntemlerin girdileri ve çıktıları vardır. Örneğin öğrencinin bir dersten aldığı sınavların ortalamasını alan bir yöntemimiz varsa, öğrencinin sınavlardan aldığı sonuçlar yönteme girdi olarak geçilir ve geriye bu sınav sonuçlarının ortalaması olan puan döner. Başka bir ifadeyle söylersek, yöntemler; yöntem parametreleri olarak adlandırılan değişkenelri girdi olarak alırlar, bir takım işlemlere tabi tutarlar ve dönen değer olarak bir çıktı üretirler. Yöntemlerin bir belirteçleri bir de dönen değerleri olur. Bnular yöntem isminin soluna yazılır. Daha sonra yöntem isminin önüne parantez içerisinde aralarına virgül konularak yöntem parametreleri olan değişkenelr yazılır. Daha sonra yöntemin gövdesi gelir. Bu gövde küme parantezleri içerisine alınır. Eğer yöntemin bir dönen değeri yoksa dönen değer olarak void yazılır. Yöntem parametresi almayacaksa yöntem isminin önüne boş parantezler konur. Şimi Main yöntemini yazalım. 1 static void Main() 2 { 3 int Elma, Armut, Toplam; 4 5 Elma = 2; 6 Armut = 3; 7 Toplam = Elma + Armut; 8 } Çoğu programcı yöntem içeriğini girintili olarak yazmayı tercih eder. Ben de girintilemeyi severim. 1 static void Main() 2 { 3 int Elma, Armut, Toplam; 4 5 Elma = 2; 6 Armut = 3; 7 Toplam = Elma + Armut; 8 } Bazı programcılar sınıfın başlangıcını ve bitimini belirten küme parantezlerinden ilkini hemen sınıfın bildiriminin yapıldığı ilk satırın sonuna koyarlar. Ben bu şekilde yazmayı tercih etmiyorum. C# derleyicisi bizim girintileme tarzımızla ilgilenmez. Çalıştığınız şirket ya da birlikte çalıştığınız proje yöneticisi sizi bir tarzı kullanmaya zorlayabilir. Eğer böyle bir zorunluluk yoksa istediğiniz girintileme tarzını seçer devam edersiniz. Bir C# programında en temel birim yöntem değildir tabiî ki. Daha önce de bahsettiğimiz gibi en temel birim sınıftır. Yöntemler bir araya gelerek sınıfları oluştururlar. Mesela yukarıda yazdığımız Main de bir yöntemdir. Temel bir C# programı bir adet sınıftan ve bir de Main isminde yöntemden oluşur. Sınıflara isim belirlerken değişkenlerin isimlendirilmesinde dikkat ettiğimiz kurallar geçerlidir. Main kelimesi anahtar kelime olmamasına rağmen, Main isminde bir yönteme sahipse sınıf ismi olarak Main kullanılmaz. Sınıf bildirim de class kelimesi, sınıf ismi ve sınıf gövdesinden oluşur. Sınıf gövdesini de yine küme parantezleri içine alırız. Sınıf gövdesinde sınıfı oluşturan yöntemler bulunur. Sınıf içeriğini de girintilemek benim tercih ettiğim bir tarzdır. Demek oluyor ki yöntem içerikleri iki defa girintelenecek. Şimdi çalışan bir bütün C# programı yazalım. Bir sonraki ünitede de derleme ve çalıştırma işlemlerini inceleriz. 1 class BirProgram 2 { 1 static void Main() 2 { 3 int Elma, Armut, Toplam; 4 5 Elma = 2; 6 Armut = 3; 7 Toplam = Elma + Armut; Console.Writeline (Toplam); 8 } 8 } |
Cevap: C# Hakkında Herşey. C# Yaz, Derle, Çalıştır Yaz, Derle, Çalıştır Bir bilgisayar programı başlangıçta basit bir metin dosyası olarak hayata başlar. Mesela C# programları .cs uzantılı dosyalardır. Bir programın birden çok kaynak dosyası olabilir. Programı yazıp bitirdiğimizde programımızın kaynak dosyasındaki kodu, C# derleyicisi IL (Ara Dil) denilen bir koda çevirir. Genelde yazmış olduğumuz kod hatasız olmaz. Derleyici bir hata tespit ettiğinde bu hata ile ilgili gerekli bildirimleri yapar. Bu tür hatalara yazma zamanı hataları denir. Eğer herhangi bir hata bildirimi varsa geri dönüp programınızdaki hatayı düzeltmemiz gerekir. Derleme işlemini başarıyla tamamlarsak programın çalıştırılabilir EXE dosyası oluşur. Bu aşamadan sonra kontrol işletim sistemine geçer. Bazen yazdığımız programlar bellekte izin verilmeyen bir bölgeye ulaşmak ister. CLR bu durumda bir hata mesajı ile bizi uyarır. Bu tür problemler çalışma zamanı hatalarıdır veya istisna durumlardır. Aynı şekilde geriye dönüp hatayı düzeltmeliyiz. Bir programın yazma işlemi bittiğinde her şey tam gibi görünür, fakat genellikle problemsiz olmaz. Bazen hatayı yakalamak kolaydır ama program büyüdükçe yakalamak zorlaşır, hemen hemen imkânsız hale gelir. Derleme ve hata ayıklama ile ilgili yazılmış pek çok kitap var. Daha sonra bu kitaplardan birini alıp hata ayıklama üzerine de bilgi edinebilirsiniz. C# programı yazmak ve derlemek için birçok seçenek var. Microsoft tarafından üretilen Visual Studio 2005 paketi, .net ortamında yazılım geliştirme araçları içerir. 30 günlük deneme sürümü olan C# Express yazılımını Microsoft web sitesinden indirip deneyebilirsiniz. Ama bu kadar karmaşık bir geliştirme ortamı yerine Charles Petzold tarafından geliştirilen daha basit ve ücretsiz bir araç olan Key Of Csharp isimli araç başlangıç seviyesi bir kullanıcının işini görecektir. Biz de çalışmalarımızı bu aracı kullanarak yapacağız. Programı indirdikten sonra çalıştırdığımızda karşımıza kurulum ekranı gelecektir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Bu ekranda I aggree diye başlayan kutuyu işaretlersek üzerinde Install yazan buton aktifleşecektir. Install butonuna basıp programı kurma işlemine başlarız. Kırma işlemi tek adımda gerçekleşir ve OK butonuna basarak kurulumu bitiririz. Masaüstüne gelen kısayol simgesi yardımıyla programı açıp ilk kodlarımızı yazmaya başlayalım. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] File menüsünden New Project seçince proje ismi olaral Project01 yazan bir pencere gelir. O pencerede programın verdiği ismi kabul ediyorsak OK butonuna basıyoruz ve yeni bir projeye başlamış oluyoruz. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Program default olarak ürettiği dosyaları Belgelerim klasörü içerisinde Key of C# Projects klasörü altına Project01, Project02 gibi isimlerle kaydeder. Bu Project01 gibi klasörlerin içerisinde .cs uzantılı olan bizim yazdığımız kodları içeren kaynak dosya, .exe uzantılı derlenmiş çalıştırılabilir dosya ve .kcsproj uzantılı programın proje bilgilerini tuttuğu kendi özel dosyası bulunur. Şimdi daha önce yazdığımız örneği Key Of Csharp ile yazıp derleyelim. Önce bir Project ismi vererek programı açıyoruz. Örneğimizi editörde yazıyoruz. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Daha sonra örneğimizi yazıp Build menüsünden Compile seçtiğimizde aşağıdaki durum çubuğunda Ready yazar. Bu durumda yine Build menüsünden Run seçilerek ekran çıktısı görülebilir. Ama daha henüz ekran çıktısı üreten bir program yazamadığımız için sadece Pres any key to continue ibaresi çıkar, klavyeden bir tuşa bastığımızda da konsol ekranı kaybolur. Bu iki işlemi birlikte yapmaya yarayan Build menüsünde Compile and Run seçilirse ya da klavye kısayolu olan F8’e basılırsa da yine aynı ekran karşımıza gelir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Kullanıcı etkileşimi olmadığı için, hiçbir çıktı üretmediği için, hiçbir girdi almadığı için şu anda programımız bir işe yaramıyor. Ama temel bir C# programının bütün öğelerine sahip. Daha sonra ekrana bir şeyler yazan programlar da yazacağız. |
Cevap: C# Hakkında Herşey. C# Ekranda Yazı Yazdırmak Ekranda Yazı Yazdırmak 19 Şubat 2007 Program yazmanın iki boyutundan bahsedebiliriz, bunlar ise programcı açısından program ve kullanıcı açısından programdır. Program geliştiriciler olarak başlangıçta her iki kişi de biziz. Rolümüz programcıdan kullanıcıya değişince ya da kullanıcıdan programcıya değişince, bakış açımız da değişecektir. Mesela, programımızın verdiği çıktı, kullanıcı açısından girdidir. Kullanıcının programa girdiği veriler program açısından girdi, kullanıcı açısından çıktıdır. Burada bahsedilen girdi ve çıktı kavramları üzerinde durmak istiyorum. Programın dış dünyaya verdiği bilgiler, gösterdiği tepkiler çıktı olarak tanımlanırken, dış dünyadan aldığı bilgiler ise girdi olarak tanımlanır. Bir bilgisayar programı da aldığı girdileri yorumlar, saklar, bu bilgilere dayanarak dış dünyaya bir takım sonuçlar gönderir. Bu modele I/O modeli denir. I/O Modelleri Windows ortamında çalışan bir program kullanıcıdan girdileri klavye, mouse, buton ya da kaydırma çubukları gibi çeşitli kontroller yardımı ile alır. Bir Windows programı çıktıyı kullanıcıya yazı veya grafik olarak gösterir. Bir fırını çalıştıran program ise farklı bir kullanıcı I/O modeline sahiptir. Burada girdiler fırınını ön panelindeki butonlarla yapılır. Çıktılar ise fırının açılması, fırının kapanması, tepsinin döndürülmesi, ışığın yakılması şeklinde olacaktır. C ve C# gibi dillerde kullanıcı girdi ve çıktısı için özel bir model yoktur. Bu bir eksiklik gibi görünüyor fakat değil. Bunu şöyle söylemek daha doğru olacaktır: C#, kullanıcıyı herhangi bir girdi ve çıktı modelini kullanmaya zorlamaz. Siz yazdığınız programın nerede kullanılacağına göre girdi ve çıktı modelinizi kendiniz seçersiniz. Bu bölümde konsol ekranı yardımıyla kullanıcıya çıktı verebilen bir program yazmaya çalışacağız. Bunu yapmadan önce bazı kavramları açıklamakta yarar var. Ekranda yazı göstermeye yarayan System.Console.WriteLine() ve System.Console.Write komutlarıdır. Bu komutlar neden üç parçadan oluşuyor? Bu parçaların adları nelerdir? System bir isimuzayıdır. İsimuzayları C#’a C++ dilinden miras kalmıştır. İsimuzayları birbiri ile alakalı yöntemleri bir paket içinde toplamaya yarayan bir paketleme sistemidir. Bir isimuzayının içindeki bir yöntemin adı diğer bir isimuzayı içinde de bulunabilir. Bu da isimuzayının bir diğer işlevidir. System isimuzayı; kullanıcı ile iletişim kurmaya yarayan I/O modeli olan Console, matematiksel işlemlerin bir araya toplandığı Math gibi temel sınıfları içinde barındırır. Burada sınıf terimi geçti. Bir önceki bölümde de anlattığımız gibi, C# programının temel birimi sınıftır. Bunu daha doğrusu şöyle söylemek lazım: Nesne yönelimli dillerin temel birimi sınıftır. Sınıfların özellikleri ve yöntemleri vardır. Bir arabayı örnek alalım. Rengi, modeli fiyatı gibi özellikleri vardır. Hareket etmek, korna çalmak, durmak gibi yöntemleri vardır. Daha sonra bu temel araba sınıfından bir takım farklı özellik ve yöntemlere sahip olan otobüs, kamyon, minibüs gibi sınıflar türetiriz. Bu sınıfların örnekleri olan nesneler ise araba sınıfının niteliklerini taşırlar. Türetilmiş sınıftan oluşturulan nesne de türetilmiş sınıfın özelliklerini ve temel sınıfın özelliklerini taşır. Yöntemler ise sınıfın dış dünya ile etkileşimini sağlayan eylemleridir. Mesela Console sınıfının WriteLine yöntemi ekranda bir satır yazı gösterir. Write yöntemi ise ekranda yazı gösterir ama alt satıra geçmez işini bitirince. WriteLine yöntemini kullanan bir program bu yönteme bir argüman yollar: 1 System.Console.WriteLine(ToplamMeyve); Bazı programcılar parantez ile argümanı ayırmak için argümanın sağına ve soluna boşluk koymayı tercih ederler. 1 System.Console.WriteLine( Toplam ); WriteLine yöntemine bir değişkeni argüman olarak geçebildiğimiz gibi, bir sayısal ifadeyi de geçebiliriz. 1 System.Console.WriteLine( Elma + Armut ); Yukarıdaki iki satırı incelersek ilkinde bir işlemin sonucunu tutan değişkenin değerini yazdırıyoruz. İkincisinde ise işlemin kendisini direkt parantezlerin içine yazıyoruz. Sonucu hesaplayıp ekrana yazıyor. Eğer amacımız sadece 2 ve 3 sayılarının toplamını ekrana yazdırmak ise 1 System.Console.WriteLine( 2+3 ); yazabiliriz. using Direktifi Eğer programda birden fazla System.Console.WriteLine yöntem çağrısı yapıyorsak System isimuzayınu using direktifini sınıf tanımı yapmadan önce programımızın başına ekleriz. using direktifi ile tanımladığımız herhangi bir isimuzayına dahil sınıfların yöntemlerini çağırırken artık isimuzayı ismini yazmadan sadece sınf.yöntem() şeklinde yöntemi yazarız. Bu bize zaman kazandırır. using direktifine direktif denmesinin sebebi programın çalışma zamanında hiçbir işlevinin olmamasındandır. 1 Console.WriteLine(Toplam); Şimdi artık çalışan ve ekrana yazı yazan bir program yazalım. 1 using System; 2 class BirProgram 3 { 4 static void Main() 5 { 6 int Elma, Armut, Toplam; 7 8 Elma = 2; 9 Armut = 3; 10 Toplam = Elma + Armut; 11 Console.WriteLine ( Toplam ); 12 } 13 } |
Cevap: C# Hakkında Herşey. C# Aritmetik İşlemler Aritmetik İşlemlerAritmetik operatörler ve kullanım şekilleri Bilgisayarlar yapıları gereği, çeşitli matematiksel hesaplamaları gerçekleştirirler. Bu sebeple, C# ile temel matematiksel işlemlerin nasıl yapıldığını inceleyelim. Temel matematiksel işlemler derken toplama, çıkarma, çarpma ve bölme işlemlerini kastediyorum. Daha önceki bölümlerden, toplama işleminin C#’ta nasıl yapıldığını biliyoruz: 1 C = A + B; Bir tamsayıdan diğer bir tamsayıyı çıkarmak da bu kadar kolaydır: 1 C = A - B; Yukarıda yaptığımız işlemlerde kullandığımız artı ve eksi işaretlerinin her ikisi de aritmetik işaretlerdir. Bu işaretlere aynı zamanda ikili operatör de denilir. Bu durumda, bu işaretlere operatör, sağında ve solunda bulunan ifadelere de operand denir. İkili operatör denmesi de, işaretin sağında ve solunda iki tane operand bulunmasındandır. 1 C = A + -B; 1 C = -B + A; Yukarıdaki iki örneği incelersek, burada eksi işaretleri tekli operatördür. Çünkü bu işaretler B’nin değerini işlem sırasında negatif yapmak için orada bulunuyorlar ve sadece sağında bir operandı var. Toplama işlemi için bir ikili operatör olan artı işareti aynı zamanda tekli operatör olarak da kullanılabilir. 1 C = +A - +B; Ama bu örnekte olduğu gibi artı işaretinin değişkenin önünde olması hiçbir şeyi değiştirmez. O yüzden sırf olabileceğini göstermek için yazdığım bu tür bir ifadeyi daha sonra hiç yazmayacağım. C#’ta çarpma işlemi yapmak istediğimizde çarpma için gerçek dünyada kullandığımız gibi bir çarpı işaretinin olmadığını göreceksiniz. Bu işlemi asteriks ile yapıyoruz. Asteriks işareti genelde bütün programlama dillerinde çarpma için kullanılır. 1 Alan = En * Boy; Bazı programcılar asteriks için yıldız kelimesini kullanır, ama Alan eşittir En çarpı Boy demek istedikleri bellidir. Klavyede bölme işlemi için de, matematikteki bölme işareti yoktur. Bunun için bölü işaretini kullanacağız. 1 Saat = Dakika / 60; Saat eşittir dakika bölü altmış. Bölme İşlemi ve Sıfıra Bölünme Durumu Dört temel matematiksel işlemden kuşkusuz en zoru bölme işlemidir, çünkü tamsayılarla bölme işlemi yaparken bir takım problemler ortaya çıkar. Şimdi 3 tane ekmek var ve bunu 2 kişi eşit paylaşacaklar diye düşünelim. 1 int ekmek, kisi, hak; 2 ekmek = 3; 3 kisi = 2; 4 hak = ekmek / kisi; Bu örnekteki hak neye eşittir? Kesinlikle 1.5 değil, çünkü hak değişkeni tamsayı olarak tanımlanmış. ekmek ve kisi değişkenleri de tamsayı. Eğer gerçekten 1.5 çıksın istiyorsak o zaman başka yöntemler var, onları ilerde tartışacağız. Burada tamsayı olarak sonuç çıkmasının nedeni, iki tane tamsayı arasında yapılacak herhangi bir işlemin sonucunun yine tamsayı olması gerektiğidir. Bu kuraldan dolayı C#, iki tamsayı arasında bölme işlemi gerçekleştiğinde sonucun küsurat kısmını atar ve tamsayı kısmını alır. Küsurat kısmını atma işlemi, negatif tamsayılarla işlem yaparken de gerçekleşir. Aşağıdaki örnekte sonuç -1.5 değil, -1 olacaktır. Küsuratı atma işlemine sıfıra yuvarlama da denir. Bir tamsayı bölme işleminde sonuç, sıfıra en yakın olan bir sonraki tamsayıdır. 1 int ekmek, kisi, hak; 2 ekmek = 3; 3 kisi = 2; 4 hak = ekmek / kisi; 5 kalan = ekmek % kisi; İşlem sonucunda hak, 1 çıkacaktır. Her kişiye 1 tane ekmek düşüyor. kalan ise 1 ekmektir. Kalanı bu şekilde elde edebiliriz. Negatif sayılarla yapılacak kalan bulma işleminde ise sonuç her zaman % işaretinin solundaki sayının işareti ile aynıdır. Kalan operatörü ile yapabileceğimiz güzel uygulamalar var. Bunlardan birkaçını inceleyelim. Mesela 1995, 2005 gibi dört basamakla yazılan yılları 95, 05 gibi 2 basamaklı halde yazmak isteyebiliriz. Bu durumda kalan operatörü işimize yarar. 1 IkiBasamakliYil = DortBasamakliYil % 100 ; Sonuç her zaman 00 ile 99 arasında olacaktır. Sonuç her zaman 00 ile 99 arasında olacaktır. Eğer bir işin sonucu toplam dakika olarak verilmişse, bunu saat ve dakika olarak ayırmak istersek, bunu kalan operatörü ile yapabiliriz. Eğer bir işin sonucu toplam dakika olarak verilmişse, bunu saat ve dakika olarak ayırmak istersek, bunu kalan operatörü ile yapabiliriz. 1 Saat = ToplamSure / 60; 2 Dakika = ToplamSure % 60; Bir sayının diğer bir sayıya bölünüp bölünemeyeceği ile ilgili durumlarda da kalan operatörü kullanılabilir. Artık yıl hesabı bu şeklide yapılır. Eğer bir yıl dörde bölünebiliyorsa artık yıldır. Eğer Yil % 4 ifadesi sıfıra eşit olursa Yil sayısı dörde tam bölünüyor demektir ve dolayısıyla artık yıldır. Şimdi aşağıdaki ifadeyi dikkatli inceleyelim. Bu işlemde bir problem var. 1 A = 3; 2 B = 0; 3 C = A / B; Yukarıdaki bölme işleminin sonucunda division by zero denilen istisna oluşur ve bu işleme tamsayılarda izin verilmez. Şimdi aşağıdaki şekilde bu örneği baştan yazalım ve sonucunu çalıştırıp görelim. 1 using System; 2 class SifiraBolunme 3 { 4 static void Main() 5 { 6 7 int A, B, C; 8 9 A = 3; 10 B = 0; 11 12 Console.WriteLine (A); 13 Console.WriteLine (B); 14 15 C = A / B; 16 17 Console.WriteLine (C); 18 } 19 } Program çalıştığında ekrana A ve B değişkenlerinin değerlerini yazar ve daha sonra aşağıdaki pencere çıkar. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Eğer iptal seçersek aşağıdaki pencere gelir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Just – In – Time Debugger penceresinden de no seçtikten sonra aşağıdaki ekran gelir ve istisna, konsol ekranında görüntülenir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] C değişkenini ekrana yazan Console.WriteLine ifadesi, program kesildiğinden dolayı görüntülenmez. Bir program, üç evreden geçer. Yazma, derleme ve çalıştırma evreleri. Genelde program hataları yazma evresinde yazım hataları olarak meydana gelir. Bu örneğimizde ise çalıştırma evresinde ortaya çıkan bir istisna var. Program çalışmaya başlıyor ve yarısına gelince kesiliyor. Programı kesip ekrana sebebini yazan sınıf ise System isim uzayındaki System.DivideByZeroException sınıfıdır. Daha sonra, başka bir yazıda bu sınıfı kullanarak oluşan istisna durumlarla başa çıkma yollarını inceleyeceğiz. Eğer yukarıda yazdığımız programda C = A / B ifadesini C = 3 / 0 haline getirip yeniden derlersek derleyici aşağıdaki ekranda görülen hatayı derleme evresinde algılayacak ve programı derlemeyecektir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Şu ana kadar yaptığımız aritmetik işlem örneklerinde hep iki tane sayı kullandık. Karmaşık işlemleri de bir ifadede yazabiliriz. 1 using System; 2 class IslemOnceligi1 3 { 4 static void Main() 5 { 6 7 int A = 2, B = 4, C = 5; 8 9 int D = A / B + C + 2*A; 10 11 Console.WriteLine (D); 12 } 13 } Çarpma ve bölme işlemlerinin toplama ve çıkarma işlemlerine göre önceliği vardır. İşlemleri soldan sağa doğru incelersek, önce A/B işlemi meydana gelir, 2*A işlemi hesaplanır ve sonuçta çıkan üç tane sayı toplanır. Bölme ile çarpma işlemi aynı önceliğe sahiptir. Toplama ile çıkarma da öyle. Eğer bunlardan ikisi, mesela bölme ve çarpma, aynı ifadede yan yana gelirlerse, soldan sağa doğru bakılıp daha solda olan daha önce yapılır. Parantezin önceliği çarpma ile bölme, toplama ile çıkarma işlemleri ile kıyaslandığında daha yüksektir. O zaman, daha önce yapılmasını istediğimiz işlemleri parantez içine almalıyız. 1 using System; 2 class IslemOnceligi2 3 { 4 static void Main() 5 { 6 7 int A = 2, B = 4, C = 5; 8 9 int D = (A + B) + (C + 2*A – C/(B – A) ); 10 11 Console.WriteLine (D); 12 } 13 } Yukarıdaki örnekte ilk olarak en içteki parantez olan B – A işlemi yapılır. Daha sonra diğer parantezlerin içindeki işlemler, en sonunda da toplama ve çıkarma yapılır. Tekli artı ve eksi operatörleri ise hem çarpma ile bölme, hem de toplama ile çıkarmadan daha yüksek önceliğe sahiptir. Eşittir operatörü ise öncelik tablosunun en altındadır. Yaptığı iş, sağdaki ifadeyi soldaki değişkene atamaktır. Bir ifade içerisinde birden fazla eşittir operatörü kullanılabilir. 1 A = B = C = 10; Yukarıdaki örnekte önce C değişkeni 10 değerini alır, daha sonra B değişkeni C değişkenine eşit olur, daha sonra da A değişkenine B değişkeni atanır. Şimdi aşağıdaki ifadeyi inceleyelim. 1 C = (A = 10) + (B = 20); Önce A değişkeni 10, B değişkeni de 20 değerlerini alır, daha sonra da C değişkenine bunların toplamı atanır. Yukarıda görülen ifadeyi parantezleri kullanmadan yazmak mümkün olmaz. Mümkün olamaması da toplama işleminin atama işlemine göre önceliğinin olmasından kaynaklanır. Çünkü, yukarıdaki ifadeyi aşağıdaki gibi yazdığımızda üçüncü operand olan + işaretinin solundaki ifade değişken olmaz. 1 C = A = 10 + B = 20; Yazmanın mümkün olamayacağı diğer bir ifade de aşağıda görülen, hiçbir işlevi olmayan ifadedir. 1 A + 20; Programlama dillerinde, bir değişkenin değerinin üzerine bir ilave yapmak, ya da bir eksiltme yapmak ihtiyacı çok sık görülür. 1 ToplamOgrenciSayisi = KatilanOgrenciSayisi + IzinliOlanlar; Yukarıdaki ifadeyi yazarken aynı değişken adını tekrar yazamktansa aşağıdaki gibi yazmak mümkündür. 1 ToplamOgrenciSayisi += IzinliOlanlar; Bu örnekteki += operatörlerine birlikte, bitişik atama operatörü de denir. Bitişik atama operatörünü diğer dört işlem operatörleri ile de yazmak mümkündür. 1 Devamsizlar -= GecGelenler; Karmaşık ifadeler yazarken de birleşik atama operatörü kullanabiliriz. 1 C = (A += 4) / (B *= 7); Artırma ve Azaltma Operatörleri Programlamada bir değişkenin değerini 1 artırmak ve bir azaltmak da çok yaygındır. Bunu yapmak için aşağıdaki gibi bir ifade yazılabilir. 1 A = A + 1; Bu ifadeyi daha kısa ve kolay yazmak da C#ta mümkündür. 1 A += 1; Şimdi bunu daha kolay ve kısa yazalım. 1 A ++; ++ operatörü artırma operatörü olarak da söylenir, C tabanlı dillerde vardır ve yaygın kullanılır. Tabiî ki eksiltme operatörü de vardır. Bu da -- operatörü. Operatörlerin bu şekilde yazılması sonek şeklinde yazmaktır. 1 A --; Artırma ve eksiltme operatörleri, bu şekilde yapılabileceği gibi, önek olarak da yazılabilir. 1 ++A; 2 --B; Önek ve sonek arasında bir nüans vardır ve önemlidir. Aşağıdaki örneği çalıştırırsak aradaki farkı görebiliriz. 1 using System; 2 class ArtirmaEksiltme 3 { 4 static void Main() 5 { 6 7 int A = 2, B = 4, C, D; 8 9 C = A++; 9 D = ++A; 10 11 Console.WriteLine (C); 11 Console.WriteLine (D); 12 } 13 } A değişkeni başlangıçta 2 dir. Sonra 9. satırda C değişkeni, A değişkeninin 2 olan değerini alır, daha sonra A, 1 artarak 3 olur. 10. satırda ise önce A, 1 artırılıyor yani 4 oluyor, daha sonra da A’nın değeri, D’ye atanıyor. Yani D, 4 oluyor. 17. ve 18. satırlarda ise ekrana yazdırıp test ediyoruz |
Cevap: C# Hakkında Herşey. C# Yorum Cümleleri Yorum Cümleleri Şimdi yaptığımız çalışmalar çok kısa ve basit olsa da, gerçek bir program çok uzun, karmaşık ve anlaşılması güç olabilir. Programcı bazen bir şey denemeye başlar, bitirir ve bitirdiği zaman da ne yaptığını unutur. Bazen de bizim yazdığımız programı başkaları devam ettirmek durumunda olabilir. Diğer bir deyişle kodumuzun dokümantasyonunu yapmamız gerekebilir. Değişkenleri isimlendirirken, anlamlı isimler seçmek gerektiğinden bahsetmiştim. Ama sadece değişkenlerin anlamlı isimlere sahip olması yetmez. Bazen anlamlı isimler seçerken de çok açık, anlaşılır seçemediğimiz durumlarda işin içinden çıkılmaz olur. Yalın saylar kullanmaktan kaçınmak da kolalık sağlar. Mesela aşağıdaki örnek çok açık değildir: 1 HaftalikUcret = 80 * GunSayisi; Bunun yerine aşağıdaki gibi bir kullanım daha açıklayıcı olur: 1 GunlukUcret = 80; 2 HaftalikUcret = GunlukUcret * GunSayisi; Değişkenlerin anlamlı isimlere sahip olması ve tanımlanmamış sayıları kullanmaktan kaçınmak, programcıların kendi kendisinin dokümantasyonunu yapan programlar yazmak için kullandıkları yöntemlerdir. Yorum cümleleri yazmak da kendi kendisinin dokümantasyonunu yapan program yazmanın güzel bir yoludur. Yorum cümleleri, derleyici tarafından dikkate alınmayan, ama programın üzerinde çalışacak olanlar için açıklayıcı bilgiler içeren, programcı tarafından programın yazıldığı esnada ya da daha sonra eklenen yazılardır. Programcılar genellikle yorum satırları yazmak istemezler. Çünkü yorum satırları programın çalışması açısından hiçbir şey ifade etmez. Program bittikten sonra ve çalışmaya başladıktan sonra yorum satırları ekleyebilirsiniz. Fakat yazma aşamasındayken yorum satırı eklemek daha iyi bir yaklaşımdır. Zira, daha sonra unutacağınız bazı şeyler o anda aklınızdadır ve onları yazarsanız kaybolmamış olur. C# iki çeşit yorum satırını destekler. Bunlardan birincisi tek satırlık yorum cümlesi denilen iki tane sağa eğik çizgi ( // ) kullanmaktır. İlk olarak C++ dilinde kullanılan ve daha C programcılarının da kullanmak istediği tek satırlık yorum cümlesi, daha sonra C diline de eklendi. Bu şekilde bir kullanımda satırın sonuna kadar olan her şey, derleyici tarafından yorum cümlesi olarak kabul edilir. C# da tek satırlık yorum cümlesi yapısını miras almıştır. 1 int Ogrenciler = 32; //Bir sınıfın öğrenci mevcudu. C#’ta genellikle satır sonları önemli değildir. Bir çok ifade tek satırda yazılabileceği gibi bir ifadeyi birden çok satıra bölmek de mümkündür. Bu yapı ifadeler arasında bırakılan fazladan boşluklar ya da diğer bir deyişle beyaz boşluklar gibidir. Tek satırlık yorum cümleleri ise bu kuralın dışındadır. Çünkü yorum cümlesi, satırın bittiği yerde sona erer. Bu durum C# dilinde, satır sonlarının diğer beyaz boşluklardan farklı değerlendirildiği çok nadir durumlardan biridir. Diğer yorum cümlesi yazma şekli de sınırlanmış yorum cümlesidir. C’de uzun yıllar tek yorum cümlesi yazma şekli sınırlanmış yorum cümlesi oldu. /* karakterleri ile başlar, */ ile biter. Bir sınırlanmış yorum ifadesi birden çok satır tutabilir. /* karakterleri ile başlar, alt satırda da devam edebilir, */ karakterleri ile sona erer. Yorum cümleleri derleyici tarafından hiçbir şekilde dikkate alınmaz. 1 /* Bu satırda yorum cümlesi başladı, 2 Alt satırda devam etti, hala devam ediyor, şimdi bitti */ Yorumun kendisi /* karakterlerini içerebilir, derleyici bunu kabul edebilir. 1 /* Şimdi yorumun içinde /* karakteri kullandım, ama problem olmadı. */ Her iki yorum cümlesi türünü iç içe kullanabilirsiniz, ama bazen problem olur. Mesela aşağıdaki gibi bir kullanım yanlıştır: 1 // Tek satırlık yorum cümlesi /* sınırlanmış yorum cümlesi, 2 Sınırlanmış yorum cümlesinin devamı. */ Yukarıdaki yorum cümlelerinin kullanımının yanlış olmasının sebebi, her iki türün de anlamlarından kaynaklanıyor. // karakterleri, önünde bulunan satırın sonuna kadar tamamını yorum cümlesi kabul eder. Bu durumda alt satırda devam ettiğini düşündüğümüz yorum cümlesinin başlama karakterleri olan /*, hiç algılanmamış olur. Bu durumda alt satırdaki */ karakterlerinin daha önce başlamış bir yorumu bitirdiğini fark edemez. Hata olur. Oysa aşağıdaki kullanım doğrudur: 1 /* sınırlanmış yorum cümlesi // Tek satırlık yorum cümlesi */ Derleyici // ifadelerini dikkate almaz, çünkü /* karakterleri ile başlan yorum cümlesi */ karakterlerine kadar devam eder. // karakterleri de yorumun bir parçası kabul edilir. Bir çok programcı, yazdıkları kod sayfalarının en üstüne aşağıdaki gibi bir açıklayıcı ifade eklemeyi uygun bulur: 1 /************************************************** **************************** 2 3 ExcelBenzeri.cs 4 5 Yazan Yunus Özen, Mart 2006 6 7 Bu Excel benzeri programı gördükten sonra Excel kullanmak istemezsiniz artık 8 9 ************************************************** ****************************/ Yukarıda görülen yorum cümleleri de standart /* karakterleri ile başlar, */ ile biter. Ama aradaki fazladan asteriksler estetik için koyulmuş, özel bir anlam ifade etmiyor. Bunun gibi, yazdığımız her sınıfın veya yöntemin başına açıklama cümleleri ekleyebiliriz. Çok uzun bir program yazmışsak, programın başkaları tarafından anlaşılabilmesi böylece çok kolaylaşmış olur. Yazdığımız ifadeleri de program içerisinde hemen bir üst satırlarına tek satırlık oyrum cümlesi ekleyerek anlaşılır hale getirebiliriz. 1 // Burada bir işçinin haftada kazanacağı parayı hesaplıyorum. 2 HaftalikUcret = GunlukUcret * GunSayisi; Değişkenlere isim verirken, anlamlı isimler seçmek ve düzgün kodlamak bazen yetmeyebilir. Mesela bir program bloğunu denedikten sonra, fikrimizi değiştirip başka bir blok denemek isteyebiliriz. Bu durumda ilk bloğu sınırlı yorum cümleleri haline getirip diğer bloğu yazabiliriz. Gerekirse de ikinci bloğu yorum cümleleri haline getirip ilk bloğu açarız. 1 /* 2 GeldigiGunSayisi += 10; 1 KalanGun = ToplamGun – GeldigiGunSayisi; 2 */ Deneme yanılma yöntemi programlamada çoğu zaman işe yarar. Tecrübelerimiz de bize yol gösterir. Ama doğru programlamayı da öğrenmek gerekir. |
Cevap: C# Hakkında Herşey. checked – unchecked durumları Belirtilen sınırların dışında bir sayıyı int türünde bir değişkende tutmak istersek taşma meydana gelir. Eğer -2.147.483.648 sayısından daha küçük bir sayı tutmak istersek underflow, 2.147.483.647 sayısından büyük bir sayı tutmak istersek overflow durumu oluşur. Biz genel olarak her iki durumu da overflow olarak adlandırırız. Bunu engellemek mümkündür. Eğer program yazmak için key of csharp kullanıyorsak, bunu aşağıdaki resimde görüldüğü gibi compile options menüsünden yapabilirsiniz. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Eğer resimde gördüğünüz Check For Arithmetic Overflow seçeneği işaretli değilse, oluşacak taşmaları dikkate almadan işlemler yapılacaktır ve sonuçların yanlış çıkma ihtimali yükselecektir. Eğer, resimde görülen seçenek işaretli olursa, taşmalar dikkate alınacak ve çalışma sırasında taşma hataları görülecektir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Belirli bir program bloğunun, aritmetik işlem taşmalarından muaf tutulmasını sağlayabiliriz ya da tam tersi olarak, taşma işlemlerinde hata oluşturacak şekilde işaretleyebiliriz. Bu işi de checked ya da unchecked program blokları oluşturarak yaparız. Mesela programımız derleme sırasında aritmetik taşma işlemlerini denetleme seçeneği aktifken derlenmiş olsun. Bu durumda programı çalıştırdığımızda aritmetik taşma işlemi olunca program kesilecektir. Bir program bloğunu seçelim ve checked bloğu yapalım. Taşma durumu oluştuğunda checked bloğunun içerisindeki kodlarda oluşan taşmalar dikkate alınmaz. Derleme sırasında aritmetik taşma işlemlerini denetle seçeneği aktif değilken ise unchecked bloğu için tam tersi mümkün oluyor. Aşağıdaki örneği aritmetik taşma işlemlerinde taşma hatası verecek şekilde ayarlanmış olarak derlerseniz taşma durumu oluşmayacaktır ve sonuç ekrana yazdırılacaktır. Bunu sağlayan ise unchecked bloğudur. 1 using System; 2 class Program 3 { 4 static void Main() 5 { 6 unchecked 7 { 8 int A = 1000000000; 9 int B = A * 20; 10 Console.WriteLine(B); 11 } 12 } 13 } Buraya kadar olan kısımda tamsayı türü olarak sadece int bahsedildi ama, tamsayılar sadece 32 bitlik işaretli tamsayılar değildir. Ama int C#’ta en çok kullanılan tamsayı türüdür. Mesela bir etkinliğe katılan insan sayısını tutacaksanız, bunu negatif sayılara da izin veren int türü ile yapmak zorunda değilsiniz. İşaretsiz 32 bit tamsayıları tutabilen uint türü bir tamsayı değişkende tutabilirsiniz. uint, 32 bitliktir, tamsayı tutar ama 0 ile 4.294.967.295 arasındaki tamsayıları tutabilir. uint türünde de yine taşma hataları oluşabilir ve bunu yine checked ve unchecked blokları ile muaf tutabiliriz. Eğer yazdığınız uygulamada, 32-bit sayılar yetmiyorsa, daha büyük ve daha küçük sayıları kullanabilmek için long ve ulong tamsayı türlerini kullanmalısınız. long işaretli 64-bit, ulong ise işaretsiz 64 bit tamsayıdır. 32 bitten daha küçük sayılar tutmak için de tamsayı türleri vardır. short ve ushort tipleri işaretli ve işaretsiz 16-bit tamsayı türleridir. sbyte ve byte ise 8-bit işaretli ve işaretsiz tamsayı türleridir. System isim uzayının içerisinde Int32, Int16, Int64 gibi yapılar vardır. int, short , long gibi aliaslar yardımıyla da bu yapılara erişebiliriz. Mesela int tamsayı türü aslında Int32 ismiyle System isim uzayında bulunur ama int yazarak ulaşabiliriz. Aşağıdaki tanımlamalardan her ikisi de doğrudur. int A; System.Int32 A; Aşağıdaki tabloda .net tarafından desteklenen tamsayı türleri, .net içindeki yapı isimleri ile alabilecekleri en küçük ve en büyük değerler toplu olarak bulunmaktadır. C# Tür .NET Yapısı En Küçük En Büyük sbyte System.SByte -128 127 byte System.Byte 0 255 short System.Int16 -32,768 32,767 ushort System.UInt16 0 65,535 int System.Int32 -2,147,483,648 2,147,483,647 uint System.UInt32 0 4,294,967,295 long System.Int64 -9,223,372,036,854,775,808 9,223,372,036,854,775,807 ulong System.UInt64 0 18,446,744,073,709,551,615 .net ailesinde yer alacak dillerin uyması gereken CLS (Ortak Dil Özellikleri), bütün dillerin bir birleri ile haberleşebilmeleri için oluşturulmuştur. .net aliesine katılacak bir dil, en azından bu özellikleri taşımalıdır. Yukarıda görülen tablodaki SByte, UInt16, UInt32 ve UInt64 tamsayı veri türleri CLS uyumlu değildir. CLS, Byte, Int16, Int32 ve Int64 veri türlerini gereklilik olarak şart koşar ama diğerlerini değil. Bazı diller (mesela Visual Basic.net); Byte, Int16, Int32 ve Int64 haricindeki tam sayı türlerini desteklemez. Eğer diğer diller tarafından da kullanılacak bir dll yazıyorsanız, sbyte, uint16, uint32 ve uint64 veri türlerini kullanmaktan sakınmalısınız. Yoksa, yazdığınız dll mesela Visual Basic .net tarafından kullanılamaz. Bir int, 32-bit işaretli tamsayı anlamına gelir ama aynı zamanda int, System.Int32 adlı yapının bir örneğidir. Böyle olmasının getirdiği bir takım avantajlar var. Tamsayı türlerini ifade etmekte kullandığımız yapıların ToString ve Parse diye adlandırılan ve en çok kullanılan yöntemleri vardır. Her birinin, MinValue ve MaxValue adında iki tane de alanı vardır. Alanlar da yöntemler gibidir. Bir yapının ya da sınıfın üyesi olurlar. Ama alan daha basittir. Bunu bir değişken ya da sabit olarak düşünebilirsiniz. Mesela MinValue ve MaxValue alanları sabit değerlere sahiptirler. Program içerisinde alanları sınıfınismi.alanismi şeklinde kullanabilirsiniz. Aşağıdaki program, int tamsayı türünün alabileceği en küçük ve en büyük sayısal değeri ekrana yazar. 1 using System; 2 class Program 3 { 4 static void Main() 5 { 6 Console.WriteLine(Int32.MinValue); 7 Console.WriteLine(Int32.MaxValue); 8 } 9 } Aynı şekilde diğer tamsayı türlerinin de alabileceği en küçük ve en büyük sayısal değerleri de ekrana yazdırabilirsiniz. Integer literalleri, hexadecimal notasyonda da yazabilirsiniz. Hexadecimal sayılar, 0x ya da 0X ile başlar ve devamında 16lı sistemde yazılmış bir sayı gelir. int A = 0x12A4; int B = 0X34CA; Sınırları aşmamak kaydıyla tamsayı veri türlerini aritmetik işlemlerde birlikte kullanabilirsiniz. ushort US = 45867; int I = 523; int S = US + I; Yukarıdaki örnekte toplama işlemi meydana gelmeden önce, C# otomatik olarak ushort yapıdaki sayıyı 32-bit işaretli tamsayıya dönüştürür. Çünkü toplama gibi aritmetik işlemler ancak aynı tür iki sayı arasında meydana gelebilir. Daha sonra toplama işlemi yapılır ve sonuç yine 32-bit işaretli bir tamsayıdır. Burada dönüştürme işlemi programcının müdahalesi olmadan C# tarafından yapılmıştır. Bu tür dönüşümlere kapalı dönüştürme denir. Eğer derleme evresinde sabit kalacak bir tamsayı sabiti tanımlamışsak, ve tamsayı 8-bit ya da 16-bit bir türdeyse, tanımlanan sabit geçerlidir ama C# onu 32-bit işaretli tamsayıya dönüştürerek derler. byte B = 120; Birden çok işlemi içine alan karmaşık bir işlem sırasında, adım adım dönüştürme işlemleri yapılır. Bir atama işlemi sırasında operatörün sağındaki ifadenin türü solundaki ifadenin türüne kapalı dönüştürme ile dönüştürülür. Dönüştürme işlemleri asıl işlemden daima önce yapılır. Eğer bir int ile bir uint sayı arasında işlem yapılacaksa, C# önce her ikisini de long türüne dönüştürür. Çünkü, hem int hem de uint türünü kapsayan tamsayı türü longdur. Bu durumda aşağıdaki örnek çalışmayacaktır: 1 using System; 2 class Program 3 { 4 static void Main() 5 { 6 uint UI = 45867; 7 int I = 523; 8 int A = I + UI; // Bu satırda derleme hatası oluşur! 9 } 10 } Hatanın nedeni, işlemin sonucununu int türü bir tamsayıya atamaya çalışmamızdır. Çünkü UI, bir uint türü sayıdır; I ise int türündedir. Bu iki türün bir işlemde kullanılması sonucu oluşacak sonuç long türünde olacaktır ve ancak long türü bir değişkene atanabilir. Oysa yukardaki örnekte sonuç , int türünde bir değişkene atanmaktadır. Bazen, C# derleyicisinin kapalı dönüştürme yapmak istemediği bir işlemi yapma istersiniz. Bu işlemi yapmak güvenlidir ama C# derleyicisi buna müsaade etmez. O zaman, açık dönüştürme işlemi yaparsınız. Aşağıdaki örnekte bu şekilde açık dönüştürme yapılmıştır ve C# derleyicisi, bu örneği derler. 1 using System; 2 class Program 3 { 4 static void Main() 5 { 6 uint UI = 45867; 7 int I = 523; 8 int A = (int) (I + UI); 9 Console.WriteLine(A); 10 } 11 } Her bir değişkeni tek tek de açık dönüştürme işlemine tabi tutabilirsiniz. Yukarıdaki örneği incelerseniz, UI adlı değişken uint türündedir ve sadece onu dönüştürerek de int türündeki A değişkenine sonucu atayabilirsiniz. 1 using System; 2 class Program 3 { 4 static void Main() 5 { 6 uint UI = 45867; 7 int I = 523; 8 int A = I + (int) UI; 9 Console.WriteLine(A); 10 } 11 } Toplama işlemi yapılmadan önce UI değişkeni 32-bit işaretli tamsayı türüne dönüştürüldü ve işlem iki tane 32-bit işaretli tamsayı arasında yapıldı. Bu tür dönüştürmeye daha çok type casting (tür dönüştürme) de denir. Bundan sonraki yazılarda sadece casting olarak kullanacağız. Casting işlemi sırasında bit kayıpları da oluşabilir. Mesela bir 32-bit işaretli sayıyı 8-bit işaretli sayıya dönüştürecek olursak 8-bit işaretli tamsayı snırılarını aşan kısım ihmal edilecektir. Eğer aritmetik taşma işlemlerini denetleme seçeneği aktifse çalışma evresinde taşma istisnası oluşacaktır. Casting işlemi birçok kolaylık sağlar ama suiistimale de açıktır. Kullanırken dikkat etmek gerekir. Oluşabilecek istisnaları yakalayacak yordamlar yazmak gerekir ki, bu işlemin nasıl yapacağını başka bir yazıda ele alacağız. |
Cevap: C# Hakkında Herşey. C# String Veri Türü String Veri Türü Yıllardır bilgisayarlar kullanıcılarla iletişim kurmak için yazıyı kullanırlar. Programlama dillerinde karakter kelimesi, bir harf, sayı, noktalama işareti ya da bir sembol anlamına gelir. String kelimesi ise karakterlerin yan yana gelerek oluşturdukları dizi anlamına gelir. C# Dilinde string bir anahtar kelimedir. String türünde bir değişken tanımlarken aşağıdaki gibi yazarız. string Yazi; Burada Yazi adında, string türünde bir değişken tanımlaması yapılmıştır ya da başka bir deyişle, Yazi string bir değişkendir. C#taki string veri türü .net Framework içerisindeki System.String sınıfının bir aliasıdır yani string yazmakla System.String yazmak aynı şeydir. Yani aşağıdaki gibi de string değişken tanımlaması yapılabilir. System.String Yazi; Eğer programımızın üst kısmında using direktifi ile using System; yazmışsak, başındaki System. ifadesini yazmayabiliriz. Bunu zaten daha önceki yazılardan biliyorsunuz. String Yazi; Şimdi burada bir karışıklık oldu. Eğer usnig direktifi ile System isim uzayı direktifi yazılmışsa büyük harfle yazılan String yeterlidir ama C#ta bir veri türü olan ve küçük harfle yazılan string kelimesi de kendi başına System.String anlamına gelen bir alias olduğundan aşağıdaki gibi bir ifadeyi yazmak yanlış olur. System.string Yazi; //Yanlış oldu. Çünkü string kelimesinin karşılığı olan System.String ifadesini yukarıdaki ifadede yerine yazarsak System.System.String Yazi; //Yanlış oldu. yazmış oluruz. Tabi ki böyle bir ifade yoktur, çalışmaz. Şimdi string türünde bir değişken nasıl tanımlanır öğrendiğimize göre değer ataması yapalım. Yazi = "C#Türkü çok seviyorum."; Yukarıdaki ifadenin sağındaki değere string literal denir. Bir string literal sıfır ya da daha fazla karakterden oluşur. Karakterin tanımını yukarıda yaptığımıza göre içinde neler bulunabileceği de açıktır: Harf, rakam, noktalama işareti ayda sembol. Dikkat ederseniz bir string literal çift tırnak arasına yazılır. Bu durumda string literali başlatan ve bitiren çift tırnak işaretleri string ifadenin kendisine dâhil değildir. Yazı dilinde noktalı virgül, soru işareti gibi işaretler çift tırnakların içine yazılır. Ama C#ta noktalı virgül atama işlemini bitiren işarettir ve en sona yazılır. Karıştırmamak gerekir. Bir string literal tek satır olmak zorundadır. Aşağıdaki atama işlemi çalışmayacaktır. Yazi = "C#Türkü çok seviyorum."; // Yanlış oldu. Tamsayılar yazısında da anlattığımız gibi, string türü değişkenlere de tanımlama esnasında ilk değer ataması yapabiliriz. string Yazi = "C#Türkü çok seviyorum."; Bir stringi ekranda göstermek için daha önceden de bildiğimiz Console.Write ya da Console.WriteLine yöntemlerini kullanabiliriz. Console.WriteLine(Yazi); Bu ifade konsolda aşağıdaki gibi bir çıktı verecektir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Çift tırnak işaretleri, ekranda görünmedi. Çünkü onlar string ifademizin bir parçası değildir. Bir değişken tanımlaması yapmadan da bir string ifadeyi direkt Console.Write ya da Console.WriteLine yöntemlerine geçebilirsiniz. Console.WriteLine("C#Türkü çok çok seviyorum"); Console.WriteLine ile tamsayıları gösterebildiğimiz öğrenmiştik. Şimdi de string ifadeleri gösterebildiğini öğrendik. Bunu yapması mümkündür, çünkü Console.WriteLine yönteminin aynı isimde birden çok sürümü vardır. Aynı yöntemin birden çok sürümleri olmasına yöntemlerin aşırı yüklenmesi denir. Başka bir yazıda bu meseleyi anlatacağız. Aşağıdaki ilginç örneği dikkatle inceleyelim. using System; class stringler { static void Main() { string A, B, C; A = "Merhaba, "; B = "Dünya"; C = A + B; Console.WriteLine(C); Console.ReadLine(); } } Ekran çıktısını incelersek çok temel bir örnek, ama programda ilginç bir yer var. 3 tane değişken tanımladık. İlk 2 tanesine değer ataması yapma işlemi daha öncekilerle aynı, sadece sayı değil de yazı kullandık. 3. değişkene değer ataması yapma işlemi biraz ilginç görünüyor. Çünkü iki tane yazı arasında toplama işlemi yapmaya çalışyıoruz. Bu ne anlama geliyor? Artı işareti iki tane string ifadeyi birleştirir. Programı çalıştırdığımızda aşağıdaki çıktıyı görürüz. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Merhaba dünya cümlesi çok meşhur bir programcı selamıdır. 1978 yılında C Programlama Dili kitabının yazarları Brian W. Kernighan ve Dennis M. Ritchie tarafından ilk defa kullanılan bu ilk yazılan programın dünyaya merhaba demesi olayı gelenek haline geldi. Ama Kernighan ve Ritchie string birleştirme örneğini yapamadılar, çünkü standart C dilinde string birleştirme yoktur, hatta string yoktur. Değişik işlemler için aynı operatörün kullanılması, mesela toplama operatörü, operatörlerin aşırı yüklenmesi olarak bilinir. Bu meseyi de yine başka bir yazıda anlatacağız. Dikkat ederseniz A değişkenine bir string literal ataması yaptık ama virgülden sonra bir boşluk bıraktık. Çünkü 2 tane stringi birleştirdiğimizde arasına kendisi boşluk koymaz bunu bizim belirtmemiz lazım. Stringlerle de yine artı eşittir operatörünü kullanabilirsiniz. string Yazi = "Bu bir yazıdır."; Yazi += "Bu da bir yazıdır."; Artı eşit operatörü, ilk string ifadenin sonuna ikinci string ifadeyi ekler. Bunlardan başka diğer operatörler stringlerle kullanılmaz. String birleştirme işlemi, eğer çok uzun bir string ifadeyi bir değişkene atayacaksak çok işlevseldir. string Kavgam = "Kader beni, iki Alman devletinin tam sınırları üzerinde bir kasabada," + "Braunau am Inn'de dünyaya getirdi. Alman olan Avusturya, büyük Alman vatanına" + "tekrar dönmelidir. Hem bu birleşme, iktisadi sebeplerin sonucu olmamalıdır. " + "Bu birleşme, iktisadi bakımdan zararlı olsa bile, mutlaka olmalıdır." + "Aynı kan, aynı imparatorluğa aittir. "; Aynı zamanda string literaller ile string değişkenlerin bir kombinasyonu olarak string birleştirmeyi kullanabilirsiniz. string programlama_dili = "C# "; Console.WriteLine("Ben " + programlama_dili + " programlamayı çok seviyorum." + " Ya sen?"); Yukarıdaki birleştirilmiş ifade aslında aşağıdaki şekilde ayrı ayrı da yazılabilir. string programlama_dili = "C# "; Console.Write("Ben"); Console.Write(programlama_dili); Console.Write(" programlamayı çok seviyorum."); Console.WriteLine(" Ya sen?"); Dikkat ederseniz ilk dört ifadede Console.Write kullanırken sonuncusunda Console.WriteLine kullandık. Çünkü Console.Write yöntemi imleci alt satıra geçirmez. Yukarıda yazdığımız her iki örneğin de ekran çıktısı aşağıdaki şekildedir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] System.String sınıfının Length diye bir özelliği vardır. Yöntem ve alan gibi özellik de bu cümlede teknik terim olarak kullanıldı. Özellikler de alanlar gibidir. Başka bir yazıda alanlar ve özelliklerden bahsedeceğiz. Şimdilik sadece Length özelliğinin ne işe yaradığını bilelim. Bir string ifadenin karakter sayısını bize verir. Kavgam.Length ifadesi bize 327 sayısını verir. C#ta stringleri çift tırnak arasına yazarız. Eğer string literalin kendi içinde çift tırnak varsa onu nası yazabiliriz? Mesela aşağıdaki gibi bir string literali ekranda göstermek istiyoruz. Atalarımız boşuna söylememiş “sakla samanı, gelir zamanı” diye. Bu tür özel karakterlerin kullanılması programlama dillerinde her zaman problem olur. C# çözümü C ve C++ dillerinden almıştır. Bir string literal çift tırnak içeriyorsa, çift tırnakların soluna bir ters bölü işareti koymalıyız. string Yazi = "Atalarımız boşuna söylelemiş \"sakla samanı, gelir zamanı\" diye"; Bu ters bölü işareti burada kaçış karakteri olarak görev yaptı. Kaçış karakteri sağındaki özel işaretin gerçek anlamında kullanılmasını engeller. Peki, ters bölü işaretinin kendisini yazı içerisinde nasıl kullanırız? Yazı dilinde belki çok fazla kullanılmayan bir işaret ama MS-DOS ya da Windows programlarında dizin isimlerini ayırmada ters bölü işareti kullanılır. Bu ters bölü işaretinin çok acıklı bir hikâyesi var. UNIX işletim sisteminde dizin isimleri normal bölü işareti ile ayrılır, ters bölü işaretiyle değil. C dilinde de kaçış karakteri olarak kullanılma sebebi hiçbir özel anlamı olmamasıdır. MS-DOS 1.0 işletim sisteminde ise UNIX benzeri hiyerarşik bir dizin yapısı olmadığından normal bölü işareti komut satırı argümanı olarak kullanıldı.UNIX işetim sisteminde komut satırı argümanlarının solunda çizgi vardır. MS-DOS 2.0 işletim sisteminde hiyerarşik dosya yapısı gelince, C dilinde problem olacağı hiç akıllarına gelmedi ve dizin isimlerini ayırmakta normal bölü işareti yerine ters bölü işareti kullanıldı. Bir string literal içerisinde eğer ters bölü işareti varsa yan yana iki tane kullanırız. string Dizin = "C:\\Makaleler\\String Makalesi\\Metin.doc"; Şimdi bunu ekrana yazdırıp çıktısına bakalım. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Artık MS-DOS ya da Windows programlarında ters bölü işareti kullanma zorunluluğumuz yok, onun yerine normal bölü işareti de kullanabilirsiniz. string Dizin = "C:/Makaleler/String Makalesi/Metin.doc"; Bilgisayarın içerisinde bir string literalin karakterleri sayılarla ve nihayetinde bitlerle saklanır. Uzun yıllar, bir çok bilgisayar ASCII (American Standard Code for Information Interchange – Bilgi Değişimi İçin Amerikan Kod Standardı) dediğimiz bir karakter kodlaması kullandı. ASCII 7-bit kodlardan oluştuğu için toplam 128 (27) çeşit karakteri gösterebilir. Eğer standart Amerikan İngilizcesi klavyesi kullanıyorsanız, Üst Karakter Tuşuna (Shift Tuşu) bağlı olarak (harf, sayı ya da sembollerden) 47 tane tuştan 94 tane karakter oluşturabilirsiniz. Boşluk tuşu ayrı bir ASCII karakteri ile temsil edilir. ASCII ayrıca, yazıda gösterilmeyen, yazının nasıl gösterileceğini kontrol eden 33 tane kontrol karakteri sağlar. Bunlardan sadece bazıları günümüzde kullanılıyor. Satır başı tuşu, Sonraki satıra geçme tuşu (Bu ikisi imlecin bir sonraki satırın başına gitmesini sağlar), Geri Al Tuşu, Tab Tuşu, ESC tuşu. Bütün ASCII karakterleri klavyeden Ctrl tuşunu harf ve sembol kombinasyonları ile kullanarak oluşturulabilir. Yani 128 tane ASCII kodunu klavyeden yazabiliriz. Fonksiyon tuşları (F1,…, F12), yön tuşları ve imleç hareket tuşları biraz farklıdır. Bunlar ASCII kodu üretmezler. Pratikte kişisel bilgisayarlar ASCII tarafından sağlanan 128 karakteri de içeren yazı karakterlerini göstermek için 8-bit kullanırlar. Bu 8-bit kodlamaya ise genişletilmiş ASCII karakter kodlama seti denir. Maalesef, genişletilmiş ASCII, tek standart değildir. Orijinal IBM Bilgisayar çizgi çizmek ve basit matematik semboller için ek rarakterler de kullandı. Windows ise Batı Avrupa dillerinde kullanılan sembolleri göstermek için Latin 1 adlı bir kodlamayı da destekler. Bir çok ülkede standart komiteleri kendi karakter kodlamalarını oluşturdular. Tabi ki bunların içinde Latin olmayan Arapça, İbranice, Yunanca, Kiril (Rusça) da var. Sonuç karışıklık ve belirsizlik oldu. Eğer başka bir ülkeden ya da Apple Machintosh gibi başka platformlardan gelen e-posta mesajları almışsanız ve bunlarda anlamsız karakterler görmüşseniz bunların sebebi iki değişik 8-bit karakter kodlamasıdır. 1980lerin başında bu problemlere bir çözüm bulmak için çalışmalar yapıldı. Sonuç Unicode oldu. Unicode; Çince, Japonca ve Korece gibi şekilsel alfabeler de dâhil, bilgisayar iletişiminde kullanılan bütün dillerin karakterlerini gösterebilecek şekilde 65,536 (216) tane karakter içeriyor, 16-bit kodlama kullanıyor. Unicode karakterlerinin ilk 128 karakteri yine ASCII’nin aynısıdır. İkinci 128 tanesi ise Latin 1 karakterlerinin aynısıdır. Unicode hakkında daha fazla bilgi [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] adresinde mevcuttur. Unicode Standart Verison 3.0 adlı kitabın online sürümüne de yine bu siteden ulaşabilirsiniz. 8-bit karakter kodlamalarının yerini 16-bit Unicode karakterlere bırakması için uzun bir yol var. Ama bazı programlama dilleri, mesela C#, stringleri 16-bit Unicode olarak tutuyor. Unicode ile aşağıdaki gibi bir string ifadeyi rahatlıkla yazabilirsiniz. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Hem Yunan alfabesi hem de derece işareti ASCII karakter tablosunda yoktur. Yunan harflerini Yunanca klavye ile rahatlıkla yazarsınız, ama derece işareti Yunan klavyeside yoktur. Genellikle, bir Unicode karakteri string içerisinde kullanabilmek için karakteri Unicode standardı sürüm 3.0 şekilde yazmak lazım ya da [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] adresindeki şekilde ve bir ters bölü şareti daha sonra küçük ya da büyük harflerle U ya da X koyduktan sonra 4-basamak hex karakter kodu yazarak gösterilir. string Angle = "The angle \u03B1 equals 60\u00B0"; İlginçtir ama \u ve 4-basamak hex karakter kodlarını değişken isimleri diğer belirteçlerde kullanabilirsiniz. bu konuda daha fazla bilgi için C# Language Specification, 2.4.2 özellik dokümanına bakabilirsiniz. C# ayrıca C dilinden aşağıdaki kaçış durumlarını da miras almıştır. Kaçış Karakterleri Unicode Kodlaması Karakter İsmi \0 \u0000 Null \a \u0007 Uyarı (beep) \b \u0008 Geri al Tuşu \t \u0009 Tab \n \u000A Yeni Satır \v \u000B Dikey Tab \f \u000C Form besleme \r \u000D Satır başı \" \u0022 Çift Tırnak \’ \u0027 Tek Tırnak \\ \u005C Ters Bölü İşareti Örneğin aşağıdaki ifadede ekrana yazı gösterirken \a karakterine gelince hoparlörden beep sesi çıkar ve devam eder. \a sadece konsolda geçerlidir. \v ve \f ise sadece yazıcıda geçerlidir. Console.WriteLine("Uyarı sinyali ver \a ve devam et."); ASCII kodlamasının çıkış kaynağı daktiloda kullnılan karakterlerdir. Mesela \r ve \n işlemini ancak daktilo ile anlayabiliriz. \r Satır başı kodu, yazma kafasını satırın başına getirir. \n ise yazma kafasını bir sonraki satıra geçirir. \n ve \r birlikte kullanıldığında bir sonraki satırın başına gitmiş oluruz. Text dosyalarda bu işlemler olmaz, platform uyumsuzluğu vardır. MS-DOS ve Windows platformlarında text dosyalarda bütün satırlar satır başı ve yeni satır kodlarıyla sonlanır. UNIX platformunda ise sadece yeni satır koduyla sonlanır. Macintosh ortamında ise sadece satır başı kodu satırı sonlandırır. C# konsol programlamada, sadece yeni satır kodu bir sonraki satırın başına geçmek için yeterlidir. Aşağıdaki ifadelerden her ikisi de aynı işi yapar. Console.Write("\n"); Console.WriteLine(); C# kaçış karakteri olarak ters bölü kullnmaya bir alternatif sunar. Eğer bir string literalin önüne @ işareti koyarsak kaçış karakteri kullanmaya gerek kalmaz. string Dizin = @"C:\Makaleler\\String Makalesi\Metin.doc"; Buna verbatim string (harfi harfine – aynısı) de denir. Ters bölü işareti de normal diğer karakterlerden biri olarak algılanır. Tabi bu durumda çift tırnak için iki tane çift tırnak kullanmak gerekiyor. string Yazi = @"Atalarımız boşuna söylelemiş ""sakla samanı, gelir zamanı"" diye"; Daha önce artı işaretinin string ifadeleri birleştirmek için kullanıldığını göstermiştik. Artı işaretini string ifadeleri sayılarla birlikte yazmak için de kullanabiliriz. int toplamTutar = 100; Console.WriteLine("Toplam tutar :" + toplamTutar + " YTL dir."); Burada kural oldukça basittir. Eğer artı operandının bir tarafındaki ifade string ise diğer tarafındaki ifade de string ifadeye dönüştürülür ve daha sonra da string birleştirme işlemi gerçekleşir. Aşağıdaki ilginç durumu inceleyelim. int A = 12; int B = 20; Console.WriteLine(A + B + " toplamlarıdır."); Console.WriteLine("Toplamları " + A + B); Yukarıdaki program kodunun çıktısı aşağıdaki gibi olacaktır. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Peki neden ikisi farklı çıktı. Operatör önceliği kavramından tamsayılar yazısında bahsetmiştik. Operatör önceliği kurallarına göre toplama işlemlerinde öncelik soldan sağa doğrudur. İlk ifadede soldan itibaren başlandığından önce A + B işlemi yapıldı daha sonra da string ifadeye dönüştürülerek sonraki string ifade ile birleştirildi. İkinci WriteLine çağrısında ise “Toplamları” string ifadesi 12 ile birleştirildi. Daha sonra “Toplamları 12” string literali 20 ile birleştirildi. “Toplamları 1220” ifadesi oluştu. Bu problemi çözmek için aşağıdaki gibi bir çözüm bulabiliriz. int A = 12; int B = 20; Console.WriteLine(A + B + " toplamlarıdır."); Console.WriteLine("Toplamları " + (A + B)); Parantezlerin toplama işlemine göre önceliği olduğundan ilk önce parantez içindeki işlem gerçekleşir ve sonuç aşağıdaki gibi olur. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Tamsayılar yazısında da ifade edildiği gibi bütün tamsayı türler .net Framework içerisindeki yapılardan türetilir. string veri tipi ise System.String sınıfından türetilir. Sınıflar ve yapılar birbirlerine benzerler. Ama çok temel bir farklılıkları var, yapılar değer tiptirler, sınıflar referans tip. Daha fazla bilgiyi Değer Tip & Referans Tip adlı yazımızdan öğrenebilirsiniz. |
Cevap: C# Hakkında Herşey. C# Değer Tip & Referans Tip Değer Tip & Referans TipDeğer-Tip & Referans-Tip (Value-Type & reference-Type) Yüksek seviye dillerin bir iyi tarafı da, bilgisayarın arka planda nasıl çalıştığı konusunda programcının bilgi sahibi olmasına gerek kalmamasıdır. Ama bazen bilmekte de yarar var. Mesela bellekte değişkenlerin nasıl saklandığını bilmek isteyebilirsiniz. Program çalışırken değişken için bellekte değişkenin türüne göre yer ayrılır ve değişkene ihtiyacımız kalmadığında ise belleğin o bölgesi serbest bırakılır. Bir yöntem çalışmaya başladığı zaman, içerisindeki bütün değişkenler için bellekte yer ayrılır. Bu yere stack denir. Yöntemin kullanımı sona erdiği zaman ise belleğin o bölgesi serbest bırakılır. Şöyle bir örnek düşünelim : int A,B; long C; string D; Stack bölgesinde A ve B için 4’er byte, C için 8 byte yer ayrıldı. Peki D için ne kadar yer lazım? Bu miktar, string türündeki D değişkeninin ne kadar uzun olacağına bağlıdır. Bir string ifade çok kısa da olabilir, çok uzun da. Bu yüzden string değişkenlerin boyutu değişkendir. Eğer string türü bir değişkene sabit bir ifade atanmışsa, boyut sabit olarak düşünülebilir. Eğer değişkenin içeriği kullanıcıdan istenen bir değer ise, veya dosyadan okunan ya da internetten alınan bir ifade ise boyutunu program çalışana kadar bilemeyiz. Bu yüzden, string ifadeler, stack bölgesinde saklanmaz. Program çalışırken, string ifade için gereken yer heap adı verilen bölgede oluşturulur. Heap bölgesi, program çalışırken, ayırma ve serbest bırakma işlemleri yapmayı olanaklı kılan genel amaçlı bir bölgedir. Yalnız stack ve heap bölgeleri hakkında bilinmesi gereken diğer bir gerçek var. Yukarıdaki kod bloğundaki D değişkeninin kendisi stack bölgesinde saklanır, heap bölgesinde bir alana referans içerir. D değişkeninde tutacağımız string ifadenin kendisi ise ilgili referansın gösterdiği heap bölgesindedir. Heap bölgesindeki string ifade programın akışı sırasında küçülebilir ya da büyüyeblir ama stack bölgesindeki referansı barındıran alan sabittir. Referans derken neyi kastettiğimize biraz bakalım. Belleğin her bir hücresi numaralandırılımıştır ve bu numaralara bellek adresi denir. Program, bir bellek bölgesine erişmek isterse bu numaralardan yararlanır. Bir bellek bölgesine referans içermek demek o bölgenin adresini tutumak demektir. Yapısal programlama ile uğraşmış olanlar bunun işaretçi (pointer) demek olduğunu bilirler. Peki, içinde referans tutan bir değişken stack bölgesinde ne kadar yer kaplar? Günümüz yaygın işletim sistemleri 32-bit olduğuna göre 32 bit yani 4 byte yer kaplar. Şimdi string ifade tutan bir değişken bellekte ne kadar yer kaplar sorusunun cevabını da bulmuş olduk. Değişkenin kendisi stack bölgesinde 4 byte yer kaplar ama string ifadenin kendisi heap bölgesinde değişken bir yere sahiptir. Kapladığı alan içeridği ifadenin boyutuna göre değişir. Değer-Tip & Referans-Tip (Value-Type & Reference-Type) Yeri gelmişken referans-tip nedir, değer-tip nedir sorusuna da cevap arayalım. C#’ta yapılar değer-tiptirler. Sınıflar ise referans-tip. Bunun ne anlama geldğini anlamak için, biraz açalım. Aslında bir çok değer tipi daha önce kullandık. Bütün tamsayı türler .Net Framework içerisindeki yapıların aliaslarıdır. Tamsayı türdeki bir sayının gerçek değeri stack bölgesinde saklanır. Sınıflar ise referans-tiplerdir. string veri tipi, Syste.String sınıfının bir aliasıdır. Yani bir sınıftır. Sınıf da referans-tiptir. Bir referans tip, heap bölgesinde bir alanı gösteren bir referans olarak stack bölgesinde saklanır. Yapılar değer-tiptirler. Sınıflar referans-tiptirler. Bir yöntemin aşağıdaki tanımlamayı içerdiğini düşünün şimdi. string Ad; Yöntem çalışmaya başladığında, stack bölgesinden 4 byte’lık yer ayrılır. Bu yerde, heap bölgesinden bir alana referans barındırılabilir. Ama Ad değişkenine bir değer ataması yapılmadığı müddetçe heap bölgesinden bir alan tahsisi yapılmaz. Şimdi bir değer atayalım. Ad = "Ali"; Heap bölgesinde string ifade sığacak kadar yer ayrıldı ve artık stack bölgesindeki yerimiz heap bölgesinde string ifadeyi barındıran alanın adresini tutuyor, yani o bölgeye referans tutuyor. Bir string değişkene aşağıdaki gibi hiçbir şey atamak istemezsek ne olur, inceleyelim. Ad = " "; Şu anda hiçbir karakter içermiyor ama bir atama işlemi söz konusu olduğu için heap bölgesinden yer tahsisi yapılır. Ad.Length ifadesinin değerini ekrana yazdırırsak 0 göreceksiniz. bu da heap bölgesinde yer içeriği boş olan bir yer ayrıldığını gösteriyor. Çöp Toplama (Garbage Collection) Bir string türü değişkenin değerini değiştirip heap bölgesinde bir yere referans içermemesini sağlayabiliriz. Bunu da Ad = null; atamasıya yaparız. Biz bunu yaptığımız zaman ya da Ad = "Veli"; gibi başka bir değer ataması yaptığımız zaman, ilk atadığımız “Ali” ifadesi hala heap bölgesinde mevcuttur ama hiçbir referans onu göstermediği için ulaşılamaz haldedir. Bu şekilde artık kullanımı biten verileri heap bölgesinden temizleyen ve o bölgeleri kullanılabilir hale getiren çok güzel bir yapı barındırır C# ve CLR (Ortak Dil Çalışma Zamanı) : Çöp toplama (Garbage Collection). Programcı işi biten bölgeleri temizleme derdinden kurtulmuştur. Çöp Toplayıcı bunu programcının yerine yapar. Heap bölgesinde hiçbir yere referans içermeyen yani null bir string değişkenin uzunluğunu bulmak için Ad.Length ifadesinin değerini öğrenmeye çalışırsak aşağıdaki istisna oluşur. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Yukarıda anlatıldığı gibi, null string ile boş bir string aynı gibi görünse de aynı değildir. Bir string null’a eşitse, stack bölgesinde saklanan değer 0’a eşittir ve heap bölgesinde hiçbir yere referans içermez. Eğer bir string, boş bir string’e eşitse stack bölgesinde saklanan değer heap bölgesinde bir bölgeye referans ifade eder. Heap bölgesinde de uzunluğu 0 olan bir string için yer ayırma işlemi yapılmıştır. |
Cevap: C# Hakkında Herşey. C# String Dönüşümleri String DönüşümleriSTRING DÖNÜŞÜMLERİ Bilgisayar ile insan iletişimi genelde yazı ile oluyor. Bilgisayarın çıktıları genellikle yazı olarak vermesini isteriz. Eğer sayıları göstermesi gerekiyorsa ekranda, göstereceği sayıyı yazıya dönüştürerek yapar. Meselâ, 45 sayısını 32-bit tamsayı olarak saklar. Bellekteki bitler aşağıdaki gibidir. 0000-0000-0000-0000-0000-0000-0010-1101 Buna sayının ikili gösterimi denir. Bir sayının ekranda gösterilebilmesi için onun Unicode karaktere dönüşmüş olması gerekir. Unicode karakterin gerçek değeri sayının genliğine eşittir. Meselâ 45 sayısı 4 ve 5 karakterlerinden oluşur. Yani iki tane 16-bit koddan oluşur. 0000-0000-0011-0100 ve 0000-0000-0011-0101 Bildiğiniz gibi, Console.Write ve Console.WriteLine yöntemleri ekranda gösterebilmek için otomatik olarak tamsayıları string haline dönüştürürler. Bazen string veriyi tamsayıya, tamsayıyı stringe dönüştürmek istersiniz. Bir string ifadeyi tamsayıya dönüştürmek için string ifade sadece rakamlardan oluşmalıdır, eksi işareti de içerebilir. Şimdi bir tane tamsayı bir tane de string değişken tanımlayarak işe başlayalım. int I = 45; string S; Basit bir şekilde bir tamsayıyı string ifadeye dönüştüremezsiniz. S = I; // Bu şekilde olmaz. Eğer yukarıdaki ifadeyi denerseniz aşağıdaki gibi bir hata mesajı alırsınız. Cannot implicitly convert type ‘int’ to ‘string’ (int türünde bir sayıyı string türüne kapalı dönüşümle dönüştüremezsiniz.) Aşağıdaki gibi casting yapmak da mümkün değildir. S = (string)I; // Bu şekilde de olmaz. Eğer yukarıdaki ifadeyi denerseniz aşağıdaki gibi bir hata mesajı alırsınız. Cannot convert type ‘int’ to ‘string’ (int türünü string türüne dönüştüremedi.) C# tip güvenli bir dildir yani farklı türlerin kapalı dönüşüm ya da açık dönüşüm ile dönüştürülmesinde bir takım kurallar ve kısıtlamalar söz konusudur. Ama buna rağmen bazı durumlarda tamsayı bir türün string bir türe dönüştürülmesi sahne arkasında meydana gelir, meselâ Console.WriteLine yöntemi böyledir. Bir tamsayıyı string ifadeye dönüştürmenin bir yolu, onu boş bir string ile birleştirmektir. S = "" + I; ya da S = I + ""; Her iki durumda da C# tamsayıları string bir ifade ile birleştirebilmek için dönüştürme işlemini yapar. Tamsayı ile birleştirilmek istenen string boş olduğuna göre sonucu etkilemez, neticede tamsayı bir ifade string bir ifadeye dönüşmüş olur. Mesela I değişkeni 45 sayısına eşit olsa dönüştürme işleminden sonra ‘4’ ve ‘5’ karakterlerinden meydana gelen bir yazı olur. Hala dönüştürme işlemi sahne arkasında yapıldı. Biraz da hile yaptık. Ama açık bir şekilde bir tamsayıyı string ifadeye dönüştürmek için ToString isminde bir yöntem kullanabiliriz. Herhangi bir değişkeni string ifadeye dönüştürür. S = I.ToString(); // Dönüştürme işlemi başarılı. Bu işlem sonucunda S string ifadesi “45” olan iki karakterli bir yazı oldu. ToString bir yöntemdir. her zaman yöntemleri isminin sonunda parantez aç ve parantez kapa işaretleri ile birlikte kullanırız. Yöntemi tanımlarken de, kullanırken de bu böyledir. Yukarıdaki ifadede geçen ToString yöntemi hiç argümana sahip değildir ama dönen değeri bir string ifadedir. Console ve WriteLine arasında noktaya ihityaç duyduğumuz gibi, tamsayı değişkenimiz ve ToString arasında da noktaya ihtiyaç duyduk. Hatta ToString yöntemini bir tamsayı ifadenin önünde kullanabilirsiniz. S = 279.ToString(); Fark ettiğiniz gibi ToString yöntemi çok sık ihtiyaç duyulan bir yöntemdir. Bu yöntemi her nesne ve tür ile kullanırsınız ve nesnelerin yazıya dönüşmüş hallerini elde edersiniz. Şimdi string bir ifadeyi tamsayıya dönüştürelim. Önce string bir değişken tanımlayalım ve rakamlardan oluşan bir değer atayalım. S = "57"; Şimdi bu string ifadeyi tamsayıya dönüştürmek istiyoruz. Şansımıza, string ifademiz de sadece rakamlardan oluşuyor. Burada da söylemek gerekirse atama işlemini yine kullanamayız. int I = S; // İşe yaramaz. Hemen derleme hatasını görürsünüz. Cannot implicitly convert type ‘string’ to ‘int’ (string ifadeyi tamsayı bir ifadeye kapalı dönüştürme ile dönüştüremezsiniz.) Şimdi casting yapalım. int I = (int)S; // Hala işe yaramadı. Aşağıdaki derleme hatası oluştu. Cannot convert type ‘string’ to ‘int’ (string türünü int türüne dönüştüremezsiniz.) Hemen aklımıza bir yöntem olabileceği geliyor. ToString bi bir yöntem olsa da dönüştürme işlemini yapsak. I = S.ToInt(); // Ama böyle bir yöntem yok. Yok ama doğru yoldasınız. int Türü System.Int32 yapısının bir aliasıdır. Bu yapının Parse diye bir dönüşüm işi yapan bir yöntemi var. I = Int32.Parse(S); Int32.Parse yönteminin dönen değeri bir tamsayıdır. Parse yöntemine geçeceğimiz string rakamlardan oluşmalıdır ama eksi işaretine sahip olabilir. Sağında solunda boşluk olabilir. Mesela aşağıda doğru yazılmış bir ifade var. I = Int32.Parse(" -572 "); Eğer string, sayısal olmayan karakterler içeriyorsa ya da eksi işareti ile sayı arasında boşluk varsa Parse yöntemi bir istisna ortaya çıkaracaktır. Sayının int sınırlarının dışında olması da Parse yönteminin istisna ortaya çıkarmasına neden olur. Şimdi her iki dönüşümü yapan yöntemleri bir karşılaştıralım, benzer ya da farklı yanlarına bakalım. S = I.ToString(); I = Int32.Parse(S); Her iki yöntem de System.Int32 yapısının elemanıdır. Aralarında temel bir fark var. ToString yönteminin sol tarafına bakalım. Bir tamsayı değişken var. ToString yöntemi belirli bir tamsayı var ve ona uygulanıyor. Fakat Parse yönteminin sol tarafında bir değişken yok. Int32 yapısının ismi var. Parse yöntemi belirli bir tamsayıya uygulanmıyor. Bir tamsayı oluşturuyor. Aralarındaki temel fark ise ToString bir instance (örnek) yöntemdir, Parse ise static (durağan) bir yöntemdir. ToString bir örnek yöntemdir, dolayısıyla belirli bir tamsayıya uygulanır, diğer bir deyişle Int32 yapısının bir örneğine uygulanır. Bir tamsayıya ya bir tamsayı değişkene ya da Int32 yapısının bir örneğini yani tamsayı döndüren bir yönteme sahip olasınız ki ToString kullanabilesiniz. Int32.Parse static bir yöntemdir. Yöntemin soluna Int32 yapısının adını yazdıktan sonra kullanırsınız. Int32.Parse yöntemini çağıracak belirli bir tamsayıya sahip olmanıza gerek yok. Yöntemin kendisi bir tamsayı oluşturur. Başka durağan yöntemler de biliyoruz. Console.Write ve Console.WriteLine yöntemleri, Main yöntemi de durağan yöntemlerdir. MinValue ve MaxValue (field) alanları ise Int32 yapısının durağan alanlarıdır. Bu yöntemlerin önüne yapıların adını yazmak gerekiyor. String sınıfının Length yöntemi bir örnek alandır. Belirli bir string ifadeye uygulayabilirsiniz. Bildiğiniz gibi int veri türü System.Int32 yapısının bir aliasıdır. Bu durumda System.Int32 yerine int yazabilirsiniz hatta using direktifi ile System isim uzayını deklare etmişseniz sadece Int32 de yazabilirsiniz. I = Int32.Parse(S); Ya da aşağıdaki gibi olabilir. I = int.Parse(S); Her iki kullanım da aynı işi yapar ama gerçek sınıfın ya da yapının adını kullanmayı tercih edebilirsiniz. Bütün tamsayı türleri ToString ve Parse yöntemine sahiptirler. Meselâ: ushort US = UInt16.Parse(S); ya da ushort US = ushort.Parse(S); Parse yöntemini işaretsiz tamsayılarla kullanırken eksi işareti kullanmak bir istisna ortaya çıkaracaktır. Yöntem çağrılarının işlem önceliği vardır. Peki aynı ifade içerisinde 2 tane yöntemi yan yana çağırırsak ne olacak? string S2 = Int32.Parse(S).ToString(); Aynı önceliğe sahip 2 tane yöntem var. Bu tür durumlarda öncelik sırası soldan sağa doğrudur. Öncelikle Int32.Parse yöntemi çalışır. Bu durağan yöntemin çalışması sonucunda bir tamsayı oluşur. O zaman ifade aşağıdaki şekle dönüşür. string S2 = 45.ToString(); Artık kolay. ToString yöntemi örnek yöntemdir. 45 sayısını ‘4’ ve ‘5’ şeklinde 2 tane karakterden oluşan S2 string ifadesine dönüştürür. Şimdi tersini yapalım. Önce bir tamsayıyı string ifadeye dönüştürelim, sonra bu string ifadeyi tekrar tamsayıya dönüştürelim ve tamsayı bir değişkende tutalım. int I2 = Int32.Parse(I.ToString()); Bu iç içe yöntem çağırmadır. Bir yöntem diğer bir yönteme argüman olarak yazılmış. Bu durumda görünüşe bakılırsa Parse yöntemi önce çalışacak gibi ama değil. Öncelikle argüman gerekiyor. Bunun için de ToString yönteminin çalışması gerekiyor. Çalışınca ifade aşağıdaki şekle dönüşür. int I2 = Int32.Parse("45"); Daha sonrası zaten kolay. Parse yöntemi çalışır ve bir tamsayı döndürür. System isim uzayı Covert diye de bir sınıf barındırır. Çok güzel bir sınıftır. Bütün temel türleri diğerlerine dönüştürebilecek durağan yöntemlere sahiptir. Şimdi aşağıda gördüğünüz örnek bir string ifadeyi tamsayıya dönüştürmek için alternatif yol sunar. I = Convert.ToInt32(S); Covert sınıfının dokümanları incelendiğinde Int32.Parse kullandığı görülür. Onun için olan bütün kurallar ve kısıtlamalar Convert için de geçerlidir. Aşağıdaki örnek de ToString örnek yöntemine durağan bir alternatiftir. S = Convert.ToString(I); Convert sınıfı aynı zamanda bu yöntemlerin aşırı yüklenmiş şekillerine de sahiptir. Sayı tabanları ile çalışmaya da izin verir. Bu aşırı yüklenmiş yöntemler virgülle ayrılmış 2 tane argümana ihtiyaç duyarlar. Meselâ: I = Convert.ToInt32(S, 16); Bu örnekte S değişkenindeki string ifadenin hexadesimal rakamlar içerdiğini varsayar. Yöntemin ikinci argümanı sadece 16 değil 2, 8, 10, 16 olabilir. Her durumda ilgili string ifade o tabanda geçerli olacak rakamlara sahip olmalıdır. Meselâ eğer ikinci argman 2 ise string ifade sadece 0 ve 1 rakamlarını içermelidir. Benzer şekilde aşağıdaki ifade de tamsayıyı hexadesimale çevirir. Aşağıdaki gibi bir ifadede de yine ikinci argüman 2, 8, 10, 16 olabilir. S = Convert.ToString(I, 16); Parse yönteminin de aşırı yüklenmiş sürümleri var. Yöntemlerin aşırı yüklenmesi meselesini de başka bir yazıda ele alacağız. |
Cevap: C# Hakkında Herşey. C# Konsoldan Veri Girmek Konsoldan Veri Girmek 11 Mayıs 2007 KONSOLDAN VERİ GİRMEK Programlar çoğu zaman bizim girdiğimiz verilere göre işlemlerini yürütürler. Daha önce, görsel programlarda fare hareketleri ile, butonlara tıklamalarla veya yazı kutularına klavyeden bir şeyler yazarak veri girişi yaptık. Veri girişlerinin klavye veya fare ile yapıldığını bu nedenle biliyoruz zaten. C# konsol uygulamalarında veri girişi daima klavyeden yazı yazma ile gerçekleşir. Genellikle konsol uygulamalarında program kullanıcıdan bir şeyler girmesini ister ve kullanıcının verdiği yanıta göre kullanıcının ne demek istediğini anlamaya çalışır. İşte bizim konsolda klavyeden giriş yapmamızı sağlayan Console sınıfının Read ve ReadLine yöntemleridir. Console.WriteLine ve Console.Write yöntemlerini kullanırken giriş argümanlarını yazmamız gerekiyordu. Ve bu yöntemlerden dönen bir argüman yoktu. Console.Read ve Console.ReadLine yöntemlerinde ise giriş argümanı yok ama bu yöntemlerden dönen dönüş argümanları mevcut. Biz bu iki yöntemi içeren bir program yazdığımızda ve bu yöntemleri çağırdığımızda kontrol biz Enter tuşuna basana kadar programa tekrar geçmeyecektir. Buradan da bu iki yöntemin ve dolayısı ile programın çalışmaya devam edebilmesi için bu yöntemlerin çağrıları yapıldıktan sonra Enter tuşuna basmamız gerektiğini anlıyoruz. Bu arada Console.ReadLine yönteminin bu iki yöntem içinde kullanımı kolay olan yöntem olduğunu söyleyebiliriz. Şimdi konsoldan string girişi yapan ilk programı yazalım. 1 string yazi; 2 yazi = Console.ReadLine(); Yukarıda görüldüğü gibi 1. satırda string tipinde bir değişken tanımlandı ve ikinci satırda Console.ReadLine() yöntemi çağrılarak yazı adlı stirng değişkene bu yöntemden dönen ( kullanıcının konsol ekranında yazdıkları ) değerler atandı. Burada dikkati çeken bir noktada Console.ReadLine yönteminden dönen değerin string bir değişken herhangi bir işleme tabi tutulmadan direkt olarak atanabildiğidir. Burada iki satırda yaptığımız işlemi tek satırda da gerçekleştirebilmemizin mümkün olduğunu biliyoruz. 1 string yazi = Console.ReadLine(); Şimdi kullanıcıdan bir şeyler alan bir program yazalım. 1 using System; 2 class KonsoldanVeriGirisi 3 { 4 static void Main() 5 { 6 Console.Write("Bir şeyler yaz ve Enter tuşuna bas:"); 7 string yazi = Console.ReadLine(); 8 Console.WriteLine("Klavyeden yazdığınız yazı:" + yazi ); 9 } 10 } Yukarıdaki programda kullanıcıdan bir şeyler yazmasını istedik ve bu yazdıklarını bir string değişkene Console.ReadLine yöntemi ile atayarak daha sonra bu değişkeni Console.WriteLine yöntemi ile konsolda görüntüledik. Burada dikkat edilirse ilk satırda Write yöntemi kullanıldı çünkü kullanıcının yazdıklarının bizim Console.Write yöntemi ile konsola yazdırdığımız yazıların yanına yazılmasını istedik. Kullanıcı bir şeyler yazıp Enter tuşuna bastığında Console.ReadLine yöntemi imlecin aşağı satıra düşmesini sağlıyor. Tam bu sırada Console.ReadLine yöntemi değer döndürme işlemini gerçekleştiriyor. Console.WriteLine ve Console.Write yöntemleri bir integer değişkeni kapalı bir şekilde string tipine dönüştürerek konsola yazdırıyordu. Ama Console.ReadLine yönteminin böyle bir özelliği mevcut değil. Yani biz klavyeden bir integer okumak istediğimizde bunu Int32.Parse yöntemini kullanarak integer tipine çevirmemiz gerkiyor. 1 using System; 2 class KonsoldanVeriGirisi 3 { 4 static void Main() 5 { 6 string S; 7 int I; 8 Console.Write("Bir sayı yaz ve Enter tuşuna bas:"); 9 S = Console.ReadLine(); 10 I = Int32.Parse( S ); 11 Console.WriteLine(“Girdiğin numara:” + I ); 12 } 13 } Yukarıdaki programda iki durumdan söz edebiliriz. Birincisi; Console.ReadLine yönteminden dönen değerin bir string olması ve string değişkene doğrudan atanabilmesi. İkincisi ise; bu string değişkenin Int32.Parse yöntemi ile integer bir değişkene aktarılması. Ayrıca buradaki S string değişkenini Console.ReadLine ve Int32.Parse yöntemlerini birleştirerek ortadan kaldırabiliriz. 1 I = Int32.Parse(Console.ReadLine()); Bu satırda ilk olarak Console.ReadLine yöntemi çağrılıyor ve konsoldan girilen yazıları okuyor. Daha sonra okuduğu değerleri Int32.Parse yöntemine aktarıyor. Şimdi kullanıcıdan sayı almayı bildiğimize göre gerçek hayata yakın bir program yazabiliriz. 1 using System; 2 class Bilet 3 { 4 static void Main() 5 { 6 int YetiskinUcreti = 10 , CocukUcreti =7 ; 7 8 Console.Write("Yetişkin bilet adedini giriniz:"); 9 int YetiskinBiletSayisi = Int32.Parse(Console.ReadLine()); 10 11 Console.Write("Cocuk bilet adedini giriniz:"); 12 int CocukBiletSayisi = Int32.Parse(Console.ReadLine()); 13 14 int ToplamMaliyet = YetiskinUcreti * YetiskinBiletSayisi + CocukUcreti*CocukBiletSayisi; 15 16 Console.WriteLine("Toplam bilet ücreti=" + ToplamMaliyet); 17 } 18 } Program kullanıcıdan yetişkin ve çocuk bilet adedini alıyor. Daha sonra, önceden bildiği bilet ücretleri ile adetleri çarpıp toplam ücreti bize söylüyor. Konsoldan veri girişi yapmak konsol çıktısı almaktan daha zordur. Veri girişlerinde kontrol her zaman zordur. Kullanıcı konsoldan istediğimiz şartlara uymayan veriler de girebilir. Mesela program aşağıdaki konsol çıktısını verir. 1–100 arasında bir sayı giriniz: Ve kullanıcı aşağıdaki ifadeyi girer. 10A Burada yanlış yazılma ihtimali var. Ama başka programlarda olduğu gibi yanlış yazıları düzelten bir durum söz konusu değil. Bazı programlar bu tür yanlışlar için doğrulama ve kontrol etme işlemleri gerçekleştirirler. Mesela yanlış yazılan “A” harfini ekrana yazmamak veya bir beep sesi ile uyarmak gibi. Ama maalesef. Net konsolu bu tür tekniklere izin vermez. Konsol kullanıcının satır boyunca yazmasını ve Enter tuşuna basmasını bekler ve kullanıcının yazdığını işlemeye başlar. Eğer uygun giriş yapılmamışsa sonuç elde edilemez. Ama kullanıcıdan tekrar giriş yapması istenebilir. Kullanıcı girişlerini kontrol eden ve oluşan istisnaları anlaşılır bir şekilde kullanıcıya gösteren kontrol yapıları daha sonraki yazılarda bahsedilecek. |
Cevap: C# Hakkında Herşey. C# Sabitler Sabitler Şimdi bir sinema bileti programı yazalım. Normal bilet ve öğrenci bileti için ayrı ayrı fiyat seçenekleri olsun. Program sinemaya gidince ödeyeceğimiz toplam tutarı bulsun. using System; classSinemaBileti { staticvoid Main() { int TamBilet = 10, OgrenciBileti = 7; Console.Write("Kaç tane tam bilet: "); int TamBiletSayisi = Int32.Parse(Console.ReadLine()); Console.Write("Kaç tane öðrenci bileti: "); int OgrenciBiletiSayisi = Int32.Parse(Console.ReadLine()); int ToplamTutar = TamBiletSayisi * TamBilet + OgrenciBiletiSayisi * OgrenciBileti; Console.WriteLine("Toplam tutar (YTL)" + ToplamTutar); Console.ReadLine(); } } Yukarıdaki programda 5 tane değişken var. 2 tanesi ilk değer almış ve 2 tanesi kullanıcıdan isteniyor ve 1 tanesi de hesaplama sonucu oluşuyor. İlk değer ataması yaptığımız 2 değişkene bir de başka açıdan bakalım. Bu 2 değişkeni hiç kullanmasak ve programı aşağıdaki gibi değiştirsek yine aynı işlevi yerine getirir. using System; classSinemaBileti { staticvoid Main() { //int TamBilet = 10, OgrenciBileti = 7; Console.Write("Kaç tane tam bilet: "); int TamBiletSayisi = Int32.Parse(Console.ReadLine()); Console.Write("Kaç tane öðrenci bileti: "); int OgrenciBiletiSayisi = Int32.Parse(Console.ReadLine()); //int ToplamTutar = TamBiletSayisi * TamBilet + // OgrenciBiletiSayisi * OgrenciBileti; int ToplamTutar = TamBiletSayisi * 10 + OgrenciBiletiSayisi * 7; Console.WriteLine("Toplam tutar (YTL)" + ToplamTutar); Console.ReadLine(); } } Aralarında bir fark yok ama bu yeni şekilde 10 ve 7 değerleri birer sayı ve isimleri yok. Belki yorum satırları eklesek yardımcı olur. Eğer yorumlar olmazsa bir vakit sonra birisi sizin yazdığınız koda bakar ve “bu sayılar da ne?” der. Hatta bu kişi siz bile olabilirsiniz. Yazdığımız kodun okunurluğunu ve anlaşılırlığını kaybetmesi çok kötü bir durumdur. Diğer yandan, kullanıcının bilet fiyatlarını kendisinin girmesine izin de vermek istemiyoruz. Aslında aşağıdaki gibi yapabilirdik. Console.Write("Tam bilet fiyatýný gir: "); int TamBilet = Int32.Parse(Console.ReadLine()); Bilet fiyatlarının programın kaynak kodunda bulunmasını istiyoruz. Pogramın kodlarının içerisine değerleri yazmak en iyi çözüm değil. Bilet fiyatları değiştikçe kodu açıp değiştirip tekrar derlememiz lazım. Eğer sadece kendimiz kullanacaksak problem yok. Ama kodu değiştirip tekrar derledikten sonra yeni programı bütün kullanıcılara tekrar göndermek, yüklemek büyük problemler. Kodu yeniden derlemektense, diskte bir dosyada tutmak ve gerektiğinde yeniden programı derlemeden sadece o dosyayı değiştirmek güzel bir çözüm. Bu işlerin nasıl yapılabileceğini başka yazılarda anlatacağız. Şimdilik bu değişkenleri kodun en üstüne koyalım, program açılır açılmaz değiştirilmesi kolay olsun. Program kodlarının en üstünde aşağıdaki gibi iki ücret tanımlaması var. int TamBilet = 10, OgrenciBileti = 7; Ama programın sonlarına doğru aşağıdaki gibi bir kod bloğu gördüğünüz düşünün. TamBilet = 12; OgrenciBileti = 9; Bilet fiyatları değişmiş. Muhtemelen siz değiştirdiniz ama yorum cümlesi eklemeyi unuttunuz. Bunun gibi bir programda TamBilet ve OgrenciBileti fiyatlarının değişken olmaması gerekiyor. Sadece bir tek değere sahip olmaları ve program boyunca da değiştirilememeleri gerekiyor. Diğer bir deyişleTamBilet ve OgrenciBileti değişken değil de sabit olmalıdır. Sabitleri başlarına const yazarak tanımlarız. constint TamBilet = 10; constint OgrenciBileti = 7; Bir tanımlama ifadesinde const kullandıktan sonra artık TamBilet ve OgrenciBileti için değişken değil de sabit ifadesini kullanmak daha doğru olacaktır, TamBilet ve OgrenciBileti sabitleri. Sabitlerin değişkenlerden ne farkı olduğunu inceleyelim. Tanımlama işlemini yaptıktan sonra değerini değiştirmeye çalıştığınız zaman derleme hatası ile karşılaşırsınız. TamBilet = 12; Eğer programın bir yerlerinde yukarıdaki gibi bir ifade kullanırsanız C# derleyicisi size aşağıdaki hata mesajını verecektir. The left-hand side of an assignment must be a variable, property, or indexer. (Bir atama ifadesinin sol tarafında bir değişken, özellik ya da indeksleyici bulunmalıdır.) Ve TamBilet yukarıda sayılanlardan hiç birisi değildir. Gerçekte bir değişken değil, sabittir. Böyle bir derleme hatası aldığınız durumda, kendinize sormalısınız: “Acaba programın ilerleyen bölümlerinde değiştirmek isteyeceğim bir şeyi sabit olarak mı tanımladım?” ya da bu örnekte olduğu gibi “Acaba bir sabit tanımladım ama programın ilerleyen bölümlerinde yanlışlıkla değerini mi değiştirmeye çalıştım?” diye. Bir sabit tanımladığınız zaman ona bir değer ataması da yapmalısınız. constint TamBilet; // Derleme hatasý! Eğer yapmazsanız aşağıdaki hata mesajını görürsünüz. A const field requires a value to be provided. (Sabit bir alan için bir değer tanımlamanız gerekiyor.) Program boyunca değeri değişmeyecek olan bir değişken sabit olmaya adaydır. Sabit tanımlamak sadece programcının değer değiştirmek suretiyle hata yapmasını önlemez, aynı zamanda programın performansını da artırır. Derleyici sabitlerin sakladığı değerleri stack bölgesinde oluşturmak durumunda kalmaz. Eğer TamBilet ve OgrenciBileti değerlerini saklamak için sabit tanımlarsanız, derleyici ToplamTutar değerini ilk yaptığımz örnekte olduğu gibi değil de ikinci örnekteki gibi hesaplar. Sabitleri tanımlarken sadece literaller değil ifadeler de kullanabilirsiniz. constint TamBilet = 10; constint OgrenciBileti = 3 * TamBilet / 4; OgrenciBileti, TamBilet değeri ile yapılan bir takım matematiksel hesaplamalardan sonra ortaya çıktı. TamBilet değerini değiştirerek OgrenciBileti değerini de değiştirebilirsiniz. Bu durumda TamBilet, OgrenciBileti’nden önce tanımlanmış olmalıdır. Yukarıdaki örnekte de olduğu gibi, bir sabite değer ataması yaparken başka bir sabitin değeri kullanılabilir ama değişken kullanılmaz. Yorum Cümleleri adlı yazımızda geçen örneği hatırlarsak eğer, aşağıdaki gibi bir ifade vardı. haftalikUcret = 80 * GunSayisi; Bu örnekteki 80 sayısının ne için orada bulunduğunu kestirmek zor. Açıklayıcı bir isimle değiştirilse daha iyi olur. Yorum Cümleleri adlı yazımızda bir değişkenle değiştirmiştik. Fakat sabir kullanmak daha doğru bir karardır. constint GunlukUcret = 80; haftalikUcret = GunlukUcret * GunSayisi; Sabit kullanmak ifadeyi daha anlaşılır yaptı, ama daha da anlaşılır yapabiliriz. Sabit ifadeyi değerini açık hesaplamalar şeklinde yazarak da tanımlayabiliriz. constint GunlukUcret = 8 * 10; //Günde 8 saat çalýþýldýðýný varsaydýk. Yukarıdaki çarma işlemi derleme esnasında yapıalcağı için programnı çalışmasında da bir performans kaybı olmayacaktır. Bir sabitin değeri program derlenirken belli olmak zorundadır. Meselâ, conststring Prompt = "Adýnýzý giriniz: "; Promt bir sabit olduğu için başka bir string ifade ataması yapılamaz. Fakat şu şekilde bir stringi bir sabite atayamazsınız. conststring Response = Console.ReadLine();// Olmaz. ReadLine çağrısı çalışma esnasında oluşur, derleme esnasında değil. Derleme esnasında değeri belirli olan bir şeyi ancak bir sabite atayabilirsiniz. |
Cevap: C# Hakkında Herşey. C# Decimal Veri Tipi Decimal Veri Tipi Bazı programlama dillerinde değişkenlerin kullanımı veri tiplerine bağlı olmayabilir. Basic dili böyle idi. Bazı dillerde ise türlerin tanımlanması ve doğru karar verilmiş olması gerekir. Bir türün diğer bir türe dönüştürülmesi bizzat programcı tarafından açık olarak yapılmalıdır. Bu yüzden, Basic programlama dilinde veri tipleri üzerindeki kontrollerin artması en önemli gelişmelerden birisi olmuştur. Programcılarının değişkenler için veri tiplerini seçmesi gerekir. Tamsayı olmayan sayılar için C# programlama dili floating point ve decimal olmak üzere iki ayrı alternatif sunar. Decimal veri tipi diğer dillerde olmayan farklı bir veri tipidir. Gerçek sayılar için decimal veya floating point türünde değişken kullanmamız gerekir. Bilimsel veya mühendislik uygulamaları için tanımlanacak değişkenler için floating point veri tipi kullanılır. Floating point veri tipi çok büyük ve çok küçük sayılar için kullanılır. Bazı durumlarda, floating point türü kullanıldığında çok küçük hatalı sonuçlar oluşabilir. Decimal veri tipi kesin sonuçlar verdiği için floating point kadar esnek değildir. Decimal veri tipi, System.Desimal sınıfından türetilir. Kullanımı: decimal cebimdekiPara; Eğer cebinizde bozuk para yok ise decimal tipinde değişken kullanabilirsiniz. cebimdekiPara = 70; E?er bozuk paranız da varsa, şu şekilde kullanmak isterseniz: cebimdekiPara = 70.25; //Problem olabilir. Karışıklığa mahal vermemek için sonuna M veya m eklemeniz gerekir. cebimdekiPara = 70.25m; //Düzgün çalışacaktır Aşağıdaki programı inceleyelim. //-------------------------------------------------- //biletHesabi.cs //-------------------------------------------------- using System; class biletHesabi { static void Main() { const decimal yuksekFiyat = 12.50m, dusukFiyat = 8.25m; Console.Write(""Pahaly bilet fiyatını giriniz: ""); int pahaliBiletSayisi = Int32.Parse(Console.ReadLine()); Console.Write(""Ucuz bilet fiyatını giriniz: ""); int ucuzBiletSayisi = Int32.Parse(Console.ReadLine()); decimal toplamFiyat = pahaliBiletSayisi * yuksekFiyat + ucuzBiletSayisi * dusukFiyat; Console.WriteLine(""Toplam fiyat:"" + toplamFiyat + "" YTL""); } } Gördüğünüz gibi, decimal sayıları ve tamsayıları aynı ifade içinde kullanabiliyoruz. C# herhangi bir tamsayı değişkeni decimal türüne çevirebilir. Decimal değerler ve tamsayı değerler arasındaki hesaplama sonucu decimal değerdir. Fakat C#, decimal tipleri tamsayı tipine dönüştürmez. decimal toplamPara = 54.25m; int para = toplamPara; //Derleme Hatası C# derleyicisi bu şekildeki çevirmeyi önlemektedir. Decimal veri tipinden tamsayı veri tipine çevirmede kayıp oluşabilir. casting işlemi yaparak decimal tipte bir sayıyı kayıplarla birlikte tamsayı türüne dönüştürmek mümkündür. int para = (int)toplamPara; Bir bilme işlemin sonucunun decimal olabilmesi için işlem yapılacak sayılardan en az birisinin decimal olması gerekir, ya da decimal türüne dönüştürülmesi gerekir. int a = 25, b = 10; decimal c = a/b; //sonuc 2 çykacaktyr. Çünkü bir tamsayının diğer bir tamsayıya bölünmesi sonucu bölüm yine bir tamsayıdır. İşleme giren sayılardan birisini açık dönüştürme ile decimal sayıya dönüştürelim. int a = 25, b = 10; decimal c = (decimal) a/b; //sonuc 2.5 Çıkan sonucu yuvarlamak isteyebiliriz. Bunu da kaç basamak yuvarlayacağımızı belirterek yapabiliriz. decimal x = 25.77m; decimal y = .05m; decimal sonuc = x * y; // sonuc 1.2885 decimal yuvarlanmis = decimal.Round(sonuc, 2); //yuvarlanmis = 1.29 olur. |
Cevap: C# Hakkında Herşey. C# Kayar Nokta Veri Türleri Kayar Nokta Veri Türleri Bilimsel ve mühendislik uygulamalarda, genellikle çok küçük ve çok büyük sayılarla çalışmak ve daha fazla esnek olmak istersiniz. C#taki decimal veri türü sadece ondalık kısmın sağında ve solunda 28 basamağa kadar izin verir. Bu sınırlamalardan dolayı esnek değildir. Mesela güneşin ağırlığı yaklaşık 2*1030 kilogramdır. Elektronun ağırlığı ise yaklaşık 9*10-31 kilogramdır. Uzun yıllar, bilim adamları 3 ya da 4 hassasiyetli sayılarla işlemlerini kaydırma kuralları ile yaptılar. Günümüzde, kayar nokta veri türlerini kullanarak bilimsel gösterime yakın bir biçimde sayıları gösterip bilimsel hesaplamalarını yapıyorlar. C#ta 2 tane kayar nokta türü vardır, float ve double. 1985 yılında IEEE kayar nokta türleri ile ilgili standartları belirledi. İki tane tür belirlendi. 4 byte gerektirene tek hassasiyet 8 byte gerektirene de çift hassasiyet denildi. .net Framework içerisinde, bu iki kavramı karşılayan System.Single ve System.Double adında iki tane yapı vardır. Fakat C# double ve float isimlerini C dinliden miras aldı. Aşağıdaki tablo double ve float hakkında bilinmesi gerekenleri özetlemektedir. C# Türü .NET Türü Anlamlı Kısım Üssel Kısım float System.Single 23 bits (7 basamak) 8 bits (-45 to 38) double System.Double 52 bits (15–16 basamak) 11 bits (-324 to 308) Sağ taraftaki iki sütun float türünün 32 bitinin ve double türünün 64 bitinin, anlamlı kısımla üssel kısım arasında nasıl paylaşıldığını göstermektedir. Ek bir bit ise anlamlı kısmın işaretini tutar. Aşağıdaki sayıyı inceleyelim. 8.364 10-24 Anlamlı kısmı 8.364 olan kısmıdır. Float veri türünde 23 bit anlamlı kısım için ayrıldığına göre bu kısım yaklaşık 7 basamağa kadar olabilir. Üssel kısım için ise 8 bit ayrılmıştır. float ve double veri türlerini gösterirken Macar gösterimi kullanalım. float için f önekini, double için de d önekini kullanalım. float f; Tabi ki virgülden sonraki kısmı olmayan bir sayıyı yani bir tamsayıyı da float bir değişkende tutmak mümkündür. f = 123456789; Tamsayının kayar nokta türüne dönüşümü sırasında tamsayı hassasiyet kaybına uğrar. Eğer bu sayıyı ekranda görmek istersek aşağıdaki kodu yazıp çıktısını görelim. float f; f = 123456789; Console.WriteLine(f); Console.ReadLine(); [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Aslında aynı sayıdır. Sayının genliği değişmez ama 7 basamaktan yukarısını float ile gösteremediğimiz için hassasiyet kaybı olur. float bir değişkene ondalık kısmı olan bir sayı ataması yapılabilir. f = 45.384f; Bilimsel gösterimde bir sayıyı da float bir değişkene atayabiliriz. f = -34.78e-14f; Yukarıdaki örneklerde de görüldüğü gibi eğer tamsayı değil de ondalık kısmı olan ya da bilimsel gösterimdeki bir sayıyı float bir değişkende tutmak istersek sayının sonuna küçük harfle ya da büyük harfle F yazmak gerekiyor. Ayrıca bilimsel gösterimdeki e harfini de büyük ya da küçük yazmak fark etmez. Şimdi de bir double değişken tanımlayalım. double d = 456.374584; Double bir sayı tanımlarken herhangi bir sonek koymaya gerek yok ama gene de küçük ya da büyük harfle d harfi koyulabilir. Diğer bir ifadeyle ondalık kısmı olan ya da bilimsel gösterime sahip olan sayılar varsayılan olarak double kabul edilir. Bir çok programcı sadece double kullanır ve float ile ilgilenmez. Çünkü kayar nokta işlemleri işlemcinin matematik işlemler bölümünde özel bir kısımda ele alınır, bu yüzden double yerine float kullanmanın performans üzerinde bir etkisi yoktur. Günümüz uygulamalarında çoğu zaman belleğin verimli kullanımı ihmal edilebilir. Gerekli durumlarda C# tamsayı türünden bir sayıyı kapalı olarak float ya da double türüne dönüştürebilir. Biraz hassasiyet kaybı olur ama genliğinde bir kayıp söz konusu olmaz. Hatta C# float türünü de aynı şekilde double türüne kapalı olarak dönüştürebilir. C# kapalı olarak herhangi bir tamsayı türünü float ya da double türüne dönüştürmez. Eğer dönüştürme yapacaksak casting yapmak gerekiyor. Hangi türün hangi türe kapalı olarak dönüştürülebileceği aşağıdaki şekilde görülmektedir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] IEEE kayar nokta türleri (float, double) için standart tanımlarken diğer sayısal veri türlerine göre çok farklı tanımlamıştır. Mesela kayar nokta hesapları yapılırken asla istisna oluşmaz. Aşağıda tam sayılar için sıfıra bölme istisnası oluşturabilecek bir örnek var. double dPay = 124; double dPayda = 0; double dBolum = dPay / dPayda; Console.WriteLine(dBolum); Console.ReadLine(); İşlemin sonucunda dBolum adlı değişkene çok özel bir değer dönüyor. Bu özel değerler IEEE tarafından belirlenmiştir. Infinity (sonsuz) değeri de bunlardan biridir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Eğer dPay değişkenini -124 diye değiştirirsek o zaman da –Infinity (- Sonsuz) sonucunu göreceksiniz. Eğer dPay değerini de 0 olarak değiştirirseniz NaN göreceksiniz. NaN (Not a Number – Sayı Değil) anlamına gelmektedir. Eğer kayar nokta hesabında aşağı taşma ya da yukarı taşma durumu meydana gelirse o zaman da NaN değeri görüntülenecektir. float ve double yapıları PositiveInfinity, NegativeInfinity, ve NaN olan üç adet alana sahiptir. Bu alanlar açık olarak değer ataması yapabilmek içindir. Mesela, eğer double tanımlanmış 1 sayısını Positive Infinity değerine bölerseniz 0 sonucunu alırsınız ama PositiveInfinity değerini PositiveInfinity değerine bölerseniz 1 yerine NaN sonucunu alırsınız. Başka bir yazıda bu özel değerlerle nasıl çalışılacağını anlatacağız. Şimdilik kayar nokta veri türleri ile çalışırken bu tür sonuçların görülebileceğini bilsek yeter. Kayar nokta türlerini, çok büyük ya da çok küçük sayıların bölme ve çarpma gibi işlemlerini yaparken doğal olarak tercih etmeniz gerekiyor. Çünkü bu tür bir işlemde hiçbir zaman taşma meydana gelmeyecektir. Eğer C# kullanarak bilimsel ya da mühendislik hesaplamalar yapmak isterseniz üssel, logaritmik ve trigonometrik fonksiyonlarla hesaplamalar yapmak isteyeceksiniz. Bütün bunlar System isim uzayındaki Math sınıfının içerisinde statik yöntemler olarak mevcuttur. Meselâ, üs alma işlemini Pow yöntemini kullanarak yapabilirsiniz. dSonuc = Math.Pow(dTaban, dUs); Bu yönteme virgülle ayrılmış 2 tane argüman geçeriz. double olmayan argümanlar kapalı olarak double türüne çevrilir. double dSonuc = Math.Pow(3, 4); Console.WriteLine(dSonuc); Console.ReadLine(); [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Ama decimal veri türü hiçbir türe kapalı olarak çevrilemeyeceğinden ötürü decimal sayıları bu yönteme geçmek için açık dönüşüm yapmak gerekiyor. Karekök almak için Pow yöntemini ilgili sayının 0.5 kuvvetini almak suretiyle kullanabilirsiniz. dSonuc = Math.Pow(dSayi, 0.5); Ya da karekök almak için olan Sqrt yöntemini kullanabilirsiniz. dSonuc = Math.Sqrt(dSayi); Şimdi bir dik üçgenin hipotenüsünü hesaplayabileceğimiz küçük bir örnek yazalım. Pisagor teoremine göre dik üçgenin hipotenüs uzunluğu dik kenarlar uzunluklarının kareleri toplamının kareköküne eşittir. Math.Sqrt yöntemine argüman olarak iki tane Math.Pow işleminin sonuçlarının toplamlarını geçeceğiz. using System; class Program { static void Main() { Console.Write("İlk Kenar: "); double dKenar1 = Double.Parse(Console.ReadLine()); Console.Write("İkinci Kenar: "); double dKenar2 = Double.Parse(Console.ReadLine()); double dSonuc = Math.Sqrt(Math.Pow(dKenar1, 2) + Math.Pow(dKenar2, 2)); Console.WriteLine("Hipotenüs hesaplandı: {0}", dSonuc); Console.ReadLine(); } } [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Math sınıfının ayrıca iki tane sabit alanı vardır, matematik hesaplarda sık kullanılan iki tane sabit değerli sayı. pi sayısını Math.PI, e sayısını da Math.E alanları bize verir. Bazı uygulamalarda kayar nokta vazgeçilmezdir ama her yerde değil. Gereksiz kullanımlarda bir takım sıkıntılar da meydana getirir. Klasik BASIC programlama dili bütün sayısal verileri kayar nokta şekilde tutar. Daha sonraki programla dilleri her sayı türü için ayrı değişken türü tanımlamaya olanak tanısa da programcılar çoğunlukla kayar nokta türleri tercih ederler. Çünkü alt taşma yok, üst taşma yok, daha kolay gelir. Kayar nokta türlerle uzun süre haşır neşir olmuş programcılar sıkıntılarını da iyi bilirler. Mesela 23.5 gibi bir sayı 23.50001 ya da 23.49999 olarak saklanmış olabiliyor. İkincisi büyük bir problemdir. Çünkü en yakın tamsayıya yuvarlamak istersek 23.49999 sayısı 23 sayısına 24 sayısından daha yakındır. Yeni programlama dillerinde kayar nokta türler çok fazla problem olmuyor. Sürekli birileri daha sağlıklı hesaplamalar yapmaya izin verecek çalışmalar yapıyor. Ama hala sıkıntılar var. Aşağıdaki örneği inceleyelim. Console.WriteLine(9.666e-7f); [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Gördüğünüz gibi WriteLine bize aynı sayıyı göstermedi. Şimdi de aşağıdaki örneğe bakalım. using System; class Program { static void Main() { float f1 = 1234567; float f2 = 0.1234567f; float f3 = f1 + f2; Console.WriteLine(f3); Console.ReadLine(); } } [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] float veri türü sadece 7 basamak gösterebiliyor, işlemin sonucunu da görüyorsunuz. f2 değişkeninin değeri kayıp. Eğer 7 basamaktan daha büyük sayılar gösterecekseniz double ver türünü kullanabilirsiniz. Ama double veri türünün de 16 basamaktan fazlasını tutamayacağını bilmeniz gerekiyor. Çok az denk gelse de IEEE standardı bizim istediğimiz sayıyı tutmaya yetmiyor. Bu genellikle anlamlı kısmın hassasiyetinden kaynaklanıyor. 16,777.216 ile 16,777.217 float sayıları arasındaki fark ihmal ediliyor. Çok küçük ve çok büyük sayılarda yakınsama söz konusudur. Meselâ, 12.34 sayısı float olarak saklandığı zaman 12,939,428 tamsayısının 220 ile bölümü olarak saklanır. Bu sayı yaklaşık olarak 12.34 ediyor. Eğer double olarak saklanırsa 6,946,802,425,218,990 tamsayısının 249 ile bölümü olarak saklanır. Bu sayı 12.34 sayısına çok çok yakındır, ama aynısı değildir. Aynı sayıyı decimal olarak saklarsak 1234 sayısının 102 ile bölümü olarak saklanır. Bu sayı tam olarak 12.34 eder. Bu durum decimal veri türünün ne kadar güçlü olduğunu gösteriyor. Bunun yanında şu gerçeği de göz önünde bulundurmak gerekiyor, kayar nokta türler bilimsel ve mühendislik hesaplarda kullanılsın diye var. Bilimsel ve mühendislik hesaplarda da her zaman yakınsama ve yuvarlama söz konusudur. Kesinlik gerektiren ama ondalık kısmı olan işlemler için zaten C# decimal diye bir tür içeriyor ve oldukça güçlü. |
Cevap: C# Hakkında Herşey. C# Yazı Biçimlendirme Yazı Biçimlendirme Bildiğiniz gibi C# dilinde decimal tipte bir m değişkeni şu şekilde yazıya dönüştürülür. using System; classYaziBicimlendirme { staticvoid Main() { double d = 23.45; string s = d.ToString(); Console.WriteLine(s); } } ToString metodunun kullanımı burada göründüğünden biraz fazla esnektir. .net Framework, sayısal türleri yazıya dönüştürürken istediğimiz biçimde biçimlendirip gösterme imkânı sunar. Meselâ: using System; classYaziBicimlendirme { staticvoid Main() { double d = 23.45; //string s = d.ToString(); string s = d.ToString("G"); Console.WriteLine(s); } } Buradaki G’nin anlamı (General) Genel formatlamadır. Varsayılan değer zaten G olduğu için yazmayabilirsiniz. Bu durumda yukarıdaki her iki örneğin de yapığı iş aynıdır. Farklı bir formatlama için tablodaki harfleri kullanabilirsiniz. Tablodaki harfleri büyük ya da küçük harfle yazmak fark etmiyor. Harf Anlamı Açıklama C Currency Para birimleri ile birlikte kullanılır. Üçer basamak ayırır. D Decimal Sadece integer değerler için. E Exponential Bilimsel gösterim için kullanılır. F Fixed Point Sayının bilimsel olmayan gösterimde gösterilmesini sağlar. G General Üstel ve noktalı değerlerin çok küçük olduğu yerlerde. N Number F ile aynıdır. Üçer basamak ayırır. P Percent Yüzde ifadeleri için kullanılır. Sayı 100’e bölünür, üçer basamak ayırır ve % işareti gösterilir. R Roundtrip Kayar nokta türler için kullanılır. Parse yöntemi ile geri dönüştürülebilecek bir string oluşturur. X Hexadecimal Tamsayı değerleri hexadecimal olarak gösterir. Burada dokuz tane formatlama biçimi var. Bir tanesi için örnek verelim. m 0,123 değerini tutuyorsa aşağıdaki programın çıktısı %12,30 olacaktır. using System; classYaziBicimlendirme { staticvoid Main() { double d = 0.123; string s = d.ToString("P"); Console.WriteLine(s); } } C formatlama özelliği para sembolü göstermek için kullanılır. Bu sembol mutlaka dolar işareti olmak zorunda değildir. Bölge ve dil seçeneklerine göre değişir. Ama biz özellikle bir para birimin göstermek istiyorsak, meselâ dolar işareti göstermek istiyorsak aşağıdaki gibi yazmalıyız. m.ToString (“N”) + “$” İsterseniz harften sonra rakamda kullanabilirsiniz. Meselâ; m.ToString (“P5”) Buradaki rakamın anlamı yanındaki harfe göre değişiklik gösterebilir. Aşağıdaki tabloda ToString metodu ile sayıların nasıl kullanıldığı gösteriliyor. Harf Anlamı Yazılacak Sayının Sonuca Etkisi C Currency Virgülden sonra gösterilecek basamak sayısı (Varsayılan değer 2) D Decimal Gösterilecek basamak sayısı (Eğer eksik olursa başına 0 eklenir.) E Exponential Virgülden sonra gösterilecek basamak sayısı (Varsayılan değer 6) F Fixed Point Virgülden sonra gösterilecek basamak sayısı (Varsayılan değer 2) G General Gösterilecek basamak sayısı. N Number Virgülden sonra gösterilecek basamak sayısı (Varsayılan değer 2) P Percent Virgülden sonra gösterilecek basamak sayısı (Varsayılan değer 2) R Roundtrip Kullanılmaz X Hexadecimal Gösterilecek basamak sayısı (Eğer eksik olursa başına 0 eklenir) Bir örnekle decimal tipteki bir değişkenin bütün formatlama çeşitlerini inceleyelim. using System; classNumerikFormatlama { staticvoid Main() { decimal m = 12345.345m; Console.WriteLine("Para formatında: " + m.ToString("C2")); Console.WriteLine("Üstel formatta: " + m.ToString("E2")); Console.WriteLine("Sabit noktalı formatta: " + m.ToString("F2")); Console.WriteLine("Genel formatta: " + m.ToString("G2")); Console.WriteLine("Sayı formatında: " + m.ToString("N2")); Console.WriteLine("Yüzde formatında: " + m.ToString("P2")); } } ToString yöntemi bölge ve dil seçeneklerine göre farklı sonuçlar verebilen esnek parametrelere sahiptir. Programınız hiçbir değişiklik yapmadan seçili bölge ve dil seçenekleri doğrultusunda uygun sonuçlar üretebilmektedir. Türkiye için seçili ayarlar doğrultusunda programın sonucu aşağıdaki gibi olacaktır. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Yukarıda görülen ekran çıktısı incelenirse yuvarlama işlemleri var. Ama bu yuvarlama işlemleri Round yönteminin kurallarından daha farklı yapılmıştır. İki sayı arasındaki bir değer yuvarlanacaksa yukarı yuvarlanmıştır. 12345.345 sayısı 12345.34 olarak yuvarlanması gerekirken yukarı yuvarlanmış ve 12345.35 olarak yuvarlanmıştır. Eğer bu sizin işinizi görmüyorsa ToString işleminden önce Round ile yuvarlayınız. Aşağıdaki örnekte 12345 tamsayısı sayısı hexadecimal sayıya dönüştürülmektedir. using System; classNumerikFormatlama { staticvoid Main() { int i = 12345; string s = i.ToString("X8"); Console.WriteLine(s); } } Burada 00003039 sayısı üretilir ve kısaltma sözkonusu değildir, 8 basamağa tamamlamak için başına dört tane 0 eklenmiştir. Ama aşağıdaki örnekte virgülden sonrası için 2 basamak belirtildiği için duyarlılık kaybı olacaktır. using System; classNumerikFormatlama { staticvoid Main() { int i = 12345; string s = i.ToString("E2"); Console.WriteLine(s); } } Ekranda Console.WriteLine ile birden çok sayı gösterecekseniz bu durumda string birleştirme işleminden yararlanabilirsiniz. String birleştirme işlemini string veri türü yazısında daha önce örneklerle görmüştük. using System; classNumerikFormatlama { staticvoid Main() { int A = 3, B = 4; Console.WriteLine(A + " ve " + B + " sayıları toplamı " + (A + B) + " eder."); } } Yukarıdaki örnekte gördüğünüz gibi karmaşık bir yazı şekli oldu. Bunun daha güzel bir şekli vardır. Bu da yer belirtme yöntemidir. using System; classNumerikFormatlama { staticvoid Main() { int A = 3, B = 4; Console.WriteLine("{0} ve {1} sayıları toplamı {2} eder", A, B, A + B); } } Yukarıdaki örnekte WriteLine yöntemi dört tane parametre almıştır. İlk parametre ekranda gösterilecek olan string ifadedir. Bu string ifade içersinde yer tutucular var ve dizilerde olduğu gibi 0 ile başlamıştır, küme parantezleri arasında belirtilmiştir. Bu yer tutucular gösterilecek olan string ifadeyi takip eden virgülle ayrılmış diğer üç tane parametre için yer belirtmektedir. {0} ile belirtilen yere A değişkeninin değeri, {1} ile belirtilen yere B değişkeninin değeri, {2} ile belirtilen yere de A+B işleminin sonucu gelecektir. İlk parametreden sonra belirtilecek parametreler sayısal ifadeler olabileceği gibi string ifadeler, string literaller de olabilir. Eğer yazının içerisinde küme parantezi geçecekse bunu ardı ardına iki tane kullanarak yapmalıyız. Bu yer tutucuları yazı içerisinde sıra ile yazmak zorunda değiliz. Nerede bulunmaları gerekiyorsa oraya koyabiliriz. Aşağıdaki örnekte yer tutucular {0} {1} {2} sırasıyla yazılmamıştır. using System; classNumerikFormatlama { staticvoid Main() { int A = 3, B = 4; Console.WriteLine("{2} değeri {0} ve {1} sayılarının toplamıdır.", A, B, A + B); } } İlk parametre olan string ifadeden sonra yazacağımız parametre sayısı yer tutuculardan fazla olabilir. Bir parametreyi yazmışsak ve onun için yer tutucu belirtmemişsek problem olmaz. Aşağıdaki örnekte yazılan C parametresi hiç kullanılmamıştır ama programın çalışması için bir engel teşkil etmez. using System; classNumerikFormatlama { staticvoid Main() { int A = 3, B = 4, C = 20; Console.WriteLine("{2} değeri {0} ve {1} sayılarının toplamıdır.", A, B, A + B, C); } } Aşağıdaki örnekte olduğu gibi 4 tane parametre düşünelim. 0, 1 ve 3 numaralı parametreleri kullanacağız ve 2 numaralı parametre hiç kullanılmayacak. Böyle bir kullanım da mümkündür. Kullanılmayacak olan parametrenin en son yazılma zorunluluğu da yoktur. using System; classNumerikFormatlama { staticvoid Main() { int A = 3, B = 4, C = 20; Console.WriteLine("{3} değeri {0} ve {1} sayılarının toplamıdır.", A, B, C, A + B); } } Bir yer tutucuyu tekrar tekrar kullanmak da mümkündür. using System; classNumerikFormatlama { staticvoid Main() { int A = 3, B = 4, C=20; Console.WriteLine("{3} değeri {0} ve {1} sayılarının toplamıdır. Sonu\u231 ? {3} değeridir.", A, B, C, A + B); } } Ama olmayan bir parametre için yer tutucu yazmak doğaldır ki yanlıştır ve bir istisna ortaya çıkacaktır. using System; classNumerikFormatlama { staticvoid Main() { int A = 3, B = 4, C = 20; Console.WriteLine("{0} ve {1} sayıları toplamı {3} eder", A, B, A + B); } } [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Yukarıda string birleştirme işlemi ile yazdığımız örneği bir defa daha yazalım ama açık ToString yöntem çağruları ile biçimlendirme de yapalım. using System; classNumerikFormatlama { staticvoid Main() { int A = 3, B = 4; Console.WriteLine(A.ToString("E4") + " ve " + B.ToString("E4") + " sayıları toplamı " + (A + B).ToString("E4") + " eder."); } } Karmaşık oldu, yer tutucular kullanarak yazalım. using System; classNumerikFormatlama { staticvoid Main() { int A = 3, B = 4; Console.WriteLine("{0} ve {1} sayıları toplamı {2} eder", A.ToString("E4"), B.ToString("E4"), (A + B).ToString("E4")); } } Ama gene karmaşık oldu. Daha güzel bir yöntem var. Sayısal biçimlendirme parametrelerini yer tutucularla birlikte yazabiliriz. Açık ToString yöntem çağrılarına da gerek kalmaz. using System; classNumerikFormatlama { staticvoid Main() { int A = 3, B = 4; Console.WriteLine("{0:E4} ve {1:E4} sayıları toplamı {2:E4} eder", A, B, A + B); } } Yer tutucu numarası bir iki nokta işareti ve ardından biçimlendirme parametresi geliyor. Bu parametreler normalde ToString yöntemine geçiliyor, ama bu şekilde kullanım çok daha pratik olduğu için daha çok tercih ediliyor. Çoğu durumda bir ifadenin karakter olarak ne kadar yer kaplayacağını bilmek imkânsızdır, meselâ tamsayılar 10 karaktere kadar, eğer negatif değer alabiliyorlarsa 11 karaktere kadar, üçer basamak ayrılıyorsa 4 karaktere kadar yer kaplayabilirler. Aşağıdaki örnekte sayılar iç içe geçmektedir. Console.WriteLine("{0}{1}{2}{3}", A, B, C, D); Bunu kolaylıkla aralarına boşluklar bırakarak ayırabiliriz. Console.WriteLine("{0} {1} {2} {3}", A, B, C, D); Alt alta birden çok WriteLine değeri yazdığımızı düşünürseniz belirli yerler kaplayarak sütunlar halinde alt alta yazılmasını isteyebiliriz. Alan genişliği denilen sayılar yazarak ne kadar yer kaplayacaklarını belirtebiliriz, bunu da yer tutucu numaraların yanına virgül koyup akabinde alan genişliği değerini giriyoruz. using System; classNumerikFormatlama { staticvoid Main() { decimal mA = 123.45m; string strB = "Kitap"; int iC = 12; decimal mD = 456678m; Console.WriteLine("{0,10}{1,15}{2,10}{3,20}", mA, strB, iC, mD); } } mA sayısı sağa dayalı olarak 10 karakter, strB değeri yine sağa dayalı olarak 15 karakter, iC değeri yine sağa dayalı olarak 10 karakter, mD değeri yine sağa dayalı olarak 20 karakter yer kullanılarak gösterildi. Çıktısı da aşağıdaki şekildedir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Konsolda bir satırda gösterebileceğimiz karakter sınırı da yine IBM punch kartlarındaki sınır olan 80 karakterdir. Biçimleme parametreleri ile alan genişliği parametrelerini birlikte kullanabilirsiniz. using System; classNumerikFormatlama { staticvoid Main() { decimal mA = 123.45m; string strB = "Kitap"; int iC = 12; decimal mD = 456678m; Console.WriteLine("{0,-15}{1,10:C2}{2,10:X5}{3,20:E3}", strB, mA, iC, mD); } } Yukarıdaki örnekte {0} yer tutucusunun gösterdiği değer dikkat ederseniz alan genişliği olarak -15 değerini almıştır. Bu da 15 karakterlik alanda soldan hizalama yapılacağı anlamına gelmektedir. Hem biçimlendirme hem de alan belirleme parametreleri birlikte kullanıldı. |
Cevap: C# Hakkında Herşey. C# Yöntemler ve Alanlar - I Yöntemler ve Alanlar - I .net Framework içerisinde mevcut olmayan bir yönteme ihtiyaç duyduğumuz zamanlar olur. Kendi ihtiyacımız doğrultusunda özel bir yöntem hazırlamamız gerekir. Mesela, dik üçgende hipotenüz hesabı yapan bir yöntem .net Framework içerisinde mevcut değildir. Biz pisagor teoremi ile hipotenüsün nasıl hesaplanacağını biliriz. Bunun için bir program yazmamız gerekiyor. Kısa kenarların her birinin kareleri toplamının karekökünü alırsak bu bize hipotenüs uzunluğunu verir. Karekök hesabı yapabilen ve herhangi bir sayının karesini hesaplayabilen yöntemler System.Math sınıfı içerisinde mevcuttur. Program aşağıdaki şekildedir. // ----------------------------------------------------------------- // Hipotenus projesinin kaynak kod dosyası Hipotenus.cs // ----------------------------------------------------------------- using System; class Hipotenus { static void Main() { Console.Write("Birinci kenarı giriniz: "); double dKenar1 = Double.Parse(Console.ReadLine()); Console.Write("İkinci kenarı giriniz: "); double dKenar2 = Double.Parse(Console.ReadLine()); double dSonuc = Math.Sqrt(Math.Pow(dKenar1, 2) + Math.Pow(dKenar2, 2)); Console.WriteLine("Hipotenüs: {0}", dSonuc); Console.ReadLine(); } } Eğer programımız birkaç tane hipotenüs hesabı yapacaksa kopyala yapıştır işlemleriyle bu ifadeyi çoğaltabiliriz. Ama bu etkin bir yol değildir. Üçgenin hipotenüsünü bulurken kısa kenarlar yerine taban ve yükseklik bilgilerini kullanmamız gerekirse hesap yapan ifadelerin tamamını değiştirmek gerekir. Bu çözüm hiç de esnek bir çözüm olmaz. Bir de ileride daha etkin bir hesaplama yolu bulduğumuzu düşünürsek o zaman kopyala yapıştır yaparak çoğalttığımız hesaplama satırları içinden çıkılmaz bir hal alır. Aslında Hipotenus.cs programını daha etkin bir şekilde yapmak da mümkündür. Mesela Math.Pow(dKenar1, 2) şeklinde Math sınıfının Pow yöntemini kullanmak yerine dKenar * dKenar yazarsak daha az bellek ve işlemci gücü kullanmış oluruz. Dışarıdan baktığımızda bu iki hesaplama şekli aynı gibi görünüyor. Ama Math sınıfı ve onun double türündeki her sayının istenilen kuvvetini alabilen Pow yöntemine göre çarpma işlemi yapmak daha az işlemci ve bellek kullanımı sağlayarak daha etkin bir yol sunar. Pow yönteminde genelleştirilmiş bir kuvvet alma algoritması kullanılmaktadır, oysa çarpma işlemi çok basittir ve kullanacağı bellek bölgesi çok küçüktür. Program kodu yazmaktan zevk alan bir programcı iseniz bile kopyala yapıştır yapmak yerine daha az kod kullanarak aynı işi yapmanın yolunu aramanız gerekiyor. Genellikle daha az kod daha az hata demektir. Defalarca hipotenüs hesabı yapacaksanız, bunu özel bir yöntem yazarak yapmak güzel bir yoldur. Yöntem Yöntem, küçük bir algoritmik mekanizmadır, işlenmemiş materyalleri içine gönderip ürün olarak geriye aldığımız bir fabrika gibi düşünebilirsiniz. Eğer bir yöntem yeteri kadar iyi tasarlanmış ve programlanmışsa, yöntemi kapalı bir kutu olarak görebiliriz. Yöntem doğru sonuçlar ürettiği ve anlamsız hatalar vermediği sürece hiç kimse nasıl tasarlandığı ve içerisindeki mekanizmanın nasıl işlediği ile ilgilenmez. Bir yöntem oluşturulurken izlenecek iki önemli aşama vardır. Bu aşamalardan en önemlisi yöntemin algoritmasını tasarlamak ve yapacağı işi gerçekleştirmektir ama daha önce karar verilmesi gereken diğer aşama ise yöntemin ara yüzüdür. Yöntemin ara yüzünü tasarlama işlemi, yöntemin içine neler gireceğini ve sonuçta dışarıya ne çıkacağını tanımlama işlemidir. Daha önce incelediğimiz yöntemlerde dikkat etti iseniz bir yönteme birden çok argüman girer ama geriye sadece bir tek şey döner, o da yöntemin dönen değeri olarak adlandırılır. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Bir yöntemin birden çok parametresi olabilir, hiç parametresi olmayan yöntem de olabilir. Ama muhakkak bir değer dönmesi gerekir. Eğer hiç değer dönmeyecekse, dönen değer olarak hiç değer dönmeyecek anlamına gelen void yazılır. Hipotenus yöntemi için giren ve çıkan değerler oldukça basittir. Yöntem üçgenin iki kenarını parametre olarak alacak ve yöntemden geriye hipotenus değeri dönecektir. Math.Pow yöntemini aşağıdaki gibi çağırabiliriz. double dSonuc = System.Math.Pow(dTaban, dUs); > Eğer using direktifiyle System isim uzayı programa dahil edilmişse, Pow yöntemini aşağıdaki şekilde çağırabiliriz. double dSonuc = Math.Pow(dTaban, dUs); Kendi yazdığımız Hipotenus yöntemini de aşağıdaki şekilde çağırırız. double dHipotenus = Hipotenus(dKenar1, dKenar2); Birden çok yönteme sahip olan, belki de birkaç tane ayrı sınıftan oluşan bir program yazdığımızı varsayalım. Hipotenus yöntemini birçok farklı yere yerleştirebiliriz. Şimdi bunlara farklı sürümler diyelim. Yöntemimizin ilk sürümü Main yöntemi ile aynı sınıfın içinde olacak ve ayrı bir sınıf ile isim uzayına ihtiyaç duymayacaktır. Aşağıda tipik bir sınıf tanımlaması var. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] class BenimSinif { static void Main() { // Main isimli yöntemin gövdesi } } Eğer bu sınıfın içine başka bir yöntem eklemek istiyorsak sınıfı başlatan ve bitiren küme parantezlerinin arasına eklemeliyiz, Main yöntemini başlatan ve bitiren küme parantezlerinin arasına değil. Yeni yöntemin eklenebileceği yer olarak iki seçeneğimiz var. Bu seçenekler aşağıda gösterilmiştir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] class BenimSinif { // Yeni yöntem buraya eklenebilir static void Main() { // Main isimli yöntemin gövdesi } // Yeni yöntem buraya eklenebilir } Bir yöntem, sınıf ile aynı isme sahip olamaz. (Aslında olabilir. Ama o zaman özel bir yöntem türü olur. Bu özel yöntemi başka bir yazıda anlatacağız.) C#, yeni yöntemin Main yönteminden önce ya da sonra tanımlanmasıyla ilgilenmez. Ama Main yöntemini en başta ya da en sonda yazmış olmamız bizim programlamaya yaklaşımımızı ortaya koyar. Bazı programcılar önce daha temel işlemleri yapan yöntemleri yazarlar. Daha sonra onlarla bağlantılı olan diğerlerini ve en sonunda hepsini kullanacak olan Main yöntemini. Buna tabandan tavana programlama ya da tümevaran programlama diyebilirsiniz. Bu yöntem daha çok pascal programlama dili ile ilişkilidir. Çünkü pascal dilinde bir yöntem ya da fonksiyon tanımlanmadan kullanılamaz, doğal olarak da en son ana program vardır. Bazı programcılar ise önce Main yöntemini yazarlar ve daha sonra sırasıyla diğerlerini. Buna da tavandan tabana programlama ya da tümdengelen programlama diyebilirsiniz. Bu sanki C geleneğinden gelen dillere daha yakın gibi görünüyor. Biz de bundan sonraki yazacağımız programlarda bu biçimi kullanacağız. Şimdi Hipotenus yöntemini tanımlayalım. Yöntemi Main yöntemindeki gibi static anahtar kelimesiyle tanımlamaya başlarız. static Daha sonra yöntemden geri dönen değerin tipini yazarız. Aşağıdaki örnekte Hipotenus yönteminden geriye double tipinde bir değer döner. static double Yönteme bir isim veririz. Yöntem isminden sonra parantez açarız. static double Hipotenus( Hipotenus yöntemi de aynı Main yöntemi gibi tanımlandı. Main yönteminden geriye bir değer dönmez, bu yüzden dönüş tipi void olarak tanımlandı. Aynı zamanda Main yönteminde parantezlerin içinde hiçbir şey kullanmayız. Çünkü dışardan aldığı bir değer yok. Aslında Main yöntemine de dışardan değer gelebilir ama bu çok özel bir durumdur. Bu özel durumu başka bir yazıda anlatacağız. Visual Studio 2005 ile bir konsol projesi oluşturduğumuz zaman otomatik oluşan Main yönteminin parantezleri arasında bir takım değerler yazılı olur. Biz şu anda ilgilenmiyoruz. Bizim şu anda yaptığımız gibi hiçbir şey yazmazsak da olur. Biz Hipotenus yöntemine iki tane argüman geçmek istiyoruz. Parametre ve argüman kelimeleri birbirinin yerine kullanılıyor gibi olsalar da aralarında bir nüans var. Bizim açımızdan yönteme gönderdiğimiz değerler argümadır, biz yönteme argüman geçeriz. Yöntem açısından bakıldığında ise bu değerler parametredir, yöntem dışardan parametre alır. Hipotenus yöntemine geçeceğimiz ilk parametre, d1’dir. Açtığımız parantezin içine ilk olarak bu parametrenin tipini ve adını yazarız. static double Hipotenus(double d1 Hipotenus yöntemine geçeceğimiz ikinci parametre, d2’dir. Aralarına virgül koyarak ayırırız. Parametrelerimiz bittiğine göre parantezi kapatırız. static double Hipotenus(double d1, double d2) Şimdi Main yöntemindeki gibi yöntemin gövde kısmını oluşturmak için bir çift küme parantezi eklememiz gerekiyor. static double Hipotenus(double d1, double d2) { //Yöntemin gövdesi buraya gelecek. } Yöntemlerde kullanacağımız değişkenler daha çok kendi içlerinde tanımlanır. Bu sebeple dSonuc olarak adlandırdığımız üçgenin hipotenüs uzunluğunu tutacağımız değişkeni tanımlamak istiyoruz. dSonuc’un hesaplanması dışardan aldığı iki parametre kullanılarak gerçekleştirilir. static double Hipotenus(double d1, double d2) { double dSonuc = Math.Sqrt(d1 * d1 + d2 * d2); return dSonuc; //Yöntem gövdesinin kalan kısmı buraya gelecek. } dSonuc isminde double türünde bir değişken tanımladık ve yaptığımız işlemin sonucunu bu değişkende tutuyoruz. Bu iki ifadeyi aslında birlikte yazabiliriz. Atama ve ilk değer işlemlerini birlikte yapabilmeyi daha önce atama işlemleri yazısında örneklerle açıklamıştık. Şimdi bu işlemi yapalım. Bu arada dönen değer kavramını biraz açalım. Yazının başlarında da söz ettiğimiz dönen değer kavramını hatırlayalım. Yöntemi tanımlarken zaten ilk olarak yöntemin dış dünyaya göndereceği dönen değerin tipini tanımlamıştık. Bu dönecek olan değer yöntem içerisinde return anahtar kelimesi ile belirtilir. return ifadesi aynı zamanda yöntemin çalışmasını sona erdirir. Bu yüzden return kelimesini yöntemin son ifadesi olarak kullanırız. Bununla beraber daha karmaşık durumlarda yöntem çoklu return ifadesine sahip olabilir. Aşağıda Hipotenus yönteminin tamamı ve Main yöntemi içinde kullanılmış şekli gösterilmiştir. // ----------------------------------------------------------------- // HipotenusHesaplama projesinin kaynak kod dosyası HipotenusHesaplama.cs // ----------------------------------------------------------------- using System; class HipotenusHesaplama { static void Main() { Console.Write("Birinci kenarı giriniz: "); double dKenar1 = Double.Parse(Console.ReadLine()); Console.Write("İkinci kenarı giriniz: "); double dKenar2 = Double.Parse(Console.ReadLine()); double dHipotenus = Hipotenus(dKenar1, dKenar2); Console.WriteLine("Hipotenüs uzunluğu " + dHipotenus); Console.ReadLine(); } static double Hipotenus(double d1, double d2) { double dSonuc = Math.Sqrt(d1 * d1 + d2 * d2); return dSonuc; } } Sınıf bildirimine, iki ayrı yöntemin tanımlanmasına ve programın yapısında tanımlanan küme parantezlerinin nasıl kullanıldığına dikkat edelim. Her iki yöntem de aynı sınıfın içinde yer alıyor. Bunun için sınıfın başlangıcını ve bitişini belirten küme parantezlerinin arasında bulunuyor. Her ikisi de kendi gövdelerini başlatan ve bitiren küme parantezlerine sahip. Bir yöntemi kullanırken önce onun ait olduğu isim uzayını ve o isim uzayında yöntemi barındıran sınıfın ismini yazarız. Eğer programın başında isim uzayı deklarasyonu yapılmışsa o zaman sadece sınıf adı ile birlikte yazarız. Bizim Hipotenus ve Main yöntemlerimizde olduğu gibi her ikisi de aynı sınıfın içerisinde ise sadece yöntemin adını kullanarak çağırabiliriz. Hipotenus, Main ile aynı sınıfın içinde olduğu için, Main içinde sadece yöntemin adını (Hipotenus) kullanılarak kolayca çağırdık. double dHipotenus = Hipotenus(dKenar1, dKenar2); İsterseniz Hipotenus isimli yöntemi sınıf ismini kullanarak da çağırabilirsiniz. double dHipotenus = HipotenusHesabi.Hipotenus(dKenar1, dKenar2); Şimdi adım adım programın çalışmasını inceleyelim. dHipotenus değişkeninin değer ataması işlemine kadar her şey normal işler. dHipotenus değişkenine ilk değer ataması yapılırken Hipotenus isimli yöntem çağrılır. Bunu yaparken de Hipotenus yöntemine dKenar1 ve dKenar2 adlı iki argüman geçilir. Bu noktada, artık programın işleyişi Hipotenus yöntemine geçer. Hipotenus yöntemine dışarıdan gelen dKenar1 ve dKenar2 değişkenlerini d1 ve d2 parametreleri karşılar. Yani dKenar1 ve dKenar2’nin değerleri artık d1 ve d2 parametrelerine aktarılmıştır. Hipotenus yöntemi gerekli işlemi yapar. return ifadesi Hipotenus yönteminin işleyişini durdurur. Main yöntemine işlemin sonucu return ifadesi vasıtasıyla gönderilir ve programın işleyişi Main yöntemine geçer. dHipotenus değişkeni de Hipotenus yönteminden dönen değeri karşılar, artık işlemin sonucu dHipotenus değişkeninde tutulmaktadır. Anlatılanları daha iyi kavramak için aşağıdaki şekil yardımcı olacaktır. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] |
Cevap: C# Hakkında Herşey. C# Yöntemler ve Alanlar - II Yöntemler ve Alanlar - IIKapsam – Görünürlük – Ömür (Scope – Visibility – Lifetime) Şimdi biraz da değişkenleri inceleyelim. Bir çok programcı bir yöntemden dönen değeri yöntemin adını çağrıştıracak şekilde isimlendirir. Hipotenus yönteminden dönen değeri dHipotenus isimli değişkende tuttuk, başındaki d de double türünde olduğunu gösterdi. Tabi ki bu bir zorunluluk değildir. Farklı isimler de verilebilir. Hatta Main yöntemindeki Hipotenus yöntemine geçtiğimiz değişkenlerin isimleri Hipotenus yönteminin parametreleri ile aynı olabilir. Çünkü her biri ayrı yöntemler içerisinde tanımlanmışlardır ve görünürlükleri de ait oldukları yöntemle sınırlıdır. .net kütüphanesinde birçok hazır sınıf var ve bu sınıfların birçok yöntemi var. Biz bu yöntemlere argüman geçerken acaba yöntemin içinde bizim gönderdiklerimizle aynı ya da farklı isimlerde değişkenler var mıdır ya da bizim Main içerisinde tanımladığımız değişkenlerle aynı isimde bulunup karışabilecek değişken var mıdır diye hiç düşünmeyiz. Çünkü aynı ya da farklı olması hiçbir karışıklık meydana getirmez. Yerel değişkenler, yani bir yöntemin içinde tanımlanan değişkenler sadece o yöntemin içinde geçerlidir. Başka bir yöntemin içinden erişilemezler. Örneğin dSonuc değişkenine biz hiçbir zaman Main yöntemi içinden ulaşamayız. Bu duruma yerel değişkenin kapsamı ya da görünürlüğü kendisini içeren yöntemle sınırlıdır deriz. Yöntem aynı zamanda değişkenlerin ömürlerinin ne kadar olacağına da karar verir. Yöntemin çalışması sona erdiğinde, yerel değişkenleri tutan stack bölgesi de serbest bırakılır. Dikkat ederseniz hipotenüs hesabı yapan programımızda Hipotenus isimli yöntem içinde dSonuc diye bir yerel değişken var. Ama d1 ve d2 için değişken değil de parametre ifadesini kullandık. Parametreler değişken değildirler. Ama yine de kapsamları, görünürlükleri ya da ömürleri yine ait oldukları yöntemle sınırlıdır. argüman – parametre (argument – parameter) Argüman ve parametre terimlerini biraz daha açıklayıp aralarındaki nüansı belirtmeye çalışalım. Çoğu zaman birbirinin yerine yanlışlıkla kullanılırlar ve zaten çok yakın anlamlıdırlar. Biz bir yönteme argümanlar geçeriz, yöntem de o gelen argümanların değerlerini kendi parametreleri ile eşleştirir ve yöntemin parametreleri bu değerleri alır. Yerel değişkenler gibi, parametreler de yöntemin içinde görünürlük sahibidir, dışarıdan erişilemez. En önemlisi de parametrelerle argümanlar aynı isimde olmak zorunda değildirler. Yukarıdaki örnekte de zaten ayrı isimler verdik. Bir yöntemin tanımlanmasında eğer dönen değer için bir tip yazılmışsa, return ifadesi ile bunu mutlaka yapmalıyız. Main yöntemi return ifadesine ihtiyaç duymaz çünkü döndüreceği bir değer yok. Bunu da yöntem tanımlamasında void yazarak belirttik. Ama yine de dönüş tipi void olan bir yöntemin içinde return kullanmak istersek yöntem gövdesinde en son satıra return; yazarak bunu yapabiliriz. Basitçe söylemek gerekirse return ifadesi yöntemin çalışmasını sonlandırır. Eğer hata ayıklama yapıyorsak, programın bir bölümünde kesmemiz gerekiyorsa aşağıda kalan kısmı yorum cümleleri haline getirebiliriz ya da istediğimiz yere return; yazarak Main yöntemini o şekilde çalıştırabiliriz. Bu durumda derleyici erişilemeyen bir kısım program kodu var anlamına gelen Unreachable code detected uyarısını gösterir. Çünkü return ifadesinden sonraki kod çalıştırılmaz. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Çoğu programcı bir yöntemin döndürdüğü değeri yazarken return (dSonuc); şeklinde parantezler kullanır ama bunu kullanma zorunluluğu yoktur. Yukarıda yazdığımız programda dSonuc yerel değişkenini devreden çıkarabiliriz. // ----------------------------------------------------------------- // HipotenusHesaplama2 projesinin kaynak kod dosyası Program.cs // ----------------------------------------------------------------- using System; class HipotenusHesaplama2 { static void Main() { Console.Write("Birinci kenarı giriniz: "); double dKenar1 = Double.Parse(Console.ReadLine()); Console.Write("İkinci kenarı giriniz: "); double dKenar2 = Double.Parse(Console.ReadLine()); double dHipotenus = Hipotenus(dKenar1, dKenar2); Console.WriteLine("Hipotenüs uzunluğu " + dHipotenus); Console.ReadLine(); } static double Hipotenus(double d1, double d2) { return Math.Sqrt(d1 * d1 + d2 * d2); } } Kapsülleme – Genelleme – İzole Etme (Encapsulate – Generalize – Isolate) Program yazarken, bazen yazdığımız bir kod öbeğinin başka zaman da kullanılabileceğini düşünürüz. Bu kod öbeğini bir yöntem içerisine alarak kasülleyebiliriz. Daha sonra bu yöntemi genelleyip bir kapalı kutu içerisinde izole edebiliriz. Bu işi yapmamızın sebebi tekrar kullanılabilir kod yazmak ve tekrar tekrar kod yazmaktansa yazılmış olanı kullanmaktır. Ne kadar az kod yazarsak o kadar az hata yaparız. Başka bir programda Hipotenus hesabı yapan kod öbeğini kullanmak istersek, onu bir yöntem içerisinde izole ettiğimiz için, yöntemi kopyala yapıştır yaparak kolayca başka programda kullanılır hale getirebiliriz. Tekrar kullanacağımız kod öbeğini bir yöntemin içerisinde izole edip kapsülledik. Test edip hatasız hale getirdik. İyi bir şekilde dokümantasyonunu yapıp içerisinde yapılan işleri kolayca anlaşılır hale getirdik. Daha sonra böyle bir hesap yapan yöntem lazım olduğunda içerisinde işlerin nasıl halledildiğini önemsemeksizin yöntemimizi kopyala yapıştır yaparak diğer programa taşır ve kullanırız. Ama daha iyi yaklaşımlar da var. Aşağıda adım adım Hipotenus yönteminin diğer programlarda kullanılabilir olması için yapmamız gereken işlemler var. Öncelikle Hipotenus yöntemi için ayrı bir sınıf oluşturacağız daha sonra da her yöntem için ayrı bir kaynak kod dosyası oluşturacağız. Bir program aşağıdaki genel yapıda olur. using System; class BenimSinif { // Main ya da diğer yöntemler } Bu konuya kadar yapılan çalışmalarda bir program bir tane sınıftan oluştu. Bu sınıf da sadece Main adlı bir tek yöntemden oluştu. Bir sınıf birden çok yöntemden oluşabileceği gibi bir C# kod dosyası da birden çok sınıf içerebilir. Ayrıca yeni sınıfın diğer sınıfa göre nerede bulunduğu da önemli değildir. using System; //Yeni sınıf buraya gelebilir. class BenimSinif { // Main ya da diğer yöntemler } //Yeni sınıf buraya da gelebilir Eğer bir kod dosyası birden çok sınıf barındırıyorsa, Main yöntemine sahip olan temel sınıfı en üste, diğerlerini de sırasıyla onun altına koymayı tercih ediyorum. Yeni eklediğimiz sınıfla birlikte kod dosyamız şu hale gelecektir. ing System; class BenimSınıf { // Main ve diğer yöntemler buraya gelir. } class YeniSınıf { // Sınıfın içindeki yöntemler } Şimdi yukarıda bahsedilen şeyleri birleştirip hipotenüs hesabı yapan programı yeniden yazalım. // ----------------------------------------------------------------- // HipotenusHesaplama3 projesinin kaynak kod dosyası Program.cs // ----------------------------------------------------------------- using System; class HipotenusHesaplama3 { static void Main() { Console.Write("Birinci kenarı giriniz: "); double dKenar1 = Double.Parse(Console.ReadLine()); Console.Write("İkinci kenarı giriniz: "); double dKenar2 = Double.Parse(Console.ReadLine()); double dHipotenus = Hesaplamalar.Hipotenus(dKenar1, dKenar2); Console.WriteLine("Hipotenüs uzunluğu " + dHipotenus); Console.ReadLine(); } } class Hesaplamalar { public static double Hipotenus(double d1, double d2) { return Math.Sqrt(d1 * d1 + d2 * d2); } } Programın sınıf diyagramı (class diagram) aşağıdaki şekildedir. Diyagram programın anlaşılmasını kolaylaştıracaktır. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Yeni sınıfa Hesaplamalar ismini verdik. İçinde şu anda bir tane yöntem var ama daha sonra gerektikçe başka yöntemler de eklenebilir. Hipotenus yönteminin diğer sınıf içerisinden de ulaşılabilir olması için başına public anahtar kelimesini ekledik. public static double Hipotenus(double d1, double d2) public ve static anahtar kelimelerinin hangisinin diğerinden önce yazıldığı önemli değildir ve bunlara yöntem niteleyicileri (method modifier) denir. Ama yöntemin dönüş tipi olan double muhakkak bu ikisinden sonra yazılmalıdır. public anahtar kelimesi, erişim niteleyicileri (Access modifier) adı verilen niteleyicilerdendir. Bunlar public, private, protected, internal ve protected internal kelimeleridir. Yeri gelmişken public kelimesinden kısaca bahsedelim ama diğerlerini zaten başka bir yazıda anlatacağız. Eğer hiç erişim niteleyicisi yazmazsak, varsayılan erişim niteleyicisi private niteleyicisidir, yazmasak da private niteleyicisinin özellikleri geçerli olur. Bu durumda bu niteleyiciye sahip olan yöntem sadece kendisini barındıran sınıfın içinden erişilebilir ama başka bir sınıftan erişilemez. Eğer public niteleyicisi kullanırsak, diğer sınıflar içerisinden de çağrılıp kullanılabilir. Programımızdaki diğer değişiklik ise Hipotenus yönteminin kullanılmasında oldu. Daha önce kendisini çağıran Main yöntemi aynı sınıfın içinde bulundukları için aşağıdaki şekilde kullanmıştık. double dHipotenus = Hipotenus(dKenar1, dKenar2); Ama şimdi farklı sınıfların içinde olduklarından kullanımı aşağıdaki gibi değişti. double dHipotenus = Hesaplamalar.Hipotenus(dKenar1, dKenar2); Şimdi diğer static yöntemlerin kullanımına benzedi. İsim uzayı meselesine de değinelim. .net Framework içerisindeki bütün sınıflar bir isim uzayının içerisinde organize olmuştur. Mesela System isim uzayı çok gerekli olan birçok sınıfı barındırır. Eğer bir isim uzayı belirtmezsek çalışma esnasında yazdığımız sınıflar geçici bir isim uzayı oluşturularak onun parçası haline gelir. Ama tabiî ki bu sınıfların gerçekte dâhil olduğu bir isim uzayı yoktur. Visual Studio 2005 ile bir proje oluşturduğumuz zaman, Visual Studio 2005 otomatik olarak proje ismi ile aynı isimde bir isim uzayı kendiliğinden oluşturur. Biz istediğimiz isimle değiştirebiliriz ya da silip isim uzayına dâhil olmayan bir sınıf da yazabiliriz. Şimdi Hipotenus yöntemini izole etmeye diğer adımla devam edelim. Hesaplamalar sınıfını ayrı bir kod sayfasının içerisine koyalım. Bir sınıfı kendi dosyasında izole ettiğimiz zaman, bu sınıfa ihtiyacı olan başka programlarda da kullanımı kolaylaşır. Java programlama dilinde ilginç bir kural var. Her bir sınıf ayrı bir kod dosyasında bulunmak zorundadır ve bu dosyaların isimleri içerisindeki sınıfın ismi ile aynı olmak zorundadır. C#’ta böyle bir zorunluluk yok ama eğer kullanmak isterseniz tabiî ki bu çok güzel bir yoldur. Şimdi Visual Studio 2005 ile AyriDosyalarlaHesaplama adlı bir Konsol Uygulaması projesi oluşturalım. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Projenin Progam.cs isimli kod sayfası aşağıdaki gibi olsun. // ----------------------------------------------------------------- // AyriDosyalarlaHesaplama projesinin kaynak kod dosyası Program.cs // ----------------------------------------------------------------- using System; class AyriDosyalarlaHesaplama { static void Main() { Console.Write("İlk kenarı gir: "); double d1 = Convert.ToDouble(Console.ReadLine()); Console.Write("İkinci kenarı gir: "); double d2 = Convert.ToDouble(Console.ReadLine()); double dHipotenus = Hesaplamalar.Hipotenus(d1, d2); Console.WriteLine("Hipotenüs uzunluğu: " + dHipotenus); Console.ReadLine(); } } Bu program daha önce yazdığımız HipotenusHesaplama3 projesinin Main yöntemini içeren HipotenusHesaplama3 isimli sınıfının aynısı. Projeyi bu şekilde derleyemeyiz, çünkü Hesaplamalar isimli sınıfı projeye dâhil etmedik. Şimdi projemize yeni bir dosya ekleyelim. Solution Explorer (Çözüm Gezgini) penceresinde Proje isminin üzerine sağ tıklayıp oradan Add (Ekle), oradan da New Item (Yeni Öğe) seçelim. Yeni kod dosyasının adını Hesaplamalar.cs olarak belirleyelim ve Add butonuna basalım. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Daha sonra aşağıdaki kodu içine ekleyelim. // --------------------------------------------------------------------- // AyriDosyalarlaHesaplama projesinin kaynak kod dosyası Hesaplamalar.cs // --------------------------------------------------------------------- using System; class Hesaplamalar { public static double Hipotenus(double dKenar1, double dKenar2) { return Math.Sqrt(dKenar1 * dKenar1 + dKenar2 * dKenar2); } } Her iki kod dosyasına da using System direktifini ekledik, çünkü ayrı kod dosyaları oldukarından ve her ikisinde de System isim uzayına ait sınıflar kullandığımızdan her ikisine de eklemek gerekiyor. Projeye yeni bir kod dosyası eklediğimizde Visual Studio 2005, sık kullanılan isim uzayları için using direktiflerini, projenin adıyla aynı olan isim uzayı tanımlamasını, ve kod dosyası ile aynı isimde bir sınıf tanımlamasını kendiliğinden dahil etti. Biz bunları aynı bırakabildiğimiz gibi, kendi isteğimize göre değiştirebiliriz. Şimdi projemizi derleyip çalıştırabiliriz. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Şimdi, Hesaplamalar sınıfını kullanan başka bir proje oluşturalım. Projenin Program.cs isimli kod sayfası AyriDosyalarlaHesaplama projesinin Program.cs isimli kod sayfası ile aynı oldu. // ----------------------------------------------------------------- // BaskaProgram projesinin kaynak kod dosyası Program.cs // ----------------------------------------------------------------- using System; class BaskaProgram { static void Main() { Console.Write("İlk kenarı gir: "); double d1 = Convert.ToDouble(Console.ReadLine()); Console.Write("İkinci kenarı gir: "); double d2 = Convert.ToDouble(Console.ReadLine()); double dHipotenus = Hesaplamalar.Hipotenus(d1, d2); Console.WriteLine("Hipotenüs uzunluğu " + dHipotenus); } } Şimdi projeye Hesaplamalar sınıfını dâhil etmek istiyoruz, ama yeni bir kod sayfası oluşturmak istemiyoruz. Daha önce yazdığımız kod sayfasını kullanmasını istiyoruz. Solution Explorer penceresinde projenin üzerine sağ tıklayın Add -> Existing Item (Varolan Öğe) seçtikten sonra AyriDosyalarlaHesaplama projesinin bulunduğu klasörden Hesaplamalar.cs dosyasını seçiyoruz ama Add (Ekle) butonuna basmadan yanındaki küçük oka basıp Add as Link (Bağ Olarak Ekle) seçeneğini seçiyoruz ve kod dosyamız projeye dâhil oluyor. Ama diğerlerinden farklı olarak dosya simgesinin sol tarafında küçük bir ok beliriyor. Bu simge bağlı öğe olduğunu belirtiyor. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Şimdi Hesaplamalar sınıfını kullanan iki tane programımız oldu. Bu dosya üzerinde bir hatayı düzelttiğimizde ya da yeni yöntemler eklediğimizde sadece 1 tane dosyada değişiklik yapmış oluruz. Ama bu durumda Hesaplamalar sınıfını kullanan bütün projeleri yeniden derlememiz gerekir. Tabi ki, sadece Add (Ekle) butonuna basmış olsaydık kod sayfasını BaskaProgram projesinin klasörüne taşıyacak ve projeye ekleyecekti. Böyle olunca projedeki diğer kod sayfalarından farkı olmayacak ve projenin kendisine ait bir parçası olacaktı. Bu durumda bir dosyadaki değişiklik diğer projedeki dosyayı etkilemeyecekti. Aslında başladığımız işlem basamaklarını takip edersek bir adım daha kaldı, Hesaplamalar sınıfını ayrı bir dynamic-link library (Devingen bağlı kütüphane) yani DLL içerisine koymak. Bu durumda Hesaplamalar sınıfımız da .net Framework içerisindeki diğer sınıflar gibi olurdu. DLL içerisine alınmış bir sınıf önceden derlendiği için artık başka bir projeye onun kodunu ekleyemeyiz, yani içindeki kod da başkaları tarafından görülmez. Bu adımdaki işlemlerin nasıl yapılacağını başka bir yazıda inceleyeceğiz. |
Cevap: C# Hakkında Herşey. C# Yöntemler ve Alanlar - III Yöntemler ve Alanlar - III Şimdi bir projede birçok trigonometri hesabı yapacağımızı düşünelim. Bu projede sinüs, kosinüs ve tanjant hesapları kullanacağız. System isim uzayı içerisindeki Math sınıfı bu hesaplamaları yapmaya yarayan Sin, Cos ve Tan isimli yöntemlere sahiptir. Ama bu yöntemler derece cinsinden değil de radyan cinsinden değerlerle çalışır. Bizim projemizde de derece cinsinden değerlerle çalışılacak olsun. Gerekli dönüşümleri yaparak yeni Sin, Cos ve Tan yöntemlerini yeniden yazalım. 2Pi radyan 360 derecedir. Dönüşüm işlemine bir örnek yazalım. dDerece değişkeni kullanıcıdan alınan derece cinsinden değeri tutuyor olsun. Bu açının sinüsünü hesaplayan ifade aşağıdaki gibi olacaktır. dSonuc = Math.Sin(Math.PI * dDerece / 180); Her hesaplama işleminde bu ifadeleri teker teker yazmak istemeyiz. Şimdi bu dönüşümleri içerisinde izole eden Sin, Cos ve Tan yöntemlerini yazmalıyız. Şimdi Trig1 isimli yeni bir sınıf yazalım ve içerisinde bu yöntemler bulunsun. Yeri gelmişken yaygın bir teknikten de bahsedelim. Bu sınıfı normalde başka bir projenin parçası olsun diye yazdığımız ve kendi başına kullanmayacağımız için bir Main yöntemine sahip olmayacaktır, ama test amaçlı olarak bir Main yöntemi ilave edelim. Daha sonra gerekli hata ayıklama işlemleri ve testleri yaptıktan sonra bu yöntemi silebiliriz. Trig1 isimli projenin kodları aşağıdaki gibidir. using System; class Trig1 { static void Main() { Console.WriteLine("45 derecenin sinüsü: " + Trig1.Sin(45)); Console.WriteLine("45 derecenin kosinüsü: " + Trig1.Cos(45)); Console.WriteLine("45 derecenin tanjantı: " + Trig1.Tan(45)); Console.ReadLine(); } public static double Sin(double dAci) { return Math.Sin(Math.PI * dAci / 180); } public static double Cos(double dAci) { return Math.Cos(Math.PI * dAci / 180); } public static double Tan(double dAci) { return Math.Tan(Math.PI * dAci / 180); } } Bu yöntemler daha henüz başka bir programdan çağrılmadığı halde, başlarına erişim niteleyicisi olarak public ekledik. Bu sınıfı daha büyük bir projede kullanacağımız zaman için hazır hale geldi. Main yöntemi içerisinde bu yöntemleri kullanırken, aynı sınıf içerisinde olmalarına rağmen sınıf ismi ile birlikte yazdık. İleride bu yöntemi de hiçbir şeyi değiştirmeden proje içerisindeki başka bir sınıfın içerisine taşıyabiliriz. Dikkat ederseniz her üç yöntem de aynı dönüşüm ifadelerini içeriyor. Her birinde tekrar tekrar yazdık. İyi bir programcı tekrarlayan kodları bir yere toplar ve tekrar yazmadan kullanır. Çözümlerden bir tanesi ayrı bir yöntem yazmaktır. static double DerecedenRadyana(double dDerece) { return Math.PI * dDerece / 180; } Bu durumda programın tamamı şu şekilde olacaktır. using System; class Trig2 { static void Main(string[] args) { Console.WriteLine("45 derecenin sinüsü: " + Trig2.Sin(45)); Console.WriteLine("45 derecenin kosinüsü: " + Trig2.Cos(45)); Console.WriteLine("45 derecenin tanjantı: " + Trig2.Tan(45)); Console.ReadLine(); } static double DerecedenRadyana(double dDerece) { return Math.PI * dDerece / 180; } public static double Sin(double dAci) { return Math.Sin(DerecedenRadyana(dAci)); } public static double Cos(double dAci) { return Math.Cos(DerecedenRadyana(dAci)); } public static double Tan(double dAci) { return Math.Tan(DerecedenRadyana(dAci)); } } DerecedenRadyana yöntemine dikkat etti iseniz, başında public niteleyicisi yok. Yazmadığımız için private kullanılmış gibi oldu, çünkü private varsaylan değerdir. Başka sınıflar içerisinden ulaşılmasını istediğimiz yöntemleri public, sadece sınıf içerisinde kullanılacak olan yöntemleri private yaptık. Ama ayrı bir yöntem kullanmak ve onu çağırmak programımıza fazladan yük getireceği için çok anlamlı olmadı. Bunun yerine bir dönüşüm faktörü yazıp kullanmak daha anlamlı olur. double dDonusturucu = Math.PI / 180; Sin yönteminin kullanımı da aşağıdaki hale gelecektir. return Math.Sin(dDonusturucu * dAci); Dönüşüm faktörünün nerede tanımlanacağına karar verelim. Sin yönteminin içinde tanımlarsak sadece Sin yöntemi içinde yerel olarak kullanılır diğer yöntemlerden ulaşılamaz. Diğerleri içerisinde de ayrı ayrı tanımlamak gerekiyor. Aynı ifadeleri tekrar tekrar yazmak ise bizim amacımıza terstir. Çözüm, dDonusturucu faktörünü alan olarak tanımlamaktır. Farkında olmasak da alan kavramı ile daha önce karşılaştık. Math sınıfı, PI ve E olmak üzere iki tane alana sahiptir. PI ve E, önemli sabit değerler olan pi ve e sayılarının değerlerini tutan özel değişkenlerdir. Bütün yöntemlerin dışında ama sınıfın içerisinde bir yerde alanlar tanımlanır. Daha sonra, tanımladığımız alan bütün yöntemler tarafından erişilebilen genel bir değişken olur. Alan içeren bir sınıf aşağıdaki gibi başlayabilir. class Trig3 { static double dDonusturucu = Math.PI / 180; Genellikle alan tanımlamaları sınıfın en üst kısmında olur ama tabi ki bu da bir zorunluluk değildir. Diğer yöntemler gibi alan da static anahtar kelimesi ile tanımlandı, yöntemin kopyası ile değil de sadece kendisi ile çalışabilir. Bu meseleyi de daha sonra bir yazıda anlatacağız. public niteleyicisini kullanmadık, çünkü sadece bu sınıf içerisinde ulaşılabilir olmasını istiyoruz. Şu hali ile diğer sınıflardan ulaşılamaz olsa bile alanımız sınıf içerisindeki yöntemler tarafından ulaşılabilir ve değiştirilebilir. static kelimesini const ile değiştirerek alanımızı sadece okunabilir hale getirebiliriz. Herhangi bir alan const olarak tanımlanmışsa aynı zamanda da kapalı olarak static olarak tanımlanmış demektir. class Trig3 { const double dDonusturucu = Math.PI / 180; Şimdi çık sık karşılaşılan bir soruna da çözüm bulalım. Math sınıfındaki public tanımlanmış PI alanını Pi şeklinde mi PI şeklinde mi yazacağımızı unutabiliriz. Trig3 sınıfımızın içerisine hem PI hem de Pi şeklinde iki tane public alan tanımlayalım ve istediğimiz zaman projenin her hangi bir yerinde kullanılır hale getirelim. public const double PI = Math.PI; public const double Pi = PI; Bu arada programda yapacağımız değişiklikler bittiğine göre son halini tekrar yazalım. using System; class Trig3 { public const double PI = Math.PI; public const double Pi = PI; const double dDonusturucu = Math.PI / 180; static void Main() { Console.WriteLine("45 derecenin sinüsü: " + Trig3.Sin(45)); Console.WriteLine("45 derecenin kosinüsü: " + Trig3.Cos(45)); Console.WriteLine("45 derecenin tanjantı: " + Trig3.Tan(45)); Console.ReadLine(); } public static double Sin(double dAci) { return Math.Sin(dDonusturucu * dAci); } public static double Cos(double dAci) { return Math.Cos(dDonusturucu * dAci); } public static double Tan(double dAci) { return Math.Tan(dDonusturucu * dAci); } } Trig3 projesinin sınıf diyagramı aşağıdaki gibidir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] |
Cevap: C# Hakkında Herşey. C# Mantıksal veri türü (Boolean) Mantıksal veri türü (Boolean) Gerçek hayattaki doğruların çoğu anlaşılması güç kavramlardır. Oysaki bilgisayar programlarında doğruların anlaşılması çok daha kolaydır. Örneğin bilinen bir tamsayının 100’den daha büyük olup olmadığını veya bilinen bir string ifadenin “kitap” kelimesiyle özdeş olup olmadığını bilmek son derece kolaydır. C#’ta mantıksal bir veri tipi aşağıdaki gibi tanımlanır: bool buyuk; C#’ta bool anahtar kelimesini kullanarak bir değişkeni mantıksal bir değişken olarak tanımlayabilirsiniz. Nasıl int kelimesi System.Int32 sınıfının bir aliası , string de System.String sınıfının bir aliası ise, bool da System.Boolean sınıfının bir aliasıdır. Mantıksal türlerin 0 ve 1 değerlerinden oluştuğunu düşünebilirsiniz. Aşağıdaki atama işlemi yanlıştır. buyuk=0; //Çalışmaz Bir tamsayıyı mantıksal bir değişkene atamaya çalışıyorsunuz. 0 ya da 1 yerine true ve false anahtar kelimelerini kullanmanız gerekiyor. buyuk=true; Yine tamsayılarda olduğu gibi mantıksal türde bir değişken tanımlanırken ilk değer ataması da yapılabilir. bool buyuk=true; true ve false anahtar kelimeleri küçük harfle yazılmalıdır. Yine sayısal türlerde olduğu gibi mantıksal türde de sabit tanımlamak mümkündür. const bool buyuk=true; Bu durumda buyuk isimli değişkenin değeri programın ilerleyen kısımlarında false olarak değiştirilemez. Sayısal ifadeler yalnızca rakamlardan oluşurlar. Mantıksal ifadeler de mantıksal değerlerden oluşurlar (true ve false). Mantıksal değişkenler ile normal aritmetik operatörleri (+, -, %, /) kullanamazsınız. Bunların yerine C#’ta üç tane mantıksal operatör kullanılır. Bunlar: AND,OR ve XOR operatörleri. C#, mantıksal operatörleri de C’den miras almıştır. AND işlemi için ampersand işareti (&) ya da kısaca söyleyecek olursak “ve” işareti kullanılır. İngilizce kısaltmada genel olarak VE olarak bilinen mantıksal AND’i kullanmak için ampersand (&) kullanılır. Boolean ifade: Yagmurlu & Karli; Yukarıdaki ifadenin sonucu hem Yagmurlu hem de Karli değerli true olduğu zaman true olur. bool KarlaKarisikYagmur = Yagmurlu & Karli; Mantıksal ifadeler arasında yapılan AND işleminin sonuç tablosu aşağıdaki gibidir: Mantıksal İfade 1 Mantıksal İfade 2 AND İşlemi Sonucu false false false false true false true false false true true true İkinci mantıksal operatör ise OR (veya) operatörüdür. Bu operatör klavyedeki dikey bar çubuğu (|) işareti ile gösterilir. Yagmurlu | Karli Yukarıdaki ifadenin sonucu, herhangi birisinin değeri true olduğu zaman true olur. bool Yagislimi = Yagmurlu | Karli Mantıksal ifadeler arasında yapılan OR işlemin sonuç tablosu aşağıdaki gibidir: Mantıksal İfade 1 Mantıksal İfade 2 OR İşlemi Sonucu false false false false true true true false true true true true Üçüncü mantıksal operatör Exclusive OR (Özel Veya) operatörüdür. Kısaca XOR olarak kullanılır. Bütün C temelli dillerde şapka işareti ya da inceltme işareti olarak bilinen (^) işareti ile gösterilir. Bir XOR işleminin sonucunun true olabilmesi için sadece bir tanesinin true olması gerekir, her ikisi de true ya da her ikisi de false olursa sonuç false olur. Şimdi bu ifadeyi daha iyi anlamak için aşağıdaki tabloyu inceleyelim. Mantıksal İfade 1 Mantıksal İfade 2 XOR İşlemi Sonucu false false false false true true true false true true true false Aklımızda kalması için şu şekilde de düşünebilirsiniz: Eğer mantıksal ifadelerin ikisi birbirinden farklı ise sonuç true olur, aynı iseler false olur. Şimdi iki tane atom düşünelim. Birisi negatif diğeri pozitif olan iki atom birbirini çeker, her ikisinin de işareti aynı ise birbirini iterler. Bunun için Cekim diye bir değişken tanımlayalım. Atomlarımızın değerlerine bakarak birbirlerini çekip çekmeyeceklerini inceleyelim. bool Cekim = Atom1 ^ Atom2; AND, OR ve XOR operatörlerinin her üçü de ikili operatörlerdir, şimdi de tekli operatörleri inceleyelim. NOT (Değil) operatörü tekli bir operatördür. Mantıksal tersleme operatörü de diyebilirsiniz. Ünlem işareti ile temsil edilir. Kisa = !Uzun; Eğer Uzun değeri true ise Kisa değeri false olacaktır, tersi durumda da Kisa değeri true olacaktır. XOR işleminin sonucunu diğer operatörleri kullanarak da elde edebilirsiniz. C = (A - B) & !(A & B); C = A ^ B; Yukarıda verilen işlemlerin her ikisi de aynı sonucu verir. Yukarıda verilen ilk ifadede birkaç tane parantez kullandık. Bu ifadeyi operatörlerin işlem önceliği kurallarına göre inceleyecek olursak, NOT işlemi (! İşareti), tekli operatördür ve yüksek bir önceliğe sahiptir. AND işlemi ise ikili operatördür ve NOT işlemine göre daha düşük bir önceliği vardır. Eğer bu kuralları iyi bilmezseniz gereksiz parantezler kullanmak zorunda kalırsınız. AND işlemi ile NOT işlemi arasındaki işlem önceliğini bilmeseydik, gereksiz bir tane daha parantez kullanacaktık. AND, OR ve XOR operatörlerini bitişik atama operatörü olarak da kullanmak mümkündür. bToggle = bToggle ^ true; bToggle ^= true; Yukarıdaki her iki işlemin de sonucu aynıdır. Yeri gelmişken bahsedelim, yukarıda verdiğimiz örnek çok özel bir durum örneğidir. bToggle değeri ne ise bu işlemin sonucunda değeri tersi olur. Eğer bToggle true ise false olur, false ise true olur. Boolean ifadelerin dizisi de yapılabilir. bool abYagmurluGunler = new bool[31]; Burada önceden bahsettiğimiz bir konuyu da hatırlatmakta yarar var. Diziler daima belleğin heap bölgesinde tutulur. heap bölgesinde tutulan değişkenlerin de daima bir ilk değeri olur. Mesela sayısal ifadeler 0’a eşittir. string ifadeler null değerine sahiptir. Bir bool dizisinde de ilk değerler daima false değerine eşit olacaktır. .Net Framework içerisindeki bütün yapılar gibi System.Boolean yapısının da bir ToString yöntemi vardır. Ama bu yöntemden True ve False kelimeleri döner. Eğer Console.WriteLine yöntemine bir bool ifadeyi gönderirseniz ekranda True ya da False görünecektir. Bildiğiniz gibi, C# anahtar kelimeleri olan true ve false ise küçük harfle başlarlar. bool b = Boolean.Parse(str); System.Boolean yapısının static olan bir de Parse yöntemi vardır. Bir string argüman alır. Büyük küçük harf duyarlılığı olmaksızın true ya da True, false ya da False geçebilirsiniz argüman olarak. Çok güçlü bir sınıf olan Convert sınıfı bütün türleri birbirine dönüştürebildiği için, bir sayısal ifadeyi bool bir ifadeye dönüştürebilir. bool b = Convert.ToBoolean(mValue); 0 değeri false ifadesine dönüşür, 0 olmayan ifadeler ise true ifadesine dönüşür. Bir boolean değeri sayıya dönüştürürsek, true ifadesi 1 değerine, false ifadesi de 0 değerine dönüşür. decimal mValue = Convert.ToDecimal(b); Şimdi sadece bool değişkenlerden oluşan bir program yazalım. Kedi satan bir evcil hayvan satıcısına gittiğinizi düşünün. Kısırlaştırılmış, beyaz ya da kahverengi bir erkek kedi istiyorsunuz; ya da kısırlaştırılmış, beyaz haricinde herhangi bir renkte olan bir dişi kedi istiyorsunuz ya da bir kedi istiyorsunuz sadece siyah renkli olması yeterli. Şimdi programı yazmaya başlayalım. using System; classKediSecimi { staticvoid Main() { bool bErkek, bKisir, bSiyah, bBeyaz, bKahverengi, bUygun; Console.Write("Kedi erkek mi? true ya da false: "); bErkek = Boolean.Parse(Console.ReadLine()); Console.Write("Kedi kısırlaştırılış mı? true ya da false: "); bKisir = Boolean.Parse(Console.ReadLine()); Console.Write("Kedi siyah mı? true ya da false: "); bSiyah = Boolean.Parse(Console.ReadLine()); Console.Write("Kedi beyaz mı? true ya da false: "); bBeyaz = Boolean.Parse(Console.ReadLine()); Console.Write("Kedi kahverengi mi true ya da false: "); bKahverengi = Boolean.Parse(Console.ReadLine()); bUygun = (bErkek & bKisir & (bBeyaz | bKahverengi)) | (!bErkek & bKisir & !bBeyaz) | bSiyah; Console.WriteLine("Uygunluk Durumu: " + bUygun); } } Programda kullanıcıya bir dizi soru soruluyor ve true ya da false olarak cevap bekleniyor. Kullanıcının girdiği string değerleri Boolean.Parse yöntemi yardımıyla bool değerlere dönüştürüyoruz. bUygun ifadesi de girdiğimiz kriterlere göre sonucu bulup bize bildiriyor. Programda renklerle ilgili bir problem var aslında. Kullanıcı sadece bir tane renk içni true demesi gerekirken birden çok renk için true diyebilir, bunu engelleyebiliriz ama detaya girmeyelim, kullanıcıya doğru bilgiler gireceği konusunda güvenelim şimdilik. Boolean cebirinde bazı kolaylıklar sağlayan De Morgan kuralları diye bir dizi kural var. İngiliz matematikçi Augustus De Morgan adı aynı zamanda ADA programlama dili ve ilk bilgisayar programı ifadeleri ile de birlikte anılır. De Morgan der ki, “OR işleminin olumsuzu her bir değerin olumsuzunun alınıp AND işlemine tabi tutulmasına eşittir.” ve “AND işleminin olumsuzu, her bir değerin olumsuzunun alınıp OR işlemine tabi tutulmasına eşittir.” !(A| B) eşittir !A & !B !(A & B) eşittir !A | !B bool YagisliHava = Yagmurlu | Karli Şimdi AcikHava durumunu düşünelim, YagisliHava durumunun olumsuzudur. bool AcikHava = !(Yagmurlu | Karli) Şimdi De Morgan kuralı ile yazalım bu ifadeyi daha açıklayıcı olur. bool AcikHava = !Yagmurlu & !Karli Cümle olarak yazarsak “Hava yağmurlu değilse ve karlı da değilse açıktır.” Gayet anlaşılır oldu. |
Cevap: C# Hakkında Herşey. C# Char ve String Veri Türleri Char ve String Veri Türleri C programlama dilinde string adında bir veri türü yoktur. C dili string veri türü yerine char adında bir veri türüne sahiptir. char veri türü ile meselâ B, x veya * gibi tek karakter ifade edilir. Eğer bir yazıyı değişkende saklamak gerekirse char türünden bir dizi oluşturmak gerekir. Karakterlerin bir dizisi olarak yazı ifade edilir. C# programlama dilinde de char veri türü vardır ( .net Framework içerisindeki String.Char yapısının bir aliası olarak ). Fakat C dilindeki char ile C# dilindeki char arasındaki benzerlik sadece isim benzerliğidir. İşlevleri ve yapıları farklıdır. C# dilinde bir karakter dizisini string ifadeye, string ifadeyi de karakter dizisine dönüştürmek mümkündür; fakat “string veri türü yalnızca bir karakter dizisidir” demek doğru değil, çünkü string kendi başına bir veri türüdür. Diğer bir farklılık: Tüm programlama dilleri karakterleri temsil etmek için sayıları kullanırlar, fakat C dilinde char veri tipi int, long ve short gibi nümerik bir veri tipidir. Ayrıca C dilinde karakter türü değişkenleri, signed char (işaretli karakter) veya unsigned char (işaretsiz karakter) olarak bildirebiliriz. C dilinde char türündeki veri 8 bit uzunluğunda ve bir ASCII karakteri temsil etmektedir. C# dilinde ise char türündeki veri 16 bit uzunluğunda ve Unicode karakteri temsil etmektedir. C# dilinde karakterleri ve sayıları birbirine karşılıklı dönüştürebilmenize rağmen char veri tipindeki değerler sayı değildir. Unicode karakterler ve nümerik karşılıklarını şu adreste görebilirsiniz: [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] /charts srting bir ifade, çift tırnaklar arasında yazılır, 0 ya da daha fazla karakterden oluşur. Tek bir karakteri ise tek tırnak arasında yazmak gerekir. Aşağıdaki örnekte char türü bir değişken tanımlaması yapılmıştır ve tanımlanırken de ilk değer ataması yapılmıştır. char ch = 'Z'; C# dilinde karakterden nümerik tiplere dönüştürme işlemini casting yaparak gerçekleştirebilirsiniz. int i=10; i = (int) '7'; i değişkeninin yeni değeri 7 değil de 55 olur. Niçin böyle oldu? 7 karakterinin ASCII ve Unicode karşılığı 55 olduğu için casting işlemi sonucu i değişkeni 55 değerini aldı. Şimdi de casting yaparak bir karakterin ascii değerini ifade eden tamsayıyı karakter türü bir değişkene atayalım. char ch = ‘y’; ch = (char) 97; ch değişkeninin değeri ‘a’ harfi olacaktır. Çünkü a harfinin ascii ve Unicode karşılığı 97’dir. Eğer, aritmetik işlemde sayı ve karakteri yan yana kullanırsak kapalı dönüşüm de kendiliğinden yapılır. İnt i; i = 'a' + 5; Yukarıdaki işlemin sonucu da 102 olacaktır, çünkü a karakterinin ASCII ve Unicode karşılığı 97 dir. Dolayısıyla C#, karakteri kapalı dönüşüme tabi tutacaktır. Yine aynı şekilde bir karakter ile bir string ifade birleştirme işlemine tabi tutulursa, karakter kapalı dönüşüm ile string ifadeye dönüşecektir. string str; str = "a" + 'b' Yukarıdaki işlemin sonucu “ab” string ifadesi olacaktır. Fakat aşağıdaki işlem sonucunda 195 sayısal ifadesi çıkar. i = 'a' + 'b'; String sınıfının .net framework içerisindeki bir diğer özelliği de Chars özelliğidir. Bu özellik, C# dilindeki String sınıfında indeksleyici olarak temsil edilir. Bunun anlamı, C# dili içerisinde Chars adında bir özellik yoktur fakat dizilerde indislerle dizi elemanlarına ulaşmaya yarayan indeksleyiciler gibi string ifadeyi oluşturan karakterlere ulaşmaya yarayan bir indeksleyici vardır. Bu indeksleyici .net framework içerisinde tanımlı olan Chars özelliğine karşılık gelir. Örneğin bir string ifade yazalım: string str = "Csharp Öğreniyorum"; String türündeki str değişkenimizin karakterlerine teker teker indeksleyicilerle ulaşalım. ch = str[0]; ch değişkenini ekrana yazdırdığımızda ilk harf olan ‘C’ karakterini göreceğiz. Yine aynı şekilde: ch = str[18]; Şimdi ise ch değişkenimiz ‘m’ harfini içermektedir. Örneğimize göre 0 dan küçük ve 18 den büyük değerler çalışma zamanında hata verecektir. Şu şekilde indeksleyici için yapılan atama işlemi hatalı olacaktır. str[0] = 'H'; // Derleme hatası.. String veri türü için olan indeksleyici sadece okunabilirdir, string ifadenin bir karakterini değiştirmek için onu kullanamazsınız. C# dilinde string değişkenler aslında değiştrilemez durumdadırlar denilebilir. Çünkü bir takım yöntemler yardımıyla sizin yaptığınız değişikliklerle birlikte yeni bir string ifade oluşur ve sizin değişkeninize atanır. Bir string literal için de değişkene atamaksızın indeksleyici kullanabilirsiniz. Char ch = “Csharpturk” [2]; Karakterler arasında döngü yapmak isterseniz şu tür bir ifade kullanabilirsiniz: (char) ((int) 'A' + i) Önce A harfinin Unicode değeri olan 65 ifadesi casting yapılarak tamsayıya dönüştü, sonra üzerine i ilave edildi, daha sonra da çıkan ifade karaktere casting yapılarak dönüştürüldü. String ifadelerden bir dizi de oluşturabilirsiniz. Aşağıdaki örneği inceleyiniz. string[] astr = { "Golf", "Audi", "Mercedes" }; astr[1] ifadesi bize “Audi” soncunu verecektir. Ayrıca string indeksleme ile astr[1][2] ifadesi ile ikici elemanın üçüncü harfi olan ‘d’ ye ulaşabiliriz. Burada indeksleme ile Length özelliğinin kullanımını karıştırmamalıyız. astr.Length() ifadesi 3 sonucunu verecektir. astr[1].Length ifadesi de 4 sonucunu vercektir çünkü “Audi” kelimesi uzunluğu dört karakterdir. Bir int ifadeyi parametresiz yapıcı ile tanımlayabilirsiniz. int i = new int(); Yukarıdaki ifade parametresiz bir yapıcı olduğu için hatasızdır. Ama aşağıda gördüğünüz string yapıcısı hatalıdır. string str = new string(); // çalışmayacaktır. Bunun sebebi, String sınıfı parametresiz yapıcıyı desteklememektedir. Değişken alan birkaç yapı var ve bu yapılar sayesinde karakterlerden string değişkenler oluşturabilirsiniz. String bir değişkenin karakterler dizisine dönüştürülmesini inceleyelim. Karakterler dizisini string’ e dönüştürmek için kullanacağımız string yapıcı ifadesi aşağıdaki şekilde olacaktır. char[] ach = { 'm', 'e', 'r', 'h', 'a', 'b', 'a' }; string str = new string(ach); String sınıfı içerisinde, string değişkeni karakterler dizisi haline getiren bir yöntem yer almaktadır. char[] ach2 = str.ToCharArray(); String türü bir değişken kullanmadan da bir yazıyı karakter dizisine dönüştürebiliriz. char[] ach = "merhaba".ToCharArray(); Diyelim ki 21 tane ‘@’ sembolünden oluşan bir string değişken tanımlayacaksınız. Dikkatli bir sayım ile aşağıdaki gibi yapmanız gerekiyor. string str = "@@@@@@@@@@@@@@@@@@@@@"; Aşağıdaki yöntem ise çok daha kolaydır. string str = new string('@', 21); Yapıcıların diğer bir avantajı da ikinci parametrenin değişken olarak tanımlanabilmesidir. Aşağıdaki örnek programı inceleyelim: // ------------------------------------------------------ // PCWorld.cs PCWorld dergisi içerik sayfası örneği. // ------------------------------------------------------ using System; classIcindekiler { staticstring[] bolumler = { "Teknoloji", "Donanım", "Yazılım", "İnternet", "Oyunlar" }; staticint[] sayfaNo = { 3, 10, 16, 24, 29 }; staticvoid Main() { Sat\u305 ?r(0); Sat\u305 ?r(1); Sat\u305 ?r(2); Sat\u305 ?r(3); Sat\u305 ?r(4); } staticvoid Sat\u305 ?r(int i) { constint genislik = 60; string noktalar = newstring('.', genislik - (i + 1).ToString().Length - bolumler[i].Length - sayfaNo[i].ToString().Length); Console.WriteLine("{0}. {1}{2}{3}", i + 1, bolumler[i], noktalar, sayfaNo[i]); } } Programı çalıştırdığınızda içerik bilgileri ekranda üç kolon halinde görüntülenecektir. 5 bölümün adları, 5 bölümün sayfa numaraları ve ihtiyaç miktarınca noktalar. Buradaki nokta sayısının nasıl belirlendiğine dikkat etmeliyiz. İlk parametre periyot karakteridir. İkinci parametreyi ise gerekli toplam genişlik ile bölüm numaralarının karakter sayısının farkı ile elde ediyoruz. Ekran çıktısı aşağıdadır. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Satır metodu, ekrana yazılacak verilerin formatlanmasını ve yazdırılmasını sağlıyor. Sıfır tabanlı parametre ise bölüm numarası iki dizinin indeksini belirtmekte. Main yöntemi ile Satır metoduna gönderilen indeks ile yazdırma işlemi gerçekleştiriliyor. Karakter ve string ifadeler insanların haberleşmesinin bir parçası gibidir. Char yapısı ve String sınıfı birçok metoda sahiptir, bunların içinden önemli diyebileceğimiz bazı yöntemleri inceleyelim. Char yapısı içerisinde bazı static yöntemler Boolean türünde değer döndürerek karakterin kategorisine ulaşmamızı sağlar, Meselâ: Char.IsDigit(ch) Eğer dönen değer true ise ‘ch‘ değişkeni ‘0’ dan ‘9’ a kadar bir değerdir. Ayrıca belirli bir karakterin kategorisini de tespit edebiliriz: Char.IsDigit(str, i) Eğer dönen değer true ise string str[i] karakteri ‘0’ dan ‘9’ a kadar bir değerdir. IsDigit metodunun dışında IsLetter, IsLetterOrDigit, IsLower (küçük harf için), IsUpper, IsNumber , IsPunctuation, IsWhiteSpace gibi benzer metodlar da bulunmaktadır. String değişkenini değiştiremezsiniz ancak yeni bir string oluşturup eskisini yerine koyarsınız. Bunun için String sınıfı içersinde birkaç yöntem yer almaktadır. Meselâ string değişkeninizin tüm harflerini küçük karakterlerden oluşmasını istiyorsanız aşağıdaki yöntemi kullanabilirsiniz. string str2 = str.ToLower(); ToLower yöntemi, var olan eski string ifadenin harflerini küçük karakterlere çevirir ve str2 içerisine atadığımız yeni bir string döndürür. Ayrıca orijinal değişkenin üstüne de yazdırabilirsiniz: str = str.ToLower(); Bu kullanım da çalışacaktır. Orijinal string yerine yeni oluşturulan değer yazıldı. Substring metodu da String sınıfının önemli yöntemlerindendir. Bu yöntem ile bir string’in belirli bir parçasını elde edebiliriz. string str2 = str.SubString(BaşlangıçIndeksi, KarakterSayısı); Meselâ str içerisinde “csharpturk” ifadesi olsun: str.SubString(6, 4) elde edilen string parçası “turk” ifadesidir. Ayrıca string içeris,nde büyük küçük harf duyarlı aramalar yapabilirsiniz. AnyIndexOf metodu ile string içerisinde karakter kümesi arayabilirsiniz. Bunun yanında LastIndexOf ve LastIndexOfAny metodları ile de son karaktere ulaşabilirsiniz. String sınıfının içerisinde iki farklı string’i karşılaştırmanızı sağlayan yöntemler bulunuyor. Bunlardan bazıları durağan diğerleri de türemiş yöntemlerdir. Bazıları bool türünde değer döndürürken bazıları int türünde değer döndürebilir. Bu yöntemleri aşağıdaki tabloda inceleyebilirsiniz. Yöntem Durağan / Türemiş Dönen Değer Karşılaştırma Türü Equals Her ikisi de bool Nümerik (Karakter Duyarlı) Compare Durağan int Metinsel (Seçimlik, Karakter Duyarsız) CompareTo Türemiş int Metinsel (Karakter Duyarsız) CompareOrdinal Durağan int Nümerik Geri dönüş değer tipi int olan yöntemler string ifadeleri sıralamada çok faydalı olacaktır. Meselâ, aşağıdaki ifade basit bir karşılaştırma işini yapıyor. i = String.Compare(str1, str2); int tipindeki dönüş değeri:
Nasıl oluyor da iki string karşılaştırıldığında biri diğerinden büyük yada küçük olabiliyor ? Nümerik karşılaştırma nümerik karakter kodlarının sırasına bağlıdır. Bir örnek ile nümerik sıralamanın nasıl yapıldığını inceleyelim: D < E < F < d < e < f < È < É < Ê < Ë < è < é < ê < ë Eğer string’leri alfabetik olarak sıralamak istiyorsanız bu örnek işinize yaramayacak. Bunun için şu karşılaştırma kullanılmalıdır: d < D < e < E < é < É < è < È < ê < Ê < ë < Ë < f < F Dikkat ettiyseniz büyük küçük harf duyarlı olarak sıralama yapılıyor. Örneğin “Yeni Araba” string ifadesi “yeni Araba” dan küçüktür.Eğer iki string’in karakter sayısı eşit ise küçük harfle başlayan string diğerinden küçüktür.Örneğin “the” string’i “The” string ifadesinden küçüktür. Buna karşın “Them” ifadesi “then.” ifadesinden küçüktür. Karşılaştırma işlemi için büyük küçük harf duyarlılığını eklemeyebilirsiniz: i = String.Compare(str1, str2, true); Buradaki üçüncü değer duyarlılık özelliğini aktif hale getirmektedir. String sınıfı içerisindeki bir diğer yöntem ise String.Format yöntemidir. Bildiğiniz gibi bu yöntem ile string ifadelerin istenilen biçimde yazdırılmasını sağlayabiliriz. İlk değer değişken için yer tutucu özelliğini yapılandırmamızı sağlar. Console.Writeline biçimlendirme yapısı ile benzerdir. str = String.Format("{0} + {1} = {2}", A, B, A + B); |
Cevap: C# Hakkında Herşey. C# while Döngüsü while Döngüsü Programlama gerçekten de tekrarlamadan ibarettir. Bizler nadiren sadece bir kez çalışan programlar yazarız. Yazdığımız çoğu program bir kez çalışır ve her çalışmasında hemen hemen aynı şeyi tekrarlar. Ancak her çalışmada doğru sonucu oluşturacak kadar ufak farklar vardır. Sıklıkla, bir programın içinde bile tekrarlamalar bulunur. Tabi yine ufak farklarla. Bu da bizim bu makalede inceleyeceğimiz konu. C# dili özellik olarak tekrarlama durumlarını icra eder. Biz bu tekrarlama durumlarına Döngü deriz. Yeni kiraladığımız bir evin kirasının 1000 YTL olduğunu varsayalım. Ve her yıl kirayı %5 arttıracağımızı düşünelim. Önümüzdeki 10 yıl içinde vereceğimiz kira miktarının ne olacağını hesaplayan bir program yazalım. using System; class KiraHesabi { static void Main() { decimal Kira = 1000, ArtisMiktari = 5.0m; Console.WriteLine("2006 yılındaki kira={0} YTL", Kira); Console.WriteLine("2007 yılındaki kira={0} YTL", Kira *= (1 + ArtisMiktari / 100)); Console.WriteLine("2008 yılındaki kira={0} YTL", Kira *= (1 + ArtisMiktari / 100)); Console.WriteLine("2009 yılındaki kira={0} YTL", Kira *= (1 + ArtisMiktari / 100)); Console.WriteLine("2010 yılındaki kira={0} YTL", Kira *= (1 + ArtisMiktari / 100)); Console.WriteLine("2011 yılındaki kira={0} YTL", Kira *= (1 + ArtisMiktari / 100)); Console.WriteLine("2012 yılındaki kira={0} YTL", Kira *= (1 + ArtisMiktari / 100)); Console.WriteLine("2013 yılındaki kira={0} YTL", Kira *= (1 + ArtisMiktari / 100)); Console.WriteLine("2014 yılındaki kira={0} YTL", Kira *= (1 + ArtisMiktari / 100)); Console.WriteLine("2015 yılındaki kira={0} YTL", Kira *= (1 + ArtisMiktari / 100)); Console.WriteLine("2016 yılındaki kira={0} YTL", Kira *= (1 + ArtisMiktari / 100)); } } Kopyalama ve yapıştırma mükemmel değil mi? Rakamların alt alta gelmesi için matematik hesabını WriteLine cümlesinin içinde yaptık. Her ifade Kira değişkeninin değerini arttırıyor. 2005 yılı için ifadeyi yazdıktan sonra bu ifadeyi kopyaladım ve 9 kere yapıştırdım ve yılların yazıldığı rakamları değiştirdim. Sonucu aşağıdaki gibi elde ettik. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] decimal değişken kullandığımızdan dolayı oluşan fazla haneleri saymasak iyi çalışmış gibi görünüyor. Fakat eminim ki bu programda güzel bir şeylerin eksik olduğuna benle aynı fikirdesiniz. Sadece birkaç yıl için pek fazla kötü görünmüyor. Fakat daha fazla yıl için bir hesaplama yapacak olsak işler kötüye giderdi. Birbirinin aynı koddan sayfalar dolusu istemezsiniz. Ya bu kodları yazdıktan sonra küçük bir yanlışlığa rastlarsanız ne olacak? Zorlama ile bazı problemler çözmek işe yarayabilir, genellikle döngü kullanmaktan daha kolaydır. C# ‘ta en basit döngü while ifadesidir. else kısmı olmayan bir if ifadesine çok benziyor. while anahtar kelimesini bir parantezler içerisindeki bir boolean ifade takip eder. Bir çift küme parantezi bir veya birden fazla döngü kodunu takip eder. while (boolean ifade) { // döngünün içindeki diğer ifadeler } while ile if arasındaki farklar şunlardır: if cümlesinde eğerboolean ifade doğru (true) ise küme parantezleri arasındaki ifadeleri sadece bir kez çalıştırır. while ise boolean ifadesi doğru olduğu müddetçe küme parantezleri arasındaki ifadeleri çalıştırmaya devam eder. Çalışma boolean ifade yanlış (false) olana kadara devam eder. Değeri 55 olan bir i değişkeni olduğunu varsayalım. Şimdi bir if cümlesi yazalım if ( i < 100 ) { Console.WriteLine ( i ) ; } Sonuç 55 olarak ekrana yazılacaktır. Aynı ifadeyi while için yazalım. while ( i < 100 ) { Console.WriteLine( i ) ; } Bu sefer sonuç aşağıdaki gibi olacaktır: 55 55 55 55 ... Sonsuz döngü olarak bilinen bu döngü devamlı çalışmaya devam edecektir. Fakat genellikle program bitmeden bu sonsuz döngüleri bitirmek isteyeceksin. Program sonsuz döngüye girdiğinde konsol penceresini kapatarak veya "Ctrl +C" tuşlarını kullanarak döngüyü durdurabilirsin. Tabiî ki kesinlikle sonsuz döngü içeren uygulamalar var, fakat çoğu durumda küme parantezinin içindeki kodlar boolean ifadenin içindeki değişkeni değiştirirler. Şimdi 100’e kadar sayan bir program yazalım. using System; class CountUntill100 // 100'e kadar say { static void Main() { int i = 0; while (i < 100) { Console.WriteLine(i); i++; } Console.WriteLine("i'nin son değeri:{0}", i); } } i’nin değeri 100’den küçük olduğundan, işletimin devamında while ifadesine gelindiğinde işletim while ifadesinin küme parantezlerini işleterek ilerleyecek. Küme parantezlerinin içindeki ifade i’nin değerinin yazacak ve değişkeni arttıracak. Ve işletim boolean ifadeye geri dönecek. i hala 100’dem küçük mü? Eğer öyleyse küme parantezinin içindeki ifade tekrar işletilecek. Bu işlemlerin her bir ilerlemesine iteraston (yineleme) adı verilir. Programın çıktısı aşağıdaki gibidir. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] 99 gösterildikten sonra i’nin değeri 100 e arttırılır. Programın devamı boolean ifadeye döner. i’nin değeri 100’den küçük mü? Hayır. Programın işletimi while ifadesinden sonraki program kodu ile devam eder. Şimdi i değişkenin değeri 100’e eşit oldu. En son olarak program "i'nin son değeri 100" yazar. i’nin değeri 100’e ulaştığında ( veya 100 değerinin üzerine ulaştığında ) küme parantezleri içerisindeki ifadeler işletilmeyecek. Aşağıda bu programda kullandığımız while döngüsünün başka bir varyasyonu gösterilmektedir. while ( i < 100 ) { i++; Console.WriteLine(i); } i’nin değeri Console.WriteLine çağrısından önce arttırıldığı için bu döngü 1 den 100 e kadar olan sayıları gösterir. Döngü i değeri 100’e ulaştığında hemen durmaz. WriteLine çağrısından sonra işletim döngünün başına döner ve bundan sonra boolean ifade tekrar kontrol edilir. Not: Küme parantezleri arasında sadece 1 ifade varsa küme parantezlerini kullanmanıza gerek yoktur. Şimdi i değişkenin değerini Console.WriteLine çağrısının içinde arttırarak küme parantezlerini kullanma derdinden de kurtulalım. while ( i < 100 ) Console.WriteLine(i++); Sonek arttırma operatörü değişkenin değerini ekranda gösterildikten sonra arttırır. Bu örnekte program 0’dan 99’a kadar sayıları ekranda gösterir. Eğer önek arttırma operatörünü kullanırsak; while ( i < 100 ) Console.WriteLine(++i); değişken ekranda gösterilmeden önce arttırılacak ve program ekranda 1’den 100’e kadar olan sayıları gösterecek. Aynı zamanda i değişkenini boolean ifadenin içinde de arttırabiliriz. Örneğin; while ( i++ < 100 ) Console.WtiteLine(i); Sonek artırım operatörü i değişkenin değerini boolean ifadede kullanıldıktan sonra, Console.WriteLine çağrısından önce artırıyor. Program ekranda 1’den 100’e kadar sayıları gösteriyor. Aynı ifadenin önekli versiyonu; while ( ++i < 100 ) Console.WriteLine(i); Şimdi ise program ekranda 1’den 99’a kadar sayıları görüntülüyor. i değişkenin değeri 100’e artırıldığında boolean ifaden yanlış döner ve programın işletimi while döngüsünden bir sonraki ifadeden devam eder. while döngü gövdesindeki bu farkları özellikle vurguluyorum. Problem genellikle while döngüsünün başlangıç ve bitiş sınırlarının yönetiminde ortaya çıkar. boolean ifadedeki değişkeni nerede ve nasıl değiştireceğini dikkatlice belirlemen gerekiyor. Boolean ifadede kullanılan < yerine <= ve > yerine >= ifadelerini de kullanarak döngünün sonunda ek bir döngü sağlayabilirsin. Şimdi kira hesabı yapan programımızı tekrar yazalım. using System; class KiraHesabi { static void Main() { int BaslangicYili = 2006; int BitisYili = 2016; decimal Kira = 1000; decimal ArtisMiktari = 5.0m; while (BaslangicYili <= BitisYili) { Console.WriteLine("{0} {1}", BaslangicYili, Kira); Kira *= (1 + ArtisMiktari / 100); Kira = Decimal.Round(Kira, 2); BaslangicYili++; } } } Bu hesaplama biraz değişik. Kirayı ve yılı ekrana yazdıktan sonra program gelecek yılın kirasını hesaplıyor ve decimal olarak tanımlanmış kira değerinin virgülden sonraki kısmını 2 basamak kalana kadar yuvarlıyor. Programın çıktısı aşağıdaki gibi olur. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Program 2016 yılındaki son kirası hesapladıktan sonra, Kira ve BaslangicYili değerlerini arttırarak bir sonraki döngüye hazırlıyor. Kirayı hiçbir zaman kullanmayacak olmamıza rağmen hesaplıyor. Bu örnekte çok fazla bir yük oluşturmuyor ama daha büyük programlarda problem olabilir. Programın çıktısına baktığımızda programın 2006 dan 2011 e kadar olanları kiraları hesaplamak için 11 tane WriteLine çağrısı yaptığını fark ederiz. Fakat program bu yıllar arasındaki kiraları hesaplamak için 10 kez hesap yapmaya ihtiyaç duyar. Bunun için while döngüsünün dışında fazladan bir WriteLine çağrısı yaparak bir çözüm oluşturabiliriz. using System; class KiraHesabi { static void Main() { int BaslangicYili = 2006; int BitisYili = 2016; decimal Kira = 1000; decimal ArtisMiktari = 5.0m; while (BaslangicYili < BitisYili) { Console.WriteLine("{0} {1}", BaslangicYili, Kira); Kira *= (1 + ArtisMiktari / 100); Kira = Decimal.Round(Kira, 2); BaslangicYili++; } Console.WriteLine("{0} {1}", BaslangicYili, Kira); } } Yeni program çıktısı aşağıda. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Dikkat ederseniz boolean ifadede ki içindeki <= karşılaştırmasını < olarak değistirdim. Böylelikle döngünün içinde en son olarak 2015 yılı için hesap yapılacak. Döngünün altındaki WriteLine çağrısı döngünün içinde önceden hesaplanan 2016 yılının kirasını ekrana yazdırıyor. Bir diğer varyasyon ise Console.WriteLine ile döngüden önce ilk yılı ve kirasını ekrana yazdırıp daha sonra bu değerleri döngünün içinde arttırarak yazma işlemi yapmak. Yani hesaplama döngünün başında yapılıyor ve WriteLine çağrısı döngünün en altında yapılıyor. using System; class KiraHesabi { static void Main() { int BaslangicYili = 2006; int BitisYili = 2016; decimal Kira = 1000; decimal ArtisMiktari = 5.0m; Console.WriteLine("{0} {1}", BaslangicYili, Kira); while (BaslangicYili < BitisYili) { BaslangicYili++; Kira *= (1 + ArtisMiktari / 100); Kira = Decimal.Round(Kira, 2); Console.WriteLine("{0} {1}", BaslangicYili, Kira); } } } Yine çıktısı aşağıda görülüyor. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Bu iki çözüm de ideal değil çünkü ikisi de birbiri ile aynı WriteLine çağrısı içermektedir. Birini değiştirdiğinde diğerini de değiştirmek zorundasın. Biz bu örnekte olduğu gibi döngünün içinde 11 WriteLine çağrısı ve 10 kez de hesap yapmak istiyorsak döngünün ortalarında bir yerde döngüden çıkmamız gerekiyor. break olarak adlandırılan ifade ile döngünün ortasında döngüden çıkabilirsin. Bu ifade her zaman aşağıdaki şekilde kullanılır. break; break ifadesini noktalı virgül takip eder. Bu ifade kullanıldığında döngüden çıkmaya ve programın döngüden bir sonraki ifadeden devam etmesine neden olur. Genellikle break ifadesi bir if bloğu ile kullanılır. if ( BaslangicYili == BitisYili ) break; Kira hesabının bir diğer versiyonu aşağıdaki gibi yazıldığında gereksiz bir hesaplamadan bizi kurtarır. using System; class KiraHesabi { static void Main() { int BaslangicYili = 2006; int BitisYili = 2016; decimal Kira = 1000; decimal ArtisMiktari = 5.0m; while (BaslangicYili <= BitisYili) { Console.WriteLine("{0} {1}", BaslangicYili, Kira); if (BaslangicYili == BitisYili) break; Kira *= (1 + ArtisMiktari / 100); Kira = Decimal.Round(Kira, 2); BaslangicYili++; } } } Şimdi while döngüsündeki boolean ifadeyi true kullanarak programın başka bir versiyonunu yazalım. Unutmayın ki break olmadan bu bir sonsuz döngü olacaktır. using System; class KiraHesabi { static void Main() { int BaslangicYili = 2006; int BitisYili = 2016; decimal Kira = 1000; decimal ArtisMiktari = 5.0m; while (true) { Console.WriteLine("{0} {1}", BaslangicYili, Kira); if (BaslangicYili == BitisYili) break; Kira *= (1 + ArtisMiktari / 100); Kira = Decimal.Round(Kira, 2); BaslangicYili++; } } } break gibi while döngüsü içinde kullanılan bir diğer atlama komutu da continue’dur. Genellikle if karar yapısı ile tetiklenir. Bu ifade döngü içindeki arta kalan ifadenin atlanmasını sağlar. Ve program bir sonraki iterasyondan devam eder. Örneğin, kira hesabı programımızda sonu 0 ile biten yıllarda kiranın artmamasını yani bir önceki yıl ile aynı kalmasını istediğimizi farz edelim. Yani 2010 yılında ki kiranın 2009’daki kira ile aynı kalmasını istediğimizi düşünelim. Şimdi bir önceki yazdığımız orijinal koda bir bakalım. while ( BaslangicYili<=BitisYili ) { Console.WriteLine("{0} {1}", BaslangicYili,Kira); if ( BaslangicYili == BitisYili ) break; Kira *= ( 1 + ArtisMiktari/100); Kira = Decimal.Round(Kira,2); BaslangicYili++; } Bu kodu sihirli 2010 yılı için if ifadesi ile yazmanın bir yolu aşağıdaki gibi olabilir. while ( BaslangicYili<=BitisYili ) { Console.WriteLine("{0} {1}", BaslangicYili,Kira); if ( BaslangicYili != BitisYili ) { Kira *= ( 1 + ArtisMiktari/100); Kira = Decimal.Round(Kira,2); } BaslangicYili++; } if ifadesi 2009 yılının kirası gösterildikten sonraki artışları engeller. Bu nedenle de 2009 ile 2010 yılları arasıdan kira artışı meydana gelmez. Bu işlemi aynı zamandan if ile birlikte continue while ( BaslangicYili<=BitisYili ) { Console.WriteLine("{0} {1}", BaslangicYili,Kira); BaslangicYili++; if ( BaslangicYili ==2010 ) continue; Kira *= ( 1 + ArtisMiktari/100); Kira = Decimal.Round(Kira,2); } BaslangicYili değişkenin artırılmasını döngünün başına aldım ve if ifadesini bunun devamına yazdım. Eğer BaslangicYili değişkeni 2010’a ulaşırsa continue ifadesi döngünün bir sonraki iterasyondan devam etmesini sağlayacak. Döngünün için deki son iki ifade bu şekilde atlanmış oluyor. while döngüsünün bir diğer çeşidi de do döngüsü. while döngüsünün genel ifadesini bir kez daha hatırlayalım. while ( boolean ifade ) { // while döngüsünün gövdesi } Şimdide do döngüsünün genel ifadesini tanıyalım. do döngüsü aynı zamanda while komutunu da içeriyor. do { // do döngüsünün gövdesi { while ( boolean ifade ); do döngüsün en sonunda noktalı virgül olduğuna dikkat edin. while döngüsünde olduğu gibi do döngüsünde de break ve continue ifadelerini kullanabilirsin. do döngüsünün yapısı boolean ifadeyi döngünün başında değil de sonunda değerlendirir. do döngüsünde gövde boolean ifadeyi dikkate alınmadan en az kez çalışır. do döngüsü kullanıcıdan giriş alan programlarda kullanışlıdır. Şimdi toplama yapan basit bir program yazalım. using System; class TopamaProgrami { static void Main() { string Cevap; do { Console.Write("Birinci sayıyı gir: "); double d1 = Double.Parse(Console.ReadLine()); Console.Write("ikinci sayıyı gir: "); double d2 = Double.Parse(Console.ReadLine()); Console.WriteLine("Toplam : {0}", d1 + d2); Console.WriteLine("Başka bir toplama yapmak ister misin?(e/h)"); Cevap = Console.ReadLine().Trim(); } while (Cevap.Length > 0 && Cevap.ToLower()[0] == 'e'); } } Buradaki string tipindeki Cevap değişkeni neden while bloğu içinde tanımlanmadı diye düşünebilirsiniz. Bunun nedeni; değişkenin bloğun altındaki while ifadesinin içindeki boolean ifadenin içinde kullanılmasıdır. Bu programın anahtar kısmı do döngüsünün altına yakın yerde ortaya çıkar. Buradaki bir komut kullanıcıya bir tane daha hesaplama yapıp yapmayacağını sorar ve string tipindeki Cevap değişkeni bu cevabı saklar. while ifadesinin içindeki boolean ifade ilk önce Cevap değişkenin uzunluğunun 0’dan büyük olup olmadığını kontrol eder. Eğer öyleyse Cevap değişkenin büyük harflerle yazılmış olmasına karşın değişken küçük harflere çevriliyor ve ilk harfinin ‘e’ olup olmadığına bakıyor. Eğer ilk karakter ‘e’ ise programın işletimi döngünün en başına dönecek ve oradan devam edecek. boolean ifadenin içindeki Cevap.Length ifadesi kullanıcın sorulan soruya karşılık olarak basitçe enter tuşuna basıp basmadığını kontrol etmek için kullanılıyor. Eğer kullanıcı cevap için sadece enter’e basmış ise Console.ReadLine boş bir string döndürecektir ve bu string’in ilk karakterine ulamaya çalışmak kural dışı bir durum oluşturacaktır. Kullanıcı ‘Y’ veya ‘y’ ile başlayan bir şeyler yazdığında ki yazdıklarında boşluk bıraksa bile program devam edecek. Kullanıcıdan cevabını istediğimizde kullandığımız Trim() fonksiyonu boşluklardan kurtulmamızı sağlıyor. Tabiî ki program eğer kullanıcı bizim sorduğumuz iki komuta doğru yanıtları vermez ise yani sayıları istediğimiz ve cevabı istediğimiz komutlara diğer tipler değişkenler yazarsa program hata verecektir. Bu hataları nasıl halledeceğimizi başka bir makalede anlatacağız. Bazen aşağıdaki gibi hatalar yapabiliriz. while ( i < 100 ) { // diğer ifadeler } while ( i < 101 ) Bu örnekte ilk önce bir while ifadesi yazıyoruz. Daha sonra do döngüsü oluşturduğumuzu düşünüp döngünün sonuna bir while daha yazıyoruz. while ( i < 100 ) { // diğer ifadeler } Yukarıdaki kısımda i değişkeni döngü bittiğinde muhtemelen 100 değerini alacak olduğundan ikinci kısımdaki while ( i < 101 ) ifadesi sonsuz bir döngü olacak. Bu program asılı kalacakmış gibi görünüyor. Ve muhtemelen bir çıktı da görüntülenemeyecek. Ne zaman bir konsol programı asılı kalırsa ctrl+c tuşlarını kullanarak programı durdurabilirsin. Bundan sonra kaynak kodunu tekrar incelemeli ve sonsuz döngü nerede oluşuyor bulmaya çalışmalısın. Eğer kodunda bununla ilgili bir kanıt bulamıyorsan while döngüsünün başına ve sonuna birkaç tane “Burası döngünün girişi”, “Döngü bitiyor” gibi ifadeler içeren WriteLine çağrısı koyabilirsin. Böylelikle programı çalışırken inceleyebilirsin. Bu şekilde fazladan ihtimalleri sınırlamış olursun. Döngülerin bir diğer yaygın kullanım alanı da dizilerle birlikte kullanımıdır. Şimdi önceden girilen bir sayı dizisinin sayılarının karelerini ve küplerini bula bir programı while döngüsü ile yapalım. using System; class KareKub { static void Main() { int[] SayiDizisi = {10,11,12,13,14,15}; int i = 0 ; while ( i < SayiDizisi.Length ) { Console.WriteLine("{0} {1,6} {2,6} " ,SayiDizisi[i], Math.Pow(SayiDizisi[i],3), Math.Pow(SayiDizisi[i],3)); i++; } } } Burada girilen sayı dizisin içindeki sayıları karelerini ve küplerini alan bir programı yazdık. Dizinin eleman sayısı kadar dönen bir döngü oluşturduk. Programın çıktısı da aşağıdaki gibi oluşuyor [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] |
Cevap: C# Hakkında Herşey. C# For ve Foreach Döngüleri For ve Foreach Döngüleri for ve foreach döngülerinin kullanımını sırasıyla inceleyelim. for (i = 0; i < hedef; i++) { // i değişkeni ile yapılacak işlemler } i döngü değişkenine genellikle başlangıçta 0 atanır. Dolayısıyla bir dizinin indekslenmesi ile ilgili işlemlerde kolaylık sağlar. Çoğu programcı while-do döngüsü kullanmaktansa for dögüsü kullanmayı tercih eder. Hatta bazı yerlerde while-do döngüsünü kullanmak daha uygun olduğu halde for döngüsü kullanırlar. For döngüsünün de while döngüsünde olduğu gibi karmaşık kullanım şekilleri mevcuttur. Örneğin break ve exit cümlecikleri while döngüsündeki görevinin aynısını for döngüsünde de üstlenmektedir. For kelimesinden sonra parantez açılmaldır. Parantez içerisine noktalı virgüller ile ayrılmış üç ifade yazılır. Bu ifadeler sırasıyla başlangıç değeri, koşul ve değişim değeridir. Parantez içindeki üç ifadeden ilki ile döngünün başlangıç değerini belirtiriz. Genellikle tek bir değişken kullanılır, fakat isterseniz aşağıdaki gibi birden fazla değişken için başlangıç değeri atayabilirsiniz. for (i = 0, j = 17; …… ; ….) Parantez içindeki ikinci ifade ile koşul durumunu belirtiriz. Bu bölüm boolean türünde kontrol edilir. Şart sağlanmış ise false değeri dönecek ve döngüden çıkılmış olacaktır. Eğer koşul henüz gerçekleşmemiş ise true değerini alır ve döngü işlemeye devam eder. for (i = 0; false; i++) { // işleme alınmayacaktır. } Parantez içindeki üçüncü ifade ile değişim miktarını belirtiriz. Başlangıç değerinde olduğu gibi birden fazla değişkenin değişimi eklenebilir. for (i = 0, j = 100; i < j; i++, j -= 5) { // i ve j değişkenleri kullanılabilir } Bu üç ifade belirtilirken kullandığımız değişkenlerin başlangıç değerlerini daha önceden atayabiliriz. Aşağıdaki örnek bir önceki ile aynı sonucu verecektir. j = 100; for (i = 0; i < j; i++) { // i ve j değişkenleri kullanılabilir j -= 5; } İsterseniz bu üç ifade yerini boş bırakıp sadece noktalı virgülleri parantezle içerisinde bırakabilirsiniz. for (;;) { // herhangi bir işlem.. } Bu şekilde sonsuz döngü oluşturabilirsiniz. While döngüsü ile ise sonsuz döngü aşağıdaki şekilde olacaktır. while (true) { // Herhangi bir işlem. } Başlangıç değerini belirtirken kullandığımız i değişkeni program içerisinde daha önceden tanımlamadıysanız döngü içerisinde aşağıdaki şekilde belirtmelisiniz. for (i = 0; i < hedef; i++) { // i değişkeni ile yapılan işlemler } Örneğin string bir dizi olan sdizi için döngü aşağıdaki şekilde olacaktır. for (int i = 0; i < sdizi.Length; i++) { Console.WriteLine(sdizi[i]); } Bu döngüde tek bir ifade olduğundan süslü parantezleri kullanmayabilirsiniz. Yukarıdaki örneklerde i değişkeninin değeri, eğer döngü herhangi bir sebeple yarıda sonlandırılmadıysa, döngü sonucunda hedef değerine eşit olur. Eğer C veya C++ dillerini kullanan deneyimli bir programcıya 1 den 100 ’e kadar olan sayıları C# kodu ile ekrana yazdırmasını isterseniz, aşağıdaki şekilde bir sonuç alırsınız: for (int i = 0; i < 100; i++) Console.WriteLine(i + 1); Bu program bloğunda i değişkeni 0 dan 99 ‘a kadar değerleri alıyor. Fakat ekran çıktımızda 1 den 100 ‘e kadar olan sayıları görüntülüyoruz. Üstad programcılar genellikle bu yöntemi kullanırlar. Daha akıllıca bir yazım şekli de şöyledir: for (int i = 0; i < 100; Console.WriteLine(++i)); Şimdi de herbirinde 20 karakter olan 3 kolon halinde bir dizinin elemanlarını gösterelim. for (int i = 0; i < sdizi.Length; i++) if (i % 3 == 2) Console.WriteLine("{0,-20}", sdizi[i]); else Console.Write("{0,-20}", sdizi[i]); Döngü içersinde tek bir ifade olduğundan süslü parantezleri kullanmadık. If cümleciği, ilk değerin 3 ‘e bölümünden elde edilen kalanın 2 ye eşit olup olmadığını kontrol ediyor. İ değeri yalnız 2,5,8,11 olduğunda bir sonraki satıra geçiyor ve kolonlarımız oluşuyor. Genellikle bir dizinin elemanlarını karşılaştırmak için for döngüsü kullanırız. Örneğin 30 kişilik yakın arkadaşlarımızın isimlerinden oluşan bir dizimiz var. Kaç arkadaşımızın isminde E harfi yer aldığını hesaplamak istiyoruz: char[] harfara = {'e', 'E'}; int eharfliler = 0; for (int i = 0; i < isimler.Length; i++) if (isimler[i].IndexOfAny(harfara) != -1) eharfliler++; Buradaki harfara dizisi char tipinde olup “E” ve “e” karakterlerini içermektedir. If bloğunda String sınıfının bir metodu olan IndexOfAny ile harfara dizisindeki elemanlar karşılaştırılıyor. Eğer isimde herhangi bir e karakteri yer almıyor ise IndexOfAny metodu -1 değerini döndürecektir. Eğer -1 değeri dönmez ise eharfliler değişkeni 1 arttırılıyor. Eğer bu isimleri başka bir diziye kopyalamak isterseniz : using System; class harfarama { static void Main() { string[] isimler = { "Ömer Faruk Demir","Ali Can","Elima Aydın", "Sefa Filiz", "Ebru Sevim" }; int eharfiler = 0; char[] harfara = {'z', 'Z'}; // Öncelikle “e” veya “E” harfi olanların sayısını buluyoruz for (int i = 0; i < isimler.Length; i++) if (isimler[i].IndexOfAny(harfara) != -1) eharfliler++; // yeni bir string dizi oluşturuyoruz string[] eisimler = new string[eharfliler]; // Bir diziden diğer diziye kopyalama işlemini yapıyoruz for (int i = 0, j = 0; i < isimler.Length; i++) if (isimler[i].IndexOfAny(harfara) != -1) eisimler[j++] = isimler[i]; // Yeni oluşan dizimizi ekrana yazdırıyoruz for (int i = 0; i < eisimler.Length; i++) Console.WriteLine(eisimler[i]); } } Bu programda üç adet for döngüsü yer alıyor. İlk döngü yukarı da incelediğimizin aynısı, isimleri sayıyor. Program isminde E harfi olanların yer aldığı dizinin uzunluğunu hesaplıyor. İkinci döngü ile kopyalama işlemi gerçekleştiriliyor. Son döngü ile de yeni oluşan dizimiz ekrana yazdırmak için kullanılıyor. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...] Bir dizinin tüm elemanlarına erişmek için foreach döngüsü daha pratik olacaktır. Decimal tipte bir dizinin tüm elemanlarını foreach döngüsü kullanarak toplayalım: decimal mtoplam = 0; foreach (decimal m in mdizi) { mtoplam += m } foreach cümleciğinden sonra parantezler içerisine erişeceğimiz dizinin tipinde bir değişken tanımlıyoruz.Daha sonra dizimizin adını yazarak son elemana kadar döngünün sürdürülmesini sağlıyoruz. foreach döngüsünün bazı sınırlılıkları vardır. Örneğin döngü içerisinde dizinin herhangi bir elemanına ulaşamazsınız. foreach döngüsü yalnız döngülerde kullanılmaz. Örneğin string bir değişkenin elemanlarını (karakterlerini) ekrana yazdıralım: foreach (char karakter in str) Console.WriteLine(karakter); |
Cevap: C# Hakkında Herşey. C# İstisna ve Hata Yakalama İstisna ve Hata Yakalama C# ile uğraşmaya başladığımızdan beri bir çok çalışma zamanı hataları ile karşılaşıyoruz. Örneğin bir intereger değişkeni 0’a bölemeye çalıştığımızda karşılaştırdığımız hata. Hatalar sınıflar tarafından tanımlanır. Örneğin DivideByZeroException (Sıfıra bölünme hatası) sınıfı. Temel hata sınıflarının büyük bir kısmı System isim uzayında tanımlanır. Eğer taşma kontrolü açıksa taşma olduğunda OverflowException (taşma hatası) meydana gelir. Daha öncede anlattığımız bir çok programda klavyeden girilen değerleri bir integer değişkene atarken Parse metodunu kullandık. Eğer klavyeden girilen değerler sayılsal olmayan değerler içeriyorsa o zaman bir FormatException ( Biçim hatası ) meydana gelir. Bir Parse metodu ile string değişkenine bir null değer atanırsa bir ArgumentNullException (Null argüman hatası ) gelişir. Eğer bir dizinin sınırlarının dışında bir indeksleme yapamaya çalışırsanız veya uzunluğunun dışında bir atama yaparsanız IndexOutOfRange hatası meydana getirirsiniz. C# dokümantasyonu her zaman hangi hatanın hangi metot da gelişeceğini belirler. Biz burada şimdiye kadar hatanın gelişiminden bahsettik. C# dilinde bu olay için aynı zamanda C#’ta bir anahtar kelime olan throw kullanılır. Kullanıcıya göre bir hata meydana geldiğinde programımız çökmüştür, patlamıştır. Neyse ki Windows’u da yanında götürmemiştir. (Biliyorsunuz 90’larda değiliz) Kullanıcıların programımızın çöktüğünü görmesini istemezsiniz. Aynı zamanda sizin mükemmel olmayan kodlar yazmada kabiliyetli olduğunuzu bilmelerini de istemezsiniz. Bu durumda programımızın en önemli avantajı program tarafından fırlatılan hataları nazikçe geri çevirmesi olur. Bu nazik geri çevirme için programın fırlatılan hataları yakalaması fırlatılan bu hata ile bir şeyler yapması ve sonra programımızın mutlu yoluna devam etmesi gerekiyor. Hata fırlatma ve yakalama durumları, programın çalışma zamanında meydana gelen problemleri halletmede göz önünde bulundurulan yapısal hata ayıklamanın tamamını oluşturur. Şimdi Decimal.Parse metodunu düşünelim. Bu metot bir string argüman gerktirir ve bir decimal değer döndürür. Fakat ya aldığı bu argüman harfler ve nümerik olmayan karakterler içeriyorsa? Eski gönlerde bu metot nümerik olmayan karakterleri göz ardı edecekti. Ya da iki değer döndürecekti, diğer çevirme işleminin düzgün gidip gitmediğini kontrol belirleyecek boolean olacaktı. Bazı teknikler asla sürekli olarak tamamlanmadı. Fakat yapısal hata ayıklama ile Decimal.Parse bize “Ben bu girdi ile işlem yapamıyorum, ve gerisi senin problemin” diyen bir hat fırlatır. Programın istisnanın kullanıcıya gösterilmesini veya istisnanın kendi kendine halledilmesini sağlayabilir. Eğer son bahsedilen seçenek yani programın hatayı kendi halletmesi seçeneği sana daha çekici geliyorsa try ifadesini kullan. try ifadesini kullanmanın en kolay yolu try anahtar kelimesi ile başlayıp ardından hata fırlatabilecek ifadeyi kapsayan bir çift süslü parantez kullanmaktır. Bu hatayla uğraşacak diğer blok olan catch ifadesi tarafında takip edilir. Örneğin programımızın kullanıcı tarafından girilen bir string’i okuduğunu ve bunu aşağıdaki ifadeyi kullanarak double bir ifadeye çevirdiğini düşünelim Double dDeger = Double.Parse(Console.ReadLine()); Parse metodu tarafından fırlatılan herhangi bir hatayı yakalamak için ifadeyi aşağıdaki ifade ile değiştirebilirsiniz. Double dDeger; try { dDeger = Double.Parse(Console.ReadLine()); } catch { Console.WriteLine(“Geçerli olmayan bir numara girdiniz”); dDeger = Double.NaN; } İlk önce dDeger değişkenin tanımlanma ve atanma kısımlarının ayrı olduğuna dikakt etmişsinizdir. Eğer dDeger değişkeni try bloğunda tanımlansaydı try bloğunun dışındaki herhangi bir yerde geçerli olmayacak ve catch bloğunda bu değişkene atıfta bulunulamayacaktı. Eğer Double.Parse metodu girilen string’i double’a çevirme işleminde başarılı olursa program catch bloğundan sonra takip edilen ifadeden çalışmaya devam edecekti. Eğer Parse metodu bir hata fırlatırsa catch bloğu onu yakalar. catch bloğundaki ifade işletilir ve bundan sonra programın normal işletimi catch bloğunu takip eden ifadeden işletilmeye devam eder. Dikkat edersek catch bloğu bir mesaj gösterir ve dDeger değişkenine NaN değerini atar. Muhtemelen catch bloğunu takip eden kod dDeger değişkenini NaN değerine eşitler ve kullanıccan tekrar bir değer girmesini ister. Kullanıcıdan nümerik değerler okuyan bir programda muhtemelen tyr ve catch bloklarını parse metodunu geçene kadar kullanıcıdan değerleri tekrar girmesini isteyen bir do döngüsünün içine koyarız. Aşağıda tam olarak bunu yapan bir metod içeren bir program görüyorsunuz. using System; class DoubleGiris { static void Main() { double dTaban = DoubleSayiAl("Taban sayıyı Gir:"); double dUst = DoubleSayiAl("Üst sayıyı gir:"); Console.WriteLine("{0} 'nin {1}. kuvveti = {2}",dTaban,dUst,Math.Pow(dUst,dTaban)); Console.ReadLine(); } static double DoubleSayiAl(string ifade) { double dDeger = Double.NaN; do { Console.Write(ifade); try { dDeger = Double.Parse(Console.ReadLine()); } catch { Console.WriteLine(); Console.WriteLine("Geçersiz bir sayı girdiniz"); Console.WriteLine("Lütfen Tekrar Giriniz"); Console.WriteLine(); } } while( Double.IsNaN(dDeger) ); return dDeger; } } DoubleSayiAl metodu bir string parametresi alıyor ve bir double değer döndürüyor. Metot dDeger değişkenini tanımlayarak ve NaN degeri atayarak başlıyor. do döngüsü bunu takip ediyor. string parametresini komut gibi görüntüleyerek başlıyor ve girilen string değeri bir double değere çevirme denemeleri yapıyor. Eğer bir istisna meydana gelirse metot kullanıcıya bir mesaj gösteriyor. do döngüsünün sonunda Double.IsNaN statik metodu true değeri döndürür, bu nedenle programın işletimi do döngüsünün başına dönerek oradan devam ediyor ve komutlar tekrar görüntüleniyor. Eğer parse başarılı bir şekilde değer döndürürse programın işletimi catch bloğundan sonra gelen ifadelerden devam eder. Double.IsNaN metodu false değeri döndürür ve DobuleSayiAl metodu dDeger değişkenini main metoda döndürür. Tabiî ki DoubleSayiBul metodu birçok basit Parse çağrısı yapıyor. Bu main metodu daha basit hale getirmek adına ödenmiş bir bedel. Ve tabiî ki kullanıcının programın pike yaptığını görme fırsatı olmuyor. Parse ifadesinin hata fırlattığında normalde yaptığı işleri yapmayacağını fark etmek önemli. Programın işletimi parse metodunun derinlerine bir yerlerden catch ifadesine doğru devam eder. Eğer dDeger değişkenini NaN ile ilişkilendirmezsen catch ifadesi işletilirken dDeger ilişkilendirilmemiş olacak. double yerine decimal tipteki değerlerle çalışıyorsan, geçerli bir değer girilemediğinde değişkeni NaN değerine eşitlemek zorunda değilsiniz. Bunun yerine kullanıcının bir sayı değeri girmeye fırsatı olmadığını varsayarak decimal değişkeni mümkün olan minimum değerle ilişkilendirmelisin (Decimal.MinValue) ve bu minimum değeri karşılaştırmalısınız. while ( mDeger != Decimal.MinValue ) Yada adı bGecerliDegeriAl olan ve false değeri alan sadece try bloğunun içinde Parse metodunun çağrısından sonra true değeri alan bir boolean değişkenle ilişkilendirmelisiniz. try { dValue = Double.Parse(Console.ReadLine() ); bGecerliDegeriAl = true; } Sonra da do döngüsünün sonunda bu değeri kullanırsın while ( ! bGecerliDegeriAl ) ; DoubleGiriş programının içinde kullanılan catch ifadesi genel catch ifadesi olarak bilinir. try bloğunun içinde herhangi bir istisna meydana gelirse bu ifade yakalayacak. Bunun yerine özel bir tür istisna için bir catch ifadesi belirleyebilirsiniz. try { // denenecek durum ve ya durumlar } Catch ( Exception exc ) { //hata işlemi } catch anahtar kelimesini bir metodun parametrelerine benzeyen parantezler bir değişken tanımlaması takip ediyor. Exception System isimuzayı (namespace) içinde tanımlanmış bir sınıf ve exc de ( istediğiniz herhangi bir başka ismide verebilirsiniz ) Exception tipinde bir nesne olmak için tanımlanmış. catch bloğu ile bu Exception nesnesini kullanarak hata hakkında daha fazla bilgi elde edebilirsiniz. Aşağıdaki örnekteki gibi Message özelliğini kullanabilirsiniz. Console.WriteLine(exc.Message); Bu yazının başında gösterilen programda bu Message özelliği kullanılırsa aşağıdaki gibi bi uyarı olacaktı. Girilen String doğru formatta değil Eğer kullanıcı örneğin numaralar yerine harf girerse uyarı aşağıdaki gibi olacaktı. Değer Double için çok küçük veya çok büyük Bu hata eğer bilimsel gösterimlerdeki gibi çok büyük veya çok küçük sayılar girildiğinde ortaya çıkabilir. Bunlar gibi kendiniz mesaj yazmak yerine bu Message özelliğini kullanarak mesajlar yazdırabilirsiniz. Eğer WriteLine metoduna Exception nesnesini doğrudan gönderirseniz Console.WriteLine(exc.Message); gibi etkin olarak ToString metodunu çağırabilirsiniz. O zaman bütün bir detaylı istisna mesajını görebilirsiniz. Console.WriteLine(exc.ToString()); Her ne kadar catch bloğu Exception nesnesi ile özel catch ifadesi olarak sınıflandırılsa da, bilinen catch ifadesinin genelleştirilmişidir. Çünkü bütün farklı istisna sınıfları (Sınıfra bölünebilme hatası, Taşma hatası, ve diğerleri ) Exceprion sınıfının başında bir hiyerarşi ile tanımlandı. Diğer bütün istisnalar Exception sınıfından miras alındı. Diğer makalelerde miras hakkında daha fazla bilgi bulabilirsiniz. Şimdilik herhangi bir tip istisnayı temsil eden Exception sınıfını düşünebilirsin. Diğer sınıflar Exception sınıfından alınmış daha özel miraslardır. Double sınıfmın Parse metodu üç istisnadan birini ortaya çıkarabilir: FormatException (harf yazıldığında), OverflowException (Sayı çok büyük veya çok küçük olduğunda), veya ArgumentNullException (Parse edilen argüman Null Olduğunda). Aşağıda bu üç özel istisnanın üstesinden gelmek için verilmiş bir örnek var. try { dDeger = Double.Parse(Console.ReadLine()); } catch (FormatException exc) { //FormatException hatası ile ilgili kodlar } catch (OverflowException exc) { //OverFlowException hatası ile ilgili kodlar } catch (ArgumentNullException exc) { //ArgumentNullException hatası ile ilgili kodlar } catch (Exception exc) { //Diğer bütün hatalar ile ilgili kodlar } Catch ifadeleri hatalarla eşleşme durumlarına göre birincisinden itibaren sıra ile incelendi. Son catch ifadesi hiçbir parametresi olmayan genel bir ifade olabilir. Aynı şekilde eğer özel tip istisnalar ile çalışıyorsan her zaman diğer özel bir şekilde ilgilenilmeyen istisnalar içinde genel bir catch ifadesi yazmalısınız. Yukarıdaki özel örnekte Double.Parse metodunu kullandığımızda en son catch bloğu hiçbir zaman işletilmeyecek. Çünkü metodundan doğabilecek olan her istisna ile özel olarak halledildi. Üstelik ArgumentNullException hatası bile hiçbir zaman ortaya çıkmayacak çünkü Console.ReadLine metodundan asla Null değeri dönmez. Fonksiyonel olmayan catch ifadelerinden zarar gelmez. try ifadesinin içinde kullanabileceğin finally olarak cağırılan üçüncü bir ifade daha var. finally ifadesi catch ifadelerinden sonra aşağıda gösterildiği şekli ile gelir. finally { // finally bloğu içerisindeki ifadeler } finally bloğunun içindeki ifadeler try ifadesinden sonra ( eğer istisna fırlatılmadıysa ) veya catch ifadesinden sonra çalışması garanti edilmiş ifadelerdir. Finally ifadesi ilk karşılaştığınızda karışık gelebilir. Böyle bir şey neden gerekli sorusu akla gelebilir. Eğer try bloğunda bir istisna meydana gelmediyse programın işletimi catch bloğundan sonraki ifadeden normal bir şekilde devam edecek. Eğer bir istisna meydana gelirse program catch bloğuna gidecek ve ondan sonra catch bloğundan sonra gelen ifadelerden devam edecek. Eğer try ve catch bloklarından sonra iletilecek herhangi bir kod yazmak istiyorsam neden bu kodu catch bloğundan sonraya yerleştirmiyorum? Neden finally bloğunu kullanıyorum diye düşünebilirsiniz. Bu karmaşıklığın çözümü basit: try ve catch blokları bir controle dönmek için bir return ifadesi içerebilir veya (eğer metot Main metot ise ) programı sonladırablir. Bu durumda try ifdesnin en sonundaki catch ifadesi işletilemeyecek. İşte finally ifadesi bize burada yardımcı oluyor. Eğer try ya catch ifadeleri bir return içeriyorsa her dururumda da finally bloğunun çalışması garanti ediliyor. Genellikle finally ifadesi temizlik yapmak için kullanabilirsin. Örneğin eğer programında bir dosya yazarken hata meydana geldiyse finally bloğu programı herhangi bir tamamlanmamış durumda bırakmamak için dosyayı kapatabilir ve silebilir. catch ifdesi olmadan da bir finally ifadesi kullanabilirsin. try ifadesinin üç farklı kullanım şeklini aşağıda görüyoruz. • try bloğu, bir veya birdan fazla catch bloğu • try bloğu, bir veya birdan fazla catch bloğu, finally bloğu • try bloğu, finally bloğu Son yapılandırma da program her hangi bir hata yakalamaz. Kullanıcı bir mesajla bilgilendirilir ve program sonlandırılır. Fakat program sonlandırılmadan finally bloğu çalıştırılır. Şimdi hataların nasıl yakalandığını biliyorsun. Nasıl fırlatıldığını da bilmelisin. Eğer çeşitli sıralamalar yapan ve hata meydana getirebilecek bir metot yazıyorsan, genel olarak metodun problemleri meydana getirecek olan kodlar çağırıyor olduğunu fark etmesi için bir hata fırlatmasını istersin. throw ifadesi aşağıdaki kadar basit olabilir. throw; fakat throw ifadesinin bu basit formu istisnayı tekrar fırlatması için catch bloğunun içinde kullanılır. Eğer bir istisnayı tekrar fırlatmıyorsan, throw ifadesinin içine bir argüman yerleştirmelisin. Bu argüman Exception sınıfının bir örneği veya kendi oluşturduğun indirgenmiş bir sınıfıdır. throw new Exceptinon(); new deyimi Exception sınıfının bir örneği olan bir yapıcıyı içerir. Fakat gerçektende throw değiminde Ecception sınıfının bir örneğini kullanamazsın, çünkü o sana ne çeşit bir hata olduğunu söylemez. Bir veya birden fazla özel istisna kullanmalısınız. Çok sıklıkla System isimuzayının içinde senin ihtiyacın olan ne ise ona daha yakın olan indirgenmiş istisnalar bulacaksınız. Örneğin senin metodun bir string parametre içeriyorsa ve null bir argüman gönderildiğinde çalışmıyorsa muhtemelen aşağıdaki gibi bir kod yazarsınız. İf ( strGir == null ) Throw new ArgumentNullException; Bu ArgumentNullException yapıcısına bir string argüman da gönderebilir. Argüman probleme neden olan özel bir metot parametresini gösterebilir: if (strgir == null ) Throw new ArgumentNullException(“Giriş stringi”); Yapıcıya gönderdiğin bu string bu istisna ile uğraşan catch ifadesine uygun olan istisna mesajının bir parçasına dönüşecek. throw ifadesinin işletiminden sonra metodun bittiğini tekrar vurgulayalım. Bundan sonraki kodlar işletilmeyecek. Bu if den sonraki bir else ifadesinin bir anlam ifade etmeyeceğini gösteriyor. if (strgir == null ) Throw new ArgumentNullException(“Giriş stringi”); else { //istisna fırlatılmazsa bir şeyler yap } } Throw ifadesi içeren bir if ifadesinden sonra diğer kodları basitçe devamına yazabilirsiniz. if (strgir == null ) Throw new ArgumentNullException(“Giriş stringi”); //istisna fırlatılmazsa bir şeyler yap interger’lar için bir Parse metodu yazalım. Nispeten basit olması için, negatif değerlere izin verilemesin. Normal Parse metodu gibi MyParse metodu üç tip istisna fırlasın: Eğer argüman null ise ArgumentNullException, eğer girilen değerler satır değil de harfler içeriyorsa FormatException veya eğer bir interger için uygun olmayan sayılar girilmişse OverflowException. using System; class HataFirlatma { static void Main() { int iGir; Console.WriteLine("İşaretsiz bir sayı gir:"); try { iGir = MyParse(Console.ReadLine()); Console.WriteLine("girilen Deger:{0}", iGir); } catch (Exception exc) { Console.WriteLine(exc.Message); } } static int MyParse(string str) { int iSonuc = 0, i = 0; //eğer argüman null ise bir hata fırlat if( str == null ) throw new ArgumentNullException(); //girilen degerde boşluklar varsa onları temile str = str.Trim(); //en az bir karakter girilip girilemdiğini kontrol et if ( str.Length == 0 ) throw new FormatException(); //stirngin içindeki bütün karakterleri dön while ( i < str.Length ) { //eğer karakterler sayı değilse bir hafa fırlat if( !Char.IsDigit(str,i) ) throw new FormatException(); //bir sonraki haneyi hesapla ( "chacked" e dikkat et) iSonuc = checked(10 * iSonuc + (int)str[i] - (int)'0'); i++; } return iSonuc; } } MyParse metodu ilk önce trim metodu ile girilen değerin başındaki ve sonundaki whitespace denilen boşlukları siliyor. Sonra while döngüsünü kullanarak girilen stirng içindeki bütün karakterleri dönüyor. Eğer karakter IsDigit testini geçerse metot iSonuc değerini 10 ile çarpıyor ve Unicode den nümerik bir değere çevrilmiş yeni bir basamak ile topluyor. MyParse metodu açıkça bir OverflowException fırlatmıyor. Onun yerine normal bir taşma hatası üretmek için chacked ifadesinde bir hesaplama icra ediyor. Main metot MpParse metodu ile fırlatılan bir hatayı yakalamayı tecrübe etmenizi sağlıyor. |
Cevap: C# Hakkında Herşey. C# Durumsal Operatörler Durumsal Operatörler Şöyle bir program yazdığımızı düşünelim; Evimize gelen her misafirin üç kurabiye yiyeceğini varsayan ve buna göre misafirlere yetecek kurabiye sayısını hesaplayan bir program. Bu program aşağıdaki gibi bir kod içerebilir. if (KurabiyeSayisi / MisafirSayisi < 3) { DahaFazlaKurabiyeYap(); } Bu kodu inceledikten sonra DahaFazlaKurabiyeYap metodunun tam olarak ne yaptığını merak edebiliriz. Otomatik olarak misafir sayısına göre kurabiye yapıyor olabilir. Ama eğer ya hiç misafir gelmesse? O zaman MisafirSayisi değişkenimiz 0 olcak ve bizde sıfıra bölüm hatası alacağız. Bununla beraber eğer hiç misafirimiz gelmesse bloğun içindeki kodun işletilmesini de istemeyiz. İlk yaklaşımımız şu olabilir; if ifadesi içindeki MisafirSayisi değişkenini kontrol ettirebiliriz. if (MisafirSayisi > 0 & KurabiyeSayisi / MisafirSayisi < 3) { DahaFazlaKurabiyeYap(); } Amacımıza biraz yaklaştık. MisafirSayisi değişkenimizin değeri sıfır olsa bile bölümün hala gerçeleştirileceğine dikkat edin. Ve sıfıra bölüm harasının meydana gelecek. Eğer MisafirSayisi değişkeni sıfır ise bölümü engellemek için ne yapmalıyız? Bir diğer yaklaşımda Boolean ifadeyi iç içe geçmiş iki parçaya ayırmak olabilir. if (MisafirSayisi > 0) { if (KurabiyeSayisi / MisafirSayisi < 3) { DahaFazlaKurabiyeYap(); } } Bu işe yarayacaktır. Birinci if ifadesinde MisafirSayısı sıfıra eşitse ikinci if ifadesi işletilmeyecektir. Bir diğer yaklaşım ise Durumsal VE operatörü kullanmaktır. Bu operatör bu gibi durumlarda kullanılmak üzere dizayn edildi. Normal VE operatörünün bir tane “&” işaretinden oluştuğunu biliyoruz. Durumsal VE operatörü ise “&&” ’dir. if (MisafirSayisi > 0 && KurabiyeSayisi / MisafirSayisi < 3) { DahaFazlaKurabiyeYap(); } Operatörün sağındaki kısım solundaki kısımdan True ifadesi dönmedikçe işletilmeyecektir. Bunun dışında Durumsal VE operatörü normal VE operatörüne benzer. MisafirSayısı değişkeninin sıfır olduğunu düşünelim. MisafirSayisi>0 ifadesinden False değeri dönecektir. False değerinden sonra gelen operatör Durumsal VE operatörü olduğu için operatörün sağındaki kısım her ne olursa olsun asla işletilemeyecektir. Bütün Boolean ifdenin sonucu asla True olmayacaktır. Operandın sağındaki ifadelerin işletilmesine gerek yoktur. Eğer MisafirSayisi 0 ise Bölüm asla gerçekleşmeyecektir. Şimdi normal VE operatörünü inceleyelim BooleanIfade1 & BooleanIfade2 Burada ifadelerinin ikisininde herzaman işletileceği unutulmamalıdır. BooleanIfade1 && BooleanIfade2 Bu kodda ise BooleanIfade1’den false değeri dönerse BooleanIfade2 asla işletilmeyecektir. Durumsal VE ye benzer olarak Durumsal VEYA iki dik çizgiden oluşur. (||) if (MisafirSayisi > 0 || KurabiyeSayisi / MisafirSayisi < 3) { KurabiyeYapma(); } Bu kod bloğuda içinden aynı mantığı döndürür. Eğer hiç misafir yoksa veya misafir başına en az 3 kurabiye varsa kurabiye yapılmamalıdır. Eğer Durumsal VEYA operatörünün solundaki ifade true değeri döndürüyorsa sağındaki ifadeye bakmaya gerekyoktur. Çünkü herşeye rağmen bütün ifade true olacaktir. if ( BooleanIfade1 || BooleanIfade2 ) { //Kodlar } Üsteki kodda BooleanIfade1 true ise BooleanIfade2’den ne döndüğüne bakılmaksızın Kodlar kısmı işletilecektir. BooleanIfade1 false, ve BooleanIfade2 true ise yine kodların işletileceğine dikklat edelim. C ve C++ dilinden gelen birçok C# programcısı gereksiz kodların işletilmesini engellemek için normal VE ve normal VEYA durumsal operatörleri yerine Durumsal VE ve Durumsal VEYA operatörlerini kullanmaya meyillidirler. Şimdi artık yıl hesabı yapan bir kod parçasını durumsal operatörlerle yazalım. Boolean bir AtikYil değişkenimiz olsun. True için artık yıl olduğunu False için olmadığını temsil edecek. Birde integer bir Yil değişkenimiz olsun. Şimdi kodumuzu yazalım. ArtikYil = Yil % 4 == 0 && ( Yil % 100 != 0 || Yil % 400 == 0 ); Eğer Yil değişkeni 4’e bölünemiyorsa asla artık yıl olamaz. Ve && operatörünün sağındaki kısım asla işletilmez. C# C’den kalan adına “Durumsal Operatör” denilen gerip bir mirası da destekler. Tek bir operandı bulunan tekli operatörleri, iki operatörü bulunun çiftli opertörleri biliyoruz. C’deki bu “Durumsal Operatör” C#’daki tek üçlü operatördür. Üç operand bir soru işareti (?) ve ikinokta üstüste (:) operatörleri ile ayrılır. Ve ifade aşağıdaki gibi olur BooleanIfade ? A : B ; A ve B aynı tipte ifadeler olmalıdır ( yada birbirine çevililebilen ). BooleanIfade değişkeni true ise yukarıdaki ifadenin sonucu A, eğer BooleanIfade değişkeni false ise yukarıdaki ifadenin sonucu B’dir. Bir örnekle açıklayalım. ArtikYil diye bir boolean değişkenimiz olsun. ArtikYil ? 29 : 28; Eğer ArtikYil değilkeni true ise bu ifadenin sonucu 29, eğer ArtilYil değişkenin değeri false ise yukarıdaki ifadenin sonucu 28’dir. Şöyle düşünelim. Artık yıllarda Şubat ayında 29 gün vardır. Diğer yıllarda ise 28 gün vardır. Eğer içinde bulunduğumuz yıl artıl yıl ise (ArtikYil=true) Şubat ayı 29 gündür. Eğer içinde bulunduğumuz yıl artık yıl değilse (ArtikYil=false) Şubat ayı 28 gündür. Yukarıda yazdığımız ifadeyi bir atama işleminde de kullanabilir. SubatGunSayisi diye bir integer değerimiz olsun. SubatGunSayisi = ArtikYil ? 29 : 28; Burada eğer artık yılda isek SubatGunSayisi değişkenine 29, değilsek 28 değeri atanıyor. Yukarıda anlatılanları bu örnekte daha kolay anlıyor. Durumsal operatörler alternatiflerine göre oldukça rahatlık sağlıyor if ( ArtikYil ) SubatGunSayisi = 29; else SubatGunSayisi = 28; Boolean değişkenler yerine boolean ifadeler de kullanılabilir. Bonus = Satis >= 1000 ? 100 : 50; Bu ifadede yapılan satıs 1000 YTL den büyükse 100 YTL bonus, eğer satış 1000 YTL’den az ise 50 YTL bonus verileceği gösteriliyor. Durumsal operatörler atama operatörleri hariç geri kalan operatörlerden daha düsük önceliğe sahiptirler. Yukarıdaki operatörler içinde en yüksek önceliğe sahip olan Satis >= 1000 ifadesidir. Fakat yinede kendimiz daha rahat hissetmek için Durumsal operatörleri parantez içine almak isteyebiliriz. Bonus = (Satis >= 1000 ? 100 : 50); Veya iki parantez de kullanabiliriz. Bonus = ((Satis >= 1000) ? 100 : 50); Durumsal operatörler kesinlikle koddan kazanmayı sağlarlar. Bu kolayca suistimal edilebilir. Özellikle de iç içe geçmiş durumsal operatörler kullanıldığında. Kaçıncı ayda olduğumuza göre içinde bulunduğumuz ayın gün sayısını döndüren aşağıdaki ifade buna örnektir. Kaçıncı ayda olduğumuzu tutan integer bir iAy değişkeni, Gun sayisini tutan integer bir iGunSayisi değişkeni, Artık yılda oluğ olmadığımızı gösteren boolean bir bArtikYil değiskeni tanımladığımızı varsayalım. GunSayisi = Ay == 4 || Ay == 6 || Ay == 9 Ay == 11 ? 30 : Ay != 2 ? 31 : ArtikYil ? 29 : 28 ; Yukarıdaki kodu gerçekten okumak çok zor. Bu gibi kullanımlardan kaçınmalıyız. Bu daha sonra kodumuzu okumaya çalıştığımızda yada başkaları okumaya çalıştığında başımızı ağrıtabilir. |
Cevap: C# Hakkında Herşey. C# Nedir? C# diline kısa bir bakış: C#, güçlü, modern, nesne tabanlı ve aynı zaman type-safe(tip-güvenli) bir programlama dilidir.Aynı zamanda C#, C++ dilinin güçlülüğünü ve Visual Basic' in ise kolaylığını sağlar.Büyük olasılıkla C# dilinin çıkması Java dilinin çıkmasından bu yana programcılık adına yapılan en büyük gelişmedir. C#, C++ 'ın gücünden , Visual Basic 'in kolaylığından ve Java 'nın da özelliklerinden faydalanarak tasarlanmış bir dildir. Fakat şunu da söylemeliyiz ki, Delphi ve C++ Builder 'daki bazı özellikler şimdi C# 'da var. Ama Delphi ya da C++ Builder hiçbir zaman Visual C++ ya da Visual Basic 'in popülaritesini yakalayamamıştır. C ve C++ programcıları için en büyük sorun, sanırım hızlı geliştirememedir. Çünkü C ve C++ programcıları çok alt seviye ile ilgilenirler.Üst seviyeye çıkmak istediklerinde ise zorlanırlar.Ama C# ile artık böyle bir dert kalmadı.Aynı ortamda ister alt seviyede isterseniz de yüksek seviyede program geliştirebilirsiniz.C# dili Microsoft tarafından geliştirilen .NET paltformunun en temel ve resmi dili olarak lanse edilmiştir.C# dili Turbo Pascal derleyicisini ve Delphi 'yi oluşturan takımın lideri olan Anders Heljsberg ve Microsoft'da Visual J++ takımında çalışan Scott Wiltamuth tarafından geliştirilmiştir. .NET framework'ünde bulunan CLR (Common Language Runtime), JVM (Java Virtual Machine)' ye, garbage collection, güvenilirlik ve JIT (Just in Time Compilation) bakımından çok benzer. CLR, .NET Framework yapısının servis sağlama ve çalışma zamanının kod organizasyonu yapan ortamıdır. CLR, ECMA standartlarını destekler. Kısacası C# kullanmak için CLR ve .NET Framework sınıf kütüphanesine ihtiyacmız vardır. Bu da demek oluyor ki C#, JAVA, VB ya da C++ değildir. C,C++ ve JAVA 'nın güzel özelliklerini barındıran yeni bir programlama dilidir. Sonuç olarak C# ile kod yazmak hem daha avantajlı hem daha kolay hem de etkileyicidir. SanaLBilgisayarKursun'ndan Alıntıdır. |
Cevap: C# Hakkında Herşey. sabaha kadar okudum :) okumak yetmiyor ama eline sağlık biraz bi kaç şey anladım gibi gibi ;) güzel paylaşım.. |
| Tüm Zamanlar GMT +3 Olarak Ayarlanmış. Şuanki Zaman: 15:45. |
Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2025, vBulletin Solutions, Inc.
Search Engine Friendly URLs by vBSEO
Copyright ©2004 - 2025 IRCForumlari.Net Sparhawk