C Programlama Dersi – XI

Bu yazıda öğrenecekleriniz:

Diziler

Bir bilgisayar programı yaptığınızı düşünün. Kullanıcının 100 değer girmesiisteniyor. Girilen bütün bu sayıların farklı aşamalardan geçeceğini ve bu yüzdenhepsini ayrı bir değişkende tutmamız gerektiğini varsayalım. Bu durumda neyapardınız? a0, a1, a2, …, a99 şeklinde 100 tane değişken tanımlamak elbettemümkün; ama oldukça zahmetli olurdu. Sırf değişkenleri tanımlarken kaybedeceğinizzamanı düşünürseniz ne demek istediğimi anlarsınız. Bunun için alternatif birçözümün gerektiği mutlak!

Çok sayıda değişkenin gerektiği durumlarda, diziler imdadımıza yetişir. (Dizi, İngilizce kaynaklarda array olarak geçer.) 100 değişken tanımlamamızın gerektiğiyukardaki örneğe dönelim. Tek tek a0, …, a100 yaparak bunu nasıl yazacağınızı zaten biliyorsunuz. Şimdi tek satırda dizi tanımlayarak, bunu nasıl yapacağımızı görelim:
int a[100];

Yukardaki tek satır, bellek bloğunda 100 adet int değişken yeri ayırır. Tek satırkod elbette açıklayıcı değil, o yüzden bunu aşağıdaki şekille açıklayalım:

[Array Definiton]

Her şeyin başında dizideki elemanların değişken tipini yazıyoruz; buradakiörneğimizde tam sayı gerektiği için ‘int’ yazdık. Daha sonra diziye ‘a’ yazarakbir isim veriyoruz. Değişkenleri nasıl isimlendiriyorsak, aynı kurallar diziler içinde geçerli… Son aşamada bu dizinin kaç eleman içereceğini belirtiyoruz. Köşeliparantezler ( [ ] ) içinde yazdığımız 100 sayısı, 100 adetint tipinde değişkenin oluşturulmasını sağlıyor.

Bir değişkene ulaşırken, onun adını yazarız. Dizilerde de aşağı yukarı böyle sayılır.Fakat ufak farklar vardır. Bir dizi, birden çok elemandan oluşur. Bu yüzden sadecedizi adını yazmaz, ulaşmak istediğimiz elemanı da yer numarasını yazarak belirtiriz.Örneğin a dizisinin, 25.elemanı gerekiyorsa, a[24] ile çağrılır. Sanırım 25 yerine 24yazıldığını fark etmişsinizdir. C programlama dilinde, dizilerin ilk elemanı 0’dır. Diziler 0’dan başladığı için, ulaşmak istenilen dizi elemanı hangisiysebir eksiğini yazarız. Yani a dizisinin 25.elemanı, a[24]; 100.elemanı a[99] ileçağırırız.

Şimdi basit bir örnek yapalım. Bu örnekte, her aya ait güneşli gün sayısı sorulsunve sonunda yıllık güneşli gün sayısı yazılsın.
#include<stdio.h>
int main( void )
{
// Aylari temsil etmesi icin
// aylar adinda 12 elemanli
// bir dizi olusturuyoruz.
int aylar[ 12 ];
int toplam = 0;
int i;

// Birinci dongu, deger atamak icindir
for( i = 0; i < 12; i++ ) {
printf( “%2d.Ay: “, (i+1) );
// aylara deger atıyoruz:
scanf( “%d”, &aylar[ i ] );
}

// Az evvel girilen degerleri gostermek icin
// ikinci bir dongu kurduk
printf( “\nGİRDİĞİNİZ DEĞERLER\n\n” );
for( i = 0; i < 12; i++ ) {
printf( “%2d.Ay için %d girdiniz\n”, (i+1), aylar[i] );
toplam += aylar[ i ];
}

printf( “Toplam güneşli gün sayısı: %d\n”, toplam );
return 0;
}

