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.

2 Nisan 2011 Cumartesi

Cast, downcast orneği ile nesne yönelimli programlamada tip çevirimi

“Cast” ingilizce bir kelimedir. Programladakı manası “bir kalıba dökmek” anlamından geliyor. İleride neyi ne kalıbına dökdüğümüzü göreceksin.
Türkçe karşılığı “çevirim” diye geçiyor.

Cast, nesneyi bir tipden (classtan) diğer tipe çevirme işlemidir.

Yazılışı böyledir:
(EldeEtmekİstediğimTip) EldeOlanBaşkaTipdenObject;

Daha geniş kod:
BaşkaTip EldeOlanBaşkaTipdenObject = new BaşkaTip ();
EldeEtmekİstediğimTip İstediğimObject = (EldeEtmekİstediğimTip) EldeOlanBaşkaTipdenObject;

---

Downcast, nesilde alt tipe çevirme işlemi.
- Validin evlad tipine çevrilmesi. (Casting Parent to Child type)
- Superclassın subclassa çevrilmesi.
- class Child extends Parent{}; Child B = (Child) new Parent();

---

Ha, niye “Down”:
Child extends Parent.

Parent ParentA = new Parent();
Child ChildA = new Child();

Parent ParentB = ChildA; // it's ok. You give a child to it's parent.
Child ChildB = ParentA; // bad. XX. Compiler error. Are you missing a cast? You should use downcasting. You cannot give parent to child easily, it's big responsibility.
Child ChildC = (Child) ParentA; // it's ok.

Bu makale Java ve C# için geçerlidir.