Konuyu Oyla:
  • Derecelendirme: 5/5 - 6 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Array Nedir, Nasıl Kullanılır (Güncellendi)
#1
Çok geniş bir konu ve tüm yönlerini irdelemek daha uzun bir yazının konusu, umarım basite indirgeyebiliriz.

Bu yazıda daha çok, Pascal'daki Array kavramının ne olduğunu, nasıl tanımlandığını, klasik kullanım örneklerini ve işimizi basitleştirecek bazı ufak tefek fonksiyon önerilerini inceleyeceğiz. Fakat Array'larla ilgili pointer ve heap gibi mekanizmalara ve kompleks veri tipleriyle (class, generics vb...) nasıl kullanıldığına dair konulara değinmeyeceğiz. Bunlar daha ileri konular ve asıl konu başlı başına geniş bir içeriğe sahip olduğu için anlatımı dağıtma potansiyeline sahipler, o nedenle belki başka bir makalede bunlara değiniriz. Örneklerimizi basit veri türleri ile sınırlandıracağız ve performans ile ilgili konulara girmeyeeğiz, sadece nedir, nasıl kullanılır sorularının etrafında dolaşacağız. Bununla birlikte Arrayları kullanırken sadece basit (veya basitleştirilmiş) veri tipleriyle (byte, integer, char, TDateTime, Double, currency, string gibi) sınırlı olmadığınızı bilmeniz yararlı olur.

Girizgaha matematik ile başlayalım; Net bir tanımı olmamasına rağmen Matematikteki küme kavramı tarif edilirken "Belirli özelliğe sahip olan nesneler topluluğu" ifadesi kullanılır. Array'ları da bu çerçeveden ele alırsak bellekte oluşturduğumuz kümeler olarak düşünebiliriz. Buna göre; Aynı veri tipine sahip (aynı türde olmak zorunda da değil) değerler kümesini topluca yönetebildiğimiz, bir kolleksiyon olarak ele alabildiğimiz yapılara dizi, yani "Array" diyoruz. Değişken olarak tanımlayabildiğimiz herşeyi birer dizi olarak da tanımlayabiliriz. Çünkü Dizilerin kendisi de aslında ve aynı zamanda birer veri tipidir. Kümeyi oluşturan nesnelere kümenin "elemanları" denir. Aynı şekilde Array'lar da elemanlardan oluşur ve her bir elemanın bir indis değeri vardır. Bu indis değerini kullanarak Array'ın elemanları (Item'leri) arasında gezinebiliriz.

Pascal'da üç tip Array tanımı vardır. Bunlar durağan, sabit, yani "Statik Array" tipi, bunun tam tersi olan, çalışma zamanında boyunu anlık olarak değiştirebileceğimiz "Dinamic Array" tipi ve son olarak fonksiyon ve prosedürlere parametre olarak iletebildiğimiz Açık Dizi / Open Array'lar vardır. Boyut açısından ise tek boyutlu Array'lar ve çok boyutlu arraylar olarak ikiye ayırmak sanırım daha doğru bir yaklaşım olabilir.

Kısaca Array'ları tanıdığımıza göre artık sade ve basit misallerle yazımızı örneklendirmeye başlayabiliriz.

STATIK ARRAY / SABİT DİZİLER

Yukarıda kısaca değindiğimiz gibi bu tür diziler çalışma anındayken eleman sayısı değiştirilemeyen dizilerdir. Eleman sayısı açısından nasıl tanımlanmışlarsa o sınırlar içerisinde kullanılırlar. Eleman sayısı sabittir ve çalışma anında eleman sayısı değiştirilemez, bunun temel bir sebebi vardır, o da bu tür dizilere ayrılan bellek bölgesinin sabit olmasından kaynaklanır.

Bunun dışında başlangıç indis değeri statik dizilerde rahatlıkla belirlenebilir. Biz örneklerimizde "[0..9]" şeklinde bir kullanım sergiledik fakat bir statik dizi için bu böyle olmak zorunda değil, mesela "[5..10000]" veya "[-41..94]" gibi de tanımlanabilir. Buradaki ana belirleyici unsur, sizin indis değerini baz aldığınız durumları yönetmeye ihtiyacınızın olup olmadığıdır...

