Argumen Baris Perintah

Membaca argc dan argv untuk membangun alat command line sederhana.

Daftar isi

Program C yang dirakit sejauh ini menerima masukan dari dalam kode atau dari aliran standar. Bahasa C juga menyediakan jalur masukan yang paling umum dipakai oleh perangkat lunak terminal, yaitu argumen yang diketik bersama nama program ketika program dijalankan. Topik ini membahas parameter argc dan argv, cara menelusuri argumennya, serta pembangunan alat command line sederhana bernama statistik yang menerima deret angka dan menghitung ringkasannya.

Parameter argc dan argv#

Fungsi main dapat dideklarasikan dengan dua parameter yang diisi oleh lingkungan eksekusi saat program dijalankan. Parameter pertama, lazim dinamai argc (argument count), berupa bilangan bulat yang menyatakan banyaknya argumen termasuk nama program itu sendiri, sehingga nilai terkecilnya adalah 1. Parameter kedua, lazim dinamai argv (argument vector), berupa array pointer ke string yang berisi teks tiap argumen.

c Contoh: tanda tangan main dengan argumen
// tidak-dijalankan
int main(int argc, char *argv[]) {
    /* argc   : banyak argumen, termasuk nama program */
    /* argv[0]: nama program sebagaimana ia dipanggil */
    /* argv[1]: argumen pertama dari pengguna */
    return 0;
}

Posisi argv[0] menyimpan nama program sebagaimana dipanggil, bukan argumen pengguna, sehingga argumen pengguna dimulai dari argv[1]. Di akhir array, argv[argc] selalu berisi NULL sebagai penanda habis. Program berikut mencetak seluruh isinya.

c cetak-argv.c
// tidak-dijalankan
#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("argc = %d\n", argc);
    for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    return 0;
}
bash
# mengompilasi program pencetak argumen
gcc cetak-argv.c -o cetak-argv

# menjalankannya dengan dua argumen
./cetak-argv satu dua
text Keluaran
argc = 3
argv[0] = ./cetak-argv
argv[1] = satu
argv[2] = dua

Yang memecah baris perintah menjadi argumen-argumen tersebut adalah shell. Shell membagi masukan pada setiap spasi sebelum meneruskannya ke program. Apabila sebuah argumen memang harus mengandung spasi, argumen itu perlu diapit tanda kutip, misalnya ./cetak-argv "satu dua" yang diterima program sebagai satu argumen utuh. Tanpa argumen apa pun, program yang sama mencetak argc = 1 dan hanya menampilkan argv[0].

Meskipun berasal dari luar program, teks-teks pada argv sah untuk diubah selama program berjalan, misalnya untuk menormalkan huruf besar atau kecil sebelum diproses. Array argv itu sendiri merupakan deretan pointer yang menunjuk string-string terpisah di memori, sehingga panjang tiap argumen tidak perlu seragam. Seluruh penyiapan ini selesai sebelum baris pertama main dijalankan, sehingga argumen dapat dipakai sejak awal program tanpa persiapan apa pun.

Menelusuri argumen dengan perulangan#

Sebagian besar alat command line menelusuri argumen pengguna dengan perulangan yang dimulai dari indeks 1, karena indeks 0 adalah nama program. Bentuk perulangannya mengikuti pola di bawah ini.

c Contoh: menelusuri argumen mulai dari argv[1]
// tidak-dijalankan
for (int i = 1; i < argc; i++) {
    printf("Argumen %d: %s\n", i, argv[i]);
}

Penanda NULL pada argv[argc] memberikan alternatif kedua yang tidak memerlukan argc sama sekali, yaitu perulangan yang berhenti ketika elemennya NULL. Kedua bentuk itu setara untuk kasus biasa. Yang penting adalah konsistensi: indeks awal 1, batas atas argc, dan kesadaran bahwa setiap elemen berupa string, bukan angka. Konversi dari teks ke bilangan harus dilakukan secara eksplisit sebelum argumen dipakai dalam perhitungan.

Argumen yang diawali tanda hubung seperti -v atau --ringkas lazim diperlakukan sebagai opsi, sedangkan sisanya berupa data posisi yang diolah. Pembedaan keduanya hanya kesepakatan, karena bahasa C tidak menyediakan fungsi parsing opsi di dalam standarnya. Untuk alat kecil, pemeriksaan sederhana dengan perbandingan strcmp sudah cukup. Alat yang opsinnya terus bertambah biasanya beralih ke kerangka parsing seperti getopt yang tersedia pada banyak sistem POSIX.

Membangun alat command line: statistik nilai#

