Zig's printing functions expect format strings that are known at compile time. You can use C's printf if you need a dynamic format string.
Here's something I got running on version 0.12.0-dev.2296+46d592e48.
const c = @cImport({
@cInclude("stdio.h");
});
const std = @import("std");
// Returns a null-terminated heap-allocated string, usable in C, containing the phrase "hi " repeated numHis type.
const hi = "hi ";
fn getHis(allocator: std.mem.Allocator, numHis: usize) ![*:0]u8 {
const total_len = numHis * hi.len;
// allocSentinel ensures it ends with a \0.
const s = try allocator.allocSentinel(u8, total_len, 0);
var i: usize = 0;
while (i < total_len) : (i += hi.len) {
// repeatedly copy the phrase into the allocated memory.
std.mem.copyForwards(u8, s[i .. i + hi.len], hi);
}
return s;
}
// Returns a null-terminated heap-allocated string, usable in C, containing some border chars and the phrase "%s", which can be passed as a format string to c's printf.
const strInsert = "\n%s\n";
fn getBorderedFormatString(allocator: std.mem.Allocator, borderChar: u8) ![*:0]u8 {
const total_len: usize = 20 + strInsert.len + 2; // add 2 for leading and trailing newline
const s = try allocator.allocSentinel(u8, total_len, 0);
var i: usize = 0;
s[i] = '\n';
i += 1;
while (i < 11) : (i += 1) {
s[i] = borderChar;
}
std.mem.copyForwards(u8, s[i .. i + strInsert.len], strInsert);
i += strInsert.len;
while (i < total_len - 1) : (i += 1) {
s[i] = borderChar;
}
s[i] = '\n';
return s;
}
test "dynamic_phrase" {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
const s = try getHis(allocator, 30);
const f = try getBorderedFormatString(allocator, '+');
_ = c.printf(f, s);
}
I'm new at Zig, so maybe there is a way to use dynamic format strings in Zig directly. If so, I didn't easily discover it.
fn myFn(format: []const u8)→fn myFn(comptime format: []const u8). If not, could you give a code example of what you're trying to do and why it has to be runtime?inline for(.{"string one {s}", "string two {s}"}) |format_str| { std.log.info(format_str, .{"arg"}); }ziglang.org/documentation/master/#inline-for . You can't make a function that returns a comptime string from a runtime string though, because the result of that function needs to be known at comptime but depends on a runtime value