27 Kasım 2011 Pazar

C#’ta Yıldızlı Kelebek tarifi, içerik: iki yarım üçgen, bir sürü boşluk…

Çıktı kodun altındadır.

Kod:

  1: void KelebekYildizli(int n)
  2:         {
  3:             if (n % 2 == 0) n++;
  4:             for (int i = 0; i < n / 2; i++)
  5:             {
  6:                 for (int j = 0; j < i + 1; j++)
  7:                 {
  8:                     Console.Write("*");
  9:                 }
 10:                 for (int j = 0; j < n - 2 * i - 2; j++)
 11:                 {
 12:                     Console.Write(" ");
 13:                 }
 14:                 for (int j = 0; j < i + 1; j++)
 15:                 {
 16:                     Console.Write("*");
 17:                 }
 18:                 Console.WriteLine();
 19:             }
 20:             for (int i = 0; i < n ; i++)
 21:             {
 22:                 Console.Write("*");
 23:             }
 24:             Console.WriteLine();
 25:             for (int i = (n-2) / 2; i >= 0 ; i--)
 26:             {
 27:                 for (int j = i+1; j > 0; j--)
 28:                 {
 29:                     Console.Write("*");
 30:                 }
 31:                 for (int j =  n - 2 * i - 2; j > 0; j--)
 32:                 {
 33:                     Console.Write(" ");
 34:                 }
 35:                 for (int j = i+1; j > 0; j--)
 36:                 {
 37:                     Console.Write("*");
 38:                 }
 39:                 Console.WriteLine();
 40:             }
 41:         }
 42: 

Çıktısı:
kelebekyildizli

Not: Girlen satır sayı tek değilse, bir üst tek satır gibi algılar (mes: 6 girildise, 7 algılar). Kelebeğin simetrik olması içindir.

5 Ekim 2011 Çarşamba

Apache web sunucusu nasıl kurulur ve çalışır.

Geçen defa Microsoft IIS ile uğursuzluktan sonra Apache`ye yöneldim.

Apache kurulumu.

Apache`nin resmi sitesinden win32 binary installer indirmekle başladım.
Çalıştırdığımda Network Domain ve Server Name (site isimlerine benzer formatda) girdi istedi.
Local user için 8080 portuna kurulmayı teklif etti.

 

İlk çalıştırılması.

Kurulduktan sonra konsolda çalıştırdım ve tarayıcımı localhost:8080, 127.0.0.1:8080, 192.168.1.4:8080 (lokal ağ adresim) yöneltdim.
Her üçünde "It works!" yazısı uğuru bildirdi.

 

Web kök.

Web kök hosta denk gelen klasöre denilir. (Yani, http://localhost/ sorgusunda web sunucunun baktığı ve dosya sistemimizde yerleşen klasör.)
Web kökü Apache`nin kurulduğu klasörde htdocs`ta buldum. İçeride tek yatan index.html dosyası tarayıcımdan gördüyüm "It works!" yazısını taşıyordu.
Artık üzerinde statik bir site kurabilir web sunucum var.

 

TarayıcI taraftan bakış ve çalışma teorisi

Apache web sunucusu HTTP üzerinden hizmet sunar.
HTTP`de bir dosyanın, resmin ya her hangi başka verinin (terim olarak - kaynak) yerleştiği yeri belirtmek için onun yerleştiği hostu (site adresi gibi de algılanabilir) ve o hostda hangi yolda (klasör ve dosya gibi) bulunduğu belirtilir.
Örnek: http://example.com/index.html adresini açmak için, tarayıcımız example.com hostunda /index.html yolu sorgular.
HTTP bir TCP/IP üzerinden çalışan protokol olduğundan, tarayıcımız sunucumuzun yerleştiği IP adrese söylediğimiz port üzerinden bağlantı kurar. HTTP hizmetleri susmaya göre 80 portunu kullanır, tarayıcılar da portu girmediğimzde ona yönelir.
Sunucumuzun hangi IP adresde yerleştiğini bilmek için tarayıcımız biligisayarımızda yerleşen hosts dosyasına müracaat eder. Orada denilen host için IP adres bulmadığı halde DNS hizmetine baş vurur. DNS (alan adı sistemi) hizmeti domainlerin hangi IP adrese bağlı olduğuna cevap bulunduran global sunucular birleşmesidir - konumuzun kapsamı dışında bulunduğu için DNS hakkında bu kadar bilgi yeter.
Şimdi elimizde iki aşağı seviyeli - IP adres, port - ve iki yukarı seviyeli - host, kaynak yolu - tanımlayıcı elde etmiş oluyoruz. Tarayıcımız bunları kullanarak bize istediğimiz kaynağı getiriyor.

 

Sunucu taraftan bakış

Apache çalışmaya başlarken ayarlar dosyasını kontrol eder ve ona göre hizmet sunar.
Ayarlarda hangi IP adreste hangi portu dinlemeli olduğunu belirtebiliriz.
(Bir bilgisayarın birden fazla IP adresi ola bilir. Bu aynı zamanda farklı ağlara bağlı olabilmesinden ileri geliyor. Mesela, local ağ adresi (lan), global ağ adresi (internet üzerinden, wan))
Listen 127.0.0.1:80 dediğimizde, yalnız kendi bilgisayarmızdan erişebilen sunucu elde ederiz.
Susmaya göre ise, bilgisayara bağlanan tüm 80 nolu port soketlerine hizmet sunar.
Bağlantı kurulduğunda, web sunucu HTTP kurallarına göre gelen sorguyu bilgisayarımızdakı dosyaya karşılaştırmaya çalışır.
Web kök denilen, ve http://localhost adresine denk gelen klasör DocumentRoot ayarı ile belirtilir. (Windows`ta susmaya göre "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/htdocs/" adresi örnektir.)
Bundan sonra localhost hostunda /index.html sorduğumuzda, .../htdocs/index.html dosyası gelir.

 