Aşağıdaki örnekte basit bir statik dizi tanımı yapılmaktadır;

var
  BiDizi  : Array [0..9]  of integer;

Yukarıda "BiDizi" adında, toplamda (yani sıfır da dahil olmak üzere) "10" adet elemanı olan ve veri tipi INTEGER olan bir dizi tanımlamış olduk. Bu tanıma göre bu dizideki elemanlara nasıl erişeceğimizin de bir örneğini vermek, konunun anlaşılması açısından yardımcı olabilir;

var
  BiDizi : Array [0..9] of integer;
  I: Integer;
begin
  BiDizi[0] := 1;
  BiDizi[1] := 2;
  BiDizi[2] := 3;
  BiDizi[3] := 4;
  BiDizi[4] := 5;
  BiDizi[5] := 6;
  BiDizi[6] := 7;
  BiDizi[7] := 8;
  BiDizi[8] := 9;
  BiDizi[9] := 10;

  // Başka bir örnek;
  for I := 0 to 9 do BiDizi[I] := I + 1;

  // Diğer bir örnek;
  for I in BiDizi do begin
      BiDizi[I] := I * 2;
      Memo1.Lines.Add(BiDizi[I].ToString);
  end;

  // Daha başka bir örnek
  for I := Low(BiDizi) to High(BiDizi) do begin
      BiDizi[I] := I div 2;
      Memo1.Lines.Add(BiDizi[I].ToString);
  end;
end;

Dikkat ettiyseniz dizimizin ilk elemanı "0" ile ifade ediliyor. Eğer tanımı şu şekilde yapsaydık;

var
  BiDizi : Array [5..9]   of integer; // veya > of string; of char; of Currency; of TDateTime; // vs...

Bu diziyi BiDizi[0] şekilde kullandığımızda derleyici bize "sıfır" indisli bir dizi elemanı olmadığı için "E1012 Constant expression violates subrange bounds" şeklinde bir hata mesajı verecekti...

Konuya geri dönecek olursak, diziler sadece bir değişken olarak tanımlanmak zorunda değildir. Statik Dizileri bir sabit veya bir tip olarak da tanımlamak mümkündür;

Bir değişken olarak tanımlayacağımız zaman;

var
  BiDizi : Array [0..9] of Integer;

Bir tip olarak tanımlayacağımız zaman;

type
  TDizi = Array [0..9] of integer;
  // devamıdır;
var
  BiDizi: TDizi;

Ve dizimizin boyutunun sabit olduğu gibi, içeriğinin de sabit olmasını istiyorsak bunu bir sabit olarak da tanımlayabiliriz, şöyle;

const
  BiDizi : Array [0..9] of Integer = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
  // veya başka bir veri tipiyle daha anlaşılır başka bir örnek
  Aylar : Array [1..12] of String = ('Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık');

Tabi böyle bir tanımlama yaptığımızda dizimiz çalışma anındayken değiştirilemez (readonly) bir nitelik kazanacaktır. 

ufak bir kullanım örneğiyle bu kısmı bitirip Dinamik arraylara geçebiliriz;

const
  Aylar : Array [1..12] of String = ('Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık');
begin
  for I := Low(Aylar) to High(Aylar) do  Memo1.Lines.Add( Aylar[I] );
end;

DYNAMIC ARRAY - DİNAMİK DİZİLER

Adından da anlaşılacağı üzere bu Array tipi çalışma zamanında eleman sayısı değiştirilebilen, dolayısıyla bellekte genişleyip daralabilen dizilerdir. Dinamik diziler tanımlandığı sırada kullanacağı veri tipini belirtir fakat herhangi bir eleman sayısı bilgisine bildirmeyiz. Dinamik bir diziye bir değer atadığımızda (yani onu bir değişkenmiş gibi kullandığımızda) veya onu SetLength yordamına maruz bıraktığımızda, dinamik dizimiz için bellek yeniden ayarlanır. Dinamik diziyi bir değişken olarak kullanmayıp, doğrudan elemanlarını işlemek istediğimizde henüz bellekte kendine ait bir bölge olmadığı için diziyi "ilklendirmeliyiz". Yani "SetLength(BiDizi, 15)" komutu kullanılarak diziye bellekte kaç (örnekte 15) elemanlık bellek ayrılması gerektiğini belirtiriz. Bu durumda belleğin, bir kısmı, bu dizi için tahsis edilir. Bellekteki bu aktivitenin nasıl işlediği, mekanizmanın nasıl olduğu gibi konular bu yazının kapsamını dağıtmamak adına değinilmeyecek. Bu tarz, bellek mekanizmasına dair mevzular muhtemelen yorumlar kısmında diğer arkadaşlarım tarafından değinilecektir diye tahmin ediyorum.

