Modifikasi Referensi

Ekstraksi substring dari field dengan notasi posisi awal dan panjang.

Daftar isi

Modifikasi referensi (reference modification) menyebut potongan sebuah field dengan notasi FIELD(awal:panjang), sehingga substring dapat diambil, dibandingkan, dan ditimpa tanpa mendefinisikan field tambahan. Topik ini membahas pemakaian notasi tersebut pada MOVE, IF, dan DISPLAY, penggunaan awal dan panjang berupa variabel, serta pemeriksaan batas yang menjaga potongan tetap berada di dalam field. Demo utamanya mengambil prefiks dan sufiks kode produk, mengganti potongan tengah field, dan menolak potongan yang melewati ujungnya.

Notasi awal dan panjang literal#

Notasi KODE-PRODUK(1:3) menyebut tiga karakter dimulai dari posisi pertama field, dan penomoran posisinya berbasis satu sehingga karakter pertama adalah posisi 1. Hasilnya berupa item alfanumerik sepanjang yang disebutkan, sehingga dapat digunakan pada semua posisi yang menerima field alfanumerik, yaitu sebagai sumber atau tujuan MOVE, pembanding pada IF, dan operand DISPLAY. Notasi yang sama sah dipakai pada verb lain yang menerima field alfanumerik, misalnya sebagai sumber pada STRING atau sasaran INSPECT, sehingga potongan field dapat dirakit dan diganti tanpa field perantara baru. Program berikut membedah kode produk sepuluh karakter menjadi prefiks kota, nomor seri, dan sufiks.

cobol kode-prefiks.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. KODE-PREFIKS.
      *--------------------------------------------------------------
      * Modifikasi referensi: awal dan panjang literal.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 KODE-PRODUK PIC X(10) VALUE "JKT-4021-B".
       01 KODE-KOTA   PIC X(3).
       PROCEDURE DIVISION.
       UTAMA.
           MOVE KODE-PRODUK(1:3) TO KODE-KOTA
           DISPLAY "Prefiks : " KODE-KOTA
           DISPLAY "Sufiks  : " KODE-PRODUK(10:1)
           IF KODE-PRODUK(5:4) = "4021"
               DISPLAY "Nomor   : cocok"
           END-IF
           MOVE "SGU" TO KODE-PRODUK(1:3)
           DISPLAY "Baru    : " KODE-PRODUK
           STOP RUN.
text Keluaran
Prefiks : JKT
Sufiks  : B
Nomor   : cocok
Baru    : SGU-4021-B

Potongan (1:3) mengisi KODE-KOTA dengan prefiks JKT, pembanding (5:4) = "4021" bernilai benar tanpa field perantara, dan sufiks diambil dari posisi 10 sepanjang satu karakter. Baris terakhir memperlihatkan potongan sebagai tujuan, yaitu MOVE "SGU" TO KODE-PRODUK(1:3) menimpa tiga karakter pertama di tempat sehingga kode menjadi SGU-4021-B tanpa merakit field baru. Sifat pengubahan di tempat inilah yang membuat modifikasi referensi sering dipakai untuk membetulkan sebagian isi record.

Reproduksi keluaran di atas dengan perintah berikut, lalu jalankan ./kode-prefiks.

bash
# kompilasi program bedah kode produk
cobc -x kode-prefiks.cbl

Posisi dan panjang berupa variabel#

Angka pada notasi (awal:panjang) boleh berupa variabel numerik bilangan bulat, sehingga satu pernyataan dapat memotong posisi yang berbeda mengikuti isi data. Sebagai tujuan, potongan dengan panjang n menampung tepat n karakter, sehingga literal yang lebih panjang terpotong tanpa pesan dan yang lebih pendek diisi spasi. Variabel posisi dan variabel panjang juga harus berisi bilangan bulat positif saat pernyataan dijalankan, dan field numerik biasa seperti PIC 9(2) sudah memenuhi syarat itu. Program berikut menampilkan dan menimpa potongan tengah sebuah kalimat dengan posisi dan panjang yang dibaca dari variabel.

cobol posisi-variabel.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. POSISI-VARIABEL.
      *--------------------------------------------------------------
      * Modifikasi referensi dengan awal dan panjang variabel.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 KALIMAT PIC X(17) VALUE "statistika dasar".
       01 AWAL    PIC 9(2) VALUE 12.
       01 PANJANG PIC 9(2) VALUE 5.
       PROCEDURE DIVISION.
       UTAMA.
           DISPLAY "Sebelum : [" KALIMAT "]"
           DISPLAY "Potong  : [" KALIMAT(AWAL:PANJANG) "]"
           MOVE "lanjut" TO KALIMAT(AWAL:PANJANG)
           DISPLAY "Sesudah : [" KALIMAT "]"
           STOP RUN.
text Keluaran
Sebelum : [statistika dasar ]
Potong  : [dasar]
Sesudah : [statistika lanju ]