Yekunda, bir Apache web sunucu ile bir statik site hizmete sunuldu.
Lakin Apache web sunucusu bir bilgisayarda bir çok web site sunabiliyor.
Bunun için VirtualHost ayarı ile sunmak istediğimiz sitenin hangi IP adres, port ve hosta bağlı olduğunu, dosya sistemimizde hangi yolda yerleştiğini belirtmek gerek.
Statik html dosyaların yanında php, perl, python, ruby, asp.net gibi dillerde yazılmış scriptlerin çalıştırılabilinmesi için ilgili modülü Apache`ye yüklemek ya da dosyanı yorumlayıcıya yöneltmesi için ayarlamak gerek.
Bunlar bu başlığın dışında olduğu için burada bitiriyorum.

Herkese güzel siteler!

4 Ekim 2011 Salı

“Microsoft Internet Information Services (Microsoft IIS) nasıl kurulur?” sorusunda başarısızlık.

Microsoft Internet Information Services (Microsoft IIS) bir web server (veb sunucusu) olup, bir çok şey edebilmekle beraber, dosyalarınızı internette açmaya da yardımcı oluyor.

IIS nasıl kurulur sorusu İnternet Programlama dersinin ikinci sorusuydu, ilk olan IIS nasıl çalışır idi.

Ben de eve gelip onu kurmaya yöneldim.


Evvela Microsoft`un sunduğu Web Platform Installer (Web PI) yazılımını www.iis.net sitesinden  indirdim. Tanıtımında Microsoft Web Platformun`un bileşenlerinin - IIS ve uzantıları, SQL Server Express, .NET Framework ve Visual Web Developer gibi yazılımlara erişmekte kolaylık sağladığı yazılmıştı.
Onun arayüzünde modern frameworklarla yanaşı Install IIS görünce, klasik yolun var olduğunu hatırladım ve eskilere saygıdan onu takip etmek istediğime karar verdim.

Windows eklentilerinin idare panelinden (Control Panel > Programs > Programs and Features > Turn Windows features on or off) Internet Information Services öğesini seçip "ok" tusuna basarak kurmayı başlattım.

Kurma bitince, ne start menu`de, ne de program files`da hiç bir şey oluşturmadan, benden habersiz şekilde C:\inetpub\ klasörünün oluşturulduğu, içinde de veb kökün (wwwroot klasörü) yatdığını buldum. İlk başta yanlış kurulduğunu düşünmüştüm.
Tarayıcımı http://localhost/ adresine yönlendirdim. Ne garibse, hoşgeldin sayfasının yerine Error 404 (404.4) geldi.
Microsoftun bilgitabanında durum kodları sayfasında 404.4 hatasının açılımı "No handler configured" diye geçiyordu.
İnternette araştırmanın sonucunda benim kullandığım Windows 7 Home Basic sürümünün özellikleri kısıtlı olduğunu, hatanın da bundan dolayı oluştuğunu buldum.
(IIS 7.5`in farklı Windows sürümleri için sunduğu özellikleri gösteren tablolar: http://technet.microsoft.com/en-us/library/cc753473.aspx . Temel HTTP özelliklerinden statik sayfaları açma bile YOK. Lakin, HTTP hatalar ve yönlendirme var :\.)
IIS ile tanışmamı burada sonlandırıp - bu arada onu silmeyi unutmayarak - açık yazılıma yöneldim.

