🐨
Zigでコマンドライン引数を扱うサンプルプログラム
普通の方法
std.process.argsAlloc()
を使用します。
[:0]const u8
から []const u8
を得るにはstd.mem.sliceTo()
を使用します。
iadd.zig
const std = @import("std");
pub fn main() !void {
const alc = std.heap.page_allocator;
const args = try std.process.argsAlloc(alc);
defer std.process.argsFree(alc, args);
if (args.len < 2) {
std.debug.print("Usage: {s} decimal_numbers ..\n", .{args[0]});
std.os.exit(1);
}
var sum: i32 = 0;
for (args[1..]) |a| {
const arg = std.mem.sliceTo(a, 0);
const num = try std.fmt.parseInt(i32, arg, 10);
sum += num;
}
const stdout = std.io.getStdOut().writer();
try stdout.print("{d}\n", .{sum});
}
$ zig build-exe iadd.zig
$ ./iadd
Usage: ./iadd decimal_numbers ..
$ ./iadd 1 2 3
6
allocしない方法
以下のように書けば、Windows環境で動作しなくなりますが、Allocator
を使用せずに済みます。
引数の個数が最初にわからないので、Usageの表示の判断のためにArgIterator
を回すときにarg_num
をインクリメントしています。
iadd_no_alloc.zig
const std = @import("std");
pub fn main() !void {
var ai = std.process.args();
const cmd_name = std.mem.sliceTo(ai.next().?, 0);
var sum: i32 = 0;
var arg_num: i32 = 0;
while (ai.next()) |a| {
const arg = std.mem.sliceTo(a, 0);
const num = try std.fmt.parseInt(i32, arg, 10);
sum += num;
arg_num += 1;
}
if (arg_num == 0) {
std.debug.print("Usage: {s} decimal_numbers ..\n", .{cmd_name});
std.os.exit(1);
}
const stdout = std.io.getStdOut().writer();
try stdout.print("{d}\n", .{sum});
}
$ zig build-exe iadd_no_alloc.zig
$ ./iadd_no_alloc
Usage: ./iadd_no_alloc decimal_numbers ..
$ ./iadd_no_alloc 1 2 3 4
10
コマンドラインオプションなどもっと高度なことをするには
まだ試していませんが、このあたりのライブラリを使うのがよさそうです。
Zigの公式版パッケージマネージャができたら、こういうのを導入してみたいです。
Discussion