Örneğimizi inceleyelim. En başta 12 elemanlı aylar dizisini,”int aylar[12]” yazarak tanımlıyoruz. Her ay için değer girilmesini gerekiyor.Klavyeden girilen sayıların okunması için elbette scanf( ) fonksiyonunukullanacağız ama ufak bir farkla! Eğer ‘a’ isimde bir değişkene atama yapıyorolsaydık, hepinizin bileceği şekilde “scanf(“%d”, &a )” yazardık.Fakat dizi elemanlarına atama yapılacağından komutu,”scanf( “%d”, &aylar[ i ] )” şeklinde yazmamızgerekiyor. Döngü içindeki i değişkeni, 0’dan 11’e kadar sırasıyla artıyor.Bu sayede, döngünün her adımında farklı bir dizi elemanına değer atıyabiliyoruz.( i değişkeni, bir nevi indis olarak düşünülebilir. ) Klavyedenokunan değerlerin dizi elemanlarına atanmasından sonra, ikinci döngü başlıyor. Budöngüde girmiş olduğunuz değerler listelenip, aynı esnada toplam güneşli gün sayısı bulunuyor. Son aşamada, hesaplanan toplam değerini yazdırıp, programı bitiriyoruz.

Dikkat ederseniz, değerlerin alınması veya okunması gibi işlemler döngüleraracılığıyla yapıldı. Bunları döngüler aracılığı ile yapmak zorunda değildik.Mesela “scanf(“%d”, &aylar[5] )” yazıp, 6.ayın değerini;”scanf(“%d”, &aylar[9] )” yazıp, 10.ayın değerini klavyedenalabilirdik. Ancak böyle yapmak, döngü kullanmaktan daha zahmetlidir. Yanılgıyadüşmemeniz için döngüleri kullanmanın kural olmadığını, sadece işlerikolaylaştırdığını hatırlatmak istedim. Gerek tek tek, gerekse örnekte yaptığımızgibi döngülerle çözüm üretebilirsiniz.

Başka bir örnek yapalım. Kullanıcımız, float tipinde 10 adet değer girsin. Öncebu değerlerin ortalaması bulunsun, ardından kaç adet elemanın ortalamanın altındakaldığı ve kaç adet elemanın ortalamanın üstünde olduğu gösterilsin.
#include<stdio.h>
int main( void )
{
// Degerleri tutacagimiz ‘dizi’
// adinda bir dizi olusturuyoruz.
float dizi[ 10 ];
float ortalama, toplam = 0;
int ortalama_ustu_adedi = 0;
int ortalama_alti_adedi = 0;
int i;

// Kullanici dizinin elemanlarini giriyor:
for( i = 0; i < 10; i++ ) {
printf( “%2d. elemanı giriniz> “, (i+1) );
scanf( “%f”, &dizi[ i ] );
toplam += dizi[ i ];
}

// dizinin ortalamasi hesaplaniyor.
ortalama = toplam / 10.0;

// ortalamadan kucuk ve buyuk elemanlarin
// kac adet oldugu belirleniyor.
for( i = 0; i < 10; i++ ) {
if( dizi[ i ] < ortalama )
ortalama_alti_adedi++;
else if( dizi[ i ] > ortalama )
ortalama_ustu_adedi++;
}

// raporlama yapiliyor.
printf( “Ortalama: %.2f\n”, ortalama );
printf( “Ortalamadan düşük %d eleman vardır.\n”, ortalama_alti_adedi );
printf( “Ortalamadan yüksek %d eleman vardır.\n”, ortalama_ustu_adedi );

return 0;
}

Program pek karmaşık değil. Dizi elemanlarını alıyor, ortalamalarını hesaplıyor,elemanları ortalamayla karşılaştırıp, ortalamadan büyük ve küçük elemanlarınadedini veriyoruz. Anlaşılması güç bir şey bulacağınızı sanmıyorum. Tek karmaşıkgelecek nokta, ikinci döngüde neden bir else olmadığı olabilir. Oldukçageçerli bir sebebi var ve if else-if yapısını iyice öğrenenler böylebırakılmasını anlayacaklardır. Bilmeyenlere gelince… her şeyi ben söylersem, işintadı tuzu kalmaz; eski konuları gözden geçirmelisiniz.

