Topik ini membahas std::string, tipe teks pustaka standar yang menjadi pilihan utama untuk data huruf di C++. Pembahasannya mencakup pembentukan teks, penggabungan, pencarian, pemotongan, perubahan isi, serta perbandingannya dengan char* yang diwarisi dari C. Setelah membaca topik ini, operasi string yang paling sering dipakai sudah dapat ditulis dengan benar dan alasan menghindari pointer karakter mentah sudah dapat diuraikan.
Pembentukan dan penggabungan teks#
std::string diperoleh dari header <string> dan dapat dibentuk dari literal teks maupun string lain. Penggabungan memakai operator + dan += seperti operasi aritmetika biasa, sehingga teks tersusun tanpa fungsi khusus. Perbandingan dengan == menguji kesamaan isinya, bukan kesamaan tempat penyimpanannya, dan ukurannya selalu tersedia melalui size() atau length(). Program berikut menyusun jadwal piket, menghitung panjangnya, lalu menguji kesamaan isinya.
#include <iostream>
#include <string>
int main() {
std::string hari = "Senin";
std::string nama = "Budi";
std::string jadwal = hari + ": piket " + nama;
std::cout << jadwal << '\n';
std::cout << "Panjang: " << jadwal.size() << '\n';
std::string salinan = jadwal;
if (salinan == jadwal) {
std::cout << "Kedua string berisi teks yang sama\n";
}
return 0;
}Senin: piket Budi
Panjang: 17
Kedua string berisi teks yang samaPanjang 17 sesuai hitungan karakter pada teks Senin: piket Budi, termasuk dua spasi dan tanda titik dua. Pernyataan if bernilai benar karena == pada std::string membandingkan urutan karakternya satu per satu, berbeda dari perilaku == pada pointer karakter mentah yang dibahas di bagian akhir topik. Nilai kembalian size() bertipe std::size_t, yaitu tipe bilangan bulat tak bertanda, sehingga hasilnya selalu tidak negatif.
Perbandingan juga mencakup urutan huruf, karena operator < dan > membandingkan dua string secara kamus (lexicographic), sehingga teks apel dianggap lebih kecil daripada jeruk. Sifat ini membuat daftar nama mudah diurutkan tanpa fungsi perbandingan khusus. Penugasan antarstring menyalin isinya, sehingga salinan pada contoh berdiri sendiri dan perubahan pada salah satunya tidak menjalar ke yang lain.
Mencari dan memotong teks#
Member function find() mengembalikan posisi kemunculan pertama sebuah teks di dalam string, dengan indeks yang mulai dari 0. Apabila teks yang dicari tidak ada, find() mengembalikan nilai khusus bernama std::string::npos, sehingga hasil pencarian wajib diuji terhadap nilai itu sebelum dipakai. Member function substr() memotong string menjadi string baru, baik sampai akhir maupun sepanjang sejumlah karakter tertentu.
#include <iostream>
#include <string>
int main() {
std::string kalimat = "statistik nilai ujian kelas";
std::size_t posisi = kalimat.find("nilai");
if (posisi != std::string::npos) {
std::cout << "Kata ditemukan pada posisi " << posisi << '\n';
std::cout << "Sisa kalimat: " << kalimat.substr(posisi) << '\n';
}
std::string bagian = kalimat.substr(0, 9);
std::cout << "Bagian awal: " << bagian << '\n';
return 0;
}Kata ditemukan pada posisi 10
Sisa kalimat: nilai ujian kelas
Bagian awal: statistikKata nilai ditemukan pada indeks 10, yaitu setelah kata statistik dan satu spasi. Pemanggilan substr(posisi) mengambil teks dari posisi itu sampai akhir, sedangkan substr(0, 9) mengambil sembilan karakter pertama sehingga menghasilkan statistik. String hasil pemotongan adalah string baru yang berdiri sendiri, sehingga perubahan terhadapnya tidak memengaruhi kalimat.
Posisi yang dikembalikan find() menyatakan indeks karakter pertama dari teks yang dicari. Apabila pencarian perlu dimulai dari posisi tertentu, find() menerima argumen kedua berupa posisi awal, sehingga kemunculan kedua dan seterusnya dapat dicari di dalam perulangan. Untuk teks yang tidak ditemukan, pengujian terhadap std::string::npos wajib dilakukan sebelum posisi dipakai sebagai indeks, karena npos bukan posisi yang sah.
Mengubah isi string#
Isi std::string dapat ditambah dan ditulis ulang setelah dibentuk, dan pustaka standar mengatur memori penyangganya secara otomatis. Member function append() menambah teks di akhir, sedangkan replace() mengganti sejumlah karakter mulai dari posisi tertentu dengan teks penggantinya. Keduanya mengubah string aslinya dan mengembalikan referensi ke string itu, sehingga hasilnya dapat dirangkai.
#include <iostream>
#include <string>
int main() {
std::string daftar = "beras, telur";
daftar.append(", minyak");
daftar.replace(0, 5, "gula");
std::cout << daftar << '\n';
std::cout << "Panjang: " << daftar.size() << '\n';
return 0;
}gula, telur, minyak
Panjang: 19Pemanggilan replace(0, 5, "gula") mengganti lima karakter pertama, yaitu beras, dengan teks gula yang hanya empat karakter, sehingga panjangnya menyusut satu karakter. Perubahan seperti ini tidak memerlukan perhitungan kapasitas apa pun dari sisi penulis kode. Pada program panjang, gabungan append(), replace(), dan insert() menutup sebagian besar kebutuhan penyuntingan teks tanpa mengelola memori secara manual.
Dua member function lain yang sering dipakai adalah insert() dan erase(). Member function insert(posisi, teks) menyisipkan teks pada posisi tertentu, sedangkan erase(posisi, panjang) menghapus sejumlah karakter mulai dari posisi tersebut. Keduanya menata ulang memori penyangga secara otomatis, sehingga penyisipan dan penghapusan tidak mengharuskan penggeseran karakter yang ditulis manual seperti pada array karakter mentah.
Mengapa std::string mengungguli char*#
Tipe char* dari C adalah pointer ke deretan karakter yang diakhiri karakter khusus '\0' sebagai penanda akhir. Pointer itu tidak membawa informasi panjang teksnya, sehingga panjang harus dihitung dengan fungsi strlen() dan pertumbuhan isinya harus dikelola dengan alokasi memori manual. Selain itu, operator == pada dua pointer tersebut hanya membandingkan alamatnya, bukan isi teksnya.
| Aspek | char* | std::string |
|---|---|---|
| Panjang teks | Tidak tersimpan, dicari dengan strlen() | Melekat, dibaca dengan size() |
| Penambahan isi | Alokasi dan penyalinan manual | += atau append() |
| Perbandingan isi | strcmp(), karena == menguji alamat | == membandingkan isi |
| Memori penyangga | Dikelola penulis kode | Dikelola otomatis |
Penanda akhir '\0' juga menjadi sumber kesalahan tersendiri pada teks C. Penyangga karakter berukuran sepuluh hanya dapat menampung sembilan karakter yang bermakna karena satu tempat dipakai penandanya. Lupa menaruh penanda itu membuat fungsi seperti strlen() membaca melewati batas penyangganya. std::string menyimpan panjangnya secara eksplisit, sehingga penanda akhir tidak perlu disusun maupun dihitung oleh penulis kode.
Kebanyakan kode C++ modern memakai std::string untuk teks biasa, sedangkan char* masih muncul pada antarmuka pustaka C, argumen argv, dan kode warisan (legacy). Apabila fungsi pustaka menuntut const char*, std::string menyediakannya melalui member function c_str(). Dengan demikian, kedua dunia tersebut dapat berdampingan tanpa menyerahkan manajemen memori teks ke penulis kode.
Kesalahan umum#
Tiga kesalahan berikut paling sering muncul ketika std::string dipakai.
- Hasil
find()yang langsung dipakai tanpa diuji terhadapstd::string::npos. Apabila teks tidak ditemukan,nposadalah bilangan yang sangat besar, sehinggasubstr(npos)melemparstd::out_of_range. Uji hasilnya terlebih dahulu seperti pada contoh pencarian. - Menukar karakter dengan string satu huruf.
'a'bertipechar, sedangkan"a"bertipe string, dan keduanya tidak dapat dipertukarkan pada fungsi sepertireplace(). Perhatikan tanda kutip tunggal dan ganda pada setiap literal. - Menghitung indeks terakhir sebagai
teks[teks.size()]. Indeks terakhirnya adalahteks.size() - 1, karena indeks mulai dari 0 dansize()menyatakan banyaknya karakter.
Satu kebiasaan menutup sebagian besar kesalahan di atas, yaitu membaca tanda tangan member function sebelum memanggilnya. Nilai kembalian, urutan parameter, dan makna posisinya berbeda antarfungsi, sehingga pemeriksaan singkat ke dokumentasi lebih murah daripada menelusuri program yang berperilaku aneh. Kebiasaan yang sama mempermudah penemuan kesalahan indeks serta perbedaan tipe antara char dan string.
Ringkasan#
std::stringmengelola teks beserta memori penyangganya secara otomatis, dengan ukuran yang melekat dan penggabungan melalui operator+serta+=.- Pencarian memakai
find()yang mengembalikanstd::string::nposapabila tidak ditemukan, sedangkan pemotongan memakaisubstr(). - Dibandingkan
char*, tipe ini menghilangkan penghitungan panjang manual, alokasi manual, dan jebakan==yang hanya menguji alamat.
Referensi#
- std::basic_string — cppreference.com — Dokumentasi lengkap std::string beserta member function-nya.
- std::basic_string::find — cppreference.com — Perilaku pencarian dan nilai kembalian npos.
- std::basic_string::substr — cppreference.com — Kaidah pemotongan dan pengecualian yang mungkin dilempar.
- Introduction to std::string — LearnCpp — Pengantar std::string beserta pembandingannya dengan string C.
- std::string length and capacity — LearnCpp — Pemakaian length(), size(), dan kapasitas penyangga string.