Zig 标准库包含函数
std.fmt.allocPrint
,它接受一个分配器,打印到用所述分配器分配的缓冲区,并返回结果,非常类似于动态 sprintf
。
对于我的特定用例,我需要在打印多个字符串后将它们附加在一起。我看到的唯一解决方案是使用
allocPrint
,首先打印到一些分配的内存,然后将字节复制到 ArrayList
,这似乎是多余的。
理想情况下,标准库将包含一个允许直接打印到
ArrayList
的函数,如下所示:
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(gpa.deinit() == .ok);
const allocator = gpa.allocator();
var list = std.ArrayList(u8).init(allocator);
defer list.deinit();
const values = [_]f64{ 5.6, 123.4, 19.6, 18.4 };
for (values) |value| {
try std.fmt.allocPrintToArrayList(list, "{e} ", .{value}); // Does not work
}
_ = list.pop();
// Ideally `list.items` would include the `values` delimited by spaces
}
有没有办法在 Zig 中做我需要做的事情?例如,也许我可以使用
ArrayList
作为分配器,这样它又可以与 allocPrint
API 一起使用。
您可以使用
ArrayList.append
将调用 allocPrint
的结果附加到 ArrayList
,因为 allocPrint
返回已打印字节的切片。在这里使用 arena 分配器很方便,因为 allocPrint
每次调用时都会进行分配。
ArrayList
还需要保存 []u8
类型而不是 u8
类型。
const std = @import("std");
const allocPrint = std.fmt.allocPrint;
const append = std.ArrayList.append;
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var list = std.ArrayList([]u8).init(allocator);
defer list.deinit();
const values = [_]f64{ 5.6, 123.4, 19.6, 18.4 };
for (values) |value| {
try list.append(
try (allocPrint(allocator, "{e} ", .{value})),
);
}
for (list.items) |s| {
std.debug.print("{s}\n", .{s});
}
}
> .\arraylist_sprintf
5.6e+00
1.234e+02
1.96e+01
1.84e+01