Herkese kolaylıklar ve bilgisayarında açık yazılım egemenliğini diliyorum!

24 Mayıs 2011 Salı

Bilgi sistemi otomatik doldurma

Ele şimdi oğrenci bilgi sistemine girdim ki, sayısal elektronik dersinin notuna bakayım.
Bir de karşıma bizim çok sevdiğimiz anketler çıktı.
Geçen sene yazdığım bir scripti hatırladım. Şimdi de sizinle bookmarklet şeklinde paylaşayım diyorum, siz de eziyyet etmeyesiniz.

Bu linki favorilerinize(bookmarklarınıza) ekleyin, Derman.
Sonra anket sayfasına gidin.
Orada o bookmarka tıklayın, ve tamam!

İyi günler dilerim. ^__^



NOT: Yalnız Google Chrome 11 için testedilmiştir.

3 Mayıs 2011 Salı

Stringi int dizisine çevirme, C# Extension Method yazarak. Ninja yolu, tek satırlık ve döngüsüz .


fibonaccisnipSık-sık girdide boşlukla ayrılmış sayılar alıyoruz.
Bunu string gibi okuyup integer dizine çevirmemiz gerekiyor.
Adeta bunu her defa for döngüsünde Convert.ToInt32 ya Int32.Parse yazarak gerçekleştiriyoruz.
Şimdi ise bunu tek satırda ve döngü kullanmadan nasıl yapıldığını göreceksiniz.
Hatta, hiç string değişkenine aktarmadan kısa ve güzel böyle bir koda varacağız:

int[] data = Console.ReadLine().ToIntArray()

