Zig 中的字符串缓冲区和切片

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

我知道 Zig 目前对于业余爱好者来说并不理想,但尽管如此,我一直在尝试编写一个简单的控制台程序,询问用户的名字,然后是姓氏,最后打印“你的名字是x,你的姓氏是 y”只是想看看我是否可以。

我主要是通过复制和粘贴示例想到的:

const std = @import("std");
const print = std.debug.print;

pub fn main() !void {
    const stdin = std.io.getStdIn().reader();

    var buf: [100]u8 = undefined;

    print("What's your first name? ", .{});
    var fname = (try stdin.readUntilDelimiterOrEof(buf[0..], '\n')).?;

    print("What's your last name? ", .{});
    var lname = (try stdin.readUntilDelimiterOrEof(buf[0..], '\n')).?;

    print("Your first name is {s} and your last name is {s}\n", .{fname, lname});
}

现在,它可以编译,但它并没有达到我的预期。这是因为

readUntilDelimiterOrEof()
返回一个切片,因此第二次调用会覆盖变量 fname 的内容。

我可以创建一个变量 pos 来跟踪缓冲区中的位置(即 fname.len),然后将以下输入存储在

buf[pos..]
而不是
buf[0..]
中,但它很笨重,我不认为这就是缓冲区应该可以。

相反,我试图让 fname 和 lname 以某种形式(数组?)包含它们的切片副本,并继续将每个用户输入存储在

buf[0..]
中,但没有取得很大成功。我读过一些建议。使用
fname[0..(fname.len)].*
分配新变量无法编译。它仅适用于数字文字,例如
fname[0..5].*
std.mem.copy
(fname.len)
一起使用,但字符串似乎不是以 null 结尾的,因为程序末尾的打印会打印名称,然后打印问号,直到分配给这个新变量的大小。

实施这个基本程序的合理、惯用的方法是什么?谢谢你。

arrays string buffer slice zig
1个回答
3
投票

使用分配器会更惯用:

const std = @import("std");
const print = std.debug.print;

pub fn main() !void {
    // It can be any allocator, not just FBA
    var buffer: [128]u8 = undefined;
    var fba = std.heap.FixedBufferAllocator.init(&buffer);
    const allocator = fba.allocator();

    const stdin = std.io.getStdIn().reader();
    const max_size = 16;

    print("What's your first name? ", .{});
    var fname = (try stdin.readUntilDelimiterOrEofAlloc(allocator, '\n', max_size)).?;
    defer allocator.free(fname);
    
    print("What's your last name? ", .{});
    var lname = (try stdin.readUntilDelimiterOrEofAlloc(allocator, '\n', max_size)).?;
    defer allocator.free(lname);
    
    print("Your first name is {s} and your last name is {s}\n", .{fname, lname});
}

但是,您的尝试并没有那么糟糕,并且有其用途。您可以通过将缓冲区定义为切片并在每次向其中写入内容时更新它来修复它:

var memory: [100]u8 = undefined;
var buffer: []u8 = &memory;

print("What's your first name? ", .{});
var fname = (try stdin.readUntilDelimiterOrEof(buffer, '\n')).?;
buffer = buffer[fname.len..];

print("What's your last name? ", .{});
var lname = (try stdin.readUntilDelimiterOrEof(buffer, '\n')).?;
buffer = buffer[lname.len..];

print("Your first name is {s} and your last name is {s}\n", .{fname, lname});
© www.soinside.com 2019 - 2024. All rights reserved.