Dizilere İlk Değer Atama

Değişken tanımı yaparken, ilk değer atamayı biliyoruz. Örneğin “int a = 5;” şeklinde yazacağınız bir kod, a değişkenini oluşturacağı gibi, içine 5değerini de atayacaktır. ( Bu değişkene, tanımladıktan sonra farklı değerleratayabilirsiniz. ) Benzer şekilde, bir diziyi tanımlarken, dizininelemanlarına değer atayabilirsiniz. Aşağıda bunu nasıl yapabileceğinizigörebilirsiniz:
int dizi1[ 6 ] = { 4, 8, 15, 16, 23, 42 };
float dizi2[ 5 ] = { 11.5, -1.6, 46.3, 5, 21.56 };

Küme parantezleri içinde gördüğünüz her değer, sırasıyla bir elemana atanmıştır.Örneğin dizi1’in ilk elemanı 4 olurken, son elemanı 42’dir.

Yukardaki tanımlamalarda farkedeceğiniz gibi dizi boyutlarını 6 ve 5 şeklindebelirttik. İlk değer ataması yapacağımız durumlarda, dizinin boyutunu belirtmenizgerekmez; dizi boyutunu yazıp yazmamak size bağlıdır. Dilerseniz dizi boyutunubelirtmeden aşağıdaki gibi de yazabilirdiniz:
int dizi1[ ] = { 4, 8, 15, 16, 23, 42 };
float dizi2[ ] = { 11.5, -1.6, 46.3, 5, 21.56 };

Derleyici, atanmak istenen değer sayısına bakar ve dizi1 ile dizi2’ninboyutunu buna göre belirler. dizi1 için 6, dizi2 için 5 tane değerbelirtmişiz. Bu dizi1 dizisinin 6, dizi2 dizisinin 5 elemanlı olacağını işaret eder.

Değer atamayla ilgili ufak bir bilgi daha aktarmak istiyorum. Aşağıda iki farklı ilk değer atama yöntemi bulunuyor. Yazım farkı olmasına rağmen, ikisi de aynı işiyapar.
int dizi[ 7 ] = { 0, 0, 0, 0, 0, 0, 0 };

int dizi[ 7 ] = { 0 };

Bir diziyi tanımlayın ve hiçbir değer atamadan, dizinin elemanlarını printf( ) fonksiyonuyla yazdırın. Ortaya anlamsız sayılar çıktığını göreceksiniz. Bir dizi tanımlandığında, hafızada gerekli olan yer ayrılır.Fakat daha önce bu hafıza alanında ne olup olmadığıyla ilgilenilmez. Ortaya çıkananlamsız sayılar bundan kaynaklanır. Önceden hafızada bulunan değerlerin yansımasını görürsünüz. Modern programlama dillerinin bir çoğunda, dizi tanımladığınızda,dizinin bütün elemanları 0 değeriyle başlar; sizin herhangi bir atama yapmanızagerek yoktur. C programlama dilindeyse, kendiliğinden bir başlangıç değeri atanmaz.Bunu yapıp yapmamak size kalmıştır. Kısacası işlerin daha kontrolü gitmesiniistiyorsanız, dizileri tanımlarken “dizi[ 7 ] = { 0 };” şeklinde tanımlamalaryapabilirsiniz.

İlk değer atanmasıyla ilgili bir örnek yapalım. 10 elemanlı bir diziye atadığımızilk değerin maksimum ve minimum değerleri gösterilsin:
#include<stdio.h>
int main( void )
{
// dizi’yi tanitirken, ilk deger
// atiyoruz
int dizi[ ] = { 15, 54, 1, 44, 55,
40, 60, 4, 77, 45 };
int i, max, min;

// Dizinin ilk elemanini, en kucuk
// ve en buyuk deger kabul ediyoruz.
// Bunun yanlis olmasi onemli degil;
// sadece bir noktadan kontrole baslamamiz
// gerektiginden boyle bir secim yaptik.
min = dizi[ 0 ];
max = dizi[ 0 ];

for( i = 1; i < 10; i++ ) {
// min’in degeri, dizi elemanindan
// buyukse, min’in degerini degistiririz.
// Kendisinden daha kucuk sayi oldugunu
// gosterir.
if( min > dizi[i] )
min = dizi[i];

// max’in degeri, dizi elemanindan
// kucukse, max’in degerini degistiririz.
// Kendisinden daha buyuk sayi oldugunu
// gosterir.
if( max < dizi[i] )
max = dizi[i];
}

printf( “En Küçük Değer: %d\n”, min );
printf( “En Büyük Değer: %d\n”, max );

return 0;
}