Dinamik dizilerde indis belirtilemez, dolayısıyla bu tip dizilerde indis her zaman "0" ile başlar ve negatif bir değer alamaz. Bu nedenle her zaman toplam eleman sayısı, eksi bir, olacak şekilde dizi elemanları arasında dolaşmamız gerekir. Aşağıdaki bir kaç örnek sanırım bunu açıklamaya yardımcı olacaktır;

var
  BiDizi, DiziDegiskeni : Array of Integer;
  I: Integer;
begin
  SetLength(BiDizi, 5); // BiDizi adlı dizinin eleman sayısını burada belirttiğimize dikkat edin.
  memo1.Clear;
  for I := Low(BiDizi) to High(BiDizi) do begin
      BiDizi[I] := I;
      Memo1.Lines.Add( BiDizi[I].ToString );
  end;

  DiziDegiskeni := BiDizi; // DiziDegiskeni'ni SETLENGTH ile ayarlamadığımıza, "DiziDegiskeni"'ni bir "değişken" olarak kullandığımıza dikkat edin...
  for I := Low(DiziDegiskeni) to High(DiziDegiskeni) do begin
      BiDizi[I] := I;
      Memo1.Lines.Add( DiziDegiskeni[I].ToString );
  end;
end;

Setlength kullanımına alternatif olarak doğrudan küme ifadesi de kullanılabilir;

var
  BiDizi: Array of Integer;
begin
  BiDizi := [1,2,3,4,5,6,7,8]; // doğrudan 8 elemanlı bir dinamik dizi oluşturmuş olduk.
end;

OPEN ARRAY - AÇIK DİZİLER

Yukarıdaki örnek kodda dizilerimizi bir değişken olarak tanımladık ve aynı veri tipinde olmalarına rağmen aslen pek de gerçekçi bir örnek olmadığını gördük. Gördük çünkü değişkenlerimizi ve tiplerimizi fiiliyatta tek bir noktada tanımlamayabiliyoruz. Bu sorunu aşmak için kullandığımız diziye özel veri tipleri tanımlayabiliriz. Hemen örnek verelim;

type
  TDiziTipim = array of integer;
  TAylar = array [1..12] of string;

//...

var
  BiDizi        : TDiziTipim;
  DiziDegiskeni : TDiziTipim;
  Aylar         : TAylar;

Görüldüğü üzere bir önceki örnekte BiDizi ve DiziDegiskeni adlı değişkenlerimizi tanımlarken araya virgül katmamız gerekmiş idi, şimdiki örnekte ise böyle bir kısıtlamaya maruz kalmamış olduk. Biz, bu tür bir tanımlamaya OPEN ARRAY / AÇIK DİZİ diyoruz. 

Açık dizileri, derleme zamanında elemanları henüz belirlenmemiş olan diziler olarak da düşünebiliriz. Açık dizileri dinamik dizilerden ayıran temel unsur açık dizilerin bir veri tipi olarak tanımlanmasından kaynaklanıyor. Şöyleki; Diziler parametre olarak da kullanılabilirler. Dizi parametresinin belli bir indis aralığı veya sınırı yoksa (veya istenen şey aslında dinamik bir dizi ise) bunu doğrudan değil, dolaylı olarak parametize ederiz. Bu tip dizilere AÇIK DİZİ / OPEN ARRAY denir ve "var" kısmında değil, "type" kısmında bir tip olarak tanımlanır. Delphi, açık dizilerin bellekte ne kadar yer kaplayacağını "örtülü olarak" kendisi arka tarafta yönetir. Yani setlength ile bir AÇIK ARRAY'ın kaç elemana sahip olacağını siz söylemezsiniz, bunu Delphi arka tarafta kendisi otomatik olarak yapar.

