C Programlama Diziler (Arrays)

C Programlama

Dizi (array) Nedir? 
Dizi, aynı tip verilerin birbiri arkasına tanımlanmasıdır. Dizi bir kümedir. Aynı tipte verilere tek bir isimle erişmek için kullanılır. Bir dizinin bütün elemanları bellekte peşpeşe saklanırlar. Diziler kullanılarak, aynı isimle birden fazla değişkene erişilebilir ve işlem yapılabilir. Diziler tek ya da çok boyutlu olarak tanımlanabilir ve dizi boyutu ihtiyaca göre ayarlanabilir.char, int, float ve double olarak tanımlanabilen dizilerde sadece aynı veri türünden değişken değerleri yer alabilir.

Dizileri tek boyutlu ve çok boyutlu olarak iki kısma ayırabiliriz. Tek boyutlu dizilere sayı dizilerini ve vektörleri örnek verebiliriz. Çok boyutlu dizilere ise matrisleri örnek verebiliriz..

Tek Boyutlu Diziler (one-dimensional array) : C Programlama Dilinde aynı veri tipinden olan değişkenler tek bir isim altında toplanarak tek boyutlu diziler oluşturulur. Aynı veri türünden ve farklı isimlere sahip çok fazla sayıda değişken tanımlamak yerine, dizi bildirimi yapıp tek isim kullanarak aynı sayıda değişken tanımlamak daha kolaydır.

Tek boyutlu dizilerin bildirimi için kullanılan genel yapı :  veritipi diziAdı [boyut];

Veri Tipi : Dizi elemanlarının tipini belirtir. dizi kaç elemandan oluşur ise oluşsun tipleri aynı olmak zorundadır.
Dizi Adı : Diziye programcının verecegi özerk ismi ifade eder.
Boyut : Dizilerin mutlaka bir boyutu olmak zorundadır. Dizi boyutları "[ … ]" içeriğinde tanımlanır. 

Örnek :
// Örnek Dizi Tanımlama
// 100 elemanlı ve dizi adlı bir double dizisi
double dizi[100];

Örneğimizde 100 elemandan oluşan dizi adlı bir double dizisi oluşturuluyor. Köşeli parantezle içerisindeki 100 sayısı, dizimizin 100 elemanlı olduğunu ifade etmektedir. Tek bir köşeli parantez olduğu için dizimizin tek boyutlu bir dizi olduğunu söyleyebiliriz. 

Tek Boyutlu Dizilerde Atama : Bir dizinin tanımlaması yapıldıktan sonra, atama işlemcisini kullanarak bu diziye değerler atanabilir. C Programlama Dilinde de bir dizinin ilk elemanına 0 değeri ile erişim sağlanır.

Örnek :
int dizi[30];   // 30 elemanlı dizi isimli bir dizi oluşturur. //
dizi[0] = 15;   // Dizinin ilk elemanına 15 değerini atar. //
dizi[16] = 42;  // Dizinin 17. elemanına 42 değerini atar. //

Örneğimizde İşlem Satırlarında Neler Yaptık?
Dizi isimli ve 30 elemanlı int bir dizisi oluşturuyoruz. Bilgisayar belleğinde 30 int değişkeni için yer ayrılmış oluyor. Dizinin ilk elemanına 15 sayısını ve üçüncü işlem satırında, dizinin 16. elemanına 42 sayısını atar. 

Dizi elemanları  bellekte birbirlerini takip edecek şekilde depolanırlar.  Bir tamsayı değişken bellekte 4 byte yer kaplıyorsa 5 elemanlı bir tamsayı dizisi bellekte 5x4=20 byte yer kaplayacaktır. Diziler kaç elemandan oluşursa oluşsun elemanlarının tipleri aynı olmak zorundadır.  Yani dizinin birinci elemanı double iken ikinci eleman int olamaz. Diziler sadece kendi tipinden elemanları kabul ederler. 

Örnek :
#include "stdio.h"

main()
{
  int dizi[10];
  int id1, id2;

  dizi[0] = id1 = 27;  // dizi[0] : Dizinin ilk elemanını gösterir. //
  dizi[8] = id2 = 348; // dizi[8] : Dizinin dokuzuncu elemanını gösterir. //

  printf("%d %d %d %d", id1, id2, dizi[0], dizi[8]);
}

Program Çıktısı : 

Örneğimiz öncelikle 10 elemanlık int bir dizi ve iki adet int değişken bildirimi yapar. Sonra, aynı işlem satırında dizinin ilk ve dokuzuncu elemanlarına atadığı değerleri aynı zamanda int değişkenlere atar. Daha sonra bu değerleri ekrana yazar. 

