OCCURS

Tabel ukuran tetap berdimensi satu dan banyak beserta cara menata elemennya.

Daftar isi

Klausa OCCURS menyediakan elemen data yang berulang, sehingga satu definisi dapat menampung banyak nilai dengan tata letak yang seragam di memori. Topik ini membahas tabel ukuran tetap berdimensi satu, tabel yang dibentuk dari grup item, dan tabel berdimensi dua, beserta cara menghitung ukuran memorinya. Demo utamanya berupa program yang mengisi tabel dengan lima nilai, menelusurinya dengan PERFORM VARYING, lalu menjumlahkan isinya.

Mengulang item dengan OCCURS#

OCCURS n TIMES mengulang definisi sebuah item data sebanyak n kali, dan struktur hasilnya disebut tabel (table), yaitu padanan konsep array pada bahasa pemrograman lain. Deklarasi 05 NILAI-HARI PIC 9(3) OCCURS 5 TIMES menyediakan lima field numerik tiga digit yang berdampingan di memori, sehingga grup NILAI-HARIAN yang membungkusnya berukuran 15 byte. Setiap elemen diakses melalui subskrip (subscript) yang ditulis dalam tanda kurung setelah nama item. Penomorannya berbasis satu, artinya elemen pertama adalah NILAI-HARI(1) dan bukan NILAI-HARI(0). Konvensi ini berbeda dari banyak bahasa modern yang memulai penomoran dari nol.

Subskrip boleh berupa literal maupun variabel, sehingga satu pernyataan seperti ADD NILAI-HARI(I) TO TOTAL-NILAI cukup ditulis sekali di dalam badan perulangan. PERFORM VARYING menjadi pasangan alami OCCURS karena variabel pengendalinya berjalan dari 1 sampai jumlah pengulangan. Program berikut mengisi lima nilai penjualan harian ke dalam tabel, menampilkannya satu per satu, lalu menjumlahkan seluruhnya.

cobol occurs.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. OCCURS-DASAR.
      *--------------------------------------------------------------
      * Tabel berdimensi satu: pengisian, penelusuran, penjumlahan.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 NILAI-HARIAN.
          05 NILAI-HARI PIC 9(3) OCCURS 5 TIMES.
       01 TOTAL-NILAI PIC 9(5) VALUE 0.
       01 I           PIC 9(2).
       PROCEDURE DIVISION.
       UTAMA.
           MOVE 80 TO NILAI-HARI(1)
           MOVE 75 TO NILAI-HARI(2)
           MOVE 90 TO NILAI-HARI(3)
           MOVE 85 TO NILAI-HARI(4)
           MOVE 70 TO NILAI-HARI(5)
           PERFORM TAMPIL-SATU
               VARYING I FROM 1 BY 1 UNTIL I > 5
           PERFORM JUMLAHKAN-SATU
               VARYING I FROM 1 BY 1 UNTIL I > 5
           DISPLAY "Total lima hari : " TOTAL-NILAI
           STOP RUN.
       TAMPIL-SATU.
           DISPLAY "Hari ke-" I " : " NILAI-HARI(I).
       JUMLAHKAN-SATU.
           ADD NILAI-HARI(I) TO TOTAL-NILAI.
text Keluaran
Hari ke-01 : 080
Hari ke-02 : 075
Hari ke-03 : 090
Hari ke-04 : 085
Hari ke-05 : 070
Total lima hari : 00400

Angka seperti 080 dan 00400 memuat nol di depan karena picture 9(3) dan 9(5) menyimpan digit dengan lebar tetap. Perulangan PERFORM TAMPIL-SATU VARYING I FROM 1 BY 1 UNTIL I > 5 menaikkan I dari 1 sampai 5, dan pada setiap iterasi subskrip NILAI-HARI(I) menunjuk elemen yang berbeda. Perulangan kedua menjumlahkan isi tabel dengan pola yang sama, sehingga angka 00400 pada baris terakhir merupakan hasil penjumlahan 80, 75, 90, 85, dan 70.

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

bash
# kompilasi program tabel berdimensi satu
cobc -x occurs.cbl

Tabel dari grup item#

Elemen tabel paling sering berupa grup, yaitu satu item level 05 yang diberi OCCURS dan memuat beberapa item anak sekaligus. Pola ini memodelkan daftar record secara alami, misalnya daftar nilai kelas yang setiap barisnya memuat nama dan nilai satu siswa. Ukuran tabelnya dihitung dengan mengalikan jumlah pengulangan dengan ukuran satu elemen. REKAMAN-KELAS pada program berikut berukuran 33 byte karena terdiri atas tiga pengulangan yang masing-masing berukuran 11 byte.

cobol tabel-grup.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. TABEL-GRUP.
      *--------------------------------------------------------------
      * Tabel dari grup: setiap elemen memuat beberapa field.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 REKAMAN-KELAS.
          05 DATA-SISWA OCCURS 3 TIMES.
             10 NAMA-SISWA  PIC X(8).
             10 NILAI-SISWA PIC 9(3).
       01 I PIC 9(2).
       PROCEDURE DIVISION.
       UTAMA.
           MOVE "Ali"   TO NAMA-SISWA(1)
           MOVE 85      TO NILAI-SISWA(1)
           MOVE "Budi"  TO NAMA-SISWA(2)
           MOVE 78      TO NILAI-SISWA(2)
           MOVE "Citra" TO NAMA-SISWA(3)
           MOVE 92      TO NILAI-SISWA(3)
           PERFORM TAMPIL-SATU
               VARYING I FROM 1 BY 1 UNTIL I > 3
           DISPLAY "[" REKAMAN-KELAS "]"
           STOP RUN.
       TAMPIL-SATU.
           DISPLAY NAMA-SISWA(I) "|" NILAI-SISWA(I).
