1. Skip to Menu
  2. Skip to Content
  3. Skip to Footer>

Çok boyutlu diziler

PDF Yazdır e-Posta

Written by Admin

Posted on 05 Eylül 2010

Son Güncelleme 05 Eylül 2010

ÇOK BOYUTLU DİZİLER

C'de diziler çok boyutlu olabilir. Çok boyutlu dizilerin genel kullanımı, satırlar ve sütunlar biçiminde düzenlenmiş değerler içeren tabloları göstermektir. Bir tablo elemanını belirleyebilmek için iki belirteç kullanmalıyız: İlk belirteç (genellikle) elemanın satırını ve ikinci belirteç (genellikle) elemanın sütununu belirler. Belirli bir elemanı tanımlayabilmek için iki belirteç kullanan tablolar ya da diziler iki-boyutlu diziler olarak adlandırılır. Çok boyutlu dizilerin iki belirteçten daha fazla belirtece sahip olabileceğine dikkat ediniz. ANSI standardı bir ANSI-C sisteminin en az 12 dizi belirtecini desteklemesi gerektiğini belirtmiştir.

Şekil 6.20, iki boyutlu olan bir a dizisini göstermektedir. Dizi 3 satır ve 4 sütun içermektedir, bu sebepten 3'e-4 dizi olarak da adlandırılır.Genelde m satırlı ve n sütunlu bir dizi m'e-n dizi olarak adlandırılır.

a [0] [0]
a [0] [1] a [0] [2] a [0] [3]
a [1] [0] a [1] [1] a [1] [2] a [1] [3]
a [2] [0] a [2] [1] a [2] [2] a [2] [3]

Şekil 6.20 3 satır ve 4 sütuna sahip iki boyutlu bir dizi

a dizisi içindeki her eleman, Şekil 6.20'de a[i][j] biçiminde bir eleman ismi ile adlandırılmıştır. Burada, a dizinin ismi, i ve j ise a içindeki her elemanı kendine has bir biçimde belirleyen belirteçlerdir. İlk satırdaki tüm eleman isimlerinin ilk belirteç olarak 0'a ve dördüncü sütundaki elemanların isimlerinin 3 belirtecine sahip olduklarına dikkat ediniz.

Genel Programlama Hataları 6.9
İki boyutlu bir diziyi a[x][y] yerine a[x,y] biçiminde belirlemek.

Çok boyutlu bir diziye tek belirteçli dizilerde olduğu gibi bildirim esnasında değerler atanabilir. Örneğin, iki boyutlu bir dizi

 

1
int b[2][2]={ {1, 2}, {3, 4} };

biçiminde bildirilip, değerlere atanabilir. Değerler parantezler içinde satırlara göre gruplandırılmıştır. Bu sebepten, 1 ve 2 b[0][0] ve b[0][1], 3 ve 4 ise b[1][0] ve b[1][1]'e atanmaktadır. Eğer bir satır için yeterince atama değeri yoksa, satırda kalan diğer elemanlar 0'a atanır. Bu sebepten,

1
int b[2][2]={ {1}, {3, 4} };

bildirimi b[0][0]'a 1, b[0][1]'e 0, b[1][0]'a 3 ve b[1][1]'e 4 atayacaktır.
Şekil 6.21, iki boyutlu dizilerde bildirim esnasında atama yapmayı göstermektedir. Program, 2 satır ve 3 sütunlu (her birinde 6 eleman olan) 3 adet dizi bildirmektedir. dizi1 bildirilirken atama listesinde 3'er elemanlı 2 adet liste kullanılmıştır. İlk liste, dizinin ilk satır elemanlarını 1, 2 ve 3 değerlerine, ikinci liste ise dizinin ikinci satırını 4, 5 ve 6 değerlerine atamaktadır. Eğer dizi1 bildiriminde listedeki parantezler kaldırılırsa, derleyici ilk satırın elemanlarını ve daha sonrada ikinci satırın elemanlarını atayacaktır. dizi2 bildiriminde (10.satır) 5 atama değeri bulunmaktadır. Atama değerleri önce ilk satıra daha sonra da ikinci satıra atanmaktadır. Özel olarak bir atama değerine sahip olmayan elemanlar otomatik olarak 0'a atanacaktır. Bu yüzden, dizi2[1][2] 0'a atanmıştır. dizi3 bildirimi (11.satır) iki liste içinde 3 atama değeri içermektedir. İlk liste, ilk satırın ilk iki elemanını özel olarak 1 ve 2'ye atamaktadır. Üçüncü eleman ise 0'a atanmıştır. İkinci satır için olan liste ise ilk elemanı 4'e atamaktadır. Kalan iki eleman 0'a atanmıştır.