(ToIntArray() metodu en son C# .Net 4 dahil string dizilerinde mevcut değil. Extension Methodla eklenildi. Kodu en aşağıda.)
Bence harika.

Önce stringin tek satırda integer dizisine nasıl dönüştüğüne bakalım.
Bunun için iki yol var. Her ikisi stringi string dizisine, onu da int dizisine çevirmekden geçiyor. (aralıklı sayılar stringi =>[işlem: string aralıklarda kesiliyor…] her elemanı bir sayı tutan string dizisi =>[işlem: her eleman stringden integere çevriliyor ve yeni dizi oluşturuluyor] istenilen int dizisi).
Stringi diziye bölmek için Split kullanıyoruz. (Split – böl, parçala.) Girdide bizde boşlukla ayrılmış sayılar olduğu için, boşlukla (‘ ‘) bölünüyor. Sonra onlar Array.ConvertAll ya Linq`in Select metodu ile int dizisine çevriliyor.

string s = Console.ReadLine()
int[] data;

data = Array.ConvertAll(s.Split(' '), i => Int32.Parse(i)); // Yol bir

data = s.Split(' ').Select(s => int.Parse(s)).ToArray(); // Yol iki, Linq ister

String.Split, Array.ConvertAll, Linq.Enumerable.Select
(bunların ilk ikisi hakkında gelecekde yazacağım)

Şimdi bu blogda ilk Extension Method yazılmasını göreceğiz.

public static class Utils
{
    public static int[] ToIntArray(this string s)
    {
        return Array.ConvertAll(s.Split(' '), i => Int32.Parse(i));
    }
}
public class Program(){
    static void Main(){
        int[] data = Console.ReadLine().ToIntArray();
    }
}

(evet, this string.  ve evet, ToIntArray parametre almıyor. hem de classın ve metotun static tanımına da bakmayın, statik tavr etmez. amma static tanımlanmalı. bu ve diğer tuhaflıklar hakkında gelecekde.)

2 Mayıs 2011 Pazartesi

String diziyi char dizisine çevirme, C#, String.ToCharArray()

String dizisini char dizilerine çevirmek için böyle kod kullanabilirsiniz. String.ToCharArray() bir stringi char dizisine çevir metottur.

public char[][] StringsToCharsArray(string[] isimler)
{
    char[][] char_isimler = new char[isimler.Length][];
    for (int i = 0; i < isimler.Length; i++) {
        char_isimler[i] = isimler[i].ToCharArray();
    }
    return char_isimler;
}

Yok, string dizisini tek bir char dizisine çevirmek gerekirse:

public char[] StringsToSingleCharArray(string[] isimler)
{
    return String.Join("", isimler).ToCharArray();
}

String.Join metoduna ilk giren parametre ayracdır. İki stringi birleştirende araya koyulacak string. Arada hiç bir şey olmasını istemiyorsunuzsa yazdığım gibi (“”) yazmak yeter.

Programlama niye eğlenceli? Programlamanın 5 sevinci.

Frederik Bruks (Frederick Brooks) “The Mythical Man-Month”* kitabında bizim sanatımızın insanını bu sanatta cezb eden sevinçleri böyle özetlemiş:

1. Yapma-oluşturma sevinci.
2. Diğer insanlara faydalı ürün yapma sevinci.
3. Bir-biri ile ilişkili dinamik elemanlardan oluşan bilmece nesneleri düzenleme prosesinin cazipliyi.
4. Sürekli yeni bilgi edinme ve gayri-adi mesele çözme sevinci.
5. Ürünlerle çalışmaya ilgi, hansılar ki, yalnız akli gücün uygulanmasıyla yaratılmışlar, ve buna rağmen mevcutlar, inkişaftalar ve tamamen anlatılamaz şeyler ediyorlar.

Programlama ona göre eğlencelidir ki, her birimizin derin içinde olan yaratıcılık hasretini gideriyor.

(Kısaltılmış ve serbest çeviri. Tam metni burada okuyun(en).)

Programlamanın bir avantajı var – bağımsızlık imkanı. İstediğin ürünü bir iş yerine bağlanmadan geliştire bilirsin. Bir ressam kimi. Ressama göre avatajı ise yukarıdakı maddelerde, esasen de ikinci maddede belirtilmiş.

O kitabı okumamışım.

*"Mythical Man-Month – mitik kişi-ay. Kişi-ay bir kişinin bir ayda gördüğü işe denir. Mesela, iki kişinin yarım ay çalışması toplamda bir kişinin bir ay çalışması kadar zaman alır. Güç birimi diyebilirsiniz. Yapılacak işin miktarını işçinin harcayacağı zaman cinsinden gösterir.  Aynı şekilde kişi-gün, kişi-hafta, ve büyük projeler için kişi-yıl kullanılır. Bir kişi-yıllık projeyi 365 kişi bir günde bitirir :).

1 Mayıs 2011 Pazar

&Referanslari unset`leyip silmeyi unutma, PHP

$paths = array('a.htm', 'b.htm', 'c.htm', 'd.htm', 'e.thm');
$dir = 'base';
 
// Path`ları standarlaştırırsan
foreach($paths as &$path)
   $path = $dir.'/'.$path;
// unset($path); <- Çözüm budur. Problem ise aşağıda.
 
// Sonra da $path`a değer atamaya kalkarsan
foreach($paths as $path) // mesela, yine foreach
echo $path.', '; 
// Kederli sonuçlar ortaya çıkar.
// base/a.htm, base/b.htm, base/c.htm, base/d.htm, base/d.htm,
// iki kez d.htm çıkmış olur. : (
&

Sorun orda ki, PHP`de foreach`de tanımlanan iterasyon değişkeni ($path) değerini foreach`in dışında da saklıyor.
Dolayısıyla, yukarıdakı foreach son döngüsünde $path`a $paths`ın sonuncusuna referans atadığından, aşağıdakı foreach $path`a her değer atadığında $paths`ın sonuncusunu değiştirmiş oluyor.

30 Nisan 2011 Cumartesi

C#`ta döngüsüz arama. Tek satırlık ninja yolu.

Geçen defa metin döngü kullanmadan nasıl ters çevrilir anlattığımda, döngüsüz aramanı anlatacağımı söz vermişdim. C#`ta döngüsüz aramak için yine System.Linq namespace`inin Extension Method`larına baş vuracağız. Onların arasında FirstOrDefault metodu (msdn) döngüsüz aramanı sağlıyor.

En basit şekilde böyle kullanılır:

string[] names = { "Hartono", "Adams", "Andersen", "Hedlund", "Ito" };
string aranilan = "Adams";
 
// Ninja yolu, tek satırda ve döngüsüz arama.
string foundName = names.FirstOrDefault(name => name == aranilan);
// Okunuşu: names`de öyle bir name ki, => o name == aranilan.
Bu kod aşağıdakılara denktir:
string foundName = null;
 
// Normalde böyle ararız:
for(int i=0; i<names.Length; i++)
    if( names[i] == aranilan ) 
        foundName = names[i];
 
// Ya da böyle:
foreach(string name in names)
    if( name==aranilan )
        foundName = name;
 
// Çıkışta, foundName==null ise, bulunmadı; değilse, aranilan-bulunan ismi içerir


FirstOrDefault`takı ‘name => name == aranilan’ ne demek diye kafanız karışabilir, onu şimdi anlatacağım.
Anlamak için, foreach`a bakın önce. Ordakı ‘string name in names’ ve ‘names.FirstOrDefault(name => name==aranilan)‘ parçasında altını çizdiğim yerler denktir. ‘name==aranilan’ ise if’in controlüne denk geliyor. Bu şekilde anlarsınız, kullanmaya yeter. Aklınızda tutun ki, ‘=>’ ile ‘)’ arasında bir bool ifade olmalı, aynı if`in içindeki gibi. (uzunluğu 7`den büyük olan ilk ismi seçmek için ‘name => name.Length>20)’ yazabiliriz.)
Aslında nasıl olduğunu bilmek istiyorsanız, Lambda Expressions (lambda ifadeler) konusuna bakmak gerek. Belki ilerde onu anlatırım.

