In ra màn hình trong Rust
Bạn đã dùng println! khá nhiều lần rồi. Trang này giới thiệu các macro in khác mà bạn sẽ gặp, và khi nào nên dùng cái nào.
println! và print!
Phần tiêu đề “println! và print!”println! in chữ ra và thêm một ký tự xuống dòng ở cuối. print! làm y như vậy nhưng không thêm ký tự xuống dòng:
fn main() { print!("Xin chào, "); print!("thế giới"); println!("!");}Kết quả:
Xin chào, thế giới!Để ý rằng cả ba lời gọi đều in trên cùng một dòng — chỉ println! mới xuống dòng mới. Trong thực tế, bạn sẽ dùng println! gần như mọi lúc; print! chủ yếu có ích khi bạn ghép một dòng từ nhiều mảnh.
Chỗ giữ chỗ: {} và tên biến
Phần tiêu đề “Chỗ giữ chỗ: {} và tên biến”Bạn đã thấy {} được dùng làm chỗ giữ chỗ (placeholder). Bạn có thể điền vào nó bằng cách truyền một giá trị sau chuỗi, hoặc đặt tên biến trực tiếp vào trong cặp ngoặc:
fn main() { let name = "Ferris"; let age = 10;
println!("{} năm nay {} tuổi", name, age); // theo vị trí println!("{name} năm nay {age} tuổi"); // viết trực tiếp (kết quả như nhau)}Kết quả:
Ferris năm nay 10 tuổiFerris năm nay 10 tuổiCả hai dòng in ra giống hệt nhau. Kiểu viết trực tiếp ({name}) mới hơn một chút và thường dễ đọc hơn, nên hãy ưu tiên nó khi có thể.
format! — tạo chuỗi thay vì in ra
Phần tiêu đề “format! — tạo chuỗi thay vì in ra”Đôi khi bạn muốn có đoạn chữ đã định dạng dưới dạng một String thay vì in ngay — chẳng hạn để lưu lại hoặc truyền cho một hàm khác. Đó là việc của format!. Nó hoạt động y hệt println! nhưng trả về một String thay vì in ra:
fn main() { let name = "Ferris"; let message = format!("Xin chào, {name}!"); println!("{message}");}Kết quả:
Xin chào, Ferris!In debug với {:?}
Phần tiêu đề “In debug với {:?}”{} thông thường chỉ dùng được cho những giá trị biết cách tự hiển thị thành chữ — số, chuỗi, boolean. Với những giá trị phức tạp hơn như tuple hay struct, {} sẽ không biên dịch được. Hãy dùng {:?} (định dạng “debug”) thay thế:
fn main() { let point = (3, 7); println!("{:?}", point);}Kết quả:
(3, 7)Để có bố cục nhiều dòng đẹp hơn cho các giá trị lớn, hãy dùng {:#?} (pretty-print):
fn main() { let point = (3, 7); println!("{:#?}", point);}Kết quả:
( 3, 7,)Định dạng số
Phần tiêu đề “Định dạng số”Vài mẹo định dạng hay gặp:
fn main() { let pi = 3.14159; println!("{:.2}", pi); // 2 chữ số thập phân -> 3.14 println!("{:5}", 42); // độn cho đủ độ rộng 5 -> " 42" println!("{:08.2}", pi); // độn bằng số 0 -> 00003.14}Kết quả:
3.14 4200003.14Bạn không cần học thuộc những thứ này — chỉ cần biết chúng tồn tại để dùng khi cần căn thẳng các con số hay làm tròn số thập phân.
Căn lề chữ, và in dấu ngoặc nhọn
Phần tiêu đề “Căn lề chữ, và in dấu ngoặc nhọn”Độ rộng cũng dùng được cho chữ, và bạn có thể chọn giá trị bám về phía nào. Sau dấu :, đặt < (trái), > (phải) hoặc ^ (giữa), rồi đến độ rộng. Bạn cũng có thể đặt một ký tự độn ở phía trước, như -:
fn main() { let coffee = 3.5; let bagel = 2.25;
println!("{:-^20}", " THỰC ĐƠN "); println!("{:<12}{:>8}", "Món", "Giá"); println!("{:<12}{:>8.2}", "Cà phê", coffee); println!("{:<12}{:>8.2}", "Bánh mì", bagel); println!("{:<12}{:>8.2}", "Tổng", coffee + bagel);}Kết quả:
----- THỰC ĐƠN -----Món GiáCà phê 3.50Bánh mì 2.25Tổng 5.75Đọc {:>8.2} từng mảnh: > nghĩa là căn phải, 8 là độ rộng, và .2 nghĩa là hai chữ số thập phân. Căn phải các con số giúp dấu chấm thập phân thẳng hàng, đó là lý do hóa đơn và bảng biểu hay làm vậy.
Rust đếm độ rộng theo số ký tự, nên chữ tiếng Việt có dấu vẫn căn thẳng hàng bình thường.
Nếu bạn muốn in ra một dấu { thật thì sao? Vì dấu ngoặc nhọn nghĩa là “chỗ giữ chỗ”, bạn phải viết đôi chúng: {{ in ra { và }} in ra }.
fn main() { println!("Tập hợp: {{{}, {}}}", 1, 2);}Kết quả:
Tập hợp: {1, 2}Luyện tập
Phần tiêu đề “Luyện tập”1. Một nhãn giá
Phần tiêu đề “1. Một nhãn giá”Lưu tên món "Sổ tay" và giá 2.5, rồi in ra Sổ tay có giá $2.50. Gợi ý: {:.2} làm tròn đến hai chữ số thập phân, và nó cũng dùng được khi viết trực tiếp: {price:.2}.
Xem lời giải
fn main() { let item = "Sổ tay"; let price = 2.5; println!("{item} có giá ${price:.2}");}Kết quả:
Sổ tay có giá $2.502. Tạo một nhãn, rồi in theo hai cách
Phần tiêu đề “2. Tạo một nhãn, rồi in theo hai cách”Dùng format! để tạo nhãn ferris-7 từ tên "ferris" và số 7. In nó một lần bằng {} và một lần bằng {:?}, rồi tìm điểm khác nhau. Gợi ý: format! nhận đúng những chỗ giữ chỗ giống như println!.
Xem lời giải
fn main() { let name = "ferris"; let id = 7; let label = format!("{name}-{id}");
println!("{label}"); println!("{label:?}");}Kết quả:
ferris-7"ferris-7"In debug hiển thị chữ có dấu ngoặc kép, nên bạn thấy chính xác chỗ nó bắt đầu và kết thúc. Điều này rất tiện khi một giá trị có dấu cách thừa.
Tóm tắt
Phần tiêu đề “Tóm tắt”println!in kèm xuống dòng;print!thì không.{}và{name}là chỗ giữ chỗ cho những giá trị có thể tự hiển thị (Display).format!hoạt động nhưprintln!nhưng trả về mộtStringthay vì in ra.{:?}(và{:#?}) in giá trị để debug, kể cả những giá trị mà{}không xử lý được.{:.2}làm tròn số thập phân;<,>và^cùng với độ rộng giúp căn lề chữ;{{và}}in ra dấu ngoặc nhọn thật.
Kiểm tra nhanh
Phần tiêu đề “Kiểm tra nhanh”Kiểm tra nhanh
1. println! và print! khác nhau thế nào?
2. Vì sao nên dùng {:?} thay vì {} để in một tuple?
Điểm: 0 / 2
Đọc thêm
Phần tiêu đề “Đọc thêm”std::fmt— standard library docs (tiếng Anh): danh sách đầy đủ các tùy chọn định dạng, gồm độ rộng, ký tự độn, căn lề và độ chính xác.- Formatted print — Rust by Example (tiếng Anh): ví dụ chạy được về đối số theo vị trí và theo tên, độn và căn lề.
- Debug — Rust by Example (tiếng Anh):
{:?}và{:#?}hoạt động thế nào và kiểu của riêng bạn có chúng ra sao. println!— standard library docs (tiếng Anh): tài liệu chính thức vềprintln!, có liên kết tớiprint!vàeprintln!.format!— standard library docs (tiếng Anh): tạo mộtStringvới cùng các quy tắc định dạng.