🪢

Zig 0.14.0 文字列操作のメモ

に公開2

環境

  • Zig 0.14.0

文字列のフォーマット

std.fmt.allocPrintを使う。
フォーマット文字列については https://ziglang.org/documentation/0.14.0/std/#std.fmt.format に記載がある。

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const s = try std.fmt.allocPrint(allocator, "hexadecimal: {x}, string: {s}, floating point: {e}, decimal: {d}, integer with binary: {b}, integer with octal: {o}", .{ 255, "foo", 3.14, 123, 123, 123 });
    defer allocator.free(s);

    std.debug.print("{s}\n", .{s});
}
出力
hexadecimal: ff, string: foo, floating point: 3.14e0, decimal: 123, integer with binary: 1111011, integer with octal: 173

参考: https://zenn.dev/ousttrue/books/b2ec4e93bdc5c4/viewer/fe2023

文字列のコピー

コピー元の文字列と同じ長さのスライスをアロケートし、@memcpyでコピーする。

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const s1 = "foo bar baz qux";
    const s2 = try allocator.alloc(u8, s1.len);
    defer allocator.free(s2);

    @memcpy(s2, s1);

    std.debug.print("s1: {s}\ns2: {s}\n", .{ s1, s2 });
}
出力
s1: foo bar baz qux
s2: foo bar baz qux

std.mem.copyForwardsでも可。(違いがわかってない)

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const s1 = "foo bar baz qux";
    const s2 = try allocator.alloc(u8, s1.len);
    defer allocator.free(s2);

    std.mem.copyForwards(u8, s2, s1);

    std.debug.print("s1: {s}\ns2: {s}\n", .{ s1, s2 });
}
出力
s1: foo bar baz qux
s2: foo bar baz qux

1文字ずつイテレートする

std.unicode.Utf8Viewを使う。

const std = @import("std");

pub fn main() !void {
    const s = "ハロー、ワールド!";
    var view = try std.unicode.Utf8View.init(s);

    var iter = view.iterator();
    while (iter.nextCodepoint()) |c| {
        std.debug.print("{u}\n", .{c});
    }
}
出力
ハ
ロ
ー
、
ワ
ー
ル
ド
!

文字列の結合(concat)

std.mem.concatを使う。

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const s1 = "foo";
    const s2 = "bar";
    const s3 = "baz";

    const s = try std.mem.concat(allocator, u8, &[_][]const u8{ s1, s2, s3 });
    defer allocator.free(s);

    std.debug.print("{s}\n", .{s});
}
出力
foobarbaz

文字列の結合(join)

std.mem.joinを使う。

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const s1 = "foo";
    const s2 = "bar";
    const s3 = "baz";

    const s = try std.mem.join(allocator, ", ", &[_][]const u8{ s1, s2, s3 });
    defer allocator.free(s);

    std.debug.print("{s}\n", .{s});
}
出力
foo, bar, baz

文字列のリストの構築

文字列をコピーしてArrayListに格納する際は都度メモリを確保する。
最後に各要素を走査して開放する。(やり方あってんのかな?)

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const keywords = [_][]const u8{
        "foo",
        "bar",
        "baz",
    };

    var data = std.ArrayList([]const u8).init(allocator);
    defer data.deinit();

    for (keywords) |k| {
        const s: []u8 = try allocator.alloc(u8, k.len);
        @memcpy(s, k);
        try data.append(s);
    }
    defer {
        for (data.items) |item| {
            allocator.free(item);
        }
    }

    for (data.items) |v| {
        std.debug.print("{s}\n", .{v});
    }
}
出力
foo
bar
baz
GitHubで編集を提案

Discussion