Diziler
Dizi Nedir Ortak özelliğe sahip birden fazla bilginin oluşturduğu bütün bilgi kümelerine veya hafızada art arda sıralanmış aynı türden verilerin oluşturduğu yapıya dizi denir. Kısaca; Bellekte ardışık bir biçimde bulunan ve aynı türden nesnelerin oluşturduğu veri yapısına dizi denir. Dizilerin kullanılmasını gerektiren iki önemli özellikleri vardır : Bellekte ardışık (contiguous) olarak bulunmaları Elemanların aynı türden nesne olmalarıdır. Program içerisinde aynı anda aynı tür bilgiden çok sayıda mevcut olması ve bu bilgiler üzerinde toplu işlem yapılması durumunda dizilerden yararlanılır.
Dizilere örnek verirsek; Dizi nin Önemi Telefon rehberindeki numaralar, haftanın günleri gibi v.b. Diziler bileşik nesnelerdir. Yani bir dizinin tanımlanması ile birden fazla sayıda nesne birlikte tanımlanabilir. Örneğin 10 elemanlık bir dizi tanımlamak yerine, şüphesiz farklı isimde 10 ayrı nesne de tanımlanabilir. Ama 10 ayrı nesne tanımlandığında bu nesnelerin bellekte ardışıl olarak yerleşmeleri garanti altına alınmış bir özellik değildir. Dizi tanımlamasıyla, dizinin elemanı olan bütün nesnelerin bellekte ardışıl olarak yer almaları garanti altına alınmış demektir.
Dizi nin Önemi 1000 adet adı, soyadı ve notu bilgisini saklamak için; Adı 1.. 1000 Adet, Soyad 1.. 1000 Adet Notu 1.. 1000 Adet Toplam 3000 adet değişkenin kullanılması gereklidir. Bir sınıfta okuyan 20 adet öğrencinin adı, soyadını ve her öğrencinin 10 farklı dersten aldıkları 3 farklı not bilgisini aynı anda bilgisayarda hafızasında tutmak için; Adı 20, Soyadı 20, Notlar 20 x 10 x 3 = 600 Toplam 20 + 20 + 600 = 640 adet değişken kullanmamız gerekir.
Dizi Tanımlama Dizi içerisinde her elemanın bir indis numarası bulunur. Bu nedenle indisli değişkenler olarak da adlandırılırlar. İndis Numarası her elemanın dizi içerisindeki yerini, yani kaçıncı elemanı olduğunu gösterir. Bir dizi şu şekilde tanımlanır; <Veri Türü> <Dizi_İsmi> [Eleman Sayısı] int ders_notu [10]; Dizi değişken tanımlamak için kullanılan tanım cümleleri diğer değişkenler için kullanılan cümlelerden farksızdır. Tek farklılık, tanımlanan değişkenin dizi değişkeni olduğunu gösteren ve değişken isminin hemen yanında bulunan [ ] (köşeli parantez) dir.
Dizi Tanımlama Dizi elemanı olan nesnelerin kullanılmasından önce tanımlanmaları gerekecektir; int a[10]; float [15]; char b[20]; double [12]; long c[30]; Daha önce verilen örneklerdeki dizileri oluşturalım; 1000 adet adı, soyadı ve notu bilgisini saklamak için; Adı 1000 Adet, Soyad 1000 Adet, Notu 1000 Adet Toplam 3000 adet değişkenin kullanılması gerekliydi. Bunun yerine; char adi[1000]; char soyadi[1000]; int notu[1000]; şeklinde dizi tanımı yapılmalıdır.
Dizi Tanımlama değer index a[i] 8 3 7 5 2 i 0 1 2 3 4 int a[5] = {8,3,7,5,2}; int a[] = {8,3,7,5,2}; veya int a[5]; a[0]=8; a[1]=3; a[2]=7; a[3]=5; a[4]=2;
Dizi Tanımlama Dizinin elemanları tanımlama sırasında da yapılabilir; int a[6]={11,22,33,44,55,66}; Kullanacağınız indis değerinin negatif olmaması gerekir; int a[-6]={11,22,33,44,55,66}; YANLIŞ Tanımlama anında indis değeri verilmezse, dizinin boyutu tanımlanan eleman sayısı kadar olur; int a[]={11,22,33,44,55,66,77}; dizi boyutu 7 dir. İndis için kullanılacak olan sayı tamsayı olmak zorunda. int a[1.1]={11,22,33,44}; YANLIŞ Karakter string tipi tanımlama için; char sc[]={'a','b','c'}; String tipi bir tanımlama için; string sadi[]={"umut","necla","hüseyin"};
Dizi Tanımlama Global tanımlanan (:: çözünürlük operatörü-scope resolution operator) dizilerin ilk dizi değerleri atanmamış ise sıfır (0) değerini, lokal (main içerisinde ya da fonksiyon v.b.) içerisinde tanımlanan dizilerde ise rastgele değer alırlar. #include <iostream> using namespace std; int x[]={}; //Diziye değer atanmadı boş. main() { int y[]={}; //Diziye değer atanmadı boş. cout << "main dışındaki x[0]=" << ::x[0] << endl; cout << "main içindeki y[0]=" << y[0] << endl; }
Dizi Tanımlama Dizinin elemanları tanımlama sırasında da yapılabilir; int i; int b[]={11,22,33,44}; i=1; cout << b[i++] << endl; // 22 i=1; cout << b[++i] << endl; // 33 i=1; cout << b[--i] << endl; // 11 i=1; cout << b[i--] << endl; // 22 i=1; cout << ++b[2] << endl; // 34 b[2]=34 i=1; cout << b[2]++ << endl; // 34 b[2]=35 i=1; cout << --b[2] << endl; // 34 b[2]=34 i=1; cout << b[2]-- << endl; // 34 b[2]=33 i=1; cout << b[2] << endl; // 33
ÖRNEK 3,6,9,11 tamsayı değerlerini bir dizi içine yerleştirdikten sonra, tek tek ekranda görüntülemek istiyoruz. Kullanacağımız dizinin adı a olsun. Bu diziye, bellekte 10 elemanlık bir yer ayıralım. Daha sonra dizinin dört elemanına ayrı ayrı 4 adet sayı yerleştiriyoruz.
Dizi Tanımlama Verileri klavyeden girmek istersek; #include <iostream> using namespace std; main() { int a[5]; for (int i=0; i<5; i++) {cout << "a icin " << i <<". degeri giriniz:"; cin >> a[i]; cout << i << "->" << a[i] << endl << endl;} } // Programı çalıştırdıktan sonra for döngüsündeki i<5 değerini i<=5 yapınız ve son a[i] değerini inceleyiniz. DİKKAT!!!! C++ yanlış indeks kullanılmasına karşı dahili bir kontrol mekanizması içermez.
Dizi Tanımlama Bir dizi tanımlaması ile karşılaşan derleyici, tanımlanan dizi için bellekte yer tahsis edecektir. Ayrılacak yer = dizinin eleman sayısı x dizinin bir eleman sayısının bellekte kapladığı yer (byte) Örneğin: int a[5]; gibi bir dizi tanımlaması yapıldığını düşünelim. 32 bit işletim sisteminde çalışıyorsak, derleyici a dizisi için bellekte 5 x 4 = 20 byte yer ayıracaktır.
Tamsayı Diziler Tek Boyutlu Diziler İki Boyutlu Diziler Çok Boyutlu Diziler Dizi Türleri Alfasayısal Diziler Karakter Diziler String Diziler
Tek Boyutlu Diziler Şimdiye kadar tanımlanan dizileri tek boyutlu olarak aşağıdaki şekilde tanımladık. <Veri Türü> <Dizi_İsmi> [Eleman Sayısı] int a[5]; Veri Türü = int Dizi_İsmi = a Eleman Sayısı = 5 #include <iostream> using namespace std; int a[5]={2,7,0,3,9}; int i; main() { for (i=0;i<=4;i++) cout << a[i] << "\n"; }
İki Boyutlu Diziler C++ içinde tek boyutlu diziler dışında çok boyutlu dizileri tanımlayarak kullanmamız mümkündür. İki boyutlu bir dizi bir tablo olarak değerlendirilebilir. Bu durumda iki farklı indeksin kullanılması söz konusu olacaktır. Birinci indeks iki boyutlu tablonun satır elemanlarını, ikinci indeks ise sütun elemanlarını gösterecektir. İki boyutlu dizilere matris işlemlerini örnek olarak verebiliriz.
İki Boyutlu Diziler İki boyutlu diziyi aşağıdaki gibi tanımlarız; <Veri Türü> <Dizi_İsmi> [Satır Eleman Sayısı] [Sütun Eleman Sayısı] <Veri Türü> <Dizi_İsmi> [1.İndis] [2.İndis] int a[3][2]; Veri Türü = int Dizi_İsmi = a Satır Eleman Sayısı = 3 Sütun Eleman Sayısı = 2 Eleman Sayısı = 3 x 2 =6 a Dizisi 1. Sütun 2. Sütun 1. Satır a(1,1) a(1,2) 2. Satır a(2,1) a(2,2) 3. Satır a(3,1) a(3,2)
int a[3][2]; a[0][0]=1 a[0][1]=2 a[1][0]=7 a[1][1]=9 a[2][0]=3 a[2][1]=8 İki Boyutlu Diziler
İki Boyutlu Diziler 4x5 matrise ait atama ve görüntüleme programını aşağıdaki şekilde yazarız;
Çok Boyutlu Diziler 3 ve daha fazla boyutlu olan dizilerdir. Bu tür diziler kullanıldığında programın anlaşılırlığı azalmaktadır. Özellikle 3 boyutludan sonrası oldukça karışık ortamlar oluşturmaktadır. Çok boyutlu diziyi aşağıdaki gibi tanımlarız; <Veri Türü> <Dizi_İsmi> [1.İndis] [2.İndis] [3.İndis] [n.indis] int a[3][2][7][n.]; Veri Türü = int Dizi_İsmi = a 1. İndis= 3 2. İndis= 2 3. İndis= 7 n Eleman Sayısı = 3 x 2 x 7 = 42
Çok Boyutlu Diziler
Karakter (Katar) Diziler <Veri Türü> <Dizi_İsmi> [Eleman Sayısı+1] char il[10]; char il[11]={'i','s','k','e','n','d','e','r','u','n','\0'}; char il[10]={'i','s','k','e','n','d','e','r','u','n'}; char il[]={'i','s','k','e','n','d','e','r','u','n','\0'}; Karakter boyutları tanımlanırken dikkatli olmak gerekir. Çünkü dizinin son karakteri NULL (\0) olacaktır.
Karakter (Katar) Diziler
Karakter (Katar) Diziler
String Diziler <Veri Türü> <Dizi_İsmi> [Eleman Sayısı+1]="string" char il[7]="ankara"; char ilce[10]={"iskenderun"}; HATA char ilce[11]={"iskenderun"}; DOĞRU char ilce[]={"iskenderun"}; DOĞRU
String Diziler 1) char *ck3[] = "karakterler"; // Hata Err 2) const char *ck4[] = "karakterler"; // Hata Err 3) char ck6[] = "karakterler"; // Doğru 4) char ck9[6]="123456"; // Hata Err 5) char ck10[6]="12345"; // Doğru 6) const char *ck5=new char[karakter_uzunluğu];// Doğru const char *ck5=new char[10]; // 10 veya 0. ck5="karakterler"; cout << ck5 << endl; // karakterler cout << ck5[2] << endl; // r
String Diziler (#include <cstring>) strcpy(s1,s2); s2 değeri s1 içine kopyalanır. Dönüş değeri yoktur. strcpy(s1,"ankara"); k1 değerine atama yapılıyor. s1="ankara Fonksiyon olarak yazacak olsaydık:
String Diziler (#include <cstring>) strcat(s1,s2); s1 e s2 eklenir. s1="ankara" s2="baskent" strcat(s1,s2); s1="ankarabaskent strlen(s1); s1 değerinin boyutu bulunur. Dönüş değeri: integer strlen(s1) ile yeni boyut 13 olur.
String Diziler (#include <cstring>) strcmp(s1,s2); s1 ve s2 değerleri karşılaştırılır s1 ve s2 stringleri sözlüksel olarak karşılaştırır Dönüş değeri: Büyük harfler ASCII tabloda daha önce bulunur. Bu durumda küçük harfle başlayan bir string ile büyük harfle başlayan bir string karşılaştırılınca, büyük harfle başlayan sözlükte daha önce yer alıyormuş gibi cevap alırız. =-1, Eğer str1 < str2 (str1 ASCII tabloda str2 den önce geliyorsa) = 0, Eğer str1 == str2 = 1, Eğer str1 > str2
String Diziler (#include <cstring>) #include <cstdlib> itoa (sayısal,string,taban) String deger taban degerine göre (2,8,10,16) integer degere dönüştürülür. atoi (string) String integere dönüşür. atol (string) String long değere dönüşür. atof (string) String reel sayıya dönüşür.
Örnek
Örnek
Dizilerin Fonksiyonlara Parametre int a [20]; olarak Gönderilmesi şeklinde tanımlanmış bir diziyi DiziGuncelle isimli bir fonksiyona argüman olarak yollayacaksak bu fonksiyonu çağrı cümlesi şöyle yazılır: DiziGuncelle( a, 20 ); C++ dizileri fonksiyonlara call-by-reference ile geçirir; yani fonksiyona yollanan dizinin ilk elemanının adresidir. Bu demektir ki, fonksiyon, dizinin elemanlarının değerlerini değiştirirse, bu değişiklik orijinal dizide yapılmış olur dizinin başka bir kopyası üzerinde değil.
Dizilerin Fonksiyonlara Parametre olarak Gönderilmesi Bir diziyi parametre olarak alacak bir fonksiyon tanımı aşağıdaki gibi yazılabilir; void DiziGuncelle(int b[],int diziboyut) Köşeli parantez içine dizinin boyutunu yazmak gerekmez; yazılırsa, derleyici bunu yok sayar; dikkate almaz. Aynı tanım şöyle de yapılabilir: void DiziGuncelle(int [], int)
Dizilerin Fonksiyonlara Parametre olarak Gönderilmesi NOT: Pointer olarak tanımlasaydık En son a[3] değeri 12 olurdu. Bu örnek, bir fonksiyona tüm diziyi geçirmekle (DiziGuncelle) tek bir dizi elemanını geçirmek (DiziElemanDegistir) arasındaki farkı göstermektedir. Fonksiyona bir dizinin tümü geçirildiğinde C++ call-byreference kullanır; yani fonksiyonda dizinin yeni bir kopyası açılmaz; orijinal dizi üzerinde işlem yapılır. Orijinal dizi üzerinde işlem yapmamak yani orijinal diziyi bozmamak istiyorsak call-byvalue kullanmamız gerekir ki bunun yolu dizi elamanlarını tek tek geçirmektir bu da uzun ve pratik olmayan bir yoldur.
Dizilerin Fonksiyonlara Parametre olarak Gönderilmesi Dizilerin fonksiyonlara call-by-reference ile geçirildiğini; bunun da orijinal dizi elemanları üzerinde işlem yapıp değerleri değiştirdiğini gördük. Bunu istemediğimiz (yani, kontrol etmek istediğimiz) durumlar olabilir. Bunu için const niteleyicisi kullanılır. const niteleyicisi kullanıldığında orijinal dizinin değiştirilemeyeceği görülür.
Dizilerin Fonksiyonlara Parametre olarak Gönderilmesi Çok boyutlu dizlerini fonksiyonlara parametre olarak geçilmelerinde dizini her bir boyutunun belirtilmesi gerekmektedir. Sadece en soldaki indisi belirtmeme şansına sahibiz. Aşağıdaki gibi tanımlanmış bir diziyi parametre olarak alacak fonksiyonun prototipi aşağıdaki gibi olacaktır. double ozellik[12][13][14]; bool hesapla(ozellik[12][13][14]); veya bool hesapla(ozellik[][13][14]);
Dizilerin Fonksiyonlara Parametre olarak Gönderilmesi Yandaki programda tanımlı fonksiyonda orijinal dizi a yı değiştirme çabası hata verecektir; çünkü fonksiyon prototipinde a const olarak tanımlanmıştır.
ÖRNEK