OCCURS DEPENDING ON

Tabel yang panjangnya mengikuti isi data, aturan penempatan pengendalinya, dan jebakannya.

Daftar isi

Klausa OCCURS DEPENDING ON membuat panjang tabel ditentukan oleh sebuah item pengendali saat program berjalan, sehingga satu definisi dapat menampung daftar yang jumlah entriannya berubah-ubah. Topik ini membahas sintaks klausanya, aturan penempatan item pengendali, perubahan panjang record yang mengikutinya, dan jebakan yang timbul saat pengendali tidak dikelola dengan benar. Contoh utamanya berupa daftar belanja yang diisi tiga entri, lalu ditampilkan dua kali dengan panjang yang berbeda.

Sintaks dan aturan penempatan pengendali#

Bentuk klausanya adalah OCCURS 1 TO 8 TIMES DEPENDING ON JUMLAH-BELI, yang menyatakan panjang minimum, panjang maksimum, dan nama pengendalinya. Memori yang dialokasikan tetap sebesar panjang maksimum, sedangkan panjang efektif record mengikuti nilai pengendali pada saat itu. Item pengendali wajib berupa bilangan bulat tanpa tanda dan wajib dideklarasikan sebelum item ber-OCCURS di dalam kode sumber, biasanya sebagai record 01 tersendiri atau sebagai field yang mendahului tabel di dalam record yang sama. Aturan urutan ini berlaku umum pada compiler COBOL, dan pelanggarannya ditolak dengan pesan seperti error: 'JUMLAH-X' OCCURS DEPENDING ON field item invalid here.

Item yang ditempatkan setelah tabel ber-OCCURS DEPENDING ON di dalam record yang sama akan bergeser posisi setiap kali pengendali berubah. Karena itu, tabel ber-OCCURS DEPENDING ON lazim diletakkan paling akhir di dalam recordnya, dan field yang harus tetap pada tempatnya dipisahkan ke record lain. Pengendali juga tidak boleh menjadi bagian dari tabel, karena posisi field di dalam tabel itu bergantung pada panjang tabelnya.

Nilai pengendali dapat berubah berkali-kali selama program berjalan, dan setiap perubahan langsung mengatur ulang panjang efektif record. Byte milik elemen di luar panjang efektif tetap berada di memori, tetapi tidak lagi dianggap bagian record sehingga tidak layak dibaca. Pemindahan record ber-OCCURS DEPENDING ON ke record lain yang strukturnya sama hanya memindahkan data sepanjang panjang efektifnya saat itu. Sifat ini pula yang membuat klausanya banyak dipakai untuk record berpanjang variabel pada berkas, yang jumlah kemunculannya baru diketahui setelah data dibaca.

Daftar belanja dengan panjang dinamis#

Program berikut menyimpan daftar belanja yang panjangnya dikendalikan oleh JUMLAH-BELI. Tiga entri diisi terlebih dahulu, seluruh entri ditampilkan melalui perulangan yang batasnya adalah pengendali itu sendiri, lalu pengendali diturunkan menjadi 2 dan daftar yang sama ditampilkan kembali.

cobol odo.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. ODO-BELANJA.
      *--------------------------------------------------------------
      * OCCURS DEPENDING ON: panjang tabel mengikuti pengendali.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 JUMLAH-BELI PIC 9(2) VALUE 3.
       01 DAFTAR-BELANJA.
          05 ITEM-BELI OCCURS 1 TO 8 TIMES
               DEPENDING ON JUMLAH-BELI.
             10 NAMA-BELI   PIC X(10).
             10 BANYAK-BELI PIC 9(2).
       01 I PIC 9(2).
       PROCEDURE DIVISION.
       UTAMA.
           MOVE "Buku Tulis" TO NAMA-BELI(1)
           MOVE 4 TO BANYAK-BELI(1)
           MOVE "Pensil    " TO NAMA-BELI(2)
           MOVE 6 TO BANYAK-BELI(2)
           MOVE "Penghapus" TO NAMA-BELI(3)
           MOVE 2 TO BANYAK-BELI(3)
           PERFORM TAMPIL-SATU
               VARYING I FROM 1 BY 1 UNTIL I > JUMLAH-BELI
           MOVE 2 TO JUMLAH-BELI
           DISPLAY "Pengendali kini " JUMLAH-BELI
           PERFORM TAMPIL-SATU
               VARYING I FROM 1 BY 1 UNTIL I > JUMLAH-BELI
           STOP RUN.
       TAMPIL-SATU.
           DISPLAY "Elemen " I " : " NAMA-BELI(I) "|"
               BANYAK-BELI(I).