Açık dizilerin kullanımı ile ilgili alternatif olarak Create oluşturucusu da kullanılabilir; Mesela;

type
  TDizi = array of Integer;
var
  BiDizi: TDizi;
begin
  BiDizi := TDizi.Create(3,5,7,9,11 {...});
end;

veya çok daha kısa bir yöntem, doğrudan küme değerlerini girmek şeklinde de olabilir;

...
begin
  BiDizi := [1,2,3,4,5,6,7,89,9];
end;
Açık dizileri birbiriyle toplamak da mümkündür; Bunun için örnekteki gibi "+" operatörü veya "concat" fonksiyonu alternatif olarak kullanılabilir;

type
  TDizi = array of Integer;
var
  BiDizi, DigerDizi: TDizi;
  I: Integer;
begin
  BiDizi := [1,3,5,7,9];
  DigerDizi := Bidizi + [2,4,6,8];
  for I := Low(DigerDizi) to High(DigerDizi) do Memo1.Lines.Add(DigerDizi[I].ToString);

  Memo1.Text := Memo1.Text + #13#10;
  DigerDizi := Concat(DigerDizi, [55,56], [100,200]);
  for I := Low(DigerDizi) to High(DigerDizi) do Memo1.Text := Memo1.Text + ', ' + DigerDizi[I].ToString;
end;

Fakat çıkarma "-" operatörünü kullanamazsınız. Bunun yerine Delete metodu kullanılabilir;

  ...
  Delete(DigerDizi, 0, 2);
  for I := Low(DigerDizi) to High(DigerDizi) do Memo1.Lines.Add(DigerDizi[I].ToString);
end;

MULTI-DIMENSIONAL ARRAY'LAR - ÇOK BOYUTLU DİZİLER 

Basit anlamda sade, statik bir dizinin, dinamik bir dizinin ve açık bir dizinin hangi yöntemlerle tanımlanabileceğini gördüğümüze göre çok boyutlu dizilerin nasıl tanımlanabileceğini de inceleyebiliriz. Gerek Statik, gerek dinamik, gerekse de açık dizi olsun, bir diziyi çok boyutlu yapan şey, bir eleman için birden çok indisin tanımlanabilmesidir.

Örneklemeyi Statik Arraylar için konuşacak olursak onları tanımlarken "[0..9]" gibi bir indis sınırlaması belirliyorduk. Bunu iki boyutlu yapmak için bir indis sınırı daha belirtmemiz gerekir, yani "[0..9  ,  1..2]" gibi... Virgülden sonraki "1..2" ibaresi, bizim ikinci boyutumuzu temsil eden indis sınırını göstermektedir. Bu şekilde, araya virgüller katarak daha çok indis (yani daha çok boyut) ekleyebiliriz. Bunu aşağıdaki örnekle daha iyi anlatabileceğimi sanıyorum;

var              
  ikiboyutluStatikBirDizi: Array [0..9 , 1..2]        of integer;
  UcBoyutluStatikBirDizi : Array [0..9 , 1..2 , 0..5] of integer;
  //                             [  A  ,  B   ,  C  ]

Görüldüğü üzere açıklama satırında "A" ile temsil edilen kısım 1. boyutu, "B" 2. boyutu, "C" ise 3. boyutu temsil etmektedir. Bu yapıları bellekte basit bir veri tablosu olarak da düşünebilirsiniz. Bu tip dizileri kullanmak için aşağıdaki örneği inceleyebiliriz;

var
  Dizi_2D : Array [0..9 , 0..9] of integer;
  A, B : Integer;
begin
  WriteLn('Çarpım Tablosu');
  for a := 0 to 9 do begin
      for b := 0 to 9 do begin
          Dizi_2D[a, b] := a * b;
          WriteLn( a.ToString + ' x ' + B.ToString + ' = ' + Dizi_2D[a, b].ToString )
      end;
  end;
end;

Benzer bir yapıyı dinamik olarak da tanımlayabiliriz. Dinamik bir çok boyutlu dizi tanımı statik bir, çok boyutlu diziden tanımı itibariyle daha esnek olabilmektedir. Bunu bir örnekle göstermek sanırım daha kolay olacak;