Örnek :
#include "stdio.h"

main()
{
    char soyad[10];         // Bir karakter dizisi tanimlayalim //
    soyad[0] = 'B';
    soyad[1] = 'A';
    soyad[2] = 'Y';
    soyad[3] = 'R';
    soyad[4] = 'A';
    soyad[5] = 'K';
    soyad[6] = 'T';
    soyad[7] = 'A';
    soyad[8] = 'R';
    soyad[9] = 0;             // Bos karakter - stringin sonu //
    printf("Soyadi %s dir. \n",soyad);
    printf("Icinden bir karakter: %c\n",soyad[2]);
    printf("Soyadinin bir parcasi: %s \n",&soyad[3]);
}

Program Çıktısı : 

Tek Boyutlu Dizilerin Bellekte Yerleşimi : Tek boyutlu dizilerin bütün elemanları, ilk elemanı en düşük adrese gelecek şekilde, bellekte birbirlerine birleşik olarak yerleştirilir.

Örnek :
#include "stdio.h"

main()
{
  int idizi[5];
  int id1, id2;

  for (id1=0, id2=3; id1<5; id1++, id2+=3) {
       idizi[id1] = id2;
    printf("%d ", idizi[id1]);
  }

  printf("\n%d %d", idizi[4], idizi[4] * idizi[4]);
}

Program Çıktısı : 
Örneğimizde önce 5 elemanlık int bir dizi ve 2 adet int değişken bildirimi yapılıyorç Sonra, bir for döngüsü ile,  dizinin elemanlarına 3'ten 15'e kadar olan sayıları 3'er arayla sırasıyla atar ve ekrana yazar. Daha sonra, dizinin son değerini ve karesini ekrana yazar.

Tek Boyutlu Dizilerde Yazdırma ve Okuma : printf ve scanf fonksiyonları bir dizinin okunması ve yazdırılması için kullanılır. scanf() fonksiyonunu kullanarak dizi elemanlarına klavyeden girilen değerler de atanabilir. Böylelikle dışarıdan girilen değerler dizi elemanlarına atanarak kullanabilir.  

Örneğin bir X dizisinin int X[10];  şeklinde bildirildiğini varsayalım. 

Bu dizinin elemanlarını klavyeden okumak için: 
for (i=0; i<10; i++)
scanf ("%d",&X[i]); 

Daha sonra değerleri ekrana yazmak için: 
for (i=0;i<10;i++)
printf("%d\n",X[i]);

Örnek :
#include "stdio.h"

main()
{
  int idizi[10];
  int id1, id2;

  for (id1=0; id1<10; id1++) {
       idizi[id1] = id1;
       printf("%d ", idizi[id1]);
  }

  printf("\n");

  printf("Lutfen bir sayi giriniz: ");
  scanf("%d", &id2);

  for (id1=0; id1<10; id1++) {
       idizi[id1] += id2;
       printf("%d ", idizi[id1]);
  }
}

Program Çıktısı : 
 
Örneğimizde, program oluşturduğu 10 elemanlı bir diziye 0-9 arasındaki sayıları sıra ile atar ve printf fonksiyonu ile ekrana yazar. Sonra, klavyeden girilen int değeri her dizi elemanına ekleyerek, dizi eleman değerlerini tekrar ekrana yazar.

Karakter Dizileri : C Programlama Dilinde karakter dizisi olarak tanımlanan bir veri çeşidi yoktur. Karakter dizisi veri desteğini sağlamak için tek boyutlu char diziler olarak kullanılır. Karakter dizisi NULL(0) değer ile sona eren bir char dizidir.

C Programlama Dilinde klavyeden girilecek olan karakter dizileri standart bir kütüphane fonksiyonu olan gets() fonksiyonu ile okutulur. Bu fonksiyon stdio.h başlık dosyasını kullanır.

Örnek 1 :
#include "stdio.h"
#include "conio.h"

main()
{
  char chdizi[20];

  printf("Bir karakter dizisi giriniz (20 karakterden az) :\n");
  gets(cdizi);

  printf("\n%s", chdizi);

getch ();
}

Örneğimizde program 20 elemanlık bir karakter dizi bildirimi yaptıktan sonra 20 karakterden az bir karakter dizisi girilmesini ister. Girilen karakter dizisini chdizi adlı diziye atar. Son olarak chdizi dizisini printf fonksiyonu ile ekrana yazar.

Örnek 2 :
#include "stdio.h"
#include "conio.h"