text Keluaran
Elemen 01 : Buku Tulis|04
Elemen 02 : Pensil    |06
Elemen 03 : Penghapus |02
Pengendali kini 02
Elemen 01 : Buku Tulis|04
Elemen 02 : Pensil    |06

Isi tabel tidak berubah di antara kedua penampilan, tetapi baris ketiga hilang pada penampilan kedua karena panjang efektif DAFTAR-BELANJA kini mengikuti nilai 2. Perulangan yang batasnya I > JUMLAH-BELI berhenti dengan sendirinya pada batas baru tersebut. Pola inilah yang membuat OCCURS DEPENDING ON cocok untuk data berpanjang variabel seperti baris transaksi pada satu nota, yang jumlahnya baru diketahui ketika data dibaca.

Urutan langkah yang aman untuk tabel semacam ini adalah mengisi pengendali terlebih dahulu, mengisi elemen pada subskrip 1 sampai nilai pengendali, lalu menelusurinya dengan batas yang sama. Pada program di atas, JUMLAH-BELI sudah bernilai 3 sejak deklarasi melalui klausa VALUE, sehingga pengisiannya langsung sah. Apabila daftar dibaca dari luar program, nilai pengendali diisi dari data tersebut sebelum elemen pertama ditulis. Disiplin yang sama berlaku saat panjang daftar bertambah, yaitu naikkan pengendalinya setelah entri barunya terisi. Elemen keempat sampai kedelapan pada program ini tetap menempati memori karena alokasinya mengikuti panjang maksimum, tetapi byte tersebut berada di luar panjang efektif selama pengendali bernilai 2.

Reproduksi keluaran di atas dengan perintah berikut, lalu jalankan ./odo.

bash
# kompilasi program tabel panjang variabel
cobc -x odo.cbl

Kesalahan umum#

  • Meletakkan pengendali setelah tabel ber-OCCURS DEPENDING ON. Aturan urutan deklarasi menuntut pengendali mendahului tabelnya, dan pelanggarannya ditolak compiler dengan pesan error: 'JUMLAH-X' OCCURS DEPENDING ON field item invalid here. Pindahkan pengendali ke record 01 tersendiri atau ke field sebelum tabel.
  • Mengakses tabel sebelum pengendali diisi. Field PIC 9(2) tanpa VALUE berisi spasi, sehingga kondisi seperti I > JUMLAH-BELI tidak dapat dievaluasi dengan benar dan panjang record menjadi tidak sah. Isi pengendali lebih dahulu, atau beri nilai awal melalui klausa VALUE.
  • Membaca elemen melebihi nilai pengendali. Akses seperti NAMA-BELI(5) saat pengendali bernilai 3 tidak ditolak, tetapi byte yang dibaca bukan bagian dari record yang sah dan berisi sisa memori. Gunakan nilai pengendali sebagai batas atas setiap penelusuran.
  • Menganggap posisi item setelah tabel tidak berubah. Item yang menyusul tabel ber-OCCURS DEPENDING ON di dalam record yang sama ikut bergeser setiap kali pengendali berubah, sehingga pembacaan field tersebut perlu dilakukan setelah pengendali bernilai final. Letakkan tabel di akhir record atau pisahkan fieldnya.

Ringkasan#

  • OCCURS n TO m TIMES DEPENDING ON mengalokasikan memori sebesar panjang maksimum, sedangkan panjang efektif record mengikuti nilai pengendali saat program berjalan.
  • Pengendali wajib berupa bilangan bulat tanpa tanda yang dideklarasikan sebelum item ber-OCCURS, dan item yang menyusul tabel di dalam record yang sama ikut bergeser saat pengendali berubah.
  • Setiap akses tabel perlu pengendali yang sudah terisi dan subskrip yang tidak melebihi nilai pengendali, karena di luar itu isi byte tidak terdefinisi.

Referensi#