DİKKAT: Eğer dizide aranan değer yoksa, dizideki veri tipinin default değeri döner. Yani, int dizisinde aradığımız sayı yoksa, sıfır döner. String dizisi için null döner. Default değerler tablosuna msdn`de bakabilrisiniz. Hatırlayın ki, referance tipler üçün default değer null olur.

Bir adım geri: FirstOrDefault C#`ta bir overload`a sahip – parametresiz kullanılabiliyor. Parametresiz kullanıldığında bir dizinin boş-olup olmamasının kontrolünü gerçekleştirir: boş değilse ilk elemanını, boş ise tipin default değerini dönderir.
Yani, parametresiz FirstOrDefault-un dahili kodu bunun gibidir (string dizisi için örnek):

public static string OrnekFirstOrDefault(string[] dizi){
    if(dizi.Length>0)
        return dizi[0];
    else
        return null;
}
/*
 Dikkat: 
  Parametre olarak gönderilen dizi 'names.FirstOrDefault()' yaptığımızda olan names`dır
  Yani, names.FirstOrDefault() <=> OrnekFirstOrDefault(names).
*/
 

 

if( names.FirstOrDefault(i => i=="Mehmet") == null )
    Console.WriteLine("Mehmet yokmuş.");

26 Nisan 2011 Salı

C#`ta girilen metni ters çevirme. Döngüsüz ninja yolu.

Bugün Şeref Akyüz kendi blogunda “C sharp’ ta Girilen Metni Ters Çevirme" başlıklı bir yazı yayınladı. Orada foreach döngüsü kullanarak string`i char dizisine tersten atadı. O yol yeni başlayanlar için foreach döngüsü oğrenmekte yararlı olacağını inanıyorum.

Ancak artık her defa for döngüsü yazmaktan yorulmuş, daha kısa ve ifadeli yollar arayanlar için bir-iki çözüm var.

Bunlara ihtiyacınız olur diye, foreach ya for döngüsü kullanmadan, metni döngüsüz ters çevirme yolunu göstermek istedim.
Hem daha kısa, hem daha anlaşılır. Hatta, tek satırlık yolu da var.

For döngüsü kullanmadan metni ters çevirmenin iki yolu:

public static string TersCevir_Dongusuz(string s)
{
char[] temp = s.ToCharArray();
Array.Reverse(temp);
return new string(temp);
}

public static string TersCevir_Dongusuz_NinjaYolu(string s)
{
return new string(s.ToCharArray().Reverse().ToArray());
}

Dikkat! Ninja yolu ile gidebilmek için başta using System.Linq; eklemeniz gerekecek.
Niçin: Kullanılan “Reverse()” fonksiyonu Extension Methods kütüphanesinden olduğu için, normalde yok, ama Linq kütüphanesini eklediğimizde var oluyor. (Bunun nasıl edilebildiğini daha sonra anlatacağım)

Şimdi de girilen metni ters çeviren programı üç satırda yazabiliriz.

using System;
using System.Linq;

class Program
{
static void Main(string[] args)
{
string s = Console.ReadLine();
s = new string(s.ToCharArray().Reverse().ToArray());
Console.WriteLine(s);
}
}

İsteyen tek satırda da yazar. Hiç değişken kullanmadan : ).

using System;
using System.Linq;

class Program
{
static void Main()
{
Console.WriteLine(Console.ReadLine().ToCharArray().Reverse().ToArray());
}
}

 

Gelen defa dizide bir elemanın bulunduğunu kontrol etmenin tek satırlık yolu hakkında yazacağım. Yani, bir nevi, dizide tek satırda for döngüzüz arama.

20 Nisan 2011 Çarşamba

Bir linkin Facebook`ta paylaşım istatistiği

YouTube`da izlediğiniz bir videonu, ya bilgisayar e-dergisinde okuduğunuz bir makaleyi, ya internette gördüğünüz güzel bir resmi facebook`ta paylaştığınız zaman sizden önce kaç kez paylaşıldığını görmek istemiş misiniz?
Ya kendiniz yayınladığınız bir paylaşımın facebook`ta paylaşma, beğenme, ve yorum sayısı ile ilgilendiniz mi? İlgilenmemişsinizse de, şimdi ilginizi çekmiştir sanırım.