var
  ikiBoyutluDinamikBirDizi : Array of       Array of       Integer;  // Çok Boyutlu dizi / Array
                         // "1. boyut"     "2. boyut"      veri tipi
  A, B : Integer;
begin
  SetLength(ikiBoyutluDinamikBirDizi, 3);         // iki boyutlu Arrayımızın ilk boyutunu 3 elemanlı olacak şekilde ayarladık.

  // Esneklikten kastım aşağıdaki 3 satırlık kodda açıkça görülebilir.
  SetLength(ikiBoyutluDinamikBirDizi[0], 4);      // iki boyutlu dizimizin ilk elemanında yer alan alt diziyi 4 elemanlı olacak şekilde ayarladık.
  SetLength(ikiBoyutluDinamikBirDizi[1], 3);      // iki boyutlu dizimizin ikinci elemanında yer alan alt diziyi 3 elemanlı olacak şekilde ayarladık.
  SetLength(ikiBoyutluDinamikBirDizi[2], 2);      // iki boyutlu dizimizin son elemanında yer alan alt diziyi 2 elemanlı olacak şekilde ayarladık.

  // İki boyutlu dizimizin tüm elemanlarının değerlerini ayarlayalım ve içeriğini yazdıralım...
  for A := 0 to High(ikiBoyutluDinamikBirDizi) do
      for B := 0 to High(ikiBoyutluDinamikBirDizi[A]) do begin
          ikiBoyutluDinamikBirDizi[A, B] := A + B;
          WriteLn( 'ikiBoyutluDinamikBirDizi[' + A.ToString + ',' + B.ToString + '] = ' + ikiBoyutluDinamikBirDizi[A, B].toString );
      end;
end;

Fakat dinamik dizilerde bu kadar esnek davranmamıza gerek olmadığında çoklu dizimizin eleman sayısını şöyle de tanımlayabilirdik;

var
  ikiBoyutluDinamikBirDizi : Array of       Array of       Integer;  // Çok Boyutlu dizi / Array
                         // "1. boyut"     "2. boyut"      veri tipi
  A, B : Integer;
begin
  SetLength(ikiBoyutluDinamikBirDizi, 3, 5);    // iki boyutlu Arrayımızın ilk boyutunu 3 elemanlı, alt array'ların her birini ise 5'er elemanlı olacak şekilde de ayarlayabiliriz. Dizideki hücrelere ise bir önceki örnekte yer alan for döngüleri ile de erişilebilir.

ARRAY ve NESNE KULLANIMI

Her ne kadar yazının başında kompleks veri tiplerine değinmeyeceğimizi söylemiş olsak da mevzuya bir kenarından dokunmazsak konu eksik kalır çekincesini taşıyorum, o nedenle yine basite indirgemek adına RECORD tipindeki bir yapının bir array içinde nasıl kullanılabileceğine dair ufak bir örnek vermek sanırım yeterli olur. Aşağıdaki örneği bir CLASS için de kullanmak mümkündür, sonuçta (neredeyse) herşey bir pointer olduğuna göre bunu bu şekilde kullanmaya da bir engel yok sanırım...

type
  TUrun = packed record
    UrunAdi : String;
    Fiyat   : Currency;
  end;
const
  Urunler: Array[0..2] of TUrun =
  (  ( UrunAdi : 'Kitap'  ;  Fiyat : 50.00 )
  ,  ( UrunAdi : 'Defter' ;  Fiyat : 10.00 )
  ,  ( UrunAdi : 'Kalem'  ;  Fiyat :  2.50 )
  );

implementation

{$R *.dfm}

uses
  System.SysUtils;

procedure TForm1.Button1Click(Sender: TObject);
var
  Mallar: Array[0..2] of TUrun;
  I: Integer;
begin
  Mallar[0].UrunAdi := 'Kitap';
  Mallar[0].Fiyat   := 50.00;

  Mallar[1].UrunAdi := 'Defter';
  Mallar[1].Fiyat   := 10.00;

  Mallar[2].UrunAdi := 'Kalem';
  Mallar[2].Fiyat   := 2.50;

  //Urunler[0].UrunAdi := 'BU BİR CONST OLDUĞU İÇİN HATA VERİR';

  for I := Low(Mallar) to High(Mallar)
   do Memo1.Lines.Add('Mallar > ' + Mallar[I].UrunAdi + ' (' +  floatToStr (Mallar[I].Fiyat) + ' TL)');

  for I := Low(Urunler) to High(Urunler)
   do Memo1.Lines.Add('Urunler > ' + Urunler[I].UrunAdi + ' (' +  floatToStr (Urunler[I].Fiyat) + ' TL)');

