ÜYE GİRİŞİ  
Kullanıcı adı :
Parola :
 
  Üye Ol!  
 
 
ANASAYFA HABERLER ASP ASP.NET PHP C/C++ C# JAVA ARAMA İLETİŞİM

ASP.NET
  Expression Web ile Site Yapimi
  Web Server Control Yazmak - 2
  Web Server Control Yazmak - 1
  Sql Cache Dependency
  Web Kontrollerini Etkin Kullanmak
  Xslt Kullanımı
  Bir Web Sayfasının Anatomisi
  Client Script Callback
  Login Kontrollerinin Kullanımı

ASP
  ASP Nesneleri
  29 Soruda ASP
  Matematiksel Uygulamalar
  Select Case Yapısı 2
  Fonksiyon(Function) Kullanımı
  IF-ELSE...
  GET Yöntemi ile İşlemler
  Asp de Tarih ve Saat fonksiyonları
  While-wend döngüsü

C Sharp (C#)
  C#'da klasör işlemleri
  C# ile diziyi tersine çevirme
  Çok Kullanılan Kontroller-1
  C# ile Kronometre Uygulaması
  Overloaded Metotların Gücü
  C# ile XMLQuery Örneği
  Rastgele Kod Üretimi
  Kontroller ile Çalışma
  Düzenli İfadeler Nedir?

DUYURULAR

F# Microsoft dil teknolojisinin en yeni üyesi.Common Lisp-Slime-Emacs tarzında etkileşimli,kıvrak,sonuçların anında görülebildiği ve yüksek performanslı bir betik dil olarak özetleyebiliriz bu yeni dili. devamı >>


Türk Telekom'dan yapılan yazılı açıklamada, Telekomünikasyon Kurumu'nun onayladığı yeni tariflerin, internet servis sağlayıcı şirketlerin maliyetlerini önemli oranlarda düşüreceği aktarıldı. devamı >>


Fonksiyon Göstericilerinin Kullanılması | Asundinay.Com
C/C++ İçin Eklenmiş Makale
 Makale Adı  :  Fonksiyon Göstericilerinin Kullanılması
 Yayın Tarihi :  12.08.2007 20:32:23 Ekleyen :  Kazım Aydın Okunma : 160

Bu yazımızda fonksiyon göstericilerini inceleyeceğiz. Ancak konuya geçmeden önce, göstericilere bir göz atmamızın yararlı olacağını düşünüyorum. Bildiğimiz gibi gösterici (pointer), belli bir türden adres tutan veri türüdür. Eğer tutacağımız adresin türü int ise, yani int türünden bir nesnenin adresini tutmak istiyorsak bunun için tanımlamamız gereken gösterici (int *) türünden olmalıdır. Benzer şekilde double nesnelerin adresini tutmak için (double *) türünden gösterici tanımlanmalıdır. Bu ifade, C dilinin tüm doğal veri türleri için, ayrıca programcının tanımladığı veri türleri için geçerli bir ifadedir. Örneğin, test isimli bir yapı tanımladığımızı düşünelim. Bu yapı türünden bir nesnenin adresini tutmak için (test *) türünden bir gösterici tanımlamamız gereklidir. Bu durumda C dilinde sonsuz türde gösterici olabilir. Şimdi bir göstericiyi nasıl tanımladığımızı örneklerle hatırlayalım :

int a = 10;
int *pi = &a;

struct test {
    //...
};
struct test t;
struct test *pt = &t;

Peki fonksiyon göstericisi ne demektir? Gösterici, adres tutan bir tür olduğuna göre, fonksiyon göstericisi de adından anlaşılacağı üzere, bir fonksiyonun adresini tutacaktır. Peki fonksiyonun adresi ne demektir? Kaynak kod içerisinde programcı tarafından yazılan fonksiyonlar, derleme aşamasında derleyici tarafından makine koduna dönüştürülür. Fonksiyonun kodları da, tıpkı tanımlanan değişkenler gibi bellekte belli bir yer kaplarlar. Fonksiyonun adresi kavramı, fonksiyonun bellekte kapladığı adresin başlangıcı anlamına gelmektedir. Tıpkı dizi isimlerinde olduğu gibi, fonksiyonların isimleri, onların başlangıç adreslerini belirtir. Aşağıdaki örneği inceleyiniz :

int Add_i(int a, int b)
{
     return a + b;
}

şeklinde bir fonksiyon tanımlandığını düşünelim. Bu durumda, Add_i ismi, bu fonksiyonun başlangıç adresini göstermektedir. Tanımlayacağımız fonksiyon göstericilerine atayacağımız değerler de fonksiyon isimleri olacaktır. C dilinde, bir fonksiyonu, adını ve adının yanına da parantez içerisinde parametre değişkenlerini yazarak çağırırız. Bu fonksiyonu uygun türden bir göstericiye atadığımız zaman, fonksiyonu bu gösterici yoluyla da çağırabiliriz. Bu durumun bize nasıl bir fayda sağlayacağını örnek üzerinde göstereceğiz. Fonksiyon göstericisi tanımlama ifadesi şu şekildedir :


<fonksiyonun geri dönüş değeri türü>(*gösterici adı)([fonksiyonun parametre türleri])

int (*Func1) (int,int);    /* Geri dönüş değeri int olan, iki parametre değişkeni olan ve parametre değişkenlerinin türleri int olan fonksiyonları göstermeye aday Func1 ismindeki fonksiyon göstericisi */
void (*Func2) (void);    //Geri dönüş değeri ve parametre değişkeni olmayan fonksiyon göstericilerini göstermeye aday Func2 ismindeki göstericisi
int Add_i(int a, int b)
{
      return a + b;
}


int(*Func1) (int,int);

Func1 = Calculate;  /* Calculate ismi fonksiyonun adresini gösterir, Func1 göstericisi artık Calculate fonksiyonunu göstermektedir*/


Calculate(10,20);   //Fonksiyonun adı ve parametre değişkenleri ile çağrılması

Func1(10,20);       //Fonskiyonun kendisini gösteren bir gösterici ve parametre değişkenleri ile çağrılması

Peki bu durumdan nasıl bir fayda sağlayabiliriz ? Bilindiği üzere, C dilinde aynı isimli birden fazla fonksiyon bulunamaz. Nesne yönelimli tekniği uygulayan yüksek seviyeli dillerde (örneğin C#), fonksiyonlar aşırı yüklenerek birden fazla tür için çalışan aynı isimli fonksiyonlar yazılabilir. Durumu bir örnekle açıklayalım : Diziler üzerinde işlem yaptığımızı düşünelim. Hem tamsayı türünden diziler hem de ondalıklı sayı türünden diziler için sıralama algoritması yazmak istiyoruz. Bu durumda C dilinin kuralları gereğince, sort_int ve sort_double isimli iki ayrı fonksiyon yazarak isteğimizi karşılayabiliriz. İki ayrı fonksiyon yazma gereği, sıralanacak elemanların türlerinin farklılığından kaynaklanmaktadır. Kullanacağımız algoritma ise her iki fonksiyon için de aynı olacaktır. Büyük bir uygulamayı göz önünde bulundurduğumuzda bu gibi durumlar sıklıkla karşımıza çıkar. Belli bir noktadan sonra, farklı türler için aynı işi yapan fonksiyonların sayıları artacaktır. Bu fonksiyonların isimlerinin farklı olması programcının algılamasını zorlaştırır. Sıralama yapmak isteyen programcı, kullanacağı tür için uygun olan fonksiyonun ismini hatırlamak zorunda kalır. Oysa bir tane sıralama fonksiyonu olsa, ismi de örneğin "Sort" olsa, programcı sıralamayı yapacağı anda bu Sort fonksiyonunu çağıracaktır. Böyle bir kullanım, kodun okunabilirliğini de artırır. Fonksiyon göstericileri yardımıyla bunu yapabiliriz. Yine farklı türler için farklı isimli fonksiyonlar yazmamız gerekecek, ancak işlemi yapacağımız anda çağıracağımız fonksiyon bir tane olacak ve biz sadece bu fonksiyonun adını hatırlamak zorunda kalacağız. Fonksiyon göstericilerini, bir yapıya veri elemanı olarak ekleyebiliriz. C dilinde, yapı türleri içerisinde fonksiyon tanımlanamaz. Ancak yapıya bir fonksiyon göstericisi eklemek yoluyla dolaylı yoldan bunu yapabiliriz.

Şimdi örnek bir uygulama yapalım. Hem tamsayı türünden, hem de ondalıklı sayı türünden diziler için en büyük ve en küçük elemanı bulma, aritmetik ortalamayı bulma ve elemanların toplam değerlerini bulma işlemlerini yapmak istediğimizi düşünelim. Her tür için işlem yapan farklı fonksiyonlar yazacağız. Ancak en son, belli işleri yapan fonksiyon göstericileri tanımlayacağız ve kullanacağımız türe göre bu fonksiyon göstericilerine türlere özel yazdığımız fonksiyonları atayacağız. Şimdi bahsettiğimiz bu yapıyı oluşturmaya başlayalım :

// Tamsayı üzerinde mi ondalıklı sayı üzerinde mi çalışıyoruz ?
typedef enum _myTypes {
    t_integer = 0,
    t_double = 1,
}MyTypes;

// Üzerinde çalışacağımız türe göre dizimizi tutacak birlik
typedef union _vals {
    double *dVals;
    int *iVals;
}Vals;

// Üzerinde çalışacağımız türe göre çağıracağımız fonksiyonların geri dönüş değerlerini tutacak birlik
typedef union _result {
    double dResult;
    int iResult;
}Result;

// Temel yapımız
typedef struct _myArray {
    MyTypes type;
    Vals vals;
    double (*GetMathAvr)(int elemNumber,Result res);
    Result (*GetSum)(void const *elems,int elemNumber);
    int (*GetMax)(void const *elems,int elemNumber);
    int (*GetMin)(void const *elems,int elemNumber);
}MyArray;

Buradaki tanımlamaları açıklayalım. MyArray isimli bir yapı tanımladık. Bu yapıda, üzerinde çalışacağımız tür bilgisini tutan tutan type isimli bir veri elemanı, dizimizin elemanlarını tutan vals veri elemanı ve dört tane de fonksiyon göstericisi bulunuyor. Eğer üzerinde çalışacağımız tür tamsayı ise type elemanına t_integer değerini, ondalıklı sayı ise t_double değerini atayacağız. Bu değeri de her iki tür için de ortak yazdığımız fonksiyonlarda, tür bilgisini alabilmek için kullanacağız. Yapımız içerisinde dört tane de fonksiyon göstericisi tanımladık. Bu fonksiyon göstericilerinin göstereceği fonksiyonların yapacağı işler şunlardır :

1- Dizinin aritmetik ortalamasını bulacak
2- Dizinin elemanlarının toplam değerini bulacak
3- Dizinin en büyük elemanını bulacak
4- Dizinin en küçük elemanını bulacak

Bu durumda, kullandığımız türe göre bu göstericilere uygun fonksiyonların adreslerini atayacağız. Farklı türler için fonksiyonlar çağırırken, farklı fonksiyon isimleri kullanmak zorunda kalmayacağız, bunun yerine tanımladığımız fonksiyon göstericilerinin adını kullanacağız.

Fonksiyon göstericilerinin göstereceği fonksiyonların parametre değişkenlerinde (void *) türünün kullanılmasının nedeni türden bağımsızlığı sağlayabilmektir. Farklı türler için aynı işlemleri yapan fonksiyonları çağırmak için bir tane fonksiyon göstericisi tanımladık. Bu göstericiye atayacağımız fonksiyonun parametrik yapısı da göstericinin parametrik yapısına uygun olmalıdır. Bu durumda kullanılabilecek en uygun tür de (void *) olacaktır. Fonksiyonlara göndereceğimiz (int *) ve (double *) türünden nesnelerimizi (void *) türüne tür dönüşümü ile dönüştüreceğiz. Türe bağımlı yazacağımız fonksiyonlarda ise, parametre değişkenini kullanılan türe göre (int *) veya (double *) türüne dönüştüreceğiz. Bu yapı biraz karmaşık gibi görünse de birkaç uygulama yapılarak rahatlıkla anlaşılabilir. Öncelikle türe bağımlı işlemleri yapacak fonksiyonları tanımlayalım :

Result GetSumDouble(void const *elems,int elemNumber)
{
    double const *myElems = (double *)elems;
    int i;
    double sum = 0.0;
    Result res;

    for (i = 0; i < elemNumber; ++i)
    sum += myElems[i];

    res.dResult = sum;
    return res;
}


Result GetSumInt(void const *elems,int elemNumber)
{
    int const *myElems = (int *)elems;
    int i,sum = 0;
    Result res;

    for (i = 0; i < elemNumber; ++i)
       sum += myElems[i];

    res.iResult = sum;
    return res;
}

Bu iki fonksiyon, parametre olarak geçilen dizinin elemanlarının değerleri toplamını Result türünden bir nesnenin ilgili elemanına atamaktadır. Dizi parametresini (void *) türünden tanımladık. Çünkü bu fonksiyonu yapımız içerisindeki GetSum fonksiyon göstericisine atayacağız ve parametrik uyum sağlamalıyız. Biz, her iki fonksiyon içerisinde de tür bilgisine sahip olacağımız için tür dönüşümü ile istediğimiz türe dönüşüm yapabiliriz. void göstericiler için, gösterici aritmetiği geçerli olmadığı için bu tür dönüşümünü yapmak zorundayız. Aksi durumda void bir gösterici için köşeli parantez operatörünü kullanmak mümkün değildir. Biz dizi elemanlarına ulaşmak için bu operatörü kullanacağız. Bu durumda tür bilgisine de sahip olmamız kaçınılmazdır. Yukarıdaki fonksiyonlarda da bu işlemi gerçekleştirdik. Tamsayı türü için yazılan fonksiyonda parametre değişkenini (int *) türüne, ondalıklı sayı türü için yazılan fonksiyonda ise (double *) türüne dönüştürdük. Bu sayede dizimizin elemanlarına köşeli parantez operatörü ile ulaşmayı mümkün kıldık.

int GetMaxInt(void const *elems,int elemNumber)
{
    int const *myElems = (int *)elems;

    int i, maxIndex = 0;
    int max = myElems[0];

    for (i = 1; i < elemNumber; ++i)
    {
       if (myElems[i] > max)
       {
          max = myElems[i];
          maxIndex = i;
       }
    }
    return maxIndex;
}

int GetMaxDouble(void const *elems,int elemNumber)
{
    double const *myElems = (double *)elems;

    int i, maxIndex = 0;
    double max = myElems[0];

    for (i = 1; i < elemNumber; ++i)
    {
       if (myElems[i] > max)
       {
          max = myElems[i];
          maxIndex = i;
       }
    }
    return maxIndex;
}

Yukarıdaki iki fonksiyon, parametre olarak aldıkları dizilerin en büyük elemanlarının indekslerine geri dönmektedir. Bu fonksiyonlarda da yukarıda bahsettiğimiz tür dönüşümü işlemini gerçekleştirdik. En büyük elemanı bulma fonksiyonunun başında, tipik olarak öncelikle dizinin ilk elemanı en büyük eleman kabul edilir ve ilgili türden bir değişkene bu değer atanır. Sonraki adımlarda ise dizinin diğer elemanları, bu değişkenin değeri ile karşılaştırılarak işlemlere devam edilir. İlk fonksiyonda, bu değişkenin türü int, ikinci fonksiyonda ise double olmalıdır. Dolayısıyla bu iki fonksiyonu tek bir fonksiyon haline getirmek mümkün değildir. İki farklı isme sahip fonksiyon yazılması zorunludur. Ancak bir fonksiyon göstericisi tanımlarsak, bu iki fonksiyonu, tanımlayacağımız bu göstericiye atayabiliriz. En büyük elemanı bulmak için çağıracağımız fonksiyon her iki durumda da yapı içerisinde tanımladığımız fonksiyon göstericisinin gösterdiği fonksiyon olacaktır. Yukarıdaki fonksiyonlara benzer şekilde dizinin en küçük elemanının indeksine dönen fonksiyonlar da yazılır.

int GetMinInt(void const *elems,int elemNumber)
{
    int const *myElems = (int *)elems;

    int i, minIndex = 0;
    int min = myElems[0];

    for (i = 1; i < elemNumber; ++i)
    {
       if (myElems[i] < min)
       {
          min = myElems[i];
          minIndex = i;
       }
    }
    return minIndex;
}

int GetMinDouble(void const *elems,int elemNumber)
{
    double const *myElems = (double *)elems;

    int i, minIndex = 0;
    double min = myElems[0];

    for (i = 1; i < elemNumber; ++i)
    {
       if (myElems[i] < min)
       {
          min = myElems[i];
          minIndex = i;
       }
    }
    return minIndex;
}

Aritmetik ortalamayı hesaplayan fonksiyonlar ise şu şekilde tanımlanır :

double GetMathAvrDouble(int elemNumber,Result res)
{
    return (double)res.dResult / elemNumber;
}


double GetMathAvrInt(int elemNumber,Result res)
{
    return (double)res.iResult / elemNumber;
}

Bu fonksiyonlar, parametre değişkeni olarak Result türünden bir değişken ve dizinin eleman sayısını tutan int türünden bir değişken almaktadır. Fonksiyonlar, üzerilerinde çalıştıkları türe göre, Result türünden nesnenin iResult ya da dResult değerine erişerek ortalamayı hesaplıyorlar. Bu durumda bu fonksiyonlara gönderilecek Result türünden değişkenin ilgili veri elemanında, dizi elemanlarının toplam değerleri atanmalıdır. Zaten biz bu işlemi yapan birer fonksiyon da yazmıştık. Şimdi tanımladığımız bu yapıyı nasıl kullanacağımızı inceleyelim. Programımız hem tamsayı dizileri, hem de ondalıklı sayılar dizileri üzerinde işlem yapacak. Kullanıcıdan bu bilgiyi alacağız. MyArray yapısı türünden bir nesne tanımlayarak elemanlara ilgili değerleri atayacağız. Bu yapı nesnesinin elemanlarının doldurulması işlemini de bir fonksiyon ile yapalım. Ancak her iki tür için de tek bir fonksiyon yazacağız. Bu noktada, yapımızın type elemanından faydalanacağız :

void StartOperation(MyArray *array,void *myVals)
{
    if (array->type == 0) //integer
    {
       array->vals.iVals = (int *)myVals;
       array->GetSum = GetSumInt;
       array->GetMin = GetMinInt;
       array->GetMax = GetMaxInt;
       array->GetMathAvr = GetMathAvrInt;
    }

    else if (array->type == 1) //double
    {
       array->vals.dVals = (double *)myVals;
       array->GetSum = GetSumDouble;
       array->GetMin = GetMinDouble;
       array->GetMax = GetMaxDouble;
       array->GetMathAvr = GetMathAvrDouble;
    }
}

Eğer türümüz tamsayı ise ilk koşul gerçeklenir ve bu bloktaki işlemler yapılır. Bu blokta yapımızın fonksiyon göstericisi elemanlarına, tamsayılar üzerinde işlem yapan fonksiyonların adresleri atanmıştır. Eğer türümüz ondalıklı sayı ise ikinci koşul gerçeklenir. Bu durumda da fonksiyon göstericisi elemanlarına ondalıklı sayılar üzerinde işlem yapan fonksiyonların adresleri atanır. Bu yapı nesnesini bir defa oluşturduktan sonra artık farklı fonksiyon isimlerini hatırlamak zorunda kalmayacağız. Göstericilerimiz ilgili fonksiyonları gösterdiklerine göre, bize düşen sadece yapının fonksiyon göstericisi isimlerini kullanarak ilgili parametrelerle fonksiyonları çağırmak olacak. Şimdi programımızın ana bloğunu inceleyelim :

int main()
{
    MyArray array;
    int opNum = 0,i;
    int myIntArray[] = {1,2,3,4,5,6,7,8,9,10};
    double myDoubleArray[] = {1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.10};
    Result tmpRes;


    while (opNum < 1 || opNum > 3)
    {
       printf("Tamsayi islemleri icin : 1\n");
       printf("Ondalikli sayi islemleri icin : 2\n");
       printf("Programdan cikmak icin : 3\n");
       printf("Giriniz..\n");
       scanf("%d",&opNum);
    }

    if (opNum == 1)
    {
       array.type = t_integer;
       StartOperation(&array,(void *)myIntArray);
       printf("Dizinin Elemanlari :\n");

       for (i = 0; i < ARRAY_SIZE; ++i)
          printf("%d\n",array.vals.iVals[i]);

       tmpRes = array.GetSum(array.vals.iVals,ARRAY_SIZE);
       printf("Toplam = %d\n",tmpRes.iResult);
       printf("En Kucuk Eleman = %d\n",array.vals.iVals[array.GetMin(array.vals.iVals,ARRAY_SIZE)]);
       printf("En Buyuk Eleman = %d\n",array.vals.iVals[array.GetMax(array.vals.iVals,ARRAY_SIZE)]);
       printf("Aritmetik Ortalama = %lf\n",array.GetMathAvr(ARRAY_SIZE,tmpRes));
    }

    else if (opNum == 2)
    {
       array.type = t_double;
       StartOperation(&array,(void *)myDoubleArray);
       printf("Dizinin Elemanlari :\n");

       for (i = 0; i < ARRAY_SIZE; ++i)
          printf("%lf\n",array.vals.dVals[i]);

       tmpRes = array.GetSum(array.vals.dVals,ARRAY_SIZE);
       printf("Toplam = %lf\n",tmpRes.dResult);
       printf("En Kucuk Eleman = %lf\n",array.vals.dVals[array.GetMin(array.vals.dVals,ARRAY_SIZE)]);
       printf("En Buyuk Eleman = %lf\n",array.vals.dVals[array.GetMax(array.vals.dVals,ARRAY_SIZE)]);
       printf("Aritmetik Ortalama = %lf\n",array.GetMathAvr(ARRAY_SIZE,tmpRes));
    }

    else if (opNum == 3)
    {
       printf("Program Sonlaniyor...\n");
    }

    return 0;
}

Kullanıcı klavyeden 1 değerini girerse, yapımızı tamsayı türüne göre, 2 değerini girerse ondalıklı sayı türüne göre oluşturuyoruz. Daha sonra yapımızın fonksiyon göstericilerini kullanarak istediğimiz fonksiyonların çağrılmasını sağlıyoruz. Programın çıktı görüntüleri şöyledir :

Seçeneklerin sunulması :

    

Tamsayı seçeneğinin seçilmesi :                                Ondalıklı Sayı Seçeneğinin Seçilmesi :

          
   

Uygulamanın tamamını aşağıdan indirebilirsiniz. MinGW 2.05 ve Microsoft Visual C++ 6.0 derleyicilerinde derlenmiştir.

Bir sonraki makalemizde görüşmek üzere..

Kaynak kod için tıklayın.


 

Kaynak : csharpnedir.com


 

C/C++ İçin Eklenmiş Tüm Makaleler
C/C++ İçin En Son Eklenen 5 Makale
 Makale Adı  :  C ögreniyorum -8-
 Yayın Tarihi :  16.10.2008 17:20:17 Ekleyen :  özen karaçakır Makaleyi Oku  
 Makale Adı  :  C ögreniyorum -7-
 Yayın Tarihi :  22.06.2008 15:48:18 Ekleyen :  özen karaçakır Makaleyi Oku  
 Makale Adı  :  C ögreniyorum -6-
 Yayın Tarihi :  20.06.2008 18:15:06 Ekleyen :  özen karaçakır Makaleyi Oku  
 Makale Adı  :  C ögreniyorum -5-
 Yayın Tarihi :  26.10.2007 10:24:15 Ekleyen :  özen karaçakır Makaleyi Oku  
 Makale Adı  :  C ögreniyorum -4-
 Yayın Tarihi :  13.09.2007 23:36:40 Ekleyen :  özen Karaçakır Makaleyi Oku  

C/C++
  C ögreniyorum -8-
  C ögreniyorum -7-
  C ögreniyorum -6-
  C ögreniyorum -5-
  C ögreniyorum -4-
  C ögreniyorum -3-
  C ögreniyorum -2-
  C ögreniyorum -1-
  İlk C++ Programımız

JAVA
  Java ile Histogram Eşitleme
  JAVA İçinde Thread Kullanımı
  Serialization İşlemleri 2
  Serialization İşlemleri
  İlk Bakışta JSP
  Servletler ile Web Sayfaları
  Java ile Grafik Çizim
  Java, MySql Bağlantısı
  JBuilder ile Database

PHP
  php dersleri -1-
  php/access ile silme işlemi
  php ile access'e bağlanma - 2
  php ile access'e bağlanma - 1
  Döngü ve Diziler - BÖLÜM 5
  Döngü ve Diziler - BÖLÜM 4
  Döngü ve Diziler - BÖLÜM 3
  Döngü ve Diziler - BÖLÜM 2
  Döngü ve Diziler - BÖLÜM 1

İSTATİSTİKLER
  Toplam ziyaret :  24684
  Toplam üye sayısı :  1077
  Asp makale sayısı :  20
  Asp.Net makale sayısı :  54
  Php makale sayısı :  26
  C/C++ makale sayısı :  51
  C# makale sayısı :  29
  Java makale sayısı :  33
  Toplam makale saıysı :  213
Copyright asundinay® 2007 Her Hakki Saklidir
Tasarim & Programlama asundinay®