string_format
『Zig』では、書式付き文字列の生成に std.fmt.allocPrint() と std.fmt.bufPrint() を使います。allocPrint() はアロケータを使ってヒープにメモリを確保しながら文字列を生成し、bufPrint() は呼び出し側が用意したバッファに書き込みます。用途に応じて使い分けることで、メモリ管理を明示的に制御しながら柔軟なフォーマット処理を実現できます。
構文
// -----------------------------------------------
// std.fmt.allocPrint — アロケータを使って書式付き文字列を生成します
// -----------------------------------------------
const result = try std.fmt.allocPrint(allocator, format, args);
// allocator : メモリアロケータ(std.heap.page_allocator 等)です
// format : 書式文字列({s}・{d}・{any} 等のプレースホルダーを使います)です
// args : フォーマット引数のタプル(.{ val1, val2, ... } の形式)です
// 戻り値 : []u8 — 呼び出し側が allocator.free() で解放する必要があります
// -----------------------------------------------
// std.fmt.bufPrint — 既存バッファに書式付き文字列を書き込みます
// -----------------------------------------------
const result = try std.fmt.bufPrint(&buf, format, args);
// &buf : 書き込み先のバッファへの参照([]u8 または [N]u8)です
// format : 書式文字列です
// args : フォーマット引数のタプルです
// 戻り値 : []u8 — バッファ内の書き込み済みスライスです
// バッファが足りない場合は error.NoSpaceLeft が返ります
// -----------------------------------------------
// よく使う書式指定子
// -----------------------------------------------
// {s} — 文字列([]const u8)を出力します
// {d} — 整数を10進数で出力します
// {f} — 浮動小数点数を出力します
// {e} — 浮動小数点数を指数表記で出力します
// {x} — 整数を16進数(小文字)で出力します
// {X} — 整数を16進数(大文字)で出力します
// {b} — 整数を2進数で出力します
// {any} — 任意の型を出力します(デバッグ用)
// {} — デフォルトフォーマットで出力します
構文一覧
| 構文/メソッド | 概要 |
|---|---|
std.fmt.allocPrint(allocator, fmt, args) | アロケータを使ってヒープ上に書式付き文字列を生成します。使用後は allocator.free() で解放する必要があります。 |
std.fmt.bufPrint(&buf, fmt, args) | 呼び出し側が用意したバッファに書式付き文字列を書き込みます。バッファが不足すると error.NoSpaceLeft が返ります。 |
std.fmt.allocPrintZ(allocator, fmt, args) | allocPrint() と同様ですが、末尾にヌル文字を付加した [:0]u8 を返します。C言語との相互運用に使います。 |
std.fmt.bufPrintZ(&buf, fmt, args) | bufPrint() と同様ですが、末尾にヌル文字を付加します。 |
std.fmt.countFormatted(fmt, args) | 生成される文字列のバイト数を計算します(メモリ確保量の事前計算に使います)。 |
{s} | 文字列([]const u8)を出力するプレースホルダーです。 |
{d} | 整数を10進数で出力するプレースホルダーです。 |
{f} | 浮動小数点数を出力するプレースホルダーです。 |
{x} / {X} | 整数を16進数(小文字/大文字)で出力するプレースホルダーです。 |
{any} | 任意の型をデフォルトフォーマットで出力するプレースホルダーです。 |
allocator.free(slice) | allocPrint() で確保したメモリを解放します。 |
defer allocator.free(slice) | defer を使うとスコープ終了時に自動的にメモリを解放できます。 |
サンプルコード
string_format.zig
// string_format.zig — std.fmt.allocPrint / bufPrint のサンプルです
// Steins;Gate のキャラクターを使って
// 書式付き文字列の生成方法をさまざまなパターンで確認します
const std = @import("std");
pub fn main() !void {
// 標準出力への Writer を取得します
const stdout = std.io.getStdOut().writer();
// -----------------------------------------------
// allocPrint のサンプル
// ページアロケータを使ってヒープ上に文字列を生成します
// -----------------------------------------------
// std.heap.page_allocator は OS からページ単位でメモリを確保します
const allocator = std.heap.page_allocator;
// Steins;Gate のキャラクター情報を定義します
const name_okabe = "岡部倫太郎";
const name_kurisu = "牧瀬紅莉栖";
const name_mayuri = "椎名まゆり";
const name_daru = "橋田至";
const name_moeka = "桐生萌郁";
// allocPrint() で書式付き文字列をヒープ上に生成します
// defer を使うことでスコープ終了時に自動的にメモリを解放できます
const greeting_okabe = try std.fmt.allocPrint(allocator, "ラボメン 001番: {s}(未来ガジェット研究所の狂気のマッドサイエンティスト)", .{name_okabe});
defer allocator.free(greeting_okabe);
const greeting_kurisu = try std.fmt.allocPrint(allocator, "ラボメン 004番: {s}(天才物理学者、論文引用数 {d}本)", .{ name_kurisu, 7 });
defer allocator.free(greeting_kurisu);
try stdout.print("=== 未来ガジェット研究所 ラボメン一覧 ===\n\n", .{});
try stdout.print("{s}\n", .{greeting_okabe});
try stdout.print("{s}\n\n", .{greeting_kurisu});
// -----------------------------------------------
// bufPrint のサンプル
// スタック上に用意したバッファに文字列を書き込みます
// -----------------------------------------------
// 128バイトのバッファをスタック上に確保します
var buf: [128]u8 = undefined;
// bufPrint() はバッファに書き込んだスライスを返します
const msg_mayuri = try std.fmt.bufPrint(&buf, "ラボメン 002番: {s} — 「{s}」", .{ name_mayuri, "トゥットゥルー!" });
try stdout.print("{s}\n", .{msg_mayuri});
// 別の書き込みにも同じバッファを再利用できます
const msg_daru = try std.fmt.bufPrint(&buf, "ラボメン 003番: {s} — ハッカー、スーパーハカー", .{name_daru});
try stdout.print("{s}\n", .{msg_daru});
const msg_moeka = try std.fmt.bufPrint(&buf, "ラボメン 005番: {s} — 謎多き携帯電話依存者", .{name_moeka});
try stdout.print("{s}\n\n", .{msg_moeka});
// -----------------------------------------------
// 数値フォーマットのサンプル
// -----------------------------------------------
// 発散番号(タイムライン固有の識別子)を各進数で表示します
const divergence: u32 = 0x4090; // 16進数で 0x4090 = 10進数で 16528
var num_buf: [64]u8 = undefined;
// {d} で10進数、{x} で16進数(小文字)、{b} で2進数に変換します
const dec_str = try std.fmt.bufPrint(&num_buf, "発散値(10進数): {d}", .{divergence});
try stdout.print("{s}\n", .{dec_str});
const hex_str = try std.fmt.allocPrint(allocator, "発散値(16進数): 0x{X}", .{divergence});
defer allocator.free(hex_str);
try stdout.print("{s}\n", .{hex_str});
const bin_str = try std.fmt.allocPrint(allocator, "発散値(2進数): 0b{b}", .{divergence});
defer allocator.free(bin_str);
try stdout.print("{s}\n\n", .{bin_str});
// -----------------------------------------------
// 浮動小数点フォーマットのサンプル
// -----------------------------------------------
// 世界線収束率を浮動小数点で表示します({f} は小数点以下6桁がデフォルト)
const convergence_rate: f64 = 99.9187;
const float_str = try std.fmt.allocPrint(allocator, "世界線収束率: {d:.4}%({s} の記憶が消える危険域)", .{ convergence_rate, name_mayuri });
defer allocator.free(float_str);
try stdout.print("{s}\n", .{float_str});
}
zig run string_format.zig === 未来ガジェット研究所 ラボメン一覧 === ラボメン 001番: 岡部倫太郎(未来ガジェット研究所の狂気のマッドサイエンティスト) ラボメン 004番: 牧瀬紅莉栖(天才物理学者、論文引用数 7本) ラボメン 002番: 椎名まゆり — 「トゥットゥルー!」 ラボメン 003番: 橋田至 — ハッカー、スーパーハカー ラボメン 005番: 桐生萌郁 — 謎多き携帯電話依存者 発散値(10進数): 16528 発散値(16進数): 0x4090 発散値(2進数): 0b100000010010000 世界線収束率: 99.9187%(椎名まゆり の記憶が消える危険域)
概要
『Zig』で書式付き文字列を生成するには、std.fmt.allocPrint() と std.fmt.bufPrint() の2つの関数を使います。allocPrint() はアロケータを受け取り、必要なサイズのメモリをヒープ上に自動確保して文字列を生成します。戻り値の []u8 スライスは使用後に allocator.free() で解放する必要があり、defer と組み合わせるとスコープ終了時に自動解放できます。一方 bufPrint() はあらかじめ用意したバッファに書き込むため、ヒープアロケーションが発生せずパフォーマンスに優れますが、バッファが不足すると error.NoSpaceLeft が返ります。書式文字列の構文は stdout.print() と同一で、{s}(文字列)・{d}(10進数整数)・{f}(浮動小数点)・{x}/{X}(16進数)・{b}(2進数)・{any}(任意型)などのプレースホルダーが利用できます。どちらの関数も第2引数が書式文字列、第3引数がタプル形式のフォーマット引数です。関連する標準出力への書き込みについては 環境構築と基本構文 を、文字列操作の詳細については 文字列の基本 を合わせて確認してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。