Subskrip dan INDEXED BY

Akses elemen dengan subskrip dan register indeks, verb SET, serta konsekuensi kinerjanya.

Daftar isi

Tabel COBOL dapat diakses melalui dua mekanisme, yaitu subskrip yang ditulis setiap kali elemen dirujuk dan register indeks yang dideklarasikan dengan klausa INDEXED BY. Topik ini membahas subskrip literal, variabel, dan relatif, pengisian serta penggeseran register indeks dengan verb SET, perbedaan kinerja keduanya, dan risiko akses di luar batas tabel. Dua program utuh memperagakan seluruh mekanisme tersebut pada tabel yang sama.

Subskrip literal, variabel, dan relatif#

Subskrip menyatakan posisi elemen yang diinginkan dan mengikuti tiga bentuk. Bentuk literal seperti NILAI-HARI(3) menunjuk satu elemen yang tetap, bentuk variabel seperti NILAI-HARI(I) menunjuk elemen yang bergantung isi I, dan bentuk relatif seperti NILAI-HARI(POSISI + 1) menggeser posisi dari sebuah nilai. Pada setiap akses, compiler menghitung letak byte elemen dari subskrip tersebut, sehingga bentuk yang dipilih tidak mengubah isi tabel melainkan hanya cara menunjuknya. Nilai yang sah berada pada rentang 1 sampai jumlah pengulangan klausanya.

cobol subskrip.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. SUBSKRIP-UJI.
      *--------------------------------------------------------------
      * Subskrip literal, variabel, dan relatif pada tabel.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 NILAI-HARIAN.
          05 NILAI-HARI PIC 9(3) OCCURS 5 TIMES.
       01 I      PIC 9(2).
       01 POSISI 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
           MOVE 2 TO POSISI
           DISPLAY "Subskrip variabel : " NILAI-HARI(POSISI)
           DISPLAY "Subskrip relatif  : " NILAI-HARI(POSISI + 1)
           STOP RUN.
       TAMPIL-SATU.
           DISPLAY "Literal " I " : " NILAI-HARI(I).
text Keluaran
Literal 01 : 080
Literal 02 : 075
Literal 03 : 090
Literal 04 : 085
Literal 05 : 070
Subskrip variabel : 075
Subskrip relatif  : 090

Lima baris pertama berasal dari subskrip variabel NILAI-HARI(I) yang dikendalikan PERFORM VARYING, persis seperti pola penelusuran tabel pada umumnya. Dua baris terakhir memperlihatkan perbedaan bentuk yang tersisa, yaitu NILAI-HARI(POSISI) yang bernilai 075 karena POSISI berisi 2 dan NILAI-HARI(POSISI + 1) yang bernilai 090 karena posisinya digeser satu. Bentuk relatif berguna saat logika mengambil elemen berikutnya atau sebelumnya dari posisi yang sedang dipegang.

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

bash
# kompilasi program subskrip literal dan variabel
cobc -x subskrip.cbl

INDEXED BY dan verb SET#

Klausa INDEXED BY pada entri ber-OCCURS mendeklarasikan register indeks (index), yaitu item khusus yang menyimpan jarak byte elemen dari awal tabel dan bukan nomor elemennya. Karena isinya berupa jarak, register indeks hanya boleh diatur melalui verb SET. SET IDX-STOK TO 1 mengisi register tersebut dengan sebuah nilai, SET IDX-STOK UP BY 1 menaikkan nilainya, dan SET IDX-STOK DOWN BY 1 menurunkannya. Register indeks dipakai sebagai subskrip dalam bentuk JUMLAH-STOK(IDX-STOK) dan boleh diuji dalam kondisi seperti UNTIL IDX-STOK > 5. Untuk membaca posisi yang sedang ditunjuk ke dalam variabel biasa, gunakan bentuk SET POSISI TO IDX-STOK.

cobol indeks-set.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. INDEKS-SET.
      *--------------------------------------------------------------
      * Register indeks INDEXED BY: diisi dan digeser lewat verb SET.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 STOK-GUDANG.
          05 JUMLAH-STOK PIC 9(4) OCCURS 5 TIMES
               INDEXED BY IDX-STOK.
       01 I          PIC 9(2).
       01 POSISI     PIC 9(2).
       PROCEDURE DIVISION.
       UTAMA.
           PERFORM ISI-SATU
               VARYING I FROM 1 BY 1 UNTIL I > 5
           SET IDX-STOK TO 1
           PERFORM TAMPIL-INDEKS
               UNTIL IDX-STOK > 5
           SET IDX-STOK TO 4
           SET POSISI TO IDX-STOK
           DISPLAY "Indeks berhenti di posisi " POSISI
           DISPLAY "Elemen pada posisi itu    : " JUMLAH-STOK(IDX-STOK)
           SET IDX-STOK DOWN BY 2
           SET POSISI TO IDX-STOK
           DISPLAY "Setelah diturunkan dua    : " JUMLAH-STOK(IDX-STOK)
           STOP RUN.
       ISI-SATU.
           COMPUTE JUMLAH-STOK(I) = I * 100.
       TAMPIL-INDEKS.
           SET POSISI TO IDX-STOK
           DISPLAY "Indeks " POSISI " : " JUMLAH-STOK(IDX-STOK)
           SET IDX-STOK UP BY 1.
