🪢
Zig 0.14.0 文字列操作のメモ
環境
- 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文字ずつイテレートする
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
Discussion
記載の用途なら
std.mem.Allocator.dupe
でもいいかも。Null終端にするのなら
Allocator.dupeZ
おお、メモリコピー用のメソッドがアロケータにあったんですね
ありがとうございます