如何在Zig中定义尺寸各异的编译期多维数组
Zig拼字游戏计分表定义与comptime查找表实现
首先解决你遇到的「unable to infer array size」错误:Zig的数组要求元素类型统一,且如果用[_]T语法需要编译器能自动推断元素数量。你之前的写法要么是外层数组元素类型不统一(比如混用不同大小的固定数组),要么是外层没使用[_]让编译器推断大小。
正确的计分表定义
用字符串字面量(本质是[]const u8切片)作为外层数组的元素,外层用[_][]const u8让编译器自动推断元素个数,这样既符合「索引对应分数、元素对应字母」的需求,又能通过编译:
const std = @import("std"); // 外层数组索引=分数,内层字符串=对应分数的字母 // 索引0留空(无0分字母),从索引1开始对应1分、2分... const score_letters = [_][]const u8{ "", // 0分 "AEIOULNRST",// 1分 "DG", // 2分 "BCMP", // 3分 "FHVWY", // 4分 "K", // 5分 "", // 6分(无对应字母) "", // 7分(无对应字母) "JX", // 8分 "", // 9分(无对应字母) "QZ", // 10分 };
自动生成comptime查找表
接下来用编译期代码把上面的计分表转换成「字母→分数」的直接查找表,修改计分表时无需改动这段转换代码:
// 定义查找表类型:覆盖所有ASCII字符,值为对应分数 const LetterScoreLookup = [256]u8; // 编译期生成查找表 const letter_score: LetterScoreLookup = comptime blk: { // 初始化所有字符分数为0 var lookup = [_]u8{0} ** 256; // 遍历计分表的每个分数和对应字母 inline for (score_letters, 0..) |letters, score| { // 遍历当前分数下的每个字母 inline for (letters) |char| { // 给大写字母设置分数 lookup[char] = @intCast(u8, score); // 如果需要支持小写字母,添加下面一行: // lookup[char | 0x20] = @intCast(u8, score); } } break :blk lookup; };
使用示例
直接通过字母的ASCII值索引查找表即可快速获取分数:
pub fn main() void { std.debug.print("A的分数:{d}\n", .{letter_score['A']}); std.debug.print("Q的分数:{d}\n", .{letter_score['Q']}); std.debug.print("x的分数:{d}\n", .{letter_score['x']}); // 如果开启了小写支持,这里会返回8 }
错误原因说明
你之前的写法大概率犯了以下两个错误之一:
- 混用不同大小的固定数组作为外层元素:比如
[_][9]u8{ {'A','E',...}, {'D','G'} },此时第二个元素是[2]u8,和第一个元素类型[9]u8不统一,编译器无法处理。 - 外层未用
[_]推断大小:比如直接写[][]const u8{ ... },Zig无法推断外层切片的长度,必须用[_][]const u8让编译器自动计数元素个数。
内容的提问来源于stack exchange,提问作者kaan_atakan
相关产品推荐
相关产品推荐

