Lebih Jauh Dengan Pointer

Pointer adalah sebuah tipe data yang berfungsi menunjukkan alamat di memori. Semua objek dalam Delphi yang diturunkan dari TObject adalah pointer. TForm, TStrings, TList, TDBGrid, semuanya pointer.

Oke. Saya mulai dengan sebuah contoh.

var
  p: Pointer;
  i, j: Integer;
begin
  i:=45;
  j:=0;
  p:=@i;
  j:=Integer(p^);
  ShowMessage(IntToStr(j));

Pertama, nilai j adalah 0, nilai i adalah 45. kemudian kita tugaskan p untuk menunjukkan alamat dari i di memori. Pada alamat tersebut terdapat nilai 45. Bilai alamat yang ditunjuk oleh p kita ambil isinya ke variabel j, maka j akan memiliki nilai 45 juga.

Kode di atas memiliki hasil:
image 

Dengan demikian kita tahu bahwa:
p := @x adalah ekspresi menugaskan p untuk menunjukkan alamat dari x disebut referencing, dan
x:=p^ adalah mengambil data/nilai pada alamat yang ditunjukkan oleh p, disebut dereferencing.

Biasanya orang bingung dengan @, dan ^. Jangan khawatir, lama-lama semuanya akan terasa biasa saja🙂

Mungkin Anda akan bertanya, apa maksudnya j:=integer(p^) ? Mudah saja, p adalah untyped pointer (pointer tak bertipe), sehingga akan membingungkan compiler berapa ukuran data/nilai yang ditunjuk oleh pointer tersebut. Mari membuat semua jelas: pointer berukuran 4 byte, tapi data/nilai di memori yang ditunjuknya tidak diketahui berapa ukurannya. Bisa jadi nilai itu adalah Char (1 byte), Integer (4 byte), Variant, atau lainnya.

Kita akan lihat alamat yang ditunjukkan oleh pointer dan mekanisme derefencing data pada alamat tersebut.

i:=45;
  p:=@i;
  ShowMessage(IntToStr( integer(p) ));

integer(p) merupakan casting/perubahan tipe dari pointer ke integer. Jadi alamat yang ditunjukkan oleh p dapat kita tampilkan dengan ShowMessage(IntToStr( integer(p) ));
image
Lantas, bagaimana mekanisme dereferencing?
image

Dengan memeriksa p, compiler tahu bahwa data yang akan direferensikan berada pada alamat 1244636 di memori. Tapi berapakah ukuran datanya? apakah cuma 1 byte atau sepanjang alamat 1244636 sampai akhir memori? Compiler takkan pernah tahu. Jadi kita harus mengarahkan compiler dengan:

j:=Integer(p^);

Kini compiler tahu bahwa kita akan mengambil data bertipe integer. Compiler tahu bahwa integer berukuran 4 byte. Dengan begitu, compiler akan mengambil data sebanyak 4 byte, dimulai dengan byte pertama pada alamat 1244636. Terakhir, compiler mengembalikan hasilnya, nilai 45.
 image

Demikian halnya bila kita ingin mengambil nilai dengan ukuran yang berbeda. Katakan kita hanya mengambil 1 byte:

j:=Byte(p^);

Bila Anda jeli, Anda dapat melihat kenapa ada tipe data PByte, PInt64, PDword, dan lainnya. Deklarasi tipe-tipe tersebut adalah:

PByte = ^Byte;

PInt64 = ^Int64;

PDword = ^Dword;

Mereka dideklarasikan sebagai tipe pointer ke tipe data dasarnya. Maksudnya, agar compiler tahu bahwa ukuran data pada alamat yang ditunjuknya.
image 

Anda lihat? Compiler kebingungan karena harus mengambil nilai yang tidak diketahui berapa ukurannya. Bagaimana jika kode di atas kita modifikasi:

image

Tidak ada masalah, kan?

Oke. Tulisan ini belum berakhir. Saya capek, maen Point Blank dulu. Nanti sambung lagi🙂

Biar gak panjang, tulisan ini telah saya bagi dua. Lanjutannya di sini.