Ben de bir gün ilgilendim, ve bunula bağlı araştırmanın sonucunda bir PHP scripti yazdım.
Scriptin çalışma sayfasına gitmek için elinize paylaşım istatistiğini bakmak istediğiniz bir link alın ve buraya tıklayın.


image

(Ekran görüntüsünde arkadaş blogcuların ve benim anasayfalarımızın paylaşım istatisiği – hiç birimiz iyi değiliz XD)

 

Özellikler:
1) Girdi kutucuğuna birden fazla link yazabilirsiniz, sadece alt-alta yazın.
2) Linkleriniz sağdakı “Son yenilemeler” blokunda gözükecek. Her yeniledinizde üste çıkacak.
3) 2-deki durumun önünü almak için, girdi kutucuğunun altındakı checkbox-i (onay kutusunu) işaretleyin. Dikkat: ilk uygulamada nasıl verdiyseniz, sonrakı yenilemelerde hep böyle kalacak. İlerde bu aksiklik değişecek.
4) Form GET metodu ile gönderiliyor. Yani, ilk kez doldurup gönderdikten sonra, adres çubuğundakı linki sık kullanılanlara ekleyebilirsiniz. Bu size takip ettiğiniz paylaşımın istatistiğine bakmak için paylaşımın linkinı her defa yeniden girmekten kurtarır.

Arka plan teknolojileri:
Facebook Legacy REST API / link.getStats metodu – gerekli bilgileri çekebilmek için.
SQLite veritabanı.
PHP`nin SimpleXML eklentisi – Facebook`tan alınan XML formatındakı cevapın içerdiği değerleri okumak için.

5 Nisan 2011 Salı

Sayfa yönlendirildi

Sayfa burada

İki for döngüsü ile yıldız rombu (eskenar dörtgen) çizimi

Sayfa burada

İki for döngüsü ile yıldızlardan eşkenar dörtgen çizimi (baklava deseni), C#

Sadece iki for döngüsü ile yıldızlardan eşkenar dörtgen çiziminin programı. (Baklava deseni de denir.)
Murat Hacıömeroğlu “Java ile nesne yönelimli programlama” dersinde ödev vermişti. Kodu C#-ta yazmışım ama.
   1: void EskenarDortgen(int n)
   2: {
   3:     for (int i = 0; i < n * 2; ++i) {
   4:         int ln = i / 2;
   5:         int cs;
   6:         char ch;
   7:  
   8:         if (i % 2 == 0) { // " "
   9:             cs = Math.Abs(n / 2 - ln);
  10:             ch = ' ';
  11:         } else { // "*"
  12:             cs = (Math.Abs(Math.Abs(n / 2 - ln) - n / 2)) * 2 + 1;
  13:             ch = '*';
  14:         }
  15:         for (int j = 0; j < cs; ++j) Console.Write(ch);
  16:         if (i % 2 != 0) Console.WriteLine();
  17:     }
  18: }
Böyle güzel çıktı veriyor:
romb9out_thumb_thumb
Not: Girilen satır sayı (yukarıda 9 girilmiş) çift olursa, verilen yıldız baklavasının ucu ısırlmış olur. Çift satırlı romb çizebilen olursa, haber versin. (not defterinde, eşaralıklı yıldızlarla.) :).

3 Nisan 2011 Pazar

Dinozor gözü, Polymorphism ve Cast artı Interface (Polimorfizm, Çok biçimlilik, Arayüz)

dinosaur_moviePolymorphism, bir nesneyi size uygun olan kalıba döküp (cast) onun üzerinde işlem yapmaktır.
Vikipedide böyle yazıyor: “Çok biçimlilik bir A türünün bir başka tür olan B gibi davranabilme ve bu tür gibi kullanılabilme özelliğidir.

Aşağıdakı hikaye kısmının yerine geçebilecek bir çalışma:
Öyle bir metot yaz ki, ona parametre olarak verilen nesnenin tipinden asılı olmayarak, o nesnenin SuperBirFonksiyon() metodunu çağırsın. Nesne o metodu mutlaka içerecek. O metodun istenildiği gibi çalışmasını sağlamak için metodun dışında da her hangi kod yazabilirsin (, hatta yazmalısın).

