PHP sprintf() 格式化字串

sprintf() 函數用來根據格式字串產生格式化的字串。它允許你精確控制輸出的格式,包括數字的精度、對齊方式等。

基本用法

<?php
$name = "Alice";
$age = 25;

echo sprintf("Name: %s, Age: %d", $name, $age);
// Name: Alice, Age: 25
?>

語法

sprintf(string $format, mixed ...$values): string
  • $format:格式字串
  • $values:要格式化的值
  • 回傳值:格式化後的字串

格式指定符

基本格式:%[flags][width][.precision]specifier

類型指定符

指定符說明範例
%s字串sprintf("%s", "Hello") → "Hello"
%d有符號十進位整數sprintf("%d", 42) → "42"
%u無符號十進位整數sprintf("%u", -1) → 很大的數
%f浮點數sprintf("%f", 3.14) → "3.140000"
%e科學記號(小寫 e)sprintf("%e", 1234) → "1.234000e+3"
%E科學記號(大寫 E)sprintf("%E", 1234) → "1.234000E+3"
%x十六進位(小寫)sprintf("%x", 255) → "ff"
%X十六進位(大寫)sprintf("%X", 255) → "FF"
%o八進位sprintf("%o", 8) → "10"
%b二進位sprintf("%b", 5) → "101"
%cASCII 字元sprintf("%c", 65) → "A"
%%百分號sprintf("%%") → "%"
<?php
$num = 255;

echo sprintf("十進位:%d", $num);    // 255
echo sprintf("十六進位:%x", $num);  // ff
echo sprintf("十六進位:%X", $num);  // FF
echo sprintf("八進位:%o", $num);    // 377
echo sprintf("二進位:%b", $num);    // 11111111
?>

寬度控制

最小寬度

<?php
// 最小寬度 10,預設右對齊
echo sprintf("%10s", "Hello");   // "     Hello"
echo sprintf("%10d", 42);        // "        42"

// 最小寬度 5
echo sprintf("%5d", 42);         // "   42"
echo sprintf("%5d", 12345);      // "12345"(超過寬度不會截斷)
echo sprintf("%5d", 123456);     // "123456"
?>

左對齊

使用 - 標誌:

<?php
echo sprintf("%-10s", "Hello");  // "Hello     "
echo sprintf("%-10d", 42);       // "42        "
?>

補零

使用 0 標誌:

<?php
echo sprintf("%05d", 42);    // "00042"
echo sprintf("%08d", 1234);  // "00001234"
echo sprintf("%05d", -42);   // "-0042"
?>

自訂填充字元

使用 ' 加上填充字元:

<?php
echo sprintf("%'#10s", "Hi");   // "########Hi"
echo sprintf("%-'#10s", "Hi");  // "Hi########"
echo sprintf("%'*10d", 42);     // "********42"
?>

精度控制

浮點數精度

<?php
$pi = 3.14159265359;

echo sprintf("%.2f", $pi);   // "3.14"
echo sprintf("%.4f", $pi);   // "3.1416"
echo sprintf("%.0f", $pi);   // "3"
echo sprintf("%10.2f", $pi); // "      3.14"
echo sprintf("%010.2f", $pi);// "0000003.14"
?>

字串截斷

<?php
$str = "Hello World";

echo sprintf("%.5s", $str);   // "Hello"
echo sprintf("%10.5s", $str); // "     Hello"
?>

參數位置指定

使用 n$ 指定參數位置(n 從 1 開始):

<?php
// 預設順序
echo sprintf("%s is %d years old", "Alice", 25);
// Alice is 25 years old

// 指定位置
echo sprintf("%2\$d years old is %1\$s", "Alice", 25);
// 25 years old is Alice

// 重複使用參數
echo sprintf("%1\$s %1\$s %1\$s", "Hello");
// Hello Hello Hello
?>

符號顯示

<?php
// 顯示正負號
echo sprintf("%+d", 42);   // "+42"
echo sprintf("%+d", -42);  // "-42"

// 正數前加空格
echo sprintf("% d", 42);   // " 42"
echo sprintf("% d", -42);  // "-42"
?>

printf() - 直接輸出

printf()sprintf() 相同,但直接輸出而不是回傳:

