Bỏ qua để đến nội dung

Chuỗi trong Rust

Xử lý văn bản là một trong những chỗ đầu tiên khiến Rust có cảm giác khác các ngôn ngữ khác, chủ yếu vì nó thực sự có hai kiểu chuỗi (string). Khi đã biết vì sao, mọi thứ sẽ không còn rối nữa.

  • &str (“string slice”, lát chuỗi) — văn bản đã tồn tại ở đâu đó, thường được viết trực tiếp trong code. Kích thước cố định, không thể dài thêm.
  • String — một đoạn văn bản có chủ sở hữu và có thể nới rộng. Bạn có thể thêm vào nó, và nó nằm trên heap.
fn main() {
let literal: &str = "xin chào"; // một string slice
let owned: String = String::from("xin chào"); // một String có chủ sở hữu
println!("{literal} / {owned}");
}
▶ Tự chạy thử

Một quy tắc đơn giản: nếu bạn chỉ in một đoạn chữ cố định thì "như thế này" (một &str) là đủ. Nếu bạn cần tạo dựng, nới rộng hay sửa văn bản lúc chương trình chạy, hãy dùng String.

fn main() {
let mut greeting = String::from("Xin chào");
greeting.push_str(", thế giới"); // thêm một &str
greeting.push('!'); // thêm một char
println!("{greeting}");
}

Kết quả:

Xin chào, thế giới!
▶ Tự chạy thử

Bạn có thể nối chuỗi bằng +, hoặc dùng format! (thường là lựa chọn rõ ràng hơn):

fn main() {
let first = String::from("Xin chào, ");
let second = String::from("thế giới!");
let combined = first + &second; // để ý dấu & trước second
println!("{combined}");
// format! thường dễ đọc hơn:
let name = "Ferris";
let greeting = format!("Xin chào, {name}!");
println!("{greeting}");
}
▶ Tự chạy thử

Một vài phương thức bạn sẽ dùng liên tục. Ví dụ này giữ chuỗi tiếng Anh vì kết quả phụ thuộc vào việc đổi chữ hoa/thường và số byte (chữ tiếng Việt có dấu chiếm nhiều byte hơn):

fn main() {
let text = " Hello, Rust! ";
println!("{}", text.trim()); // "Hello, Rust!" (không còn khoảng trắng hai đầu)
println!("{}", text.to_uppercase()); // " HELLO, RUST! "
println!("{}", text.to_lowercase()); // " hello, rust! "
println!("{}", text.contains("Rust")); // true
println!("{}", text.trim().len()); // 12 (độ dài tính bằng byte)
println!("{}", text.trim().replace("Rust", "World")); // "Hello, World!"
}
▶ Tự chạy thử

Để đi qua từng ký tự một, hãy dùng .chars():

fn main() {
for c in "abc".chars() {
println!("{c}");
}
}
▶ Tự chạy thử

Ai đó đã gõ " rUsT is FUN " vào một biểu mẫu. Hãy biến nó thành rust is great: bỏ khoảng trắng thừa, chuyển hết thành chữ thường, và thay fun bằng great. Sau đó in kết quả và độ dài của nó. Gợi ý: các phương thức chuỗi có thể nối tiếp nhau: text.trim().to_lowercase().... (Bài này giữ chữ tiếng Anh vì nó đổi chữ hoa/thường và đếm byte.)

Xem lời giải
fn main() {
let input = " rUsT is FUN ";
// trim trước, rồi chuyển thành chữ thường, rồi thay "fun" (giờ đã viết thường)
let clean = input.trim().to_lowercase().replace("fun", "great");
println!("{clean}");
println!("{} byte", clean.len());
}

Kết quả:

rust is great
13 byte
▶ Tự chạy thử

Thứ tự rất quan trọng: nếu bạn gọi .replace("fun", "great") trước .to_lowercase(), sẽ chẳng có gì được thay cả, vì lúc đó văn bản vẫn đang là FUN.

Cho first = "Ada" và last = "Lovelace", hãy tạo String [email protected] và in nó ra. Sau đó in ra xem nó có chứa ký tự @ hay không. Gợi ý: format! có thể nhận các biểu thức như first.to_lowercase() làm đối số cho các ô {} của nó.

Xem lời giải
fn main() {
let first = "Ada";
let last = "Lovelace";
let email = format!("{}.{}@example.com", first.to_lowercase(), last.to_lowercase());
println!("{email}");
println!("có vẻ hợp lệ: {}", email.contains('@'));
}

Kết quả:

có vẻ hợp lệ: true
▶ Tự chạy thử
  • &str là văn bản cố định được mượn; String có chủ sở hữu và có thể nới rộng.
  • Làm String dài thêm bằng .push_str() (cho văn bản) hoặc .push() (cho một ký tự).
  • Ưu tiên format! hơn + khi nối chuỗi — rõ ràng hơn và không move thứ gì cả.
  • Các phương thức hay dùng: .trim(), .to_uppercase(), .contains(), .replace(), .chars().

Kiểm tra nhanh

1. Kiểu chuỗi nào có chủ sở hữu và có thể nới rộng lúc chạy?

2. Vì sao trang này ưu tiên format! hơn + khi nối nhiều hơn một hai chuỗi?

3. Vì sao bạn không thể truy cập chuỗi Rust theo chỉ số kiểu text[0]?

4. Phương thức nào thêm một ký tự vào một String, như greeting.push('!')?

Điểm: 0 / 4