Pernyataan masukan dan keluaran dengan format asterisk, yang disebut list-directed I/O, adalah bentuk paling ringkas untuk membaca dan menulis data dalam Fortran. Sifat ringkas itu berasal dari cara kerjanya, yaitu kompiler menentukan lebar medan dan bentuk setiap nilai berdasarkan tipe datanya tanpa deskripsi format dari penulis program. Topik ini membahas cara kerja keluaran list-directed pada pernyataan print dan write, aturan repeat count pada daftar masukan beserta jebakannya pada daftar keluaran, pembacaan data dari berkas internal (internal file), serta kelompok data bernama melalui pernyataan namelist. Setiap mekanisme didemonstrasikan dengan program utuh yang dikompilasi dan dijalankan dengan gfortran, sehingga setiap blok keluaran pada topik ini merupakan hasil eksekusi nyata dan dapat diuji ulang dari direktori topik masing-masing.
Keluaran list-directed dengan format asterisk#
Pada keluaran list-directed, penanda format pada pernyataan write atau print diganti tanda asterisk. Kompiler memeriksa tipe setiap item pada daftar keluaran, memilih lebar medan yang sesuai, dan menyisipkan spasi pemisah antarnilai tanpa perlu campur tangan penulis program. Program berikut menampilkan larik suhu dan beberapa konstanta bertipe berbeda, membuat berkas sensor.txt yang berisi satu rekaman data, membaca kembali berkas itu, lalu menguji pembacaan dari berkas internal.
program list_directed
implicit none
integer :: unit
real :: suhu(3)
integer :: kode_sensor
real :: tekanan
integer :: nomor
real :: kadar
character(len=32) :: baris
suhu = [24.5, 25.0, 23.75]
print *, "Suhu tercatat:", suhu
print *, 42, 3.14, .true.
! JEBAKAN: pada daftar output, 3*24.5 hanyalah perkalian biasa
print *, "3*24.5 pada daftar output :", 3*24.5
! program membuat berkas datanya sendiri sebelum membacanya
! nilai array ditulis dengan menyebut nama array-nya saja
open (newunit=unit, file="sensor.txt", status="replace", action="write")
write (unit, *) 101, suhu, 1013.25
close (unit)
open (newunit=unit, file="sensor.txt", status="old", action="read")
read (unit, *) kode_sensor, suhu, tekanan
close (unit)
print *, "Kode sensor:", kode_sensor
print *, "Suhu :", suhu
print *, "Tekanan :", tekanan
! repeat-count 3*24.5 HANYA sah pada daftar INPUT list-directed
baris = "102 3*24.5 1013.25"
read (baris, *) kode_sensor, suhu, tekanan
print *, "Repeat-count pada input :", kode_sensor, suhu, tekanan
baris = "7 9.5"
read (baris, *) nomor, kadar
print *, "Internal file:", nomor, kadar
end program list_directed# mengompilasi program dari direktori topik
gfortran list-directed.f90 -o list-directed
# menjalankan program
./list-directed Suhu tercatat: 24.5000000 25.0000000 23.7500000
42 3.14000010 T
3*24.5 pada daftar output : 73.5000000
Kode sensor: 101
Suhu : 24.5000000 25.0000000 23.7500000
Tekanan : 1013.25000
Repeat-count pada input : 102 24.5000000 24.5000000 24.5000000 1013.25000
Internal file: 7 9.50000000 Keluaran tersebut memperlihatkan konvensi yang berlaku pada keluaran list-directed gfortran. String dicetak tanpa tanda kutip, bilangan bulat dicetak rata kanan pada medan yang lebarnya ditentukan kompiler, dan setiap bilangan real presisi tunggal dicetak dengan sekitar sembilan angka signifikan, misalnya 24.5000000. Nilai 3.14000010 pada baris kedua perlu penjelasan tersendiri, karena bilangan 3.14 tidak dapat diwakili dengan tepat dalam biner presisi tunggal sehingga sisa pembulatan representasinya ikut tercetak. Nilai logis .true. dicetak sebagai satu huruf T, dan tiga elemen larik suhu ditulis berurutan hanya dengan menyebut nama lariknya.
Repeat count pada masukan dan jebakannya pada keluaran#
Bentuk r*nilai pada daftar masukan list-directed disebut repeat count, yakni pengulangan satu nilai sebanyak r kali. Baris data 102 3*24.5 1013.25 mengandung lima nilai meskipun penulisannya hanya terdiri atas tiga bagian, karena 3*24.5 mengisi tiga item berurutan dengan nilai 24.5. Pada baris keluaran Repeat-count pada input, kelima item masukan, yaitu kode_sensor, ketiga elemen suhu, dan tekanan, terisi penuh dari pembacaan baris itu. Bentuk ini berguna untuk data yang banyak elemennya bernilai sama, misalnya baris pengukuran yang elemen-elemen kosongnya diisi nilai pengganti yang sama.
Bentuk yang sama tidak memiliki makna pengulangan pada daftar keluaran. Baris keluaran 3*24.5 pada daftar output : 73.5000000 menunjukkan akibatnya, yaitu kompiler mengevaluasi 3*24.5 sebagai perkalian biasa dan mencetak satu nilai 73.5. Karena bentuknya sah secara sintaks, tidak ada pesan error yang muncul, dan kesalahan jenis ini baru terlihat ketika data yang ditulis tidak sesuai harapan. Cara yang benar untuk menulis tiga nilai yang sama adalah menyebut item satu per satu atau menulis nama lariknya, sebagaimana pernyataan write pada program di atas yang menulis 101, suhu, 1013.25 menjadi lima nilai dalam satu rekaman.
Berkas internal untuk membaca dari string#
Berkas internal (internal file) adalah variabel karakter yang berperan sebagai rekaman bagi pernyataan read, sehingga teks yang sudah berada di memori dapat diurai dengan aturan masukan list-directed yang sama seperti saat membaca berkas biasa. Program di atas memuat baris 102 3*24.5 1013.25 ke dalam variabel baris, kemudian pernyataan read (baris, *) menguraikannya menjadi lima item sekaligus. Mekanisme yang sama mengisi nomor dan kadar dari string 7 9.5, dan keluaran Internal file: 7 9.50000000 membuktikan pengisiannya.
Berkas internal praktis ketika sebuah baris perlu dibaca sebagai teks terlebih dahulu, misalnya untuk memeriksa tanda khusus pada awal baris sebelum barisnya diurai sebagai data. Pola kerjanya terdiri atas dua langkah, yaitu membaca satu rekaman berkas dengan format "(A)" ke variabel karakter, lalu mengurai variabel karakter itu dengan read list-directed. Dengan pemisahan dua langkah ini, baris yang tidak sesuai pola dapat diperiksa dan dilewati tanpa mengganggu posisi pembacaan pada berkas utamanya, karena setiap langkah tetap membaca tepat satu rekaman.
Kelompok data bernama dengan namelist#
Kelompok namelist adalah deklarasi yang memberi nama pada sekumpulan variabel agar semuanya dapat ditulis dan dibaca sekaligus dengan menyebut nama kelompoknya. Deklarasi namelist /konfigurasi/ lokasi, jumlah_sensor, ambang pada program berikut membentuk kelompok bernama konfigurasi, yang kemudian ditulis ke berkas dengan penanda nml=konfigurasi dan dibaca kembali dengan penanda yang sama. Program ini menulis berkas konfigurasi.nml, menampilkan isinya baris demi baris, mengosongkan ketiga variabel anggotanya, lalu mengisi ulang semuanya dari berkas yang sama.
program demo_namelist
implicit none
character(len=24) :: lokasi
integer :: jumlah_sensor
real :: ambang(4)
integer :: unit
integer :: status
character(len=80) :: baris
namelist /konfigurasi/ lokasi, jumlah_sensor, ambang
lokasi = "Stasiun Bandung"
jumlah_sensor = 3
ambang = [25.0, 30.0, 27.5, 40.0]
open (newunit=unit, file="konfigurasi.nml", status="replace", action="write")
write (unit, nml=konfigurasi)
close (unit)
! menampilkan isi berkas namelist persis seperti yang tertulis
open (newunit=unit, file="konfigurasi.nml", status="old", action="read")
do
read (unit, "(A)", iostat=status) baris
if (status /= 0) exit
print "(A)", trim(baris)
end do
close (unit)
! mengosongkan nilai, lalu membaca kelompok namelist kembali
lokasi = ""
jumlah_sensor = 0
ambang = 0.0
open (newunit=unit, file="konfigurasi.nml", status="old", action="read")
read (unit, nml=konfigurasi)
close (unit)
print *, "Dibaca kembali:", trim(lokasi), jumlah_sensor, ambang
end program demo_namelist# mengompilasi program dari direktori topik
gfortran namelist.f90 -o namelist
# menjalankan program
./namelist&KONFIGURASI
LOKASI="Stasiun Bandung ",
JUMLAH_SENSOR=3 ,
AMBANG= 25.0000000 , 30.0000000 , 27.5000000 , 40.0000000 ,
/
Dibaca kembali:Stasiun Bandung 3 25.0000000 30.0000000 27.5000000 40.0000000 Berkas konfigurasi.nml berformat teks dan dapat disunting dengan editor biasa. Header &KONFIGURASI membuka kelompok, setiap variabel ditulis dengan namanya beserta nilainya, dan tanda garis miring menutup kelompok. Berbeda dengan keluaran list-directed pada bagian sebelumnya, string pada keluaran namelist ditulis dalam tanda kutip dan diberi spasi pengisi sampai panjang deklarasi variabelnya, yaitu 24 karakter untuk lokasi. Pembacaan kembali mengisi variabel berdasarkan nama, bukan berdasarkan posisi, sehingga urutan penulisan variabel di dalam berkas boleh berbeda dari urutan deklarasinya dan variabel anggota yang tidak disebut di dalam berkas tetap mempertahankan nilainya. Sifat ini menjadikan namelist pilihan yang lazim untuk berkas konfigurasi program ilmiah.
Kesalahan umum#
Kesalahan pertama adalah memasang repeat count pada daftar keluaran dengan harapan nilai terulang. Perbaikannya sama dengan yang dijelaskan pada bagian repeat count di atas, yaitu menyebut item satu per satu atau menulis nama lariknya pada pernyataan write. Kesalahan ini tidak memunculkan pesan error, sehingga hasil cetaknya perlu dibandingkan dengan data yang dimaksud, bukan cukup diverifikasi berhasilnya kompilasi.
Kesalahan kedua adalah mencantumkan item masukan yang tipenya tidak cocok dengan datanya, misalnya membaca teks abc ke dalam variabel bertipe integer. Pernyataan read tanpa penanda iostat menghentikan program saat berjalan, sedangkan dengan iostat=status kegagalan tersebut dapat ditangani oleh program sendiri dan baris data yang bermasalah dapat dilaporkan. Pola penanganan dengan iostat dan iomsg dibahas lebih lanjut pada topik berkas dan unit di modul ini.
Kesalahan ketiga pada namelist adalah membaca kelompok yang namanya atau variabelnya tidak terdapat dalam deklarasi. Pembacaan berakhir dengan error karena sistem waktu berjalan (runtime) kompiler mencocokkan header berkas dengan nama kelompok yang diminta pada pernyataan read. Pastikan header berkas, misalnya &KONFIGURASI, sama dengan nama kelompok pada deklarasi, dan setiap variabel yang ditulis di dalam berkas sudah menjadi anggota kelompok tersebut.
Ringkasan#
- Format asterisk membuat kompiler menentukan lebar medan dari tipe setiap item, sehingga
print *, suhumenulis seluruh elemen larik tanpa deskripsi format. - Repeat count
r*nilaimengisiritem berurutan dan hanya sah pada daftar masukan, sedangkan pada daftar keluaran3*24.5dievaluasi sebagai perkalian. - Berkas internal memungkinkan string karakter diurai dengan aturan masukan list-directed melalui
read (baris, *). - Kelompok
namelistmenulis dan membaca sekumpulan variabel berdasarkan nama, sehingga cocok untuk berkas konfigurasi yang disunting manusia.
Referensi#
- Learn: tutorial resmi Fortran — fortran-lang — Kumpulan tutorial resmi komunitas Fortran yang mencontohkan masukan dan keluaran list-directed serta namelist.
- The GNU Fortran Compiler — GNU Project — Manual gfortran yang menjadi rujukan perilaku keluaran list-directed dan format berkas namelist pada jalur ini.