İlk değer atanması
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* Şekil 6.21: fig06_21.c
Çok boyutlu dizilere ilk değer atanması */
#include <stdio.h>
 
void diziyiYazdir( const int [ ][ 3 ] );
 
int main( )
{
int dizi1[ 2 ][ 3 ] = { { 1, 2, 3 }, { 4, 5, 6 } },
dizi2[ 2 ][ 3 ] = { 1, 2, 3, 4, 5 },
dizi3[ 2 ][ 3 ] = { { 1, 2 }, { 4 } };
 
printf( "Satır satır dizi1'in elemanları:\n" );
diziyiYazdir ( dizi1 );
 
printf( " Satır satır dizi2'in elemanları:\n" );
diziyiYazdir ( dizi2 );
 
printf( " Satır satır dizi3'in elemanları:\n" );
diziyiYazdir ( dizi3 );
 
return 0;
}
 
void diziyiYazdir ( const int a[ ][ 3 ] )
{
int i, j;
 
for ( i = 0; i <= 1; i++ ) {
for ( j = 0; j <= 2; j++ )
printf( "%d ", a[ i ][ j ] );
 
printf( "\n" );
}
}

Satır satır dizi1'in elemanları:
1 2 3
4 5 6
Satır satır dizi2'in elemanları
1 2 3
4 5 0
Satır satır dizi3'in elemanları
1 2 0
4 0 0

Şekil 6.21 Çok boyutlu dizilere atama yapmak

Program, her dizinin elemanlarını yazdırmak için diziyiYazdir fonksiyonunu (25.satırda tanımlanmıştır) çağırmaktadır. Fonksiyon tanımının, dizi parametresini const int a[ ][3] olarak belirlediğine dikkat ediniz. Tek belirteçli bir dizi fonksiyon argümanı olarak kullanıldığında, fonksiyonun parametre listesindeki dizinin parantezleri içini boş bırakıyorduk. Çok boyutlu dizilerde ilk belirtece gerek yoktur ancak sonraki diğer tüm belirteçler belirtilmelidir. Derleyici, bu belirteçleri çok boyutlu dizi elemanlarının hafıza konumlarını belirlemek için kullanır. Tüm dizi elemanları, dizinin belirteç sayısı ne olursa olsun, hafızada ard arda tutulur. İki boyutlu dizilerde hafızaya önce ilk satır daha sonra ise ikinci satır yazılır.
Belirteç değerlerini parametre bildirimlerinde belirtmek, derleyicinin fonksiyona dizideki bir elemanı nasıl bulacağını söylemesini sağlatır. İki boyutlu bir dizide her satır aslında tek belirteçli bir dizidir. Belli bir satırdaki bir elemanın konumunu belirlemek için derleyici her satırda kaç eleman bulunduğunu bilmek zorundadır. Böylece dizi elemanına ulaşırken uygun sayıda hafıza konumunu atlayabilir. Bu sebepten, örneğimizde a[1][2]'ye ulaşırken derleyici ikinci satıra ulaşabilmek için ilk satırın üç elemanını atlaması gerektiğini bilir. Daha sonra derleyici o satırın üçüncü elemanına ulaşır.
Çoğu dizi işlemi for döngü yapısını kullanır. Örneğin, aşağıdaki yapı Şekil 6.20'deki a dizisinin 3.satırındaki tüm elemanları 0'a atar.

1
2
for(sutun = 0; sutun <= 3; sutun++)
a[2][sutun]=0;