end;

UFAK BİR ÖRNEK

Her ne kadar yazının kısa olmasını istesem de buraya kadar okuma sabrını gösterdiğiniz için teşekkürler. Yazının bundan sonrası için arraylarla ilgili bazı örnekler üzerinde duracağız. Array konusu çok kapsamlı ve geniş bir konu, yazdıkça yenileri ortaya çıkıyor ve Delphi Array'larla ilgili zamanın verdiği birikim nedeniyle çok geniş bir yetenek kolleksiyonuna sahip. Aşağıdaki örnek fonksiyonlar bir dizide belirtilen bir elemanın varsa hangi indiste olduğunu söylüyorlar. Bunların overload'ları çeşitlendirilebilir veya generics bir tip tanımı üzerinden daha gelişmiş örnekler haline de getirilebilir, örnek olması açısından incelemenize sunuyorum.

(EKLEME) Aşağıdaki örnek aynı zamanda AÇIK DİZİ'lerin (OPEN ARRAY) parametre olarak nasıl kullanılabildiğini ve boş parametre veya varsayılan parametreleri nasıl verebileceğimizi de ayrıca göstermesi açısından tamamlayıcı niteliktedir.

type
  TArrayStr = array of string;
  TArrayInt = array of Integer;
  TArrayVar = array of Variant;
...
  function Exists(aAranan: String;  aDizi: TArrayStr = []): Integer; overload;
  function Exists(aAranan: Integer; aDizi: TArrayInt = []): Integer; overload;
  function Exists(aAranan: Variant; aDizi: TArrayVar = []): Integer; overload;

Implementation

function Exists(aAranan: String; aDizi: TArrayStr = []): Integer;
var
  I: Integer;
begin
  Result := -1;
  for I := Low(aDizi) to High(aDizi) do
      if (aDizi[I] = aAranan) then begin
          Result := I;
          Break;
      end;
end;

function Exists(aAranan: Integer; aDizi: TArrayInt = []): Integer;
var
  I: Integer;
begin
  Result := -1;
  for I := Low(aDizi) to High(aDizi) do
      if (aDizi[I] = aAranan) then begin
          Result := I;
          Break;
      end;
end;

function Exists(aAranan: Variant; aDizi: TArrayVar = []): Integer; overload;
var
  I: Integer;
begin
  Result := -1;
  for I := Low(aDizi) to High(aDizi) do
      if ( VarType(aDizi[I]) = VarType(aAranan)) then begin
          if (aDizi[I] = aAranan) then begin
              Result := I;
              Break;
          end;
      end;
end;


Kullanımı da şöyle olabilir;

  if Exists( 55.72, ['test', 12, 55, 72, true, 55.72, 'metin']) > -1 then ShowMessage('Eleman dizide mevcut');
  
  // veya

  ShowMessage (  Exists(null, ['', null, varEmpty, 0]).ToString  );   // 1. indiste null değerini bulacaktır...

  // veya elemanımız var fakat dizinin içi boş olsun;

  ShowMessage( Exists(33, []).ToString );   // bulunamayacağı için -1 üretecektir.

Array konusu çok geniş ve bu yazı burada bitmez ama bir yerde dur demek lazım. Faydalı olması dileğiyle...
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
WWW
Cevapla
#2
Elinize sağlık süper döküman olmuş.

Ufacık bir soru,
Bir dizim var SetLength(Dizi, 30); diyip iiçini doldurdum, değerleri atadım.
Daha sonra SetLength(Dizi, 10); Dedim, Sonra tekrardan SetLength(Dizi, 30); yaptım , bu dizinin 10'dan sonraki elemanlarına tekrar erişebilir miyim ?
WWW
Cevapla
#3
Teşekkürler, ellerinize sağlık çok güzel bir anlatım olmuş.
Cevapla
#4
(18-12-2017, Saat: 08:36)yhackup Adlı Kullanıcıdan Alıntı: Elinize sağlık süper döküman olmuş.