main()
{
  char chdizi[20];
  int id1;

  printf("Bir karakter dizisi giriniz (20 karakterden az) :\n");
  gets(chdizi);

  printf("\n%s\n", chdizi);
  printf(chdizi);
  printf("\n");
  for (id1=0; chdizi[id1]; id1++) printf("%c", chdizi[id1]);

getch ();
}

2.Örneğimizde program klavyeden girilen karakter dizisini chdizi adlı diziye atadıktan sonra, önce printf() fonksiyonu ve %s format tanımlayıcısı, sonra sadece printf() fonksiyonu ve en son olarak bir for döngüsüyle her defasında bir karakter olmak üzere diziyi ekrana yazar. for döngüsü içindeki chdizi[id1] koşulu dizideki karakter dizisi sonunda bulunan NULL(0) değerine ulaştığı zaman döngü sonlanır. 

Örnek 3  Bir karakter dizisinin uzunluğunu bulmak : 
#include "stdio.h"
#include "conio.h"

int main(void)
{
   char s[40];
   int  k = 0;

   printf("Bir seyler yazin : ");
   gets(s);

   while( s[k]!='\0' )
      k++;

   printf("Dizinin uzunlugu : %d\n",k);

getch ();
}

Programın Çıktısı : 

Örnek 4  Bir karakter dizisinin tersini bulmak : 
#include "stdio.h"
#include "conio.h"

int main(void)
{
   char s[40], gecici;
   int  i, n;

   printf("Bir seyler yazin : ");
   gets(s);

   for(n=0; s[n] != '\0'; n++)
      ;

   for(i=0; i<n/2; i++){
      gecici   = s[n-i-1];
      s[n-i-1] = s[i];
      s[i]     = gecici;
   }

   printf("Tersi : %s\n",s);

getch ();
}

Programın Çıktısı : 

Tek Boyutlu Dizilerde Sıralama (Sorting) : Dizilerde sıralama işlemini veren bir çok algoritma ( QuickSort, Insertion, Shell Sort, vs… ) vardır. Bu sıralama algoritmalarının kendilerine göre algoritmik olarak (hız, kullanılan bellek alanı vs....) avantajları ve dezavantajları vardır. Burada iç içe döngüler içeren bu algoritmalardan kavraması en kolay olan kabarcık yani bubble sort algoritmasını göreceğiz.

Örneğin bir sayı dizisi olsun ve bu dizinin elemanlarını büyükten küçüğe sıralamamız gereksin. Bubble sort algoritmasında dizide eğer n tane eleman varsa dıştaki döngü diziyi n-1 kare tarar. Dizi elemanlarının birbirleriyle karşılaştırılmasını ise içteki döngü gerçekleştirir. İçteki döngü bitişik dizi elemanlarını karşılaştırır ve eğer önceki eleman sonraki elemandan küçükse bu iki elemanı yer değiştirir. Yer değiştirme işleminde C Programlama dilinde swap adı verilir. Swap işlemi kısaca iki değişkenin değerlerinin üçüncü bir geçici değişken yardımıyla yer değiştirmesidir.

Örnek 1 : Kabarcık Sıralama (Bubble Sort) Algoritması ile birdizinin elemanlarını büyükten küçüğe dogru sıralayan bir C Programı
#include <stdio.h>
#define n 10

int main(void)
{
   int   a[n] = {100, -250, 400, 125 ,550, 900, 689, 450, 347, 700};
   int   j,k,gecici;

   /* Dizinin kendisi */
   printf("Once : ");
   for(k=0; k<n; k++)
      printf("%5d ",a[k]);

   /* Sırala */
   for(k=0; k<n-1; k++)
   for(j=0; j<n-1; j++)
      if( a[j]<a[j+1] ){
         gecici = a[j];
           a[j] = a[j+1];
         a[j+1] = gecici;
      }

   /* Sıralama bitti */
   printf("\nSonra: ");
   for(k=0; k<n; k++)
      printf("%5d ",a[k]);

   printf("\n");

  return 0;
}

Program Çıktısı :

Çeşitli sıralama algoritmaları için kaynak siteler :
Çok Boyutlu Diziler (Multidimensional Arrays): C Programlama Dilinde diziler birden fazla boyuta sahip olabilirler. Çok boyutlu dizileri elemanları dizilerden oluşan diziler olarak düşünebiliriz. Aşağıdaki işlem satırlarının ilki tek boyutlu, ikincisi iki boyutlu ve üçüncüsü ise üç boyutlu bir dizi tanımlar. Çok boyutlu dizi tanımlamanın, tek boyutlu dizi tanımlamaktan yapı olarak büyük bir farkı yoktur. Diziye eklenen her bir boyut için yine [] işaretleri arasında bir sayı tanımlanmaktadır. Çok boyutlu bilgileri veya veri tablolarını saklamak için kullanılırlar.