Dizilerin fonksiyonlara aktarımı

Dizileri fonksiyonlara aktarmak, tıpkı değişkenleri aktarmaya benzemektedir. Uzunuzadıya anlatmak yerine, örnek üstünden gitmenin daha fayda olacağını düşünüyorum.Bir fonksiyon yazalım ve bu fonksiyon kendisine gönderilen dizinin elemanlarını ekrana yazsın.
#include<stdio.h>
void elemanlari_goster( int [ 5 ] );
int main( void )
{
int dizi[ 5 ] = { 55, 414, 7, 210, 15 };
elemanlari_goster( dizi );
return 0;
}
void elemanlari_goster( int gosterilecek_dizi[ 5 ] )
{
int i;
for( i = 0; i < 5; i++)
printf( “%d\n”, gosterilecek_dizi[ i ] );
}

Fonksiyon prototipini yazarken, dizinin tipini ve boyutunu belirttiğimizifark etmişsinizdir. Fonksiyonu tanımlama aşamasında, bunlara ilaveten parametreolarak dizinin adını da yazıyoruz. ( Bu isim herhangi bir şey olabilir,kendisine gönderilecek dizinin adıyla aynı olması gerekmez. ) Bir dizi yerinesıradan bir değişken kullansaydık, benzer şeyleri yapacaktık. Farklı olan teknokta; dizi eleman sayısını belirtmemiz. Şimdi main( ) fonksiyonunadönelim ve elemanlari_goster( ); fonksiyonuna bakalım. Anlayacağınızgibi, “dizi” ismindeki dizinin fonksiyona argüman olarak gönderilmesi içinsadece adını yazmamız yeterli.

Fonksiyonlarla ilgili bir başka örnek yapalım. Bu sefer üç fonksiyon oluşturalım.Birinci fonksiyon kendisine gönderilen dizideki en büyük değeri bulsun; ikincifonksiyon, dizinin en küçük değerini bulsun; üçüncü fonksiyon ise elemanlarınortalamasını döndürsün.
#include<stdio.h>
float maksimum_bul( float [ 8 ] );
float minimum_bul( float [ 8 ] );
float ortalama_bul( float [ 8 ] );
int main( void )
{
// 8 boyutlu bir dizi olusturup buna
// keyfi degerler atiyoruz.
float sayilar[ 8 ] = { 12.36, 4.715, 6.41, 13,
1.414, 1.732, 2.236, 2.645 };
float max, min, ortalama;
// Ornek olmasi acisindan fonksiyonlar
// kullaniliyor.
max = maksimum_bul( sayilar );
min = minimum_bul( sayilar );
ortalama = ortalama_bul( sayilar );
printf( “Maksimum: %.2f\n”, max );
printf( “Minimum: %.2f\n”, min );
printf( “Ortalama: %.2f\n”, ortalama );

return 0;
}
/* Dizi icindeki maksimum degeri bulur */
float maksimum_bul( float dizi[ 8 ] )
{
int i, max;
max = dizi[0];
for( i = 1; i < 8; i++ ) {
if( max < dizi[ i ] )
max = dizi[ i ];
}
return max;
}
/* Dizi icindeki minimum degeri bulur */
float minimum_bul( float dizi[ 8 ] )
{
int i, min;
min = dizi[ 0 ];
for( i = 1; i < 8; i++ ) {
if( min > dizi[ i ] ) {
min = dizi[ i ];
}
}
return min;
}
/* Dizi elemanlarinin ortalamasini bulur */
float ortalama_bul( float dizi[ 8 ] )
{
int i, ortalama = 0;
for( i = 0; i < 8; i++ )
ortalama += dizi[ i ];

return ortalama / 8.0;
}