Ufacık bir soru,
Bir dizim var SetLength(Dizi, 30); diyip iiçini doldurdum, değerleri atadım.
Daha sonra  SetLength(Dizi, 10); Dedim, Sonra tekrardan SetLength(Dizi, 30); yaptım , bu dizinin 10'dan sonraki elemanlarına tekrar erişebilir miyim ?

SetLength(Dizi, 10) yaptığınızda Dizi'nin son 20 elemanını kesip atmış olursunuz. 
Teorik olarak tekrar SetLength(Dizi, 30) yaptığınızda, önceden kesilip atılan 20 elemana erişemezsiniz.
Cevapla
#5
Elinize sağlık. Güzel bir doküman olmuş...
Cevapla
#6
(18-12-2017, Saat: 10:14)FunnyBlue Adlı Kullanıcıdan Alıntı:
(18-12-2017, Saat: 08:36)yhackup Adlı Kullanıcıdan Alıntı: Elinize sağlık süper döküman olmuş.

Ufacık bir soru,
Bir dizim var SetLength(Dizi, 30); diyip iiçini doldurdum, değerleri atadım.
Daha sonra  SetLength(Dizi, 10); Dedim, Sonra tekrardan SetLength(Dizi, 30); yaptım , bu dizinin 10'dan sonraki elemanlarına tekrar erişebilir miyim ?

SetLength(Dizi, 10) yaptığınızda Dizi'nin son 20 elemanını kesip atmış olursunuz. 
Teorik olarak tekrar SetLength(Dizi, 30) yaptığınızda, önceden kesilip atılan 20 elemana erişemezsiniz.

Teşekkürler geçenlerde bir arkadaş ile bahsi geçmişti, Erişilebileceğini söylemişti ama deneme fırsatım olmadı tabi.
WWW
Cevapla
#7
(18-12-2017, Saat: 11:12)yhackup Adlı Kullanıcıdan Alıntı:
(18-12-2017, Saat: 10:14)FunnyBlue Adlı Kullanıcıdan Alıntı: SetLength(Dizi, 10) yaptığınızda Dizi'nin son 20 elemanını kesip atmış olursunuz. 
Teorik olarak tekrar SetLength(Dizi, 30) yaptığınızda, önceden kesilip atılan 20 elemana erişemezsiniz.

Teşekkürler geçenlerde bir arkadaş ile bahsi geçmişti, Erişilebileceğini söylemişti ama deneme fırsatım olmadı tabi.

Aşağıdaki kod ile bir deneme yapabilirsiniz,

procedure ArrayTest;
var
  BiDizi: array of Integer;
  I: Integer;
begin
  SetLength(BiDizi, 30);
  for I := Low(BiDizi) to High(BiDizi) do begin
      BiDizi[I] := I * 2; // sadece bu noktada değer ataması yaptık.
      Memo1.Text := Memo1.Text + I.ToString +':'+ BiDizi[I].ToString + ', ';
  end;
  Memo1.Lines.Add('');

  SetLength(BiDizi, 10);
  for I := Low(BiDizi) to High(BiDizi) do begin
      Memo1.Text := Memo1.Text + I.ToString +':'+ BiDizi[I].ToString + ', ';
  end;

  Memo1.Lines.Add('');

  SetLength(BiDizi, 30);
  for I := Low(BiDizi) to High(BiDizi) do begin
      Memo1.Text := Memo1.Text + I.ToString +':'+ BiDizi[I].ToString + ', ';
  end;
end;
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
WWW
Cevapla
#8
Küçük değerli uzunluk ataması yaparsanız o esnada hafıza değerleri değişmez.
Tekrar atama yapmadan arrayin adresini alıp kaçıncı elemanına ulaşmak istiyorsanız o kadar arttırıp okuma yapabilirsiniz.
Tekrardan uzunluk ataması yaptığınızda silinecektir.

Örnek :
var
  aArray: array of byte;
begin
 SetLength(aArray,10);
 aArray[6] := 25;
 SetLength(aArray,5);
 ShowMessage(IntToStr( byte(pointer(integer(@aArray[0]) + 6)^)));
 SetLength(aArray,10);
 ShowMessage(IntToStr(aArray[6]));
