sprintf() trả về một chuỗi được tạo từ một định dạng và danh sách giá trị: mỗi chỗ giữ % trong định dạng được thay bằng giá trị tiếp theo. sprintf('%s is %d years old', 'Ada', 36) trả về "Ada is 36 years old". printf() nhận cùng các đối số nhưng in kết quả ra thay vì trả về.
Các chỗ giữ được điền theo thứ tự, từ trái sang phải. %.2f luôn hiển thị hai chữ số thập phân (4.50, không phải 4.5), còn %05d đệm số bằng các số 0 cho đủ năm chữ số.
Các ký hiệu định dạng
Một chỗ giữ gồm %, các modifier tùy chọn, rồi một chữ cái cho kiểu dữ liệu:
| Ký hiệu | Ý nghĩa | sprintf(...) | Kết quả |
|---|---|---|---|
%s | chuỗi | sprintf('%s', 'PHP') | PHP |
%d | số nguyên (có dấu) | sprintf('%d', 42.9) | 42 |
%f | số thực, mặc định 6 chữ số thập phân | sprintf('%f', 1.5) | 1.500000 |
%.2f | số thực, 2 chữ số thập phân | sprintf('%.2f', 1.5) | 1.50 |
%e | ký hiệu khoa học | sprintf('%e', 1234.5678) | 1.234568e+3 |
%x / %X | hệ thập lục phân | sprintf('%x', 255) | ff |
%o | hệ bát phân | sprintf('%o', 8) | 10 |
%b | hệ nhị phân | sprintf('%b', 5) | 101 |
%c | ký tự từ một mã | sprintf('%c', 65) | A |
%u | số nguyên không dấu | sprintf('%u', 3) | 3 |
%% | một dấu phần trăm | sprintf('%d%%', 50) | 50% |
Đổi các giá trị bên dưới rồi chạy lại:
%d cắt bỏ phần thập phân của số thực về phía 0, nên 42.9 thành 42. Nếu bạn muốn 43, hãy làm tròn trước: sprintf('%d', round(42.9)). Một chuỗi không phải số, như 'abc', sẽ thành 0 với %d.
Thêm số 0 ở đầu
Giữa % và chữ cái, bạn có thể đặt một ký tự đệm và một độ rộng. %05d nghĩa là "đệm bằng 0 cho đủ độ rộng 5". Đây là cách thường dùng để định dạng mã đơn hàng, mã hóa đơn, giờ và ngày.
Độ rộng là mức tối thiểu. Một số dài hơn độ rộng vẫn được in đầy đủ.
%05.2f: độ rộng và số thập phân cùng lúc
Với số thực, độ rộng tính mọi ký tự của kết quả, kể cả dấu thập phân và dấu trừ. Đó là lý do %05.2f với 3.14159 cho ra 03.14: tổng cộng năm ký tự, hai trong số đó nằm sau dấu chấm.
%f dùng dấu thập phân của locale hiện tại (đặt bằng setlocale()), còn %F luôn dùng dấu chấm. Nếu code của bạn có đặt locale và bạn cần dấu chấm cho JSON, CSV hoặc một API, hãy dùng %F.
Căn chỉnh văn bản thành cột
Độ rộng dương sẽ căn phải, dấu - trước độ rộng sẽ căn trái, và ' theo sau là một ký tự sẽ đặt ký tự đệm tùy chỉnh. Kết hợp lại, chúng giúp căn thẳng hàng các báo cáo và hóa đơn dạng văn bản thuần.
%-14s đệm tên món ở bên phải cho đủ 14 ký tự, %8.2f căn phải giá tiền trong 8 ký tự, và %'-27s với một chuỗi rỗng in ra một dòng 27 dấu gạch ngang. %'*10s đệm bằng * thay vì khoảng trắng.
Đánh số đối số để dùng lại hoặc đổi thứ tự
%1$s nghĩa là "đối số thứ nhất dưới dạng chuỗi", %2$d là "đối số thứ hai dưới dạng số nguyên". Chỗ giữ có đánh số cho phép bạn dùng một giá trị hai lần hoặc đổi thứ tự mà không phải sửa danh sách đối số, điều mà người dịch rất cần khi trật tự từ khác nhau giữa các ngôn ngữ.
vsprintf, printf và giá trị trả về
vsprintf() nhận các giá trị dưới dạng một mảng, rất tiện khi chúng đã nằm sẵn trong mảng. printf() trả về số byte nó đã in, còn vprintf() là phiên bản dùng mảng của printf().
Con số từ printf() tính cả dấu xuống dòng, nên "Hello\n" là 6 byte. Với văn bản nhiều byte như tiếng Việt có dấu, nó đếm byte chứ không đếm ký tự.
Thiếu đối số sẽ ném lỗi
Từ PHP 8, một định dạng có nhiều chỗ giữ hơn số giá trị sẽ ném ArgumentCountError thay vì trả về false. Khi gặp lỗi này, hãy đếm các chỗ giữ % (bỏ qua %%).
Thông báo lỗi tính cả chuỗi định dạng là một đối số: ArgumentCountError: 4 arguments are required, 3 given. Đối số thừa thì bị bỏ qua mà không báo gì, nên lỗi ngược lại sẽ không hiện ra như một lỗi. Nếu kết quả sprintf trông không đúng, hãy in chuỗi định dạng ra cạnh các giá trị. Khi bạn chỉ cần dấu phân cách hàng nghìn, number_format() đơn giản hơn tự tạo bằng sprintf. Danh sách đầy đủ các modifier có trên php.net.
Câu hỏi thường gặp
Làm sao thêm số 0 vào trước một số trong PHP?
Dùng sprintf('%05d', 42), kết quả là "00042". 0 là ký tự đệm và 5 là tổng độ rộng. Với chuỗi, str_pad('42', 5, '0', STR_PAD_LEFT) cho cùng kết quả.
Làm sao định dạng số với 2 chữ số thập phân bằng sprintf?
Dùng %.2f: sprintf('%.2f', 3.14159) trả về "3.14" và sprintf('%.2f', 5) trả về "5.00". Thêm độ rộng để đệm luôn: %08.2f cho ra "00003.14".
printf và sprintf trong PHP khác nhau thế nào?
sprintf() trả về chuỗi đã định dạng để bạn lưu lại. printf() in ngay chuỗi đó ra và trả về số byte đã in. echo sprintf(...) và printf(...) cho cùng một đầu ra.
%s trong PHP nghĩa là gì?
%s là chỗ giữ cho một chuỗi trong sprintf() và printf(): sprintf('Hello, %s', 'Ada') trả về "Hello, Ada". Số truyền vào %s được chuyển thành chuỗi. %d dành cho số nguyên và %f cho số thực.
Làm sao dùng cùng một đối số hai lần trong sprintf?
Đánh số các chỗ giữ: sprintf('%1$s loves %2$s, and %2$s loves %1$s', 'Ada', 'PHP'). Đặt chuỗi định dạng trong dấu nháy đơn: trong dấu nháy kép PHP đọc $s thành biến, nên "%1$s" biến thành %1 theo sau là giá trị của $s.