<?php
// sprintf 回傳字串
$str = sprintf("Hello, %s!", "Alice");
echo $str;

// printf 直接輸出
printf("Hello, %s!", "Alice");  // 輸出:Hello, Alice!
?>

vprintf() 和 vsprintf()

接受陣列作為參數:

<?php
$values = ["Alice", 25];

// vsprintf 回傳字串
$str = vsprintf("Name: %s, Age: %d", $values);
echo $str;  // Name: Alice, Age: 25

// vprintf 直接輸出
vprintf("Name: %s, Age: %d", $values);
?>

常見應用

格式化貨幣

<?php
function formatMoney(float $amount, string $currency = 'TWD'): string {
    $symbols = ['TWD' => 'NT$', 'USD' => '$', 'EUR' => '€'];
    $symbol = $symbols[$currency] ?? $currency;
    
    return sprintf("%s%,.2f", $symbol, $amount);
}

echo formatMoney(1234.5);       // NT$1,234.50
echo formatMoney(999.99, 'USD'); // $999.99
?>

格式化日期

<?php
$date = [
    'year' => 2024,
    'month' => 3,
    'day' => 5
];

// 補零格式化
echo sprintf("%04d-%02d-%02d", $date['year'], $date['month'], $date['day']);
// 2024-03-05
?>

生成 ID

<?php
function generateOrderId(int $id): string {
    return sprintf("ORD-%08d", $id);
}

echo generateOrderId(123);    // ORD-00000123
echo generateOrderId(9999);   // ORD-00009999
?>

格式化表格

<?php
$users = [
    ['id' => 1, 'name' => 'Alice', 'score' => 95.5],
    ['id' => 2, 'name' => 'Bob', 'score' => 87.25],
    ['id' => 3, 'name' => 'Charlie', 'score' => 92.0],
];

// 表頭
printf("%-5s %-10s %8s\n", "ID", "Name", "Score");
printf("%s\n", str_repeat("-", 25));

// 資料行
foreach ($users as $user) {
    printf("%-5d %-10s %8.2f\n", $user['id'], $user['name'], $user['score']);
}

// 輸出:
// ID    Name           Score
// -------------------------
// 1     Alice          95.50
// 2     Bob            87.25
// 3     Charlie        92.00
?>

除錯輸出

<?php
function debug(string $message, ...$args): void {
    $timestamp = date('Y-m-d H:i:s');
    printf("[%s] %s\n", $timestamp, sprintf($message, ...$args));
}

debug("User %s logged in", "Alice");
// [2024-12-09 10:30:00] User Alice logged in

debug("Found %d items, total: $%.2f", 5, 99.99);
// [2024-12-09 10:30:00] Found 5 items, total: $99.99
?>

十六進位顏色

<?php
function rgbToHex(int $r, int $g, int $b): string {
    return sprintf("#%02X%02X%02X", $r, $g, $b);
}

echo rgbToHex(255, 128, 0);  // #FF8000
echo rgbToHex(0, 0, 255);    // #0000FF
?>

進度顯示

<?php
function showProgress(int $current, int $total): string {
    $percent = ($current / $total) * 100;
    return sprintf("[%3d%%] %d/%d", $percent, $current, $total);
}

echo showProgress(25, 100);  // [ 25%] 25/100
echo showProgress(100, 100); // [100%] 100/100
?>

注意事項

<?php
// 參數數量不匹配會產生警告
// printf("%s %s", "Hello");  // 警告:參數不足

// 型別不匹配會自動轉換
printf("%d", "42abc");  // 42(字串轉為數字)
printf("%s", 123);      // "123"(數字轉為字串)
?>

與其他方式比較

<?php
$name = "Alice";
$age = 25;

// sprintf
$str = sprintf("Name: %s, Age: %d", $name, $age);

// 字串連接
$str = "Name: " . $name . ", Age: " . $age;

// 雙引號插值
$str = "Name: $name, Age: $age";

// heredoc
$str = <<<EOF
Name: $name, Age: $age
EOF;

// 當需要精確格式控制時使用 sprintf
echo sprintf("Price: $%8.2f", 99.5);  // Price: $   99.50
?>