我可以在 Zig 中 sprintf 到 ArrayList 吗?

问题描述 投票:0回答:1

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 memory-management format zig
1个回答
0
投票

您可以使用

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
© www.soinside.com 2019 - 2024. All rights reserved.