“Ha, bu niçin gerek?” Hikaye kısmı.
Diyelim ki, hayali bir insan göz doktoru var.
Göz doktoru, tabii ki göz inceler. Şimdi dünyada tüm varlıkların göz yapısı yaklaşık aynı olduğunu varsayalım. (Belki bu dediğim gerçeğe yakındır.)
Doktor hep insan gözü ile ilgilenmiş, ‘insan gözü doktoru’ gibi kendini tanımlamış.
Bir gün ise ona dinozor getirmişler. Şaşırıp kalmış. Hani ben insan gözü doktoruyum da, dinozor gözünü nasıl incelerim ki? Böylece kalmış.
Şimdi hatırlayalım ki, dünyada tüm varlıkların göz yapısını aynı kabul etmiştik. Oysa, dünyada çok tür canlı var. Her birisi için ayrı doktor mu hazırlayacağız şimdi?
Akıl diyor ki, öyle olmaz.
O zaman, doktorları hep ‘insan gözü doktoru’ değil, ‘gözlü-canlı gözü doktoru’ gibi eğitirsek doktorlar yukarıdakı hayali doktor gibi şaşırıp kalmaz.
Bununlar yanaşı, doktorun canlının türüne göre göz aramaması için böyle bir şey yapalım: bir delikli kutu alıp, doktora canlıları o kutuda sunarız, canlının gözünü kutunun deliğine dayayıp. Böylelikle, hem insana, hem dinozora ‘gozlü-canlı’ gibi muammele ede biliyoruz.
Şimdi düşün, doktora ne kadar kolay ve universal bir yol sunuldu – hep aynı şekildeki kutunun aynı yerindeki deliğinden, farklı-farklı türlü canlıların gözünü inceleyebiliyor. Soyutlaştırmanın zaferi!
Mühteşem ya!

Polymorphism (çok biçimlilik) kavramı, ve onü mümkün eden casting (çevirim) işlemi de işte böyle bir şeydir.

”Programlamada nasıl karşımıza çıkar?”
Burada yazdığım kodlar Java dilinde, lakin genel mantık tüm bilgisayar bilimi dalına ait.
Diyelim ki, iki figürun alanların toplayan metot yazıyorsun
(ilkel devir, ‘tekrar biliyin anasıdır’ modu):

   1: class Kare{
   2:     private int alan;
   3:     public int getAlan(){ return this.alan; }
   4:     // ... burada Kare`ye has metot ve alanların kodu
   5: }
   6:  
   7: class Daire{
   8:     private int alan;
   9:     public int getAlan(){ return this.alan; }
  10:     // ... burada Daireye`ye has metot ve alanların kodu
  11: }
  12:  
  13: class AlanIsleri{
  14:     public static int AlanlariTopla(Kare figur1, Kare figur2){
  15:         return figur1.getAlan() + figur2.getAlan();
  16:     }
  17:     public static int AlanlariTopla(Daire figur1, Daire figur2){
  18:         return figur1.getAlan() + figur2.getAlan();
  19:     }
  20:     public static int AlanlariTopla(Daire figur1, Kare figur2){
  21:         return figur1.getAlan() + figur2.getAlan();
  22:     }
  23: }


Şimdi düşün, daha çok farklı figür türü ola bilir (ve var da) – üçgen, beşgen, … .
Onların hepisi için ayrı bir metod yazmak yerine, doktora dinozor getirmiş gibi programcı gibi düşünelim.
Metodun parametrelerine bakalım önce. Her defa farklı tipde parametre alıyoruz.
Sonra, içeriğine bakalım. Görüyoruz ki, kodumuz hep aynı: “figur1.getAlan() + figur2.getAlan()”.
Bu ne demek oluyor? Aynı kodu yazmak için, belli aynı isimli metotları çağırmak için farklı-farklı metodlar tanımlıyoruz, amma aynı içerikli! Yükarıdakı ‘İNSAN gözü doktoru’ olayı ile benzeşme hiss ediyor musun? ;)
Keşke Kare`leri, Daire`leri de böyle güzel, tanıdığımız delikleri olan bir kutuya salabilsek, sadece gereken o metoduna ulaştıracak kutuya…

“Yaşasın Kommunizm Polymorphism Çok Biçimlilik!”
Ve işte burda casting (çevirim, kalıba dökme) yardımımıza geliyor.
En ilkel şekilde, tüm figür tiplerini ‘Figur’ adlı ortak üstklastan genişleteceğim (extend). Sonra da AlanlariTopla metotların hepsini sileceğim, birinden başka. O birinin de parametrelerinin tipini Figur türünde alacağım
(kitle imha silahları devri, ‘bir mermi ile tüm nesli’ modu):

   1: class Figur{
   2:     private int alan;
   3:     public int getAlan(){ return this.alan; }
   4: }
   5: class Kare extends Figur{
   6:     // ... burada Kare`ye has metot ve alanların kodu
   7: }
   8:  
   9: class Daire extends Figur{
  10:     // ... burada Daire`ye has metot ve alanların kodu
  11: }
  12:  
  13: class AlanIsleri{
  14:     public static int AlanlariTopla(Figur figur1, Figur figur2){
  15:         return figur1.getAlan() + figur2.getAlan();
  16:     }
  17: }

