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 và String
Phần tiêu đề “&str và String”&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}");}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.
Làm một String dài thêm
Phần tiêu đề “Làm một String dài thêm”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!Nối chuỗi
Phần tiêu đề “Nối chuỗi”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}");}Các phương thức chuỗi hữu ích
Phần tiêu đề “Các phương thức chuỗi hữu ích”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!"}Duyệt qua một chuỗi
Phần tiêu đề “Duyệt qua một chuỗi”Để đi qua từng ký tự một, hãy dùng .chars():
fn main() { for c in "abc".chars() { println!("{c}"); }}Luyện tập
Phần tiêu đề “Luyện tập”1. Dọn dẹp dữ liệu nhập lộn xộn
Phần tiêu đề “1. Dọn dẹp dữ liệu nhập lộn xộn”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 great13 byteThứ 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.
2. Tạo một địa chỉ email
Phần tiêu đề “2. Tạo một địa chỉ email”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ệ: trueTóm tắt
Phần tiêu đề “Tóm tắt”&strlà văn bản cố định được mượn;Stringcó chủ sở hữu và có thể nới rộng.- Làm
Stringdà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
Phần tiêu đề “Kiểm tra nhanh”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
Đọc thêm
Phần tiêu đề “Đọc thêm”- Storing UTF-8 Encoded Text with Strings — The Rust Book (tiếng Anh): chương chính thức về
String, kể cả lý do bạn không thể truy cập theo vị trí. - String Slices — The Rust Book (tiếng Anh):
&strthực chất là gì, sau khi bạn đã học về mượn (borrowing). - Strings — Rust by Example (tiếng Anh): ví dụ chạy được về
Stringvà&str, cùng ký tự thoát và raw string. String— standard library docs (tiếng Anh): mọi phương thức của mộtStringcó chủ sở hữu, mỗi cái kèm một ví dụ nhỏ.str— standard library docs (tiếng Anh): các phương thức nhưtrim,contains,replacevàsplitdùng được trên mọi đoạn văn bản.