Çok boyutlu dizilerin bildirimi için kullanılan genel yapı : 
veritipi diziAdı [boyut1] [boyut2] [boyut3]…


Çok Boyutlu Dizilerde Atama :

Örnek :
#include "stdio.h"
#include "conio.h"

main()
{
  int idizi[3][4];

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

  printf("%d %d %d %d %d\n", idizi[0][0], idizi[0][1], idizi[0][2], idizi[0][3]);
  printf("%d %d %d %d %d\n", idizi[1][0], idizi[1][1], idizi[1][2], idizi[1][3]);
  printf("%d %d %d %d %d\n", idizi[2][0], idizi[2][1], idizi[2][2], idizi[2][3]);

getch ();
}

Örneğimizde 3*4'lük ve 12 elemanlık iki boyutlu int bir dizi tanımlar. 1 sayısı ile gösterilen işlem satırında dizinin ilk satırındaki elemanlara 1 değerini, 2 sayısı ile gösterilen işlem satırında dizinin ikinci satırında yer alan elemanlara 2 değerini, 3 sayısı ile gösterilen işlem satırında ise dizinin üçüncü satırındaki elemanlara 3 değerini atar. Daha sonra printf() fonksiyonunun kullanıldığı işlem satırları ile dizinin satırlarını sırasıyla ekrana yazar.

Çok boyutlu diziler tek boyutlu diziler gibi bellekte tutulurlar. Tek boyutlu dizilerde olduğu gibi, çok boyutlu dizilerde de başlangıç değeri vermek mümkündür. Örneğin 3 satır ve 4 sütünlu (3x4=12 elemanlı) bir x matrisinin elemanları şöyle tanımlanabilir:

int x[3][4] = {11,34,42,60, 72,99,10,50, 80,66,21,38};
yada
int x[3][4] = {11,34,42,60,
                       72,99,10,50,
                       80,66,21,38};

Bu matris ekrana matris formunda yazılmak istendiğinde:
for(i=0; i<3; i++)
{
for(j=0; j<4; j++)
printf("%4d",x[i][j]);
}

Örnek İki matrisin toplamını bulan bir C Programı :
#include <stdio.h>
#include <conio.h>
#define SAT 2
#define SUT 3

int main()
{
    int a[SAT][SUT] = {5, 3, 7,  0, 1, 2};

    int b[SAT][SUT] = {1, 2, 3,  4, 5, 6};
    int c[SAT][SUT];
    int i, j;

    puts("A Matrisi:");
    for(i=0; i<SAT; i++){
      for(j=0; j<SUT; j++)
         printf("%4d",a[i][j]);
      printf("\n");
    }

    puts("B Matrisi:");
    for(i=0; i<SAT; i++){
      for(j=0; j<SUT; j++)
         printf("%4d",b[i][j]);
      printf("\n");
    }

    puts("\nC Matrisi:");
    for(i=0; i<SAT; i++){
       for(j=0; j<SUT; j++){
         c[i][j] = a[i][j] + b[i][j];
         printf("%4d",c[i][j]);
       }
       printf("\n");
    }

getch ();
}


Örnek Tek boyutlu bir diziyi iki boyutlu matrise çeviren bir C Programı :
#include <stdlib.h>
#include <conio.h>
int main()
{
    int dizi[100];
    int a[100][100];
    int i, j, n, x, st, su;
    printf("Dizi kac elemandan olusmali : ");
    scanf("%d",&n);
    for(x=0; x<n; x++)
    {
        printf("Dizinin [%d] . elemanini giriniz : ",x+1);
        scanf("%d",&dizi[x]);
    }
    printf("\nDizi elemanlari -->\n" );
    for(x=0; x<n; x++)
    {
        printf("%3d",dizi[x]);
    }
    printf("\nMatrisin Satir sayisini giriniz : ");
    scanf("%d",&st);
    printf("\nMatrisin Sutun sayisini giriniz : ");
    scanf("%d",&su);
    if(n%st==0 && n%su==0)
    {
        x=0;
        for(i=0; i<st; i++)
        {
            for (j=0; j<su; j++)
            {
                a[i][j]=dizi[x];
                x++;
            }
        }
        printf("\n\nMATRIS > \n");
        for(i=0; i<st; i++)
        {
            for(j=0; j<su; j++)
            {
                printf("%3d", a[i][j]);
            }
            printf("\n");
        }
    }
    else
        printf("HATA! Dizi Eleman Sayisi Satir veya Sutuna Tam bolunmelidir");
    getch ();
}