Alat yang dibangun pada bagian ini menerima deret angka melalui argumen, lalu melaporkan banyaknya nilai, total, dan rata-ratanya. Apabila dipanggil tanpa argumen, alat ini menampilkan petunjuk pemakaian alih-alih langsung gagal, kebiasaan yang lazim pada alat command line.

c statistik.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("Pemakaian: ./statistik angka1 angka2 ...\n");
        printf("Contoh   : ./statistik 80 75 90\n");
        return 0;
    }

    int total = 0;
    for (int i = 1; i < argc; i++) {
        total += atoi(argv[i]);
    }

    printf("Banyak nilai : %d\n", argc - 1);
    printf("Total        : %d\n", total);
    printf("Rata-rata    : %.2f\n", (double) total / (argc - 1));
    return 0;
}
text Keluaran
Pemakaian: ./statistik angka1 angka2 ...
Contoh   : ./statistik 80 75 90

Fungsi atoi mengubah teks argumen menjadi bilangan bulat, dan pengecoran (double) pada pembagian menjaga agar rata-rata tidak dipotong menjadi bilangan bulat. Alat ini dijalankan dengan argumen nyata melalui shell.

bash
# mengompilasi alat statistik
gcc statistik.c -o statistik

# menghitung ringkasan tiga nilai ujian
./statistik 80 75 90
text Keluaran
Banyak nilai : 3
Total        : 245
Rata-rata    : 81.67

Struktur alat semacam ini mampu menerima sejumlah argumen apa pun tanpa diubah, karena perulangannya mengikuti nilai argc. Konversi atoi dipilih karena singkat, tetapi konversi ini tidak melaporkan error apa pun, sedangkan parsing yang lebih aman menggunakan keluarga strtol dibahas pada topik stdlib.h Lanjutan dalam modul ini.

Apabila salah satu argumen bukan angka, atoi menganggapnya 0 dan perhitungan terus berjalan tanpa peringatan, misalnya ./statistik 80 tujuh 90 menghasilkan total 170. Perilaku itu dapat diterima untuk alat pribadi yang sederhana, tetapi menjadi sumber salah hitung yang sulit dilacak pada alat yang dipakai orang lain. Verifikasi setiap argumen sebelum dihitung, atau gunakan konversi yang dapat memeriksa errornya.

Rancangan alat command line yang sehat menaruh petunjuk pemakaian pada saat argumen tidak lengkap, karena petunjuk itu terbaca tanpa membuka dokumentasi. Syarat argc < 2 memang sederhana, tetapi sudah menutup kasus pemanggilan kosong sekalipun alat ini belum mendukung opsi bernilai. Pengembangan lanjutannya, misalnya opsi pemilihan laporan atau keluaran berformat, tetap berada pada pola yang sama, yaitu periksa, konversi, hitung, lalu laporkan.

Kesalahan umum#

  • Membaca argv[1] tanpa memeriksa argc. Program yang dipanggil tanpa argumen memiliki argc bernilai 1, sehingga argv[1] berisi NULL. Memakai NULL itu sebagai string merupakan perilaku tak terdefinisi yang sering berujung pada program yang berhenti mendadak. Periksa argc terlebih dahulu sebelum mengakses indeks mana pun.
  • Mengira argv[0] selalu berbentuk nama pendek. Isi argv[0] mengikuti cara pemanggilan, misalnya ./statistik, /usr/bin/statistik, atau teks lain pada pemanggilan tertentu. Logika program tidak boleh bergantung pada bentuk pastinya.
  • Mengoper teks angka langsung ke perhitungan. Elemen argv berupa string, sehingga argv[1] + argv[2] menjumlahkan dua alamat memori, bukan dua nilai. Konversikan setiap argumen dengan atoi atau strtol sebelum dihitung.
  • Mengabaikan banyaknya argumen yang tidak sesuai rancangan. Alat yang menuntut persis tiga angka tetap berjalan apabila diberi lima argumen, karena argc tidak pernah divalidasi lebih jauh. Periksa jumlah yang diharapkan secara eksplisit, misalnya dengan if (argc != 4), apabila format pemanggilannya memang tetap.

Ringkasan#

  • argc menyatakan banyak argumen termasuk nama program, sedangkan argv menyimpan teks tiap argumen sebagai array pointer ke string.
  • Argumen pengguna dimulai pada argv[1], dan argv[argc] selalu berisi NULL sebagai penanda habis.
  • Alat command line memeriksa argc lebih dahulu, menampilkan petunjuk pemakaian bila argumen kurang, lalu mengonversi tiap argumen sebelum dipakai dalam perhitungan.
  • Shell memecah baris perintah pada setiap spasi, sehingga teks yang mengandung spasi perlu diapit tanda kutip.

Referensi#