std::string

Operasi umum std::string dan alasan ia mengungguli char* dari C.

Daftar isi

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.

cpp penggabungan-string.cpp
#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;
}
text Keluaran
Senin: piket Budi
Panjang: 17
Kedua string berisi teks yang sama

Panjang 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.

cpp mencari-dan-memotong.cpp
#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;
}
text Keluaran
Kata ditemukan pada posisi 10
Sisa kalimat: nilai ujian kelas
Bagian awal: statistik

Kata 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.

cpp mengubah-string.cpp
#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;
}
text Keluaran
gula, telur, minyak
Panjang: 19

Pemanggilan 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.

Aspekchar*std::string
Panjang teksTidak tersimpan, dicari dengan strlen()Melekat, dibaca dengan size()
Penambahan isiAlokasi dan penyalinan manual+= atau append()
Perbandingan isistrcmp(), karena == menguji alamat== membandingkan isi
Memori penyanggaDikelola penulis kodeDikelola 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.

  1. Hasil find() yang langsung dipakai tanpa diuji terhadap std::string::npos. Apabila teks tidak ditemukan, npos adalah bilangan yang sangat besar, sehingga substr(npos) melempar std::out_of_range. Uji hasilnya terlebih dahulu seperti pada contoh pencarian.
  2. Menukar karakter dengan string satu huruf. 'a' bertipe char, sedangkan "a" bertipe string, dan keduanya tidak dapat dipertukarkan pada fungsi seperti replace(). Perhatikan tanda kutip tunggal dan ganda pada setiap literal.
  3. Menghitung indeks terakhir sebagai teks[teks.size()]. Indeks terakhirnya adalah teks.size() - 1, karena indeks mulai dari 0 dan size() 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::string mengelola teks beserta memori penyangganya secara otomatis, dengan ukuran yang melekat dan penggabungan melalui operator + serta +=.
  • Pencarian memakai find() yang mengembalikan std::string::npos apabila tidak ditemukan, sedangkan pemotongan memakai substr().
  • Dibandingkan char*, tipe ini menghilangkan penghitungan panjang manual, alokasi manual, dan jebakan == yang hanya menguji alamat.

Referensi#