Yukardaki örneklerimizde, dizilerin boyutlarını bilerek fonksiyonlarımızı yazdık.Ancak gerçek hayat böyle değildir; bir fonksiyona farklı farklı boyutlarda dizilergöndermeniz gerekir. Mesela ortalama_bul( ) fonksiyonu hem 8 elemanlı bir diziye hizmet edecek, hem de 800 elemanlı bir başka diziye uyacak şekildeyazılmalıdır. Son örneğimizi her boyutta dizi için kullanılabilecek hâle getirelimve ortalama_bul( ), minimum_bul( ) ve maksimum_bul( ) fonksiyonlarını biraz değiştirelim.
#include<stdio.h>
float maksimum_bul( float [ ], int );
float minimum_bul( float [ ], int );
float ortalama_bul( float [ ], int );
int main( void )
{
// 8 boyutlu bir dizi olusturup buna
// keyfi degerler atiyoruz.
float sayilar[ 8 ] = { 12.36, 4.715, 6.41, 13,
1.414, 1.732, 2.236, 2.645 };
float max, min, ortalama;
// Ornek olmasi acisindan fonksiyonlar
// kullaniliyor.
max = maksimum_bul( sayilar, 8 );
min = minimum_bul( sayilar, 8 );
ortalama = ortalama_bul( sayilar, 8 );
printf( “Maksimum: %.2f\n”, max );
printf( “Minimum: %.2f\n”, min );
printf( “Ortalama: %.2f\n”, ortalama );

return 0;
}
/* Dizi icindeki maksimum degeri bulur */
float maksimum_bul( float dizi[ ], int eleman_sayisi )
{
int i;
float max;
max = dizi[0];
for( i = 1; i < eleman_sayisi; i++ ) {
if( max < dizi[ i ] )
max = dizi[ i ];
}
return max;
}
/* Dizi icindeki minimum degeri bulur */
float minimum_bul( float dizi[ ], int eleman_sayisi )
{
int i;
float min;
min = dizi[ 0 ];
for( i = 1; i < eleman_sayisi; i++ ) {
if( min > dizi[ i ] ) {
min = dizi[ i ];
}
}
return min;
}
/* Dizi elemanlarinin ortalamasini bulur */
float ortalama_bul( float dizi[ ], int eleman_sayisi )
{
int i;
float ortalama = 0;
for( i = 0; i < eleman_sayisi; i++ )
ortalama += dizi[ i ];

return ortalama / 8.0;
}

Fonksiyonlara dikkatlice bakın. Geçen sefer sadece dizi adını gönderirken, artıkdizi adıyla birlikte boyutunu da yolluyoruz. Böylece dizinin boyutu n’olursaolsun, fark etmiyor. Yeni bir parametre açıp dizinin eleman sayısını isterseniz,fonksiyon her dizi için çalışabilir.

Dizilere Pointer ile Erişim

Pointer’ların değişkenleri işaret etmesini geçen dersimizde işlemiştik. Benzer şekilde dizileri de işaret edebilirler. Örneğin, int dizi[6]; şeklindetanımlanmış bir diziyi, pointer ile işaret etmek istersek, ptr = dizi; yazmamız yeterlidir. Değişkenlerde, değişken adının başına ‘&’ işaretigetiriyorduk, fakat dizilerde buna gerek yoktur. Çünkü dizilerin kendisi debir pointer’dır. Dizilerin hepsi hafıza alanında bir başlangıç noktası işaret eder.Örnek olması açısından bu noktaya 6066 diyelim. Siz “dizi[0]” dediğinizzaman 6066 ile 6068 arasında kalan bölgeyi kullanırsınız. Ya da “dizi[4]”dediğiniz zaman 6074 ile 6076 hafıza bölgesi işleme alınır.