text Keluaran
Indeks 01 : 0100
Indeks 02 : 0200
Indeks 03 : 0300
Indeks 04 : 0400
Indeks 05 : 0500
Indeks berhenti di posisi 04
Elemen pada posisi itu    : 0400
Setelah diturunkan dua    : 0200

Perulangan PERFORM TAMPIL-INDEKS UNTIL IDX-STOK > 5 menelusuri tabel tanpa variabel penghitung tambahan, karena peningkatan posisi dikerjakan oleh SET IDX-STOK UP BY 1 di akhir paragraf TAMPIL-INDEKS. Syarat perulangan diuji sebelum setiap iterasi, sehingga setelah iterasi kelima indeks bernilai 6 dan perulangan berhenti. Dua baris terakhir menunjukkan SET IDX-STOK DOWN BY 2 yang mundur dua posisi dari 4 menuju 2, dan elemen yang dibaca mengikuti posisi barunya.

Reproduksi keluaran di atas dengan perintah berikut, lalu jalankan ./indeks-set.

bash
# kompilasi program register indeks dengan SET
cobc -x indeks-set.cbl

Kinerja dan pemeriksaan batas#

Perbedaan kedua mekanisme terletak pada kapan jarak byte dihitung. Subskrip dihitung ulang pada setiap akses, sedangkan register indeks menyimpan jarak tersebut sehingga aksesnya tidak perlu perhitungan baru. Pada tabel kecil perbedaannya dapat diabaikan, tetapi pada tabel besar yang ditelusuri berulang kali penggunaan indeks mengurangi perhitungan pada setiap iterasi. Karena itu, tabel yang menjadi sasaran SEARCH dideklarasikan dengan INDEXED BY, seperti dibahas pada pencarian tabel.

Akses di luar batas tabel merupakan risiko yang terpisah dari pilihan mekanisme. GnuCOBOL menolak subskrip literal yang keluar batas sejak waktu kompilasi, sedangkan subskrip variabel yang bernilai di luar rentang tidak diperiksa sama sekali pada kompilasi bawaan dan menyebabkan perilaku tak terdefinisi, misalnya membaca atau merusak byte milik data lain. Bendera cobc -debug memasang pemeriksaan batas saat program berjalan dan menghentikannya dengan pesan seperti error: subscript of 'X' out of bounds: 7 disertai catatan batas maksimum subskripnya. Pasang bendera tersebut pada masa pengembangan untuk menangkap akses di luar batas lebih dini.

Kesalahan umum#

  • Mengatur register indeks dengan verb selain SET. Standar COBOL hanya mengizinkan pengubahan indeks melalui SET, dan sebagian compiler menolak bentuk lain dengan pesan error. Gunakan SET ... TO, SET ... UP BY, dan SET ... DOWN BY untuk seluruh pengaturannya.
  • Mengakses tabel melalui indeks yang belum pernah diisi. Nilai awal register indeks yang baru dideklarasikan tidak terdefinisi, sehingga rujukan pertama menunjuk posisi sembarangan. Isi indeks dengan SET IDX TO 1 sebelum pemakaian pertamanya.
  • Menganggap indeks menyimpan nomor elemen. Register indeks menyimpan jarak byte, sehingga nilainya tidak boleh dihitung seperti variabel biasa dan tidak boleh diisi dengan aritmetika ADD atau COMPUTE. Salin posisinya ke variabel numerik dengan SET POSISI TO IDX apabila nomor posisi diperlukan.

Ringkasan#

  • Subskrip berbentuk literal, variabel, atau relatif dihitung ulang pada setiap akses, sedangkan register indeks dari INDEXED BY menyimpan jarak byte sehingga aksesnya lebih ringan pada tabel besar.
  • Register indeks hanya diatur melalui verb SET dalam bentuk TO, UP BY, dan DOWN BY, serta dibaca ke variabel numerik melalui SET POSISI TO IDX.
  • Subskrip literal di luar batas ditolak saat kompilasi, sedangkan subskrip variabel yang keluar batas menyebabkan perilaku tak terdefinisi dan hanya terdeteksi bila program dikompilasi dengan cobc -debug.

Referensi#