Üçüncü satırı belirledik, bu sebepten ilk belirtecin her zaman 2 olacağını biliyoruz. (0 ilk satır ve 1 ikinci satırdır) for döngüsü yalnızca ikinci belirteci değiştirmektedir (yani sütun belirtecini) Aşağıdaki ifadeler az önceki for yapısına denktir.

1
2
3
a[2][0] = 0;
a[2][1] = 0;
a[2][2] = 0;

Aşağıdaki yuvalı for yapısı, a dizisi içindeki tüm elemanların toplamını hesaplamaktadır.

1
2
3
4
5
toplam = 0;
 
for(satir = 0; satir <= 2; satir++)
for(sutun = 0; sutun <= 3; sutun++)
toplam += a [satir][sutun];

for yapısı, dizinin elemanlarını satır satır toplamaktadır. Dıştaki for yapısı satir'ı 0 yaparak başlamaktadır. Böylece içteki for yapısıyla ilk satırın elemanları toplanabilir. Dıştaki for yapısı satir'ı 1'e arttırmakta böylece ikinci satırın elemanları toplatılmaktadır. Daha sonra dıştaki for yapısı satir'ı 2'ye arttırmakta böylece üçüncü satırın elemanları toplatılmaktadır. Sonuç, yuvalı for yapısından çıkıldıktan sonra yazdırılmaktadır.
Şekil 6.22, üçe dörtlük bir ogrenciNotlari dizisindeki diğer genel işlemleri for yapısı kullanarak yapmaktadır. Dizinin her satırı bir öğrenciyi ve her sütunu öğrencinin dönem boyunca girdiği 4 sınavdan birinin sonucunu göstermektedir. Dizideki işlemler dört fonksiyon tarafından yapılmaktadır. minimum fonksiyonu (satır 35), herhangi bir öğrenci tarafından dönem boyunca alınan en düşük notu belirlemektedir. maksimum fonksiyonu herhangi bir öğrenci tarafından dönem boyunca alınan en yüksek notu belirlemektedir. ortalama (satır 63) fonksiyonu herhangi bir öğrencinin dönem ortalamasını hesaplamaktadır. diziyiYazdir fonksiyonu (satır 74) iki boyutlu diziyi çizelge biçiminde yazdırmaktadır.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/* Şekil 6.22: fig06_22.c
İki boyutlu dizi kullanan örnek */
#include <stdio.h>
#define OGRENCILER 3
#define SINAVLAR 4
 
int minimum( const int [ ][SINAVLAR], int, int );
int maksimum( const int [ ][SINAVLAR], int, int );
double ortalama( const int [ ], int );
void diziyiYazdir( const int [ ][SINAVLAR], int, int );
 
int main( )
{
int ogrenci;
const int ogrenciNotlari [OGRENCILER][ SINAVLAR] =
{ { 77, 68, 86, 73 },
{ 96, 87, 89, 78 },
{ 70, 90, 86, 81 } };
 
printf( "Dizi:\n" );
diziyiYazdir (ogrenciNotlari, OGRENCILER, SINAVLAR);
printf( "\n\nEn Düşük Not: %d\nEn Yüksek Not: %d\n",
minimum(ogrenciNotlari, OGRENCILER, SINAVLAR),
maksimum (ogrenciNotlari, OGRENCILER, SINAVLAR) );
 
for (ogrenci = 0; ogrenci <= OGRENCILER - 1; ogrenci ++ )
printf( "Öğrenci %d için ortalama not %.2f\n",
ogrenci,ortalama (ogrenciNotlari [ogrenci], SINAVLAR) );
 
return 0;
}
 
/* Minimum notu bul */
int minimum( const int notlar[][SINAVLAR],
int talebeler, int testler)
{
int i, j, dusukNot = 100;
 
for ( i = 0; i <= talebeler - 1; i++ )
for ( j = 0; j <= testler - 1; j++ )
if ( notlar[ i ][ j ] < dusukNot)
dusukNot = notlar[ i ][ j ];
 
return dusukNot;
}
 
/* maksimum notu bul */
int maksimum( const int notlar[][SINAVLAR],
int talebeler, int testler )
{
int i, j, yuksekNot = 0;
 
for ( i = 0; i <= talebeler- 1; i++ )
for ( j = 0; j <= testler - 1; j++ )
if ( notlar[ i ][ j ] > yuksekNot)
yuksekNot = notlar[ i ][ j ];
 
return yuksekNot;
}
 