text Keluaran
Ali     |085
Budi    |078
Citra   |092
[Ali     085Budi    078Citra   092]

Tiga baris pertama menampilkan satu elemen tabel per baris, dengan subskrip I yang sama dipakai untuk kedua field anaknya, yaitu NAMA-SISWA(I) dan NILAI-SISWA(I). Baris keempat menampilkan isi grup REKAMAN-KELAS sebagai satu rangkaian byte. Isinya berupa gabungan ketiga entri tanpa pemisah, lengkap dengan spasi pengisi picture X(8), karena tabel dari grup tidak lebih dari rangkaian byte yang berulang secara teratur.

Reproduksi keluaran di atas dengan perintah berikut, lalu jalankan ./tabel-grup.

bash
# kompilasi program tabel dari grup
cobc -x tabel-grup.cbl

Dimensi dua dengan OCCURS bersarang#

Tabel berdimensi dua dibentuk dengan menempatkan OCCURS di dalam item yang juga ber-OCCURS. Deklarasi BARIS-GRID OCCURS 3 TIMES yang memuat NILAI-SEL PIC 9(2) OCCURS 4 TIMES menghasilkan dua belas elemen berukuran 24 byte. Aksesnya memakai dua subskrip dalam satu tanda kurung, misalnya NILAI-SEL(2, 3). Subskrip pertama memilih pengulangan BARIS-GRID, sedangkan subskrip kedua memilih pengulangan NILAI-SEL. Koma pemisah boleh diganti spasi, sehingga NILAI-SEL(2 3) bermakna sama.

cobol dimensi-dua.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. DIMENSI-DUA.
      *--------------------------------------------------------------
      * Tabel berdimensi dua: OCCURS di dalam OCCURS.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 GRID-NILAI.
          05 BARIS-GRID OCCURS 3 TIMES.
             10 NILAI-SEL PIC 9(2) OCCURS 4 TIMES.
       01 I PIC 9(2).
       01 J PIC 9(2).
       PROCEDURE DIVISION.
       UTAMA.
           PERFORM VARYING I FROM 1 BY 1 UNTIL I > 3
               PERFORM VARYING J FROM 1 BY 1 UNTIL J > 4
                   COMPUTE NILAI-SEL(I, J) = I * 10 + J
               END-PERFORM
           END-PERFORM
           DISPLAY "Sel (2, 3) : " NILAI-SEL(2, 3)
           PERFORM VARYING I FROM 1 BY 1 UNTIL I > 3
               DISPLAY "Baris " I " : "
                   NILAI-SEL(I, 1) " "
                   NILAI-SEL(I, 2) " "
                   NILAI-SEL(I, 3) " "
                   NILAI-SEL(I, 4)
           END-PERFORM
           STOP RUN.
text Keluaran
Sel (2, 3) : 23
Baris 01 : 11 12 13 14
Baris 02 : 21 22 23 24
Baris 03 : 31 32 33 34

Pengisian dilakukan oleh sepasang PERFORM VARYING yang bersarang, sehingga setiap kombinasi I dan J diproses tepat satu kali. Rumus I * 10 + J dipilih agar pola posisi setiap sel langsung terbaca dari keluarannya, misalnya sel dengan subskrip (2, 3) bernilai 23. Penelusuran per baris pada perulangan terakhir memperlihatkan cara membaca satu dimensi secara utuh sementara dimensi lainnya dikunci pada satu nilai.

Reproduksi keluaran di atas dengan perintah berikut, lalu jalankan ./dimensi-dua.

bash
# kompilasi program tabel berdimensi dua
cobc -x dimensi-dua.cbl

Kesalahan umum#

  • Mengira penomoran elemen berbasis nol. Subskrip literal nol seperti NILAI-HARI(0) ditolak saat kompilasi, sedangkan subskrip variabel yang bernilai nol tidak diperiksa dan membaca byte yang berada sebelum tabel tanpa peringatan apa pun. Mulai perulangan dari 1 dan akhiri pada jumlah pengulangannya.
  • Menghitung ukuran record tanpa memperhitungkan pengulangan. Record REKAMAN-KELAS bukan berukuran 11 byte melainkan 33 byte karena ukuran record level 01 mencakup seluruh pengulangan di dalamnya. Kesalahan ini muncul saat menaksir kebutuhan memori atau membaca record ber-OCCURS dari berkas.
  • Menuliskan OCCURS pada level 01. Standar COBOL tidak mengizinkan OCCURS pada entri level 01, dan pola yang benar adalah record 01 tanpa OCCURS yang membungkus item level 05 ber-OCCURS. GnuCOBOL menerima bentuk level 01 sebagai perluasan, tetapi kebiasaan tersebut menurunkan portabilitas program.

Ringkasan#

  • OCCURS n TIMES mengulang satu definisi item menjadi tabel berukuran tetap, dan setiap elemennya diakses dengan subskrip berbasis satu yang boleh berupa literal maupun variabel.
  • Tabel dari grup, yaitu item level 05 ber-OCCURS yang memuat beberapa field anak, merupakan pola paling lazim untuk mendaftar record dengan banyak field.
  • Ukuran tabel dihitung dari jumlah pengulangan dikalikan ukuran satu elemen, dan dimensi dua ditulis sebagai OCCURS bersarang yang diakses dengan satu subskrip per dimensi.

Referensi#