C tidak memiliki tipe data string tersendiri. Teks direpresentasikan sebagai array char yang diakhiri penanda khusus, dan hampir seluruh pengolahan teks di C berdiri di atas konvensi ini. Topik ini membahas penanda akhir string, inisialisasi dengan literal string, perbedaan literal string dan array char, serta pengolahan karakter satu per satu.
Penanda akhir string ‘\0’#
String dalam C adalah deretan karakter yang diakhiri karakter null, ditulis '\0', yaitu karakter yang byte-nya bernilai 0. Penanda ini disebut null terminator dan menjadi tanda bahwa string sudah habis. Karena penandanya ikut disimpan, string “Budi” yang tampak empat karakter menempati lima byte di memori.
Fungsi seperti printf dengan penentu format %s membaca karakter satu per satu dan berhenti tepat ketika menemukan '\0'. Apabila penandanya lupa dituliskan, pembacaan berlanjut ke memori setelah array dan hasilnya tidak dapat diprediksi. Program berikut membangun string secara manual lengkap dengan penanda akhirnya, lalu menghitung panjangnya dengan perulangan while.
#include <stdio.h>
int main(void) {
char sapaan[5];
sapaan[0] = 'H';
sapaan[1] = 'a';
sapaan[2] = 'l';
sapaan[3] = 'o';
sapaan[4] = '\0';
printf("%s\n", sapaan);
int panjang = 0;
while (sapaan[panjang] != '\0') {
panjang++;
}
printf("Panjang string: %d karakter\n", panjang);
return 0;
}Halo
Panjang string: 4 karakterArray sapaan berukuran lima karena empat karakternya ditambah satu byte penanda. Perulangan penghitung panjang berhenti pada '\0' dan tidak pernah menyentuh memori di luar array. Pola perulangan yang berhenti pada penanda ini adalah dasar dari hampir semua fungsi string di C.
Inisialisasi dengan literal string#
Membangun string karakter demi karakter seperti di atas jarang diperlukan. Bentuk yang lazim adalah menginisialisasi array char dengan literal string, dan kompilator menambahkan penanda akhirnya secara otomatis. Program berikut memakai dua string semacam itu beserta fungsi penghitung panjang sederhana.
#include <stdio.h>
int panjangString(const char s[]) {
int n = 0;
while (s[n] != '\0') {
n++;
}
return n;
}
int main(void) {
char nama[] = "Budi";
char kota[] = "Bandung";
printf("Nama: %s (%d karakter)\n", nama, panjangString(nama));
printf("Kota: %s (%d karakter)\n", kota, panjangString(kota));
printf("Ukuran array nama: %zu byte\n", sizeof nama);
return 0;
}Nama: Budi (4 karakter)
Kota: Bandung (7 karakter)
Ukuran array nama: 5 bytePada deklarasi char nama[] = "Budi";, ukuran array ditentukan otomatis menjadi lima, yaitu empat karakter ditambah satu byte penanda. Ukurannya juga boleh dituliskan eksplisit, misalnya char kota[16] = "Bandung";, dan sisa byte yang tidak terpakai berisi '\0'. Ukuran yang dituliskan eksplisit harus cukup untuk seluruh karakter beserta penandanya.
Satu batasan perlu diingat: isi array string tidak dapat diganti dengan penugasan biasa setelah deklarasi. Pernyataan kota = "Depok"; ditolak kompilator karena nama array bukan variabel yang dapat diisi ulang. Penggantian isi dilakukan dengan fungsi penyalin seperti strcpy yang dibahas pada topik Pustaka string.h.
Literal string versus array char#
Teks yang ditulis dengan tanda kutip ganda pada kode, misalnya “Bandung”, adalah literal string (string literal). Literal string disimpan sebagai array char anonim yang isinya tidak boleh diubah. Deklarasi char *judul = "Budi"; tidak menyalin teks ke array milik sendiri, melainkan hanya menyimpan alamat literal tersebut.
// tidak-dijalankan
char *judul = "Budi"; /* menunjuk literal string */
judul[0] = 'b'; /* undefined behavior: literal tidak boleh diubah */
char salinan[] = "Budi"; /* array milik sendiri, berisi salinan teks */
salinan[0] = 'b'; /* aman: array biasa yang boleh diubah */Perbedaan keduanya dirangkum pada tabel berikut.
| Bentuk deklarasi | Yang disimpan | Isinya boleh diubah |
|---|---|---|
char *judul = "Budi"; | Alamat literal string “Budi” | Tidak |
char salinan[] = "Budi"; | Salinan teks beserta '\0' pada array sendiri | Ya |
Kedua bentuk itu sama-sama sah dan pilihannya ditentukan oleh satu pertanyaan, yaitu apakah isinya perlu diubah. Bentuk array dipakai untuk teks kerja seperti penampung hasil pembacaan masukan, sedangkan pointer ke literal dipakai untuk teks tetap seperti pesan yang dicetak.
Mengolah karakter satu per satu#
Karena string adalah array biasa, karakternya dapat dibaca dan ditulis lewat indeks seperti elemen array lainnya. Perulangan yang berhenti pada '\0' adalah pola baku pengolahannya. Program berikut mengubah seluruh huruf kecil pada sebuah string menjadi huruf besar dengan mengubah arraynya langsung.
#include <stdio.h>
int main(void) {
char kata[] = "belajar array";
/* mengubah setiap huruf kecil menjadi huruf besar */
for (int i = 0; kata[i] != '\0'; i++) {
if (kata[i] >= 'a' && kata[i] <= 'z') {
kata[i] = kata[i] - ('a' - 'A');
}
}
printf("%s\n", kata);
return 0;
}BELAJAR ARRAYPada tabel ASCII, jarak antara setiap pasangan huruf kecil dan huruf besarnya selalu sama, yaitu 'a' - 'A' bernilai 32. Pemeriksaan rentang 'a' sampai 'z' memastikan hanya huruf kecil yang digeser, sedangkan spasi dan karakter lain dilewati. Perubahan dilakukan di tempat karena array kata milik main dan bukan literal string yang tidak boleh diubah.
Pola perulangan yang sama melayani berbagai kebutuhan tanpa perlu teknik baru. Menghitung kemunculan satu karakter, mencari posisi karakter pertama, dan menyalin string ke array lain semuanya adalah variasi perulangan yang berhenti pada '\0', dengan aksi di dalam badan perulangan yang berbeda.
Kesalahan umum#
- Melupakan
'\0'ketika membangun string secara manual. Tanpa penanda akhir,printfdan fungsi lain membaca melewati array sampai kebetulan menemukan byte 0, dan hasilnya tidak dapat diprediksi. - Menyediakan array yang persis sepanjang teksnya. Ukuran array harus satu lebih besar dari jumlah karakternya untuk menampung penanda akhir, sehingga teks “Budi” membutuhkan array berukuran lima.
- Membandingkan isi dua string dengan operator
==. Operator itu membandingkan alamat array dan bukan isinya, sehingga dua string berisi teks sama pun dianggap berbeda. Perbandingan isi dilakukan dengan fungsistrcmpyang dibahas pada topik Pustaka string.h. - Mengira ukuran array otomatis menyesuaikan teks yang lebih panjang. Array
charberukuran tetap sejak deklarasinya, sehingga teks yang lebih panjang membutuhkan array yang lebih besar, dan penyalinannya tetap harus menyisakan tempat untuk penanda akhir. - Menggeser nilai karakter tanpa pemeriksaan rentang. Pemeriksaan
'a'sampai'z'sebelum pergeseran membuat spasi, angka, dan tanda baca tetap utuh, sedangkan pergeseran tanpa pemeriksaan merusak karakter-karakter itu.
Ringkasan#
- String di C adalah array
charyang diakhiri karakter null'\0', dan panjang efektifnya tidak disimpan di mana pun. - Inisialisasi
char nama[] = "Budi";menyalin teks beserta penanda akhirnya ke array milik sendiri yang ukurannya satu lebih besar dari teksnya. - Literal string tidak boleh diubah, sedangkan array
charhasil inisialisasi boleh. - Pengolahan string memakai perulangan yang berhenti pada
'\0', dan perubahan karakter dilakukan lewat indeks.
Referensi#
- Null-terminated byte strings — cppreference.com — Ikhtisar konvensi string C yang diakhiri karakter null.
- String literals — cppreference.com — Aturan literal string dan sifatnya yang tidak dapat diubah.
- string(3) — Linux manual page — Ikhtisar fungsi pustaka standar untuk string yang diakhiri null.