Ziglings 笔记 100: 百题达成!并行遍历 (Multi-object For Loops)

里程碑:100 题达成!🎉

在 Ziglings 的第 100 个练习中,我们不仅收获了成就感,还学会了 Zig 中最让 C 程序员羡慕的特性之一:多重并行循环

在传统的循环中,如果我们要比较两个数组,必须引入一个中间变量 i 作为索引。但在 Zig 中,我们可以直接把两个数组扔进 for 循环,就像把两条铁轨合并成一条一样自然。

挑战:真假美猴王

我们需要比较两个数组:

  • hex_nums: 用十六进制书写的数字。
  • dec_nums: 用十进制书写的数字。

虽然写法不同,但在底层它们应该是一样的(例如 0xb == 11)。我们需要同时遍历它们来验证这一点。

解决方案

使用多重 for 循环语法:

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

pub fn main() void {
    const hex_nums = [_]u8{ 0xb, 0x2a, 0x77 }; // 11, 42, 119
    const dec_nums = [_]u8{ 11, 42, 119 };

    // 核心语法:for (A, B) |a, b|
    // Zig 会自动同步遍历这两个数组。
    // hn 是 hex_nums 的当前元素,dn 是 dec_nums 的当前元素。
    for (hex_nums, dec_nums) |hn, dn| {
        
        // 比较值
        if (hn != dn) {
            print("Uh oh! Found a mismatch: {d} vs {d}\n", .{ hn, dn });
            return;
        }
    }

    print("Arrays match!\n", .{});
}

核心知识点总结

1. 拉链式迭代 (Zipping)

这种语法 for (a, b) 在函数式编程中通常被称为 “Zip”。它极大地提高了代码的可读性。你不需要关心当前的索引是 0 还是 100,你只关心“现在的 A 和现在的 B 是一对”。

2. 长度安全检查

Zig 对安全性有执着的追求。当你写 for (a, b) 时,Zig 隐含了一个断言:a 和 b 的长度必须相等。 如果长度不一致,在 Debug 模式下程序会直接 Panic。这防止了“一个数组遍历完了,另一个还在继续访问越界内存”的经典错误。

3. 三管齐下?

这个语法支持任意数量的数组,甚至还可以带上索引!

// 同时遍历数组 a, 数组 b, 以及索引 i
for (a, b, 0..) |v_a, v_b, i| {
    // ...
}

这是 Zig 循环语法的完全体形态。


后续预告:百题之后,我们还要去哪里?Ziglings 的旅程还在继续。接下来的练习将深入更高级的主题,比如 函数指针测试系统 (Testing) 以及 C 语言构建系统的集成。让我们继续前进!