Ziglings 笔记 31: Switch 也是表达式

能返回值的 Switch

在上一篇笔记中,我们用 switch 来决定执行哪个打印语句。在 Ziglings 的第 31 个练习中,我们探索了 switch 更强大的形态——表达式 (Expression)

在 C 语言中,我们通常需要这样写:

char c;
switch (val) {
    case 1: c = 'A'; break;
    case 2: c = 'B'; break;
    // ...
}

这种写法需要先定义变量,再在每个 case 里赋值,非常啰嗦且容易出错(比如忘了 break)。

挑战:直接转换

任务是将数字数组转换为字符并打印。我们需要在 switch 中直接完成“数字 -> 字符”的映射,并把结果赋给常量 real_char

解决方案

这是利用 Switch 表达式的代码:

const std = @import("std");

pub fn main() void {
    const lang_chars = [_]u8{ 26, 9, 7, 42 };

    for (lang_chars) |c| {
        // 核心亮点:
        // switch 块的结果直接被赋值给了 real_char。
        // 这要求所有分支返回的数据类型必须一致。
        const real_char: u8 = switch (c) {
            1 => 'A',
            2 => 'B',
            3 => 'C',
            4 => 'D',
            5 => 'E',
            6 => 'F',
            7 => 'G',
            8 => 'H',
            9 => 'I',
            10 => 'J',
            // ... 省略 ...
            25 => 'Y',
            26 => 'Z',
            
            // 必须处理所有情况,对于未知的数字(如 42),返回感叹号
            else => '!',
        };

        // 注意这里使用 {c} 来打印字符,而不是数字
        std.debug.print("{c}", .{real_char});
    }

    std.debug.print("\n", .{});
}

核心知识点总结

1. 表达式 vs 语句

switch 被用作表达式时,它变得像函数调用一样,会产生一个返回值。 这种写法不仅简洁,还更安全:因为 real_charconst(常量),Zig 保证了它一旦初始化就不会被修改。而在 C 语言的写法中,我们被迫使用可变的变量。

2. 格式说明符 {c}

在 Zig 中,u8 既是字节也是字符。

  • std.debug.print("{}", .{'A'}); 会输出 65
  • std.debug.print("{c}", .{'A'}); 会输出 A。 这个细节时刻提醒我们:在底层,字符依然只是数字。

后续预告:我们已经见识了 switch 的强大。但有时候我们可能会写出一些“逻辑上永远不可能发生”的分支。Zig 提供了一个特殊的关键字 unreachable 来处理这种情况。下一篇我们将深入探讨它。