Sebagian besar bahasa memberimu tipe string yang tahu panjangnya sendiri. C tidak. Di C, string hanyalah array char dengan satu aturan tambahan: teksnya diikuti sebuah byte bernilai nol, ditulis '\0' dan disebut null terminator. Semua hal lain tentang string di C berawal dari satu konvensi itu.
String Adalah Array Char Ditambah '\0'
Deklarasikan string dengan menginisialisasi array char dari sebuah literal:
Array itu berisi empat byte, bukan tiga:
name: +-----+-----+-----+------+
| 'A' | 'd' | 'a' | '\0' |
+-----+-----+-----+------+
index: 0 1 2 3
sizeof(name) bernilai 4. Compiler menghitung karakternya, menambahkan satu untuk terminator, dan menentukan ukuran array untukmu. Byte tambahan itulah alasan char name[3] = "Ada"; adalah bug yang menunggu waktu: teksnya muat tetapi terminatornya tidak, sehingga tidak ada kode sesudahnya yang bisa tahu di mana string itu berakhir.
Jika kamu ingin ruang untuk mengubah isinya nanti, tentukan ukurannya sendiri dan sisakan ruang:
char name[32] = "Ada"; /* 3 characters, a terminator, 28 bytes spare */
Byte yang tidak terpakai diisi nol oleh inisialisasi, dan itu tidak berbahaya.
Kenapa Terminator Itu Penting
Tidak ada fungsi C yang menerima panjang string. printf("%s", s) hanya diberi satu alamat dan berjalan maju mencetak byte sampai bertemu '\0'. Jadi array char tanpa terminator bukanlah string, dan memperlakukannya sebagai string berarti membaca memori apa pun yang kebetulan ada sesudahnya.
Aturan yang perlu dihafal: sizeof memberimu ukuran penyimpanan, strlen memberimu teksnya. Untuk char buf[32] = "Ada", sizeof buf bernilai 32 dan strlen(buf) bernilai 3. Keduanya menjawab pertanyaan yang berbeda, dan mencampuradukkannya adalah salah satu bug C yang paling umum.
Literal String vs Array Char
Dua baris ini terlihat mirip tetapi berperilaku sangat berbeda:
char a[] = "hello"; /* an array you own, initialized from the literal */
char *p = "hello"; /* a pointer aimed at the literal itself */
a adalah array 6 byte yang berisi salinan teks milikmu sendiri. Kamu bisa mengubahnya. p menunjuk ke data string read-only milik program; literal itu dipakai bersama, dan menulis lewat p adalah undefined behavior yang biasanya membuat program crash saat berjalan, bukan saat kompilasi.
Tulis const char * setiap kali sebuah pointer menunjuk ke literal. Compiler lalu menolak penulisan itu saat kompilasi, alih-alih membiarkannya menjadi crash. Memilih di antara keduanya sebenarnya adalah pertanyaan tentang pointer dan array, yang dibahas di halaman pointer dan array.
Satu perbedaan lagi yang perlu diketahui: sizeof a bernilai 6, tetapi sizeof p adalah ukuran pointer (8 di kebanyakan sistem), berapa pun panjang teksnya.
Mencetak dan Membaca String
%s mencetak sebuah string; %c mencetak satu karakter.
Untuk input, hindari gets sepenuhnya. Fungsi itu dihapus dari bahasa C karena tidak bisa dipakai dengan aman. Pakai fgets, yang menerima ukuran buffer dan tidak akan overflow:
fgets menyimpan newline dari tombol Enter yang kamu tekan, dan itu hampir tidak pernah kamu inginkan di dalam string. Baris strcspn mencari '\n' pertama dan menimpanya dengan terminator. Ini cara standar yang ringkas untuk membuangnya.
Menelusuri String Karakter demi Karakter
Karena akhir string ditandai, bukan dihitung, perulangan yang idiomatis menguji karakternya langsung:
Kondisi text[i] != '\0' sering disingkat menjadi text[i] saja, karena '\0' bernilai nol dan karena itu bernilai salah. Keduanya benar; bentuk yang eksplisit lebih mudah dibaca selama kamu masih belajar.
Kamu juga bisa menelusurinya dengan pointer alih-alih indeks, yang sama idiomatisnya di C:
Cast ke unsigned char sebelum memanggil toupper bukan hiasan: fungsi-fungsi <ctype.h> tidak terdefinisi untuk nilai negatif, dan char biasa bisa bernilai negatif untuk byte di atas 127.
Kamu Tidak Bisa Menyalin String dengan =
Inilah tembok yang ditabrak setiap pemula:
char a[10];
a = "hello"; /* error: assignment to expression with array type */
char b[10] = "hi";
char c[10];
c = b; /* error - same reason */
Nama array bukan nilai yang bisa diubah, jadi = tidak punya apa-apa untuk dikerjakan. Satu-satunya tempat bentuk singkat itu berlaku adalah inisialisasi saat deklarasi, yang merupakan operasi lain yang dikerjakan compiler.
Untuk menyalin saat program berjalan, salin byte-nya dengan strcpy dari <string.h>:
Alasan yang sama menjelaskan kenapa == tidak membandingkan string. if (a == b) membandingkan dua alamat, jadi hasilnya salah untuk dua array berbeda yang berisi teks identik. Pakai strcmp(a, b) == 0. Kedua fungsi ini dan kerabatnya yang lebih aman dibahas di halaman fungsi string.
Array dari String
Daftar string bisa berupa array pointer (untuk teks tetap yang hanya dibaca) atau array char dua dimensi (jika setiap isinya harus bisa diubah):
Array pointer menyimpan tiga alamat yang menunjuk ke literal read-only: ringkas, tetapi tidak bisa diubah. Bentuk char[3][16] memesan 48 byte memori milikmu sendiri, jadi setiap barisnya bisa ditulis ulang.
Kesalahan Umum
- Lupa byte untuk terminator.
char s[5] = "hello"tidak punya ruang untuk'\0'. Tentukan ukurannya sebesarstrlen + 1. - Memakai
sizeofpadahal maksudnyastrlen.sizeofpada pointer memberikan ukuran pointer, bukan panjang teksnya. - Menulis lewat
char *ke sebuah literal. Deklarasikan pointer seperti itu sebagaiconst char *. - Membandingkan dengan
==. Itu membandingkan alamat. Pakaistrcmp. - Membaca dengan
scanf("%s", buf). Tidak ada batas ukurannya dan dengan senang hati overflow; pilihfgets.
Pertanyaan yang sering diajukan
Bagaimana cara mendeklarasikan string di C?
Sebagai array char: char name[] = "Ada";. C tidak punya tipe string bawaan. Array itu berisi 'A', 'd', 'a' dan byte keempat yang tersembunyi, '\0', yang menandai akhirnya. Jika kamu ingin ruang untuk mengubah teksnya nanti, beri array ukuran yang eksplisit: char name[32] = "Ada";.
Apa itu null terminator di C?
Byte '\0' (bernilai nol) yang menandai tempat sebuah string berakhir. Setiap fungsi standar, seperti printf("%s"), strlen, strcpy, membaca maju sampai menemukan byte itu. Array char tanpa terminator bukanlah string, dan mengirimnya ke fungsi-fungsi tersebut akan membaca melewati ujung memorimu.
Kenapa saya tidak bisa mengisi string dengan = di C?
Karena array bukan nilai yang bisa kamu salin dengan =. char a[10]; a = "hi"; tidak akan bisa di-compile. Salin karakternya dengan strcpy(a, "hi") dari <string.h>, atau inisialisasi saat deklarasi, char a[10] = "hi";, satu-satunya tempat bentuk singkat ini berlaku.
Apa perbedaan char * dan char [] di C?
char s[] = "hi" membuat array yang bisa diubah dan berisi salinan teks milikmu sendiri. char *p = "hi" membuat pointer ke literal string, yang berada di memori read-only: membacanya tidak masalah, menulis lewat pointer itu membuat program crash. Pakai array jika kamu berniat mengubah isinya, dan pointer jika hanya membaca.