String di Rust — Rust

String di Rust Rust punya dua tipe string utama yang sering membingungkan pemula: String vs &str TipeOwnershipMutableDi mana StringOwnedBisaHeap…

Rust punya dua tipe teks utama. String adalah teks milik sendiri yang bisa ditambah dan diubah. &str (dibaca string slice) adalah pinjaman untuk membaca teks yang sudah ada di tempat lain. Bayangin kasir Kedai Martabak Bang Rusdi. Nota pesanan yang dia tulis adalah miliknya: bisa ditambah "1x es teh" di bawahnya, dan kalau diserahkan ke dapur, kasir gak memegangnya lagi. Itu String. Tulisan di papan menu cuma bisa ditunjuk dan dibaca: "yang ini, Martabak Manis". Menunjuk gak mengambil apa-apa dan gak bisa menambah tulisan. Itu &str.

🧪 Tebakan cepat: kasir menggabung nota dengan +, lalu mencetak nota lamanya lagi:

let nota = String::from("2x martabak manis");
let lengkap = nota + ", 1x es teh";
println!("{}", lengkap);
println!("{}", nota);

Lolos compile? Tebak dulu, jawabannya ada di bagian "Menambah dan menggabung teks".

String dan &str

fn cetak_menu(nama: &str) {
    println!("Menu: {}", nama);
}

fn main() {
    let es: &str = "Es teh";
    let nota: String = String::from("Martabak telur");
    let nota2 = "Martabak manis".to_string();
    cetak_menu(es);
    cetak_menu(&nota);
    cetak_menu(&nota2);
}
Menu: Es teh
Menu: Martabak telur
Menu: Martabak manis

Menambah dan menggabung teks

fn main() {
    let mut nota = String::from("2x martabak manis");
    nota.push_str(", 1x martabak telur");
    nota.push('!');
    println!("{}", nota);
    let total = 102000;
    let struk = format!("{} = Rp{}", nota, total);
    println!("{}", struk);
    println!("{}", nota);
}
2x martabak manis, 1x martabak telur!
2x martabak manis, 1x martabak telur! = Rp102000
2x martabak manis, 1x martabak telur!

+ juga menggabung, tapi caranya beda. Ini kode tebakan tadi:

error[E0382]: borrow of moved value: `nota`
 --> src/main.rs:5:20
  |
2 |     let nota = String::from("2x martabak manis");
  |         ---- move occurs because `nota` has type `String`, which does not implement the `Copy` trait
3 |     let lengkap = nota + ", 1x es teh";
  |                   -------------------- `nota` moved due to usage in operator
4 |     println!("{}", lengkap);
5 |     println!("{}", nota);
  |                    ^^^^ value borrowed here after move
  |
note: calling this operator moves the left-hand side

+ mengambil String di kirinya, menempelkan teks di kanannya, lalu menyerahkan hasilnya ke lengkap. Setelah itu nota sudah kosong. Itu jawaban tebakannya: gak lolos. Sisi kanan + harus &str, jadi String di kanan ditulis dengan &: nota + &tambahan. Kalau semua bagiannya masih mau dipakai, pakai format!.

len() menghitung byte, bukan huruf

Teks Rust disimpan sebagai UTF-8: huruf biasa 1 byte, huruf seperti ê 2 byte. Kamu sudah melihat "Crêpe".len() 6 di pelajaran tipe data. Memotong teks dengan &menu[awal..akhir] juga memakai nomor byte:

fn main() {
    let menu = String::from("Crêpe");
    println!("len: {}", menu.len());
    println!("chars: {}", menu.chars().count());
    println!("{}", &menu[0..2]);
    println!("{}", &menu[0..4]);
    println!("{}", &menu[0..3]);
}
len: 6
chars: 5
Cr
Crê

thread 'main' (23389148) panicked at src/main.rs:7:25:
end byte index 3 is not a char boundary; it is inside 'ê' (bytes 2..4 of string)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Byte 0 1 2 3 4 5
Isi C r ê ê p e

Mengolah baris pesanan

Pembeli mengetik " 2x Martabak Manis ", lengkap dengan spasi berlebih. Kasir perlu jumlah porsi dan nama menunya:

fn main() {
    let baris = "  2x Martabak Manis  ";
    let rapi = baris.trim();
    println!("[{}]", rapi);
    let bagian: Vec<&str> = rapi.split(' ').collect();
    println!("{:?}", bagian);
    let porsi: u32 = bagian[0].replace("x", "").parse().unwrap();
    let menu = bagian[1..].join(" ").to_lowercase();
    println!("{} porsi {}", porsi, menu);
    println!("{}", menu.contains("manis"));
    println!("{}", menu.to_uppercase());
    println!("{}", porsi * 32000);
}
[2x Martabak Manis]
["2x", "Martabak", "Manis"]
2 porsi martabak manis
true
MARTABAK MANIS
64000

⚠️ Jebakan yang sering ketemu

TL;DR: String adalah teks milik sendiri yang bisa ditambah (String::from, .to_string(), push_str, push), &str adalah pinjaman untuk membaca (teks literal, &nota, hasil trim). Fungsi yang cuma membaca menerima &str. format! membuat String baru tanpa mengambil apa-apa, sedangkan + memindahkan String di kirinya (borrow of moved value). len() menghitung byte UTF-8 ("Crêpe" 6), chars().count() menghitung huruf (5), dan memotong di tengah huruf membuat panic. trim, split (lalu collect atau count), replace, contains, to_uppercase, dan to_lowercase mengolah teks tanpa mengubah aslinya.

Yang akan kamu pelajari