Bir diziyi işaret eden pointer aynen dizi gibi kullanılabilir. Yani ptr = dizi; komutunu vermenizden sonra, ptr[0] ile dizi[0] birbirininaynısıdır. Eğer *ptr yazarsanız, yine dizinin ilk elemanı dizi[0]’ı işaret etmiş olursunuz. Ancak dizi işaret eden pointer’lar genellikle,*( ptr + 0 ) şeklinde kullanılır. Burada 0 yerine ne yazarsanız,dizinin o elemanını elde ederseniz. Diyelim ki, 5.elemanı ( yani dizi[ 4 ] ) kullanmak istiyorsunuz, o zaman*( ptr + 4 ) yazarsanız. Bir resim, bin sözden iyidir…Aşağıdaki resmi incelerseniz, durumu daha net anlayacağınızı düşünüyorum.

[Pointer to Array Sample]

Gördüğünüz gibi dizi, 6066 numaralı hafıza adresini işaret ediyor. ptr isimli pointer ise, dizi üzerinden 6066 numaralı adresi gösteriyor.Kısacası ikisi de aynı noktayı işaret ediyorlar. Şimdi bunu koda dökelim:
#include<stdio.h>
int main( void )
{
int i;
// dizi’yi tanimliyoruz.
int dizi[ 6 ] = { 4, 8, 15, 16, 23, 42 };
// ptr adinda bir pointer tanimliyoruz.
int *ptr;
// ptr’nin dizi’yi isaret etmesini soyluyoruz.
ptr = dizi;
// ptr’in degerini artirip, dizi’nin butun
// elemanlarini yazdiriyoruz.
for( i = 0; i < 6; i++ )
printf( “%d\n”, *( ptr + i ) );

return 0;
}

Pointer’lar farklı şekillerde kullanılabilir. Her defasında, dizinin başlangıçelemanını atamanız gerekmez. Örneğin, ptr = &dizi[ 2 ] şeklindebir komut kullanarak, dizinin 3.elemanının adresini pointer’a atayabilirsiniz.Pointer’larin değişik kullanım çeşitlerini aşağıda görebilirsiniz:
#include<stdio.h>
int main( void )
{
int elm;
int month[ 12 ];
int *ptr;
ptr = month; // month[0] adresini atar
elm = ptr[ 3 ]; // elm = month[ 3 ] değerini atar
ptr = month + 3; // month[ 3 ] adresini atar
ptr = &month[ 3 ]; // month[ 3 ] adresini atar
elm = ( ptr+2 )[ 2 ]; // elm = ptr[ 4 ] ( = month[ 7 ] )değeri atanır.
elm = *( month + 3 );
ptr = month;
elm = *( ptr + 2 ); // elm = month[ 2 ] değerini atar
elm = *( month + 1 ); // elm = month[ 1 ] değerini atar

return 0;
}

Dizilerin fonksiyonlara gönderilmesini görmüştük. Parametre kısmına dizinin tipinive boyutunu yazıyorduk. Ancak bunun yerine pointer da kullanabiliriz. Örneğinaşağıdaki iki komut satırı birbirinin aynısıdır.
int toplam_bul( int dizi[ ], int boyut );

int toplam_bul( int *dizi, int boyut );

Fonksiyondan Dizi Döndürmek

Fonksiyondan bir diziyi döndürmeden önce önemli bir konuyla başlayalım.Hatırlarsanız fonksiyonlara iki şekilde argüman yolluyorduk. Birinci yöntemde,sadece değer gidiyordu ve değişken üzerinde bir değişiklik olmuyordu.( Call by Value ) İkinci yöntemdeyse, yollanılan değişken, fonksiyoniçersinde yapacağınız işlemlerden etkileniyordu. ( Call by Reference )Dizilerin aktarılması, referans yoluyla olur. Fonksiyon içersinde yapacağınız birdeğişiklik, dizinin aslında da değişikliğe sebep olur. Aşağıdaki örneğe bakalım:
#include<stdio.h>
/* Kendisine verilen dizinin butun
elemanlarinin karesini alir */
void karesine_donustur( int [ ], int );
int main( void )
{
int i;
int liste[ ] = { 1,2,3,4,5,6,7 };
for( i = 0; i < 7; i++ ) {
printf( “%d “, liste[ i ] );
}
printf(“\n”);

// Fonksiyonu cagiriyoruz. Fonksiyon geriye
// herhangi bir deger dondurmuyor. Diziler
// referans yontemiyle aktarildigi icin dizinin
// degeri bu sekilde degismis oluyor.
karesine_donustur( liste, 7 );
for( i = 0; i < 7; i++ ) {
printf( “%d “, liste[ i ] );
}
printf(“\n”);
return 0;
}
void karesine_donustur( int dizi[ ], int boyut )
{
int i;
for( i = 0; i < boyut; i++ ) {
dizi[ i ] = dizi[ i ] * dizi[ i ];
}
}