Variabel AWAL bernilai 12 dan PANJANG bernilai 5 memotong karakter kedua belas sampai keenam belas, yaitu kata “dasar” pada kalimat “statistika dasar”. Pemindahan “lanjut” yang panjangnya enam karakter ke potongan lima karakter hanya memindahkan “lanju”, sehingga hasilnya “statistika lanju” dengan satu spasi pengisi tersisa. Batas panjang inilah alasan panjang potongan harus dihitung dengan tepat, bukan diperlakukan sebagai batas maksimum semata.

Reproduksi keluaran di atas dengan perintah berikut, lalu jalankan ./posisi-variabel.

bash
# kompilasi program potongan dengan posisi variabel
cobc -x posisi-variabel.cbl

Pemeriksaan batas field#

Potongan sah apabila awal minimal 1 dan awal + panjang - 1 tidak melebihi panjang field, dan pelanggarannya tidak selalu terlihat. Tanpa pemeriksaan tambahan, GnuCOBOL membaca byte di luar field tanpa pesan apa pun, sedangkan kompilasi dengan bendera -debug menyisipkan pemeriksaan saat berjalan yang menghentikan program dengan pesan error semacam offset of 'KODE' out of bounds. Pesan error tersebut menyebut posisi yang diminta beserta batas field, sehingga penyebab pelanggaran terbaca langsung tanpa alat bantu debug. Cara yang berlaku di semua lingkungan adalah memeriksa batas dengan register khusus LENGTH OF sebelum potongan dipakai.

cobol batas-luar.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. BATAS-LUAR.
      *--------------------------------------------------------------
      * Pemeriksaan batas sebelum modifikasi referensi.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 KODE-PRODUK PIC X(10) VALUE "JKT-4021-B".
       01 AWAL        PIC 9(2) VALUE 8.
       01 PANJANG     PIC 9(2) VALUE 3.
       PROCEDURE DIVISION.
       UTAMA.
           IF AWAL >= 1 AND AWAL + PANJANG - 1 <= LENGTH OF KODE-PRODUK
               DISPLAY "Potongan : " KODE-PRODUK(AWAL:PANJANG)
           ELSE
               DISPLAY "Ditolak  : batas melewati ujung field"
           END-IF
           MOVE 12 TO AWAL
           IF AWAL >= 1 AND AWAL + PANJANG - 1 <= LENGTH OF KODE-PRODUK
               DISPLAY "Potongan : " KODE-PRODUK(AWAL:PANJANG)
           ELSE
               DISPLAY "Ditolak  : batas melewati ujung field"
           END-IF
           STOP RUN.
text Keluaran
Potongan : 1-B
Ditolak  : batas melewati ujung field

Percobaan pertama memotong posisi 8 sampai 10 dari field yang panjangnya 10 karakter, sehingga potongan “1-B” sah dan ditampilkan. Percobaan kedua menggeser AWAL ke 12, dan kondisi AWAL + PANJANG - 1 <= LENGTH OF KODE-PRODUK menjadi salah sehingga cabang ELSE menolaknya dengan pesan yang jelas. Pola pemeriksaan ini dipakai sebelum setiap pemotongan yang posisinya berasal dari data, misalnya posisi hasil pencarian dengan INSPECT.

Reproduksi keluaran di atas dengan perintah berikut, lalu jalankan ./batas-luar.

bash
# kompilasi program pemeriksaan batas potongan
cobc -x batas-luar.cbl

Kesalahan umum#

  • Menghitung posisi dari nol. Penomoran modifikasi referensi berbasis satu, sehingga posisi nol yang ditulis sebagai literal ditolak saat kompilasi, sedangkan variabel yang berisi nol membuat pembacaan jatuh di luar field saat program berjalan. Mulai dari posisi 1.
  • Membiarkan potongan melewati ujung field. Tanpa -debug tidak ada pesan dan data yang terbaca berupa byte di luar field, sedangkan dengan -debug program berhenti saat berjalan. Periksa batas dengan LENGTH OF sebelum memotong.
  • Menimpa potongan dengan literal lebih panjang daripada potongannya. Hanya sebagian literal yang dipindah dan sisanya dibuang tanpa pesan, sehingga panjang literal dihitung sama dengan panjang potongan.
  • Menerapkan notasi pada item numerik ber-USAGE biner lalu membacanya sebagai teks. Hasil modifikasi referensi selalu berupa byte alfanumerik, dan byte item COMP bukan representasi digitnya. Pindahkan terlebih dahulu ke field DISPLAY bila teks yang diinginkan.

Ringkasan#

  • Notasi FIELD(awal:panjang) menunjuk potongan berbasis satu di dalam field, dan hasilnya berlaku sebagai item alfanumerik pada MOVE, IF, dan DISPLAY, baik sebagai sumber maupun tujuan.
  • Awal dan panjang boleh berupa variabel sehingga pemotongan mengikuti isi data, dengan panjang yang menentukan tepat berapa karakter dipindah.
  • Potongan di luar batas membaca byte di luar field tanpa pesan bila program dikompilasi tanpa -debug, sedangkan cobc -debug mengubahnya menjadi error saat berjalan, dan pemeriksaan dengan LENGTH OF menjaga keamanan di semua lingkungan.

Referensi#