Selam,
Uzun bir aradan sonra eğitimime kaldığım yerden devam ediyorum. Artık daha kısa ve öz olarak devam etmeye çalışacağım. Bunun için c4learn.com üzerindeki dersleri anladığım kadar Türkçeleştirip, biraz düzenleyerek aktarmaya çalışacağım. c4learn üzerindeki konu anlatımları kısa, öz ve gayet anlaşılır çünkü.
Lafı uzatmadan hemen bugünkü konumu açıklıyorum:
Aynı tipten verileri tutan bir koleksiyon olarak düşünebiliriz.
Değişkenler sayesinde verileri tutabiliyorum lakin bir değişkende bir veri tutabilirim. Çok sayıda veri tutmam gerektiğinde tek tek değişken mi tanımlamam gerekecek? Mesela 100 öğrenci için sıra numarası tanımlamamız gerektiğini varsayalım. Bunun için siraNo1, siraNo2, siraNo3
… siraNo100
şeklinde 100 tane değişken tanımlayabiliriz. Ama bu hem zaman hem performans kaybı olur. Yani hiç ekonomik değil ve “amele!” diye yükselen çığlıklar duyabilirsiniz.
Bunun yerine bir dizi tanımlayarak, bellekten kendimize 100 blokluk “contiguous memory” olarak bir yer tahsis ederiz ve bu 100 numaraya tek bir değişken adıyla ulaşabiliriz.
Nam-ı diğer olarak continuous memory (ardışık hafıza) olarakta biliniyormuş. Özet geçmek gerekirse, bir işlem için bellekten 1000-1200 arası adresleri kendimiz için ayırttığımızı düşünelim. Bu durumda 200 blok bizim için ardışık olarak ayrılmış olacak. Tıpkı az sonra yapacağımız dizi tanımlama ya da alloc()
/ malloc()
fonksiyonları kullanmak gibi.
//<veriTipi> <diziAdi> [diziBoyutu]; int siraNo[100];
Yukarıda siraNo
isimli int
tipinde 100 boyutlu bir dizi tanımladık. Yani bellekte bizim için yan yana dizilmiş 100 tane bloğun ya da bellek hücresinin rezerve edildiğini söylebiliriz.
Dizimiz hazır olduğuna göre öğrenci numaralarını girmeye başlayabiliriz. Yanlış önce bilmemiz gereken bir ufak nokta var.
Resimde, dizimize 5 adet öğrenci numarası girilmiş. Ve dikkat ederseniz ilk elemanın konumu yani indisi 0. C dilinde dizilerin indisleri 0 dan başlayarak ilerler. Yani 100 elemanlı bir dizinin ilk elemanı 0. indistedir. 100. eleman ise 99. indistedir. E o zaman 41. eleman da 40. indistedir.
İlk elemanın 0.indisten başladığını öğrendiğimize göre dizimize nasıl veri gireceğimizi görelim:
siraNo[0] = 4; siraNo[1] = 5; siraNo[2] = 33; siraNo[3] = 13; siraNo[4] = 1;
4, 5, 33, 13, 1 bizim verilerimiz yani öğrencilerin sıra numarası. 0,1,2,3,4 ise dizinin indisi yani elemanların dizideki konumu.
Bu ayrıca şu demektir: indis numaralarıyla dizi elemanlarımıza rahatlıkla ulaşabiliriz.
100 elemanlı bir dizi tanımladım ama 5 eleman girip bırakırsam geriye kalan 95 blok içinde ne saklayacak? Tabii ki ben ne istersem onu saklamayacak. Ne saklayacağı ise tamamen sizin kısmetinize kalmış. Daha önce o hücrede saklanan bir başka değeri ya da saçma bir sayı da görebilirsiniz.
Az önce siraNo
dizisini tanımlayıp daha sonra elemanları girdim. Bunun yerine diziyi tanımlarken de elemanlarını belirtebilirim:
int siraNo[7] = {10, 71, 5, 54, 14, 53, 13};
Ya da dolaylı yoldan da dizi uzunluğunu belirtebilirdim:
int siraNo[] = {10, 71, 5, 54, 14, 53, 13};
Yukarıda dizi elemanlarını belirtmedim ama derleyici kodlar derlenmeye başladığı zaman dizideki elemanları benim için sayıyor ve buna göre dizi uzunluğunu belirliyor. Bu türden başlangıç atamalarına “Compile Time Initialization” yani “derleme zamanı atama” deniliyor. “derleme zamanı atama” kısmı ne kadar doğru bilmiyorum çünkü “Initialization” için tam olarak Türkçe karşılık bulamadım. Initialization Türkçe’ye “başlangıç, başlama” olarak çevriliyor ama yazılım için “ilk değer ataması” olarak çevirebiliriz sanırım.
int siraNo[12] = {0};
Bir önceki başlıkta bahsettiğim, dizi uzunluğu kadar veri girmezsek rastgele verilerin elemanlara atanmasını istemiyorsak, yukarıdaki şekildeki gibi bir atama yapabiliriz. Bu şekilde dizinin tüm elemanları 0 olarak belirlenecektir.
Dizideki elemanlara indis numarasıyla ulaştığımıza göre indis numarasına göre dizideki elemanları yazdırabilirim.
int siraNo[] = {10, 71, 5, 54, 14, 53, 13}; printf("%dn", siraNo[0]); printf("%dn", siraNo[3]); printf("%dn", siraNo[6]); printf("%dn", siraNo[50]); //dizide olmayan indis
Çıktı:
10 54 13 -2144480248
Şimdi basit bir örnek ile buraya kadar olan kısımları pekiştirelim. Amacımız kullanıcıdan 5 tane tam sayı almak ve bunların toplamını ve ortalamasını hesaplamak.
int sayilar[5]; int sayac, toplam = 0; float ortalama = 0; puts("5 adet tam sayı giriniz:"); for(sayac=0; sayac<5; sayac++) { printf("%d.sayi: ", sayac+1); scanf("%d", &sayilar[sayac]); toplam += sayilar[sayac]; } ortalama = (float)toplam/5; printf("Toplam: %d ve ortalama: %.2f", toplam, ortalama);
Bildiğimiz matrisler bunlar. Tek boyutlu diziyi tek satırlık bir tablo gibi düşünebiliriz. Çok boyutlu diziler ise birden fazla satır ve sütundan meydana gelirler. Genellikle 2 boyutlu diziler kullanılır. Oyun yapımlarında ise 3 boyutlu diziler kullanılabilir. x, y, z koordinatlarını tutmak için mesela.
Şimdilik 2 boyutlu dizilerle yetinmeye bakıyorum. Öncelikle 2 boyutlu dizi nasıl tanımlanırmış görelim:
//<veriTipi> <diziAdi> [satir][sütun] int sayilar[3][2];
Yukarıda 3 satır ve 2 sütundan oluşan bir matris yani 2 boyutlu dizi tanımlamış olduk. Daha net olması için şu şekilde de tanımlayabilirim:
int sayilar[3][2] = { { 1 , 4 }, { 5 , 2 }, { 6 , 5 } };
Doğal olarak tek boyutlu dizide geçerli olan kurallar çift boyutlu diziler için de geçerli. Satır ve sütun indislerinin 0 dan başlaması gibi.
int a[3][3] = { 1,2,3, 5,6,7, 8,9,0 }; int satirSayac, sutunSayac; for(satirSayac = 0; satirSayac<3; satirSayac++) { for(sutunSayac =0; sutunSayac<3; sutunSayac++) { printf("%d ", a[satirSayac][sutunSayac]); } printf("n"); }
Yukarıda çift boyutlu dizi tanımlamanın farklı bir şeklini de görmüş olduk. Şimdi gelelim kodumuzun ne yaptığına. İlk for
döngümüz dizimizdeki yani a matrisi
ndeki satır sayısı kadar çalışacak. İçteki for
döngüsü ise bulunduğu satırdaki sütunları yazdıracak.
satirSayac
= 0 olarak döngümüz başladı.for
döngüsüne geçtik ve sutunSayac
= 0 olarak döngümüz başladı.printf()
ile a[0][0]
indisini yazdırıyoruz ve sonuna bir boşluk bırakıyoruz. Yani 1.satır 1.sütun => “1 “sutunSayac
= 1 oldu ve içteki for döngüsüne devam ediyoruz.printf()
ile bu sefer a[0][1]
indisini yazdırıyoruz. Yani 1.satır 2.sütun => “2 “sutunSayac
= 2 oldu ve içteki for
döngüsü son kez çalışıyor.a[0][2]
değerini ekrana yazdırıyoruz ve içteki for
döngüsünden çıkıyoruz. => “3 “for
döngüsünden çıktıktan sonra 10. satırdaki printf()
ile bir satır aşağıya geçiyoruz.satirSayac
= 1 olarak tekrar başlıyor ve aynı adımları tekrar uyguluyor.Yazının başında bir dizi oluştuğunda ramde bizim için belirli bir bloğun tahsis edildiğini öğrenmiştim. Şimdi bunu canlı olarak görelim.
int tekBoyutluDizi[5] = {11, 22, 33, 44, 55}; int i,j; for(i=0; i <5; i++) { printf("a[%d]: %d ve bellekteki adresi: %u n", i, tekBoyutluDizi[i], &tekBoyutluDizi[i]); } int matris[3][4] = { {11, 22, 33, 44}, {55, 66, 77, 88}, {99, 14, 53, 13} }; printf("n Çift Boyutlu Dizi nn"); for(i=0; i<3; i++) { for(j=0; j<4; j++) { printf("[%d][%d]: %d <%u> ", i, j, matris[i][j], &matris[i][j]); } printf("n"); }
Diziler hakkında daha çok yol katmem gerek. Sadece ufak bir giriş yapmış oldum. Kalan kısmını başka bir derse bırakıyorum.
veriTipi diziAdi[diziBoyutu]
şeklinde dizi tanımlanırveriTipi diziAdi[satir][sütun]
şeklinde.Senaryo1: 10 boyutlu integer
tipinde bir dizi tanımlayıp içini rastgele verilerle dolduralım ve daha sonra kullanıcıdan bir değer girmesini isteyelim. Girilen değerin dizi de olup olmadığını bulalım.
Senaryo2: int
tipindeki diziyi 1-100 arası sayılarla doldurup, tek sayıları ve çift sayıları yazdıralım. Daha sonra tek ve çift sayıların ortalamasını bulalım.
Eğitimim için kullandığım örnekleri bu adresteki github reposunda saklıyorum. Ders başlığıyla eşit olan klasörde kaynak kodları bulabilirsiniz.
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int array[10]; int i, number; //generate random values and assing to array for(i=0; i<10; i++) { array[i] = (i+2)*3; } //print array for(i=0; i<10; i++) { printf("%d ", array[i]); } puts("nPlease, enter a number: "); scanf("%d", &number); //check the array for(i=0; i<10; i++) { if(number == array[i]) { printf("Here your number in array[%d]: %d", i, array[i]); return; } } printf("There is no your number."); return (EXIT_SUCCESS); }
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int numbers[100]; int i, evens=0, odds=0; int totalOdd = 0, totalEven = 0; //assing the numbers for(i=0; i<100; i++) { numbers[i] = i+1; } //print odd numbers and even numbers, also calculate total each one of them for(i=0; i<100; i++) { if( (numbers[i] % 2) == 0) { printf("Even: %dn", numbers[i]); totalEven += numbers[i]; evens++; } else { printf("Odd: %dn", numbers[i]); totalOdd += numbers[i]; odds++; } } //print averages printf("Average of even numbers: %dn", (totalEven / evens) ); printf("Average of odd numbers: %dn", (totalOdd / odds) ); return (EXIT_SUCCESS); }
Eğer yanlış ya da düzeltilmesi gereken bir nokta farkettiyseniz, lütfen bana bildirin.
Celery ile alakalı "best practice"leri ve faydalı araçları bir araya getiren güzel bir checklist'e denk…
Diziler en temel ve sık kullandığımız araçlardan... Kod yazarken işimizi kolaylaştıracak, daha temiz kod yazmamızı…
listve tuple bilginizi test etmek ister misiniz? realpython.com da keşfettiğim ve Türkçe'ye çevirdiğim mini teste…
Rehberlik sağlaması ve bilgi tazelemesi açısından faydalı olduğunu düşündüğüm bir Toptal blog paylaşımınıTürkçe'ye çevirdim.Devamını okuyunBilmeniz…
Angular componentlerine console üzerinden hızlıca erişmek için kullanılan bir teknik. Unutmamak için kendime not düşüyorum.Devamını…
Geçtiğimiz günlerde keşfettiğim ve oldukça da hoşuma giden repoyu paylaşmak istiyorum: lydiahallie/javascript-questions Genel olarak temel…