Gördüğünüz gibi fonksiyon içersinde diziyle ilgili yaptığımız değişikler,dizinin aslına da yansımıştır. Sırada, fonksiyondan dizi döndürmek var.

Aslında fonksiyondan dizi pek doğru bir isimlendirme değil. Gerçekte döndürdüğümüz şey, dizinin kendisi değil, sadece başlangıç adresi oluyor. Dolayısıyla bir dizidöndürdüğümüzü söylemek yerine, Pointer döndürdüğümüzü söyleyebiliriz. Basitbir fonksiyon hazırlayalım; bu fonksiyon kendisine gönderilen iki diziyibirleştirip, tek bir dizi hâline getirsin.
#include<stdio.h>
/* Kendisine verilen iki diziyi birlestirip
sonuclari ucuncu bir diziye atar */
int *dizileri_birlestir( int [], int,
int [], int,
int []);
int main( void )
{
// liste_1, 5 elemanli bir dizidir.
int liste_1[5] = { 6, 7, 8, 9, 10 };
// liste_2, 7 elemanli bir dizidir.
int liste_2[7] = {13, 7, 12, 9, 7, 1, 14 };
// sonuclarin toplanacagi toplam_sonuc dizisi
int toplam_sonuc[13];
// sonucun dondurulmesi icin pointer tanimliyoruz
int *ptr;
int i;

// fonksiyonu calistiriyoruz.
ptr = dizileri_birlestir( liste_1, 5, liste_2, 7,
toplam_sonuc );

// pointer uzerinden sonuclari yazdiriyoruz.
for( i = 0; i < 12; i++ )
printf(“%d “, *(ptr+i) );
printf(“\n”);

return 0;
}
int *dizileri_birlestir( int dizi_1[], int boyut_1,
int dizi_2[], int boyut_2,
int sonuc[] )
{
int i, k;
// Birinci dizinin degerleri ataniyor.
for( i = 0; i < boyut_1; i++ )
sonuc[i] = dizi_1[i];

// Ikinci dizinin degerleri ataniyor.
for( k = 0; k < boyut_2; i++, k++ ) {
sonuc[i] = dizi_2[k];
}

// Geriye sonuc dizisi gonderiliyor.
return sonuc;
}

Neyin nasıl olduğunu sanırım anlamışsınızdır. Diziler referans yoluylagönderilirken ve gönderdiğimiz dizilerin boyutları belliyken, neden bir de işiniçine pointer’ları soktuğumuzu sorabilirsiniz. İlerki konumuzda, dinamik yer ayırmakonusunu işleyeceğiz. Şimdilik çok lüzumlu gözükmese de, ön hazırlık olarakolarak bunları öğrenmeniz önemli!

Sıralama

Sıralama oldukça önemli bir konudur. Çeşit çeşit algoritmalar ( QuickSort,Insertion, Shell Sort, vs… ) bulunmaktadır. Ben sizlere en basit sıralamayöntemlerinden biri olan, “Bubble Sort” (“Kabarcık Sıralaması”) metodundan bahsedeceğim.