35 thoughts on “Lebih Jauh Dengan Pointer

  1. Mw tanya pak!
    Saya mempunyai data text sabagai berikut :

    2343426786;susilo;03/11/2010;swasta
    9305190101;sulo;05/12/2010;pelajar
    1001180101;budianto;07/11/2009;mahasiswa
    1003040101;sasto;11/11/2010;pns

    Saya mw nampilkan tanggal 07/11/2009 sampai 05/12/2010 gimana sintak lengkapnya di delphi ?
    Mohon bantuannya, sudah buntu nih.

  2. Ko gak ada kiriman balesannya!
    saya sudah selesai buat programnya dan berhasil, tapi cara membuat reportnya gimana?
    saya biasanya pake rave report kalo ada data base, berhubung programnya cuma .txt karena menggunakan borland developer studio 2006

  3. Terima kasih banyak mas atas bantuannya.
    Programnya sudah saya coba tapi waktu pilih tanggal 03/11/2010 sampai 05/12/2010
    ko gak bisa?
    mau tanya yang kiriman diatas, cara membuat reportnya gimana?
    saya biasanya pake rave report kalo ada data base, berhubung programnya cuma .txt jadi bingung sintaknya?
    karena menggunakan borland developer studio 2006

  4. Btw, bila yang dimaksud adalah menampilkan data paling awal sampai paling akhir, maka sampel di atas bermaksud lain.
    Format tanggal yang dipake dalam sampel adalah
    MM/dd/yyyy
    Sehingga data “03/11/2010” berarti “11 Maret 2010”, bukan “3 November 2010”.

  5. Mas emang hebat, jagoan neon dh. Makasih banget atas ilmunya.
    Tapi cara membuat laporannya gimana? Saya pake rave report. saya sudah coba ko gak bisa2.

  6. Kok gak bisa.
    Saya baru aja coba rave.
    1. Klik kanan ClientDataset, klik Clear Data.
    2. Klik kanan lagi, klik Fields Editor.
    3. Pada window Field Editor, klik kanan, klik New Field…
    4. Masukkan Name: Nomor, Type: String, Size: 30, FieldType: Data
    5. Masukkan Name: Nama, Type: String, Size: 30, FieldType: Data
    6. Masukkan Name: Tanggal, Type: date, FieldType: Data
    7. Masukkan Name: Nama, Type: String, Size: 30, FieldType: Data

    OK. Klik kanan lagi pada ClientDataset1 di form, klik CreateDataset

    Kini kita buat Rave report:

    1. Tambahkan komponen RvProject, RvSystem dan RvDatasetConnection
    2. RvDatasetConnection, atur property Dataset ke ClientDataset1
    3. RvProject, atur property Engine ke RvSystem1
    4. Klik menu tools, Rave Designer
    5. Klik menu File > New Data Object, pilih Direct Data View, klik Next
    6. Klik RvDatasetConnection1, cek Runtime dan Design-Time
    7. Klik Finish
    8. Klik menu Tools > Report Wizard > Simple Table
    9. Klik DataView1 (dataview yang dibuat pada langkah 5 – 7). Klik Next
    10. Pilih Field yang akan ditampilkan. Klik tombol All untuk memilih semua. Klik Next.
    11. Atur posisi (urutan) tiap Field. Klik Next
    12. Atur Judul report serta margin kertas. Klik Next
    13. Atur font tiap-tiap section/band
    14. Klik Generate. Rave Designer akan membuatkan sebuah report baru untuk kita.
    15. Klik menu File > Save As untuk menyimpan file report. Saya sarankan untuk disimpan dalam satu folder dengan aplikasi (File EXE) dan beri nama project1.rav

    Kini untuk tombol Parse Data:

    procedure TForm1.Button1Click(Sender: TObject);
    var
      list: TStringList;
      baris: String;
      Kolom: String;
      i, j:integer;
      PosPemisah: Integer;
      tgl:String;
    begin
      {
      PROSEDUR untuk memecah string CSV ke dalam format data, memasukkannya
      Ke Dataset (ClientDataSet).
      }
    
      list:=TStringList.Create();
      list.Assign(Memo1.lines);
      if list.Count = 0 then
      begin
        List.Free;
        Exit;
      end;
      {
      String terdiri dari 4 kolom, jadi kita akan membuat dataset 4 kolom( 4 field):
      }
      if  ClientDataSet1.active then
        ClientDataSet1.Close;
      ClientDataSet1.Open;
      {
      Kini kita pecah data sesuai tanda pemisah (;)
      ASUMSI: format tanggal adalah MM/DD/YYYY
      }
      //-----------------------------------------+
      ShortDateFormat:='dd/MM/yyyy';           //+
      DateTimePicker1.Format:=ShortDateFormat; //+
      DateTimePicker2.Format:=ShortDateFormat; //+
      DateTimePicker1.date:=Date;              //+
      DateTimePicker2.date:=Date;              //+
      TDateField(ClientDataSet1.Fields[2]).DisplayFormat:= ShortDateFormat;
      //-----------------------------------------+
      for i:=0 to List.Count -1 do
      begin
        ClientDataSet1.Append;
        baris:=list[i];
        PosPemisah:=Pos(';', Baris);
        j:=0;
        while PosPemisah>0 do
        begin
          Kolom:=Copy(Baris, 1, PosPemisah-1);
          Delete(baris, 1, PosPemisah);
          PosPemisah:=pos(';', Baris);
          if j = 2 then
          begin
            //  MM/dd/yyyy -> jangan lupa format tanggal inggris:
            //  akan diubah ke dd/MM/yyyy
            Tgl:=Kolom[4]+Kolom[5]+'/'+Kolom[1]+Kolom[2];
            Delete(Kolom,1, 6);
            Kolom:=tgl+'/'+Kolom;
          end;
          ClientDataSet1.Fields[j].Value:=Kolom;
          inc(j);
        end;
        Kolom:=Baris;
        ClientDataSet1.Fields[j].Value:=Kolom;
        ClientDataSet1.Post;
      end;
      List.Free;
    end;
    

    Harap perhatikan bagian-bagian yang telah saya edit sesuai kebutuhan🙂

    Untuk tombol Filter By Date:

    if not ClientDataSet1.Active then exit;
      ClientDataSet1.Filtered:=False;
      ClientDataSet1.Filter:= 'TANGGAL >= '+ QuotedStr(FormatDateTime(ShortDateFormat, DateTimePicker1.Date)) +
     ' AND TANGGAL <= '+QuotedStr(FormatDateTime(ShortDateFormat, DateTimePicker2.date));
      ClientDataSet1.filtered:=true;
    

    Sekali lagi, perhatikan kode-kode yang telah diedit!

    Nah, untuk preview dan cetak report, saya tambahkan sebuah tombol lagi, anggap namanya tombol Print. Dengan begitu, kita lihat kode tombol Print:

    procedure TForm1.Button4Click(Sender: TObject);
    begin
      RvProject1.ProjectFile:=ExtractFilePath(ParamStr(0)) +'project1.rav';
     (*
    PASTIKAN  FILE REPORT DIDIMPAN SATU FOLDER DENGAN APLIKASI!
    *)
      RvProject1.Open;
      RvProject1.Execute;
      RvProject1.Close;
    end;
    

    Untuk download source code yang telah saya modifikasi:
    Download di sini

  7. Terima kasih banget mas, memang the best dah. Btw ko bisa main logika seperti langsung cepat, caranya gimana mas? Oh ya, td masalah programnya ko cuma bisa nampilin 1 baris saja, padahal program yang sebelumnya tidak?

  8. Maaf mas ternyata bisa, bulannya duluan. ada masalah sedikit, misal klo ada spasi kaya data dibawah ini , script yang
    dirubah sebelah mananya?

    2343426786;susilo 11/03/2010;swasta
    9305190101;sulo 12/05/2010;pns
    1001180101;budianto 11/07/2010;mahasiswa
    1003040101;sasto 11/11/2010;pns
    3455040101;jasto 11/10/2010;karyawan

  9. Jadi antara Nama dan Tanggal tidak dipisah oleh tanda [ ; ] tapi oleh [ spasi ]. Nah, kode tombol Parse harus disesuaikan:

    procedure TForm1.Button1Click(Sender: TObject);
    var
      list: TStringList;
      baris: String;
      temp: String;
      Kolom: String;
      i, j, k:integer;
      PosPemisah: Integer;
      tgl:String;
    begin
      {
      PROSEDUR untuk memecah string CSV ke dalam format data, memasukkannya
      Ke Dataset (ClientDataSet).
      }
    
      list:=TStringList.Create();
      list.Assign(Memo1.lines);
      if list.Count = 0 then
      begin
        List.Free;
        Exit;
      end;
      
      {
      String terdiri dari 4 kolom, jadi kita akan membuat dataset 4 kolom( 4 field):
      }
      if  ClientDataSet1.active then
        ClientDataSet1.Close;
      ClientDataSet1.Open;
      {
      Kini kita pecah data sesuai tanda pemisah (;)
      ASUMSI: format tanggal adalah MM/DD/YYYY
      }
      //-----------------------------------------+
      ShortDateFormat:='dd/MM/yyyy';           //+
      DateTimePicker1.Format:=ShortDateFormat; //+
      DateTimePicker2.Format:=ShortDateFormat; //+
      DateTimePicker1.date:=Date;              //+
      DateTimePicker2.date:=Date;              //+
      TDateField(ClientDataSet1.Fields[2]).DisplayFormat:= ShortDateFormat;
      //-----------------------------------------+
      for i:=0 to List.Count -1 do
      begin
        ClientDataSet1.Append;
        baris:=list[i];
        PosPemisah:=Pos(';', Baris);
        j:=0;
        while PosPemisah>0 do
        begin
          Kolom:=Copy(Baris, 1, PosPemisah-1);
          Delete(baris, 1, PosPemisah);
          PosPemisah:=pos(';', Baris);
          if j = 1 then
          begin
            {
              kasus: String terdiri dari 3 kolom. Di mana kolom kedua (index 0)
              berupa nama dan tanggal yang dipisah oleh spasi.
              Nah, untuk memecah kolm 2 menjadi dua kolom (akhirnya total 4 kolom),
              kita harus memisahkan kolom dua sesuai posisi spasi.
              Ingat, nama kemungkinan terdiri atas nama depan & nama belakang,
              sehingga posisi spasi harus dicari dari belakang, bukan dari depan.   
            }
            temp:='';
            k:=Length(Kolom);
            while Kolom[k]<> ' ' do //cari posisi spasi dari belakang
            begin
              dec(k);          
            end;
            //dapat posisi spasi, potong menjadi 2 bagian: nama dan tanggal.
            temp:=copy(Kolom, 1, k-1);
            Delete(Kolom, 1, k);
            //Masukkan nama ke dataset:
            ClientDataSet1.Fields[j].Value:=Temp;
            inc(j);
            //  MM/dd/yyyy -> jangan lupa format tanggal inggris:
            //  akan diubah ke dd/MM/yyyy
            Tgl:=Kolom[4]+Kolom[5]+'/'+Kolom[1]+Kolom[2];
            Delete(Kolom,1, 6);
            Kolom:=tgl+'/'+Kolom;
          end;
          ClientDataSet1.Fields[j].Value:=Kolom;
          inc(j);
        end;
        Kolom:=Baris;
        ClientDataSet1.Fields[j].Value:=Kolom;
        ClientDataSet1.Post;
      end;
      List.Free;
    end;
    
  10. Mas ada masalah kaya gini, jadi ada data seperti ini:
    05042705051445181NJ B2005 839399
    05042705051453341NJ B2005 345535
    05042805051456431NJ B2006 453454
    05042805051503191NJ B2006 453454
    09002905051624124NJ B2005 434532
    09002905051624124NJ B2005 280605

    pembacaan textnya kaya gini:
    0504 dan 0900=nomor
    270505,280505,290505=tanggal
    1445181=jam
    NJ=nama barang
    B2005=tahun
    839399=kd gudang

    aq dah buat sistem pencariannya, misal aq cari 270505 sampai 280505, yang keluar tuh malah:
    05042705051445181NJ B2005 839399
    05042705051453341NJ B2005 345535
    05042805051456431NJ B2006 453454
    05042805051503191NJ B2006 453454
    09002905051624124NJ B2005 434532
    09002905051624124NJ B2005 280605

    harusnya cuma sampai:
    05042705051445181NJ B2005 839399
    05042705051453341NJ B2005 345535
    05042805051456431NJ B2006 453454
    05042805051503191NJ B2006 453454

    jadi karakter 280505 tuh tetep dibaca , yang sebenarnya bukan tanggal tapi kd gudang.
    mohon bantuanya master!

  11. Ralat mas, ternyata aq dah bisa buatnya. mohon maaf!
    laporannya yang tidak bisa susah banget, waktu saya pake programnya mas yang parsing delphi tuh waktu saya edit laporannya di ravereport ko tidak bisa, saya pake borland developer studio 2006. misal datanya seperti ini:

    05042705051445181NJ B2005 839399 hg 56 jk 23
    05042705051453341NJ B2005 345535 hg 45 jk 21
    05042805051456431NJ B2006 453454 hg 34 jk 11
    05042805051503191NJ B2006 453454 hg 23 jk 45

    nanti yg dibuat laporan tuh tanggal, jam, hg dan jk . misal saya ingin tampilkan tanggal 270505:
    LAPORAN
    270505 hg jk
    14:45:18 56 23
    14:53:34 45 21

    mohon bantunya master!

  12. Mas aq dah buat sintaknya seperti dibawah ini :
    var
    i:integer;
    begin
    for i := 0 to listbox1.Items.Count-1 do
    begin
    memo1.Lines.Text:=copy(listbox1.Items.ValueFromIndex[i],5,6 )+’ ‘+ copy(listbox1.Items.ValueFromIndex[i],11,6 )+”
    +’ ‘+ copy(listbox1.Items.ValueFromIndex[i],34,2 ) +’ ‘+ copy(listbox1.Items.ValueFromIndex[i],37,2 ) +’ ‘+ copy(listbox1.Items.ValueFromIndex[i],40,2)+”
    +’ ‘+ copy(listbox1.Items.ValueFromIndex[i],43,2);
    end;
    end;

    Hasil :
    270505 144518 hg 56 jk 23

    hasilnya ko cm 1 baris ja, saya mau nampilkan semua data yang di atas tapi dipotong perkarakter,
    pingin saya hasilnya kaya begini :

    270505 144518 hg 56 jk 23
    270505 145334 hg 45 jk 21
    280505 145643 hg 34 jk 11
    280505 150319 hg 23 jk 45

    • Jangan pake

      Memo1.Lines.Text := 'String';
      

      tapi pake

      Memo1.Lines.Add ( 'String' );
      

      jadi kode di atas dapat diubah menjadi:

      
      procedure TForm1.Button1Click(Sender: TObject);
      var
        i:integer;
      begin
        for i := 0 to listbox1.Items.Count-1 do
        begin
          memo1.Lines.add(
          copy(listbox1.Items.ValueFromIndex[i],5,6 )+' '
          + copy(listbox1.Items.ValueFromIndex[i],11,6 )+' '
          + copy(listbox1.Items.ValueFromIndex[i],34,2 )+' '
          + copy(listbox1.Items.ValueFromIndex[i],37,2 )+' '
          + copy(listbox1.Items.ValueFromIndex[i],40,2) +' '
          + copy(listbox1.Items.ValueFromIndex[i],43,2)
          );
        end;
      end;
      
      

      Good Luck🙂

  13. Mw tanya lg, misal ada data seperti dibawah ini :

    05042705051445181NJ B2005 839399 hg 56 jk < 23
    05042705051453341NJ B2005 345535 hg < 45 jk 21
    05042805051456431NJ B2006 453454 hg 34 jk 11
    05042805051503191NJ B2006 453454 hg < 23 jk 45

    untuk sintak yang pernah mas buat :

    procedure TForm1.Button1Click(Sender: TObject);

    var

    i:integer;

    begin

    for i := 0 to listbox1.Items.Count-1 do

    begin

    memo1.Lines.add(

    copy(listbox1.Items.ValueFromIndex[i],5,6 )+' '

    + copy(listbox1.Items.ValueFromIndex[i],11,6 )+' '

    + copy(listbox1.Items.ValueFromIndex[i],34,2 )+' '

    + copy(listbox1.Items.ValueFromIndex[i],37,2 )+' '
    + copy(listbox1.Items.ValueFromIndex[i],40,2) +' '

    + copy(listbox1.Items.ValueFromIndex[i],43,2)

    );

    end;

    end;

    sintak di atas cuma copy karakter berdasarkan letak baris karakternya, nanti hasilnya jika
    ada tanda < seperti ini nanti hasilnya tidak sesuai gara-gara tanda < ini. Gimana sintaknya supaya waktu insert DBGridnya hasilnya seperti dibawah ini :

    270505 144518 hg 56 jk < 23
    270505 145334 hg < 45 jk 21
    280505 145643 hg 34 jk 11
    280505 150319 hg < 23 jk 45

    mohon bantunnya master?

  14. Nanti logikanya seperti kaya where di sintak database , jadi where hg=’56’ and jk='< 23' tapi tuh otomatis keluar atau kaya find dalam pencarian atau buat sintak pointer ja / gimn ya mas?
    help me…. master

  15. Klo masalah kasus diatas belum, ada lagi mas, sory banget banyak pertanyaan.
    Kan aq dah buat sintak untuk pewarnaan di DBGrid, terus warna tuh sesuai dengan urutannya,
    kaya gini :

    270505 144518 hg 56 jk < 23
    270505 145334 hg < 45 jk 21
    280505 145643 hg 34 jk 11
    280505 150319 hg < 23 jk 45

    jadi baris DBGrid yang pertama berwarna biru dan 2,3 berwarna hijau trus baris 4 berwarna biru, misal ada lagi 5,6 hijau dan 7 biru dan seterusnya. Kolomnya ada 6, Aq dah buat sintaknya kaya gini:

    if (dbgrid1.DataSource.DataSet.RecNo mod 2)=1 then
    Dbgrid1.Canvas.Brush.Color:=$00E1FFF9
    else
    Dbgrid1.Canvas.Brush.Color = $00FFEBDF;
    dbgrid1.Columns[4].ReadOnly:=true;
    dbgrid1.Columns[6].ReadOnly:=true;

    Dbgrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);

    sintak di atas sudah bisa dalam pewarnaannya, tapi untuk warna pertama kolom 4 dan 6 harusnya
    bisa di edit trus warna kedua harusnya tidak bisa di edit, waktu aq coba untuk mengedit data pada
    kolom 4 dan 6 dengan warna pertama harusnya bisa di edit tapi malah tidak bisa , sintak yang aq buat:

    if (dbgrid1.DataSource.DataSet.RecNo mod 2)=1 then
    Dbgrid1.Canvas.Brush.Color:=$00E1FFF9
    else
    Dbgrid1.Canvas.Brush.Color := $00FFEBDF;
    dbgrid1.Columns[4].ReadOnly:=true;
    dbgrid1.Columns[6].ReadOnly:=true;

    Dbgrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);

  16. Selamat Idul fitri mohon maaf lahir & batin.
    Apabila ada kata yg salah/penulisan yang kurang berkenan saya mohon maaf banget.
    Btw kasus yg diatas gimn ya mas?

  17. Pak mau tanya, saya punya data seperti dibawah ini:

    270505 144518 hg 56 jk < 23
    270505 145334 ig < 45 jk 21
    280505 145643 hg 34 jk 11
    280505 150319 ig < 23 jk 45

    saya mau nyari data: ig , nanti hasilnya yang tampil seperti dibawah ini:

    270505 145334 ig < 45 jk 21
    280505 150319 ig < 23 jk 45

    jadi yang mengandung kata= ig yang muncul.
    Mohon bantuannya.

  18. Mas mw tanya, cara menghapus data di dbgrid gimana caranya? Yg pake cliendataset.
    Aq coba pake cliendataset1.close; terhapus, tapi waktu input lagi data sebelumnya nambah jadi banyak.
    cara menghapus/clearkan supaya tidak ada datanya gimn?

  19. Mohon dibales ya..
    cara buat rave report dalam pewarnaan gimana?
    Maksudnya, klo di dbgridnya tulisannya warnanya merah nanti otomatis di rave reportnya juga menyesuaikan warna yang ada di dbgridnya.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s