Tanpa format specifier, fungsi printf hanya bisa mencetak teks biasa. Kekuatan sebenarnya dari printf justru ada pada penanda seperti %d, %f, %s, dan %x yang memberitahu fungsi cara mengubah nilai variabel menjadi deretan karakter yang bisa dibaca manusia. Pada chapter ini kita akan mengenal format specifier dasar, modifier ukuran (%ld, %zu), flag (%-, %+, %0), serta cara mengatur lebar field dan presisi secara dinamis. Daftar lengkap format specifier dapat ditemukan di dokumentasi cppreference untuk <stdio.h>.
Format Specifier Dasar #
Setiap format specifier diawali tanda persen % dan diakhiri satu huruf conversion character yang menentukan bagaimana nilai akan direpresentasikan. Berikut adalah tabel penanda yang paling sering dipakai:
| Penanda | Tipe Argumen | Hasil |
|---|---|---|
%d | int | Bilangan desimal bertanda |
%u | unsigned int | Bilangan desimal tanpa tanda |
%o | unsigned int | Bilangan oktal |
%x | unsigned int | Bilangan heksadesimal (huruf kecil) |
%X | unsigned int | Bilangan heksadesimal (huruf besar) |
%c | int (karakter) | Satu karakter |
%s | char * | String dengan null terminator |
%f | double | Notasi titik tetap |
%e | double | Notasi ilmiah |
%g | double | Notasi terpendek antara %f atau %e |
%% | (tanpa argumen) | Tanda persen literal |
Mari kita lihat seluruh penanda di atas beraksi dalam satu program:
#include <stdio.h>
int main(void) {
int i = 255;
unsigned int u = 255u;
char c = 'A';
char s[] = "Belajar C";
double d = 3.141592653589793;
printf("int (%%d) : %d\n", i);
printf("unsigned(%%u) : %u\n", u);
printf("octal (%%o) : %o\n", i);
printf("hex (%%x) : %x\n", i);
printf("HEX (%%X) : %X\n", i);
printf("char (%%c) : %c\n", c);
printf("string (%%s) : %s\n", s);
printf("double (%%f) : %f\n", d);
printf("double (%%e) : %e\n", d);
printf("double (%%g) : %g\n", d);
printf("percent(%%%%) : %%\n");
return 0;
}Output yang Dihasilkan:
int (%d) : 255
unsigned(%u) : 255
octal (%o) : 377
hex (%x) : ff
HEX (%X) : FF
char (%c) : A
string (%s) : Belajar C
double (%f) : 3.141593
double (%e) : 3.141593e+00
double (%g) : 3.14159
percent(%%) : %Mari kita telaah beberapa baris kunci di atas:
- Baris 10 (
printf("octal (%%o) : %o\n", i);): argumenibernilai255(desimal). Penanda%omenampilkan bilangan dalam basis 8, menghasilkan377karena2*64 + 5*8 + 7 = 255. - Baris 11 (
printf("hex (%%x) : %x\n", i);): penanda%xmenampilkan255dalam basis 16 dengan huruf kecil, yaituff. - Baris 12 (
printf("HEX (%%X) : %X\n", i);): penanda%Xsama dengan%xtetapi memakai huruf besar, menghasilkanFF. Berguna jika kita ingin format yang seragam dengan notasi heksadesimal umum. - Baris 17 (
printf("double (%%g) : %g\n", d);): penanda%gmemilih representasi terpendek antara%fdan%e. Untuk3.141592653589793, hasilnya3.14159karena digit signifikan default6sudah cukup. - Baris 19 (
printf("percent(%%%%) : %%\n");):%%adalah penanda khusus untuk mencetak karakter persen literal. Tidak ada argumen yang dibutuhkan.
Modifier Ukuran #
Untuk tipe data yang ukurannya berbeda dari int atau double, kita memerlukan length modifier yang disisipkan di antara % dan huruf konversi. Modifier yang paling sering dipakai: h (short), l (long), ll (long long), z (size_t), dan L (long double).
#include <stdio.h>
int main(void) {
long besar = 9223372036854775807L;
unsigned long panjang = 18446744073709551615UL;
size_t ukuran = sizeof(int);
printf("long : %ld\n", besar);
printf("unsigned long : %lu\n", panjang);
printf("size_t : %zu\n", ukuran);
printf("long hex : %#lx\n", besar);
/* Flag minus untuk rata kiri */
printf("[%-10d]\n", 42);
printf("[%10d]\n", 42);
/* Flag plus dan nol */
printf("[%+d]\n", 42);
printf("[%05d]\n", 42);
printf("[% d]\n", 42);
return 0;
}Output yang Dihasilkan:
long : 9223372036854775807
unsigned long : 18446744073709551615
size_t : 4
long hex : 0x7fffffffffffffff
[42 ]
[ 42]
[+42]
[00042]
[ 42]Mari kita telaah baris-baris kode di atas:
- Baris 7 (
printf("long ... : %ld\n", besar);): modifierldi%ldmemberitahuprintfbahwa argumen bertipelong. Tanpal,printfakan membaca argumen seolah-olahintdan hasilnya terpotong. - Baris 9 (
printf("size_t ... : %zu\n", ukuran);): modifierzdi%zumenandakan tipesize_t. Tipesize_tadalah unsigned sehingga tidak boleh dicetak dengan%d. - Baris 10 (
printf("long hex : %#lx\n", besar);): flag#menambahkan prefiks0xpada output heksadesimal, sehingga pembaca tahu bahwa angka tersebut dalam basis 16. - Baris 13 (
printf("[%-10d]\n", 42);): flag-merata-kirikan angka dalam field selebar 10 kolom. Outputnya[42 ]. - Baris 14 (
printf("[%10d]\n", 42);): tanpa flag, default adalah rata kanan, menghasilkan[ 42]. - Baris 17 (
printf("[%05d]\n", 42);): flag0mengisi ruang kosong dengan angka nol, menghasilkan[00042]. Berguna untuk nomor invoice atau kode. - Baris 18 (
printf("[% d]\n", 42);): flag spasi menampilkan tanda plus sebagai spasi kosong, sehingga positif dan negatif tetap sejajar jika dicetak berdampingan.
Lebar Field dan Presisi Dinamis #
Pada chapter sebelumnya kita memakai lebar field berupa angka konstan seperti %5d. C juga mendukung lebar dan presisi yang nilainya ditentukan oleh argumen, dengan menulis * sebagai pengganti angka. Fitur ini berguna saat lebar kolom baru diketahui saat program berjalan.
#include <stdio.h>
int main(void) {
double pi = 3.141592653589793;
/* Presisi untuk float */
printf("%.0f\n", pi);
printf("%.2f\n", pi);
printf("%.6f\n", pi);
printf("%.15f\n", pi);
/* Presisi untuk string: potong panjang */
printf("%.3s\n", "Belajar C");
/* Lebar dinamis dengan asterisk */
int lebar = 8;
printf("[%*d]\n", lebar, 42);
int presisi = 3;
printf("[%.*f]\n", presisi, pi);
return 0;
}Output yang Dihasilkan:
3
3.14
3.141593
3.141592653589793
Bel
[ 42]
[3.142]Mari kita telaah baris-baris kode di atas:
- Baris 6 (
printf("%.0f\n", pi);): presisi0menghilangkan seluruh digit desimal dan membulatkan nilai, sehingga3.14...menjadi3. - Baris 9 (
printf("%.15f\n", pi);): presisi15memunculkan banyak digit. Pada tipedoubleIEEE 754, hanya sekitar 15-17 digit pertama yang akurat. - Baris 12 (
printf("%.3s\n", "Belajar C");): untuk tipe string, presisi membatasi jumlah karakter yang dicetak. Hanya tiga huruf pertama yang muncul:Bel. - Baris 16 (
printf("[%*d]\n", lebar, 42);): asterisk*mengambil nilai lebar dari argumen pertama (lebar = 8), sehingga ekivalen dengan[%8d]. - Baris 19 (
printf("[%.*f]\n", presisi, pi);): presisi juga bisa diambil dari argumen. Hasilnya sama dengan[%.3f], yaitu[3.142]karena pembulatan.