/* Belirli bir sınavın ortalama notunun hesaplanması */
double ortalama( const int notlarinKumesi [], int testler )
{
int i, toplam = 0;
 
for ( i = 0; i <= testler - 1; i++ )
toplam += notlarinKumesi [ i ];
 
return ( double ) toplam / testler;
}
 
/* Diziyi yazdır */
void diziyiYazdir ( const int notlar[][SINAVLAR],
int talebeler, int testler)
{
int i, j;
 
printf( " [0] [1] [2] [3]" );
 
for ( i = 0; i <= talebeler - 1; i++ ) {
printf( "\n ogrenciNotlari [%d] ", i );
 
for ( j = 0; j <= testler - 1; j++ )
printf( "%-5d", notlar[ i ][ j ] );
}
}

Dizi:
[0] [1] [2] [3]
ogrenciNotlari[0] 77 68 86 73
ogrenciNotlari[1] 96 87 89 78
ogrenciNotlari[2] 70 90 86 81

En Düşük Not: 68
En Yüksek Not: 96
Öğrenci 0 için ortalama not 76.00
Öğrenci 1 için ortalama not 87.00
Öğrenci 2 için ortalama not 81.00

Şekil 6.22 İki boyutlu dizilerin kullanan örnek

minimum, maksimum ve diziyiYazdir fonksiyonları 3'er argüman almaktadır; ogrenciNotlari dizisi (her fonksiyonda notlar olarak adlandırılmıştır), öğrenci sayısı (dizinin satırları) ve sınav sayısı (dizinin sütunları). Her fonksiyon, notlar dizisi içinde yuvalı for yapıları sayesinde ilerlemektedir. Aşağıdaki yuvalı for yapısı, minimum fonksiyonu tanımında yer almaktadır.

for( i=0 ; i<= talebe – 1 ; i++)
for(j=0; j<= testler –1 ;j++)
if(notlar[i][j]<dusukNot)
dusukNot=notlar[i][j];

Dıştaki for yapısı i 'yi (satır belirteci) 0 yaparak başlamakta, böylece ilk satırın elemanlarının içteki for yapısının gövdesindeki dusukNot değişkeni ile karşılaştırılmasını sağlamaktadır. İçteki for yapısı o andaki satırda yer alan dört not boyunca, her notu dusukNot ile karşılaştırmaktadır. Eğer not dusukNot değişkeninin değerinden daha küçükse, dusukNot o nota atanmaktadır. Daha sonra, dıştaki for yapısı satır belirtecini arttırarak 1 yapmaktadır. Artık ikinci satırın elemanları dusukNot değişkeni ile karşılaştırılacaktır. Daha sonra, dıştaki for yapısı satır sayısını bir arttırarak 2 yapmaktadır ve böylece üçüncü satırın elemanları dusukNot değişkeniyle karşılaştırılmaktadır. Yuvalı yapıdan çıkıldığında dusukNot, iki boyutlu dizideki en küçük notu tutmaktadır. maksimum fonksiyonu minimum fonksiyonuna benzer bir biçimde çalışmaktadır.

ortalama fonksiyonu (satır 63) iki argüman alır ; notlarinKumesi olarak adlandırılan ve bir öğrencinin test sonuçlarını tutan tek belirteçli bir dizi ile dizideki test sonuçlarının sayısı. ortalama çağrıldığında fonksiyona ilk argüman ogrenciNotlari[ogrenci] geçirilir. Bu, iki boyutlu dizinin bir satırının adresinin ortalama fonksiyonuna geçirilmesine sebep olur. ogrenciNotlari[1] , dizinin ikinci satırının başlangıç adresidir. İki boyutlu bir dizinin, tek belirteçli dizilerden oluşan bir dizi olduğunu ve tek belirteçli dizinin adının, dizinin hafızadaki başlangıç adresi olduğunu hatırlayınız. ortalama fonksiyonu, dizi elemanlarının toplamını hesaplar, toplamı test sonuçları sayısına böler ve sonucu ondalıklı bir sonuç olarak döndürür.