Elinizde, {7, 3, 66, 3, -5, 22, -77, 2} elemanlarından oluşan bir dizi olduğunuvarsayın. Dizinin en sonuna gidiyorsunuz ve 8.elemanla( dizi[ 7 ] ), 7.elemanı ( dizi[ 6 ] ) karşılaştırıyorsunuz. Eğer8.eleman, 7.elemandan küçükse bu ikisi yer değiştiriyor; değilse, bir değişiklikyapmıyorsunuz. Sonra 7.elemanla ( dizi[ 6 ] ) 6.elemaniçin aynı işlemler yapılıyor. Bu böyle dizinin son elemanına( dizi[ 0 ] ) kadar gidiyor. Buraya kadar yaptığımızişlemlere birinci aşama diyelim. İkinci aşamada da tamamen aynı işlemleriyapıyorsunuz. Sadece süreç dizinin son elemanına( dizi[ 0 ] ) kadar değil, ondan bir önceki elemanakadar sürüyor. Kısacası her aşamada, kontrol ettiğiniz eleman sayısını birazaltıyorsunuz. Aşama sayısı da, dizi eleman sayısının bir eksiği oluyor. Yanibu örneğimizde 7 aşama gerekiyor. Bunu grafik üzerinde anlatmak daha kolayolacağından, linke tıklayın: Bubble Sort Örneği

Konu biraz karmaşık; tek seferde anlaşılmayabilir. Bu dediklerimizi algoritmayadökelim:
#include<stdio.h>
void dizi_goster( int [ ], int );
void kabarcik_siralamasi( int [ ], int );
int main( void )
{
int i, j;
int dizi[ 8 ] = { 7, 3, 66, 3,
-5, 22, -77, 2 };

// Siralama islemi icin fonksiyonu
// cagriyoruz.
kabarcik_siralamasi( dizi, 8 );
// Sonucu gostermesi icin dizi_gosteri
// calistiriyoruz.
dizi_goster( dizi, 8 );
return 0;
}
// Dizi elemanlarini gostermek icin yazilmis
// bir fonksiyondur.
void dizi_goster( int dizi[ ], int boyut )
{
int i;
for( i = 0; i < boyut; i++ ) {
printf(“%d “,dizi[i]);
}
printf(“\n”);
}
// Bubble Sort algoritmasina gore, siralama islemi
// yapar.
void kabarcik_siralamasi( int dizi[ ], int boyut )
{
int i, j, temp;
// Ilk dongu asama sayisini temsil ediyor.
// Bu donguye gore, ornegin boyutu 8 olan
// bir dizi icin 7 asama gerceklesir.
for( i = 0; i < boyut-1; i++ ) {
// Ikinci dongu, her asamada yapilan
// islemi temsil eder. Dizinin elemanlari
// en sondan baslayarak kontrol edilir.
// Eger kendisinden once gelen elemandan
// kucuk bir degeri varsa, elemanlarin
// degerleri yer degistirir.
for( j = boyut – 1; j > i; j– ) {
if( dizi[ j ] < dizi[ j – 1 ] ) {
temp = dizi[ j -1 ];
dizi[ j – 1 ] = dizi[ j ];
dizi[ j ] = temp;
}

}
}
}

Çeşitli sıralama algoritmaları CodeCodex Internet sitesinde mevcut. Ayrıca sıralama demoları izlemenizi tavsiye ederim;algoritmaların ne kadar başarılı olduğunu görerek ayırt edebilirsiniz. Buradave burada güzel bir demo ile bir anlatım sayfası bulunuyor; mutlaka bakın!

Örnek Sorular

Soru 1: Kendisine parametre olarak gelen bir diziyi, yine parametre olarakbir başka diziye ters çevirip atayacak bir fonksiyon yazınız.

Cevap için tıklayınız…

Soru 2: Kendisine parametre olarak gelen bir dizinin bütün elemanlarını, mutlak değeriyle değiştiren programı yazınız.

Cevap için tıklayınız…

Soru 3: int *ptr = &month[ 3 ] şeklinde bir atama yapılıyor.Buna göre, aşağıdakilerden hangileri *ptr değerine eşittir?
a) month; e) ( month + 3 )[ 0 ];
b) ptr[ 0 ]; f) ( month + 1 )[ 2 ];
c) ptr[ 1 ]; g) *( month + 3 )[ 0 ];
d) *( month + 3 )

Cevap için tıklayınız…