end;
Ayakkabıyı sefaletten
Çok sonraları tanıdım
Öyle ufuklarda mı olurmuş Allah'ım
Giyer giyer koşardım
Toprağın dostluğundan
Oyuncaklar yaptım çamurdan
Tenimin rengini aldım topraktan
Sen bakma esmerliğim sonradan...





Cevapla
#9
program Project29;

{$APPTYPE CONSOLE}

{$R *.res}

uses
 System.SysUtils;
var
dizi:array of integer;
i:integer;
begin
 SetLength(dizi,30);
 writeln('Dizinin ilk adresi: '+inttostr(integer(@dizi[0])));
  for I := Low(dizi) to High(dizi) do begin
     dizi[I] := I * 2;
 end;
     for I := Low(dizi) to High(dizi) do begin
      writeln(dizi[i]);
      end;

        SetLength(dizi,2);
          writeln('Dizinin ikinci adresi: '+inttostr(integer(pointer((@dizi)^))));//dizi değişkenin tuttuğu adres yani dizi[0]'ın adresi .Farklı bir gösterim sadece
           SetLength(dizi,1000);
          writeln('Dizinin üçüncü adresi: '+inttostr(integer(@dizi[0])));
           for I := 0 to 30 do begin
      writeln(dizi[i]);
      end;
      readln;
end.

Yukarıda en başta  dizi adıyla stack'te  bir değişken adı oluşturuluyor.Bu değişkenin adresi program boyunca hep aynıdır çünkü statiktir; ama dizinin henüz bir boyutu yoktur ve 
ve elimizdeki sadece diziyi göstermekle yükümlü bir değişken adıdır diğer deyişle dizinin başlangıç adresini tutacak değişkendir bu.Yani elimizde boş bir gösterici vardır ve henüz bu göstericiye tahsis edilmiş bir adres yoktur.Birinci SetLength fonksiyonu bu diziye bir alan tahsis eder ve bu alanın başlangıç adresini(dizi[0]) bu değişkene yazar.Yani dizinin alanı heap'te çalışma esnasında dinamik bir şekilde oluşturulur ve stack'taki statik değişkene  atanır.Dolayısıyla siz SetLength fonksiyonunu bir daha çağırdığınızda yeni bir alan tahsis edilir ,yeni dizideki boyuta göre elemanlar bu yeni alana taşınır,bu alan dizi değişkenine atanır ve eski alan serbest bırakılır.Bu sebeple küçültme yaptığımızda kırptığımız değerlere tekrar ulaşamayız.Yukardaki kodda benim bilgisayarımda dizinin adresi  hepsinde farklı değer olarak görünüyor.Sizde aynı görünürse aradaki boyut farklarını biraz abartırsanız sizde de farklı görünecektir.Umarım anlatabilmişimdir.Uğur Bey elinize sağlık çok güzel bir çalışma olmuş bu arada.
Herhangi bir basit problem, hakkında yeterince toplantı yapılarak, çözümsüz hale getirilebilir.
https://play.google.com/store/apps/developer?id=ONGUN
WWW
Cevapla
#10
Rica ederim. Soru soran, sormayan, cevap veren veya faydalanan tüm arkadaşlarıma teşekkür ederim.
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
WWW
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  SANAL BİLGİSAYARA macOS SONOMA NASIL KURULUR? engerex 1 228 19-02-2024, Saat: 08:41
Son Yorum: yhackup
  Kendi Logaritma Fonksiyonumuzu Nasıl Yazarız? savasabd 4 3.214 10-03-2020, Saat: 22:50
Son Yorum: savasabd
  IF Nedir, Nasıl Kullanılır uparlayan 14 16.120 13-12-2019, Saat: 09:23
Son Yorum: SimaWB
  Interposer Class Nedir, Nasıl Kullanılır uparlayan 31 23.207 18-09-2019, Saat: 21:35
Son Yorum: Aktolgali
  ACID nedir? Neden önemlidir? csunguray 1 4.343 01-01-2019, Saat: 15:01
Son Yorum: frmman



Konuyu Okuyanlar: 1 Ziyaretçi