İşte! Figur`un tüm altklasları için geçerli tek bir metot.

Üzüntü notu: Bu kod, sadece ortak ataları olan klaslar için geçerli. Yani, (engel:) getAlan metoduna sahip, lakin, Figur`un altklası olmayan hiç bir klas için geçerli değil. Yani, dinozoru ‘gözlü-canlı’ kalıbına koysa bile, kalıba sokma şeklini gözünün (getAlan`ın) olmasına göre değil, insan ile ortak özelliklerine (atasına, Figur`a) göre belirliyor (O_O). :(.

Hatırlatma notu:
Yalnız bir klassı genişletebiliyoruz, dolayısıyla bu engeli kaldırmak için iki farklı ata koyamayız, extend A, B diyemeyiz.

Tarihi not: Bunun (hatırlattığımın) nedeni, farklı klaslardan kalıtım alma – farklı klasları genişletme – prorgamlamada önceden görülemeyen hatalara izin veriyordu. C++`da birden fazla klası genişletmek mümkün. Java da ordakı hataların tecrübesinden bu imkanı aradan kaldırmaya karar vermiş.

“Tıpta gelişim!”
doktorların kalıblama asistanların eğitiminden sonra…
Fikrin ve prorgamlama dillerinin gelişimi bize arayüzleri (interfeys, interface) sundu.

İnterface: bir artısı var, tanımlamada çoklu implements A, B diye yaza biliyoruz. Bu artıyı dengelemek için bir eksisi var, interface`te metodun içeriğini yazmak gayrı-mümkün.

Arayüzde kullanılacak fonksiyonları tanımlanır. Arayüzü uygulayan (implement) klas arayüzün tüm taleplerini hayata geçirmek – metodları yazmak zorunda. Arayüz, bir nev anlaşma gibidir.

“Arayüz yaşasın mı?”
(son devir, ‘kalıba sok ve bak’):

   1: interface AlaniOlan{
   2:     int getAlan();
   3: }
   4: class Figur implements AlaniOlan{
   5:     private int alan;
   6:     public int getAlan(){ return this.alan; }
   7: }
   8: class Kare extends Figur{
   9:     // ... burada Kare`ye has metot ve alanların kodu
  10: }
  11:  
  12: class Daire extends Figur{
  13:     // ... burada Daire`ye has metot ve alanların kodu
  14: }
  15:  
  16: class HardDisk implements AlaniOlan{
  17:     public int getAlan(){ return Integer.MAX_VALUE; }
  18: }
  19:  
  20: class AlanIsleri{
  21:     public static int AlanlariTopla(AlaniOlan figur1, AlaniOlan figur2){
  22:         return figur1.getAlan() + figur2.getAlan();
  23:     }
  24: }
  25:  
  26: public class Main {
  27:     public static void main(String[] args) {
  28:         Kare k1 = new Kare();
  29:         HardDisk d1 = new HardDisk();
  30:         int alantoplami = AlanIsleri.AlanlariTopla(d1, k1);
  31:     }
  32: }

Buyurun. Soyutlaştırmanın zaferi arayüz uygulamasında.

“Cast yaptığımın mı verisi gelir, üst sınıfın mı?”
Ya…
Dinozoru kutuya koyduğuna, içindeki yine de dinozor, değil mi?
Sadece, kutunun (kalıbın) sağladığı deliklerden baka ve el gezdirebiliyorsun, o kadar.

<Kalıp Tip burada> a = new <Hafızada Ayrılacak Tip burada>
A a = new B(); // dersen
// 'a.metot()', 'a.alan' diyebilmen için 'metot()' ve 'alan' A klasında tanımlı olmalı.
a.AKlassindaTanimliFonk();
// Lakin, fonkun içeriği B`den çalışır.
a.klassIsmimiYazdir(); // ekrana B çıkar.
Bu arada A ile B arasında akrabalık alakası olduğunu unutmayın.

Yani, sanki A`ya bakıyorsunuz, amma aslında içindeki B.
İşaretciler (metotlar ve değişkenler) KalıpTipi`ın tanımladığı, işlemler Hafızada Ayrılmış Tip`in.
Delikler gözlünün, göz dinozorun. :)

 

 

 

dinosaur245x289






Yürek sözü olarak,
sana kalıplarsız düşünmeği arz ediyorum.