Как я могу создавать многомерные массивы произвольных размеров?

#arrays #multidimensional-array #zig

#массивы #многомерный массив #зиг

Вопрос:

Я пишу функцию в Zig, которая должна принимать многомерные массивы произвольных размеров. Могут быть ограничения, но я не могу заранее жестко задать размеры.

Вот пример:

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

fn printMap(map: []const [4]bool) void {
    for (map) |row| {
        for (row) |tile| {
            warn("{}t", .{tile});
        }
        warn("n", .{});
    }
}

pub fn main() !void {
    const map = [_][4]bool{
        [_]bool{ false, false, false, false },
        [_]bool{ false, true, true, false },
        [_]bool{ false, true, true, false },
        [_]bool{ false, false, false, false },
    };
    printMap(map[0..]);
}
  

Это компилируется и запускается, но если я изменю сигнатуру функции на

 fn printMap(map: []const []bool) void
  

Я получаю сообщение об ошибке

 expected type '[]const []bool', found '[]const [4]bool'
  

Возможно ли это выразить в Zig?

Ответ №1:

Ваш map объявлен как многомерный массив [4][4]bool , а длина массива является частью типа времени компиляции (исходя из моего понимания https://ziglang.org/documentation/master/#Slices ).

Как вы поняли, printMap если вы хотите, чтобы эти размеры определялись во время выполнения, вам придется использовать срезы (типы с указателем и длиной), например [][]bool

Чтобы ваш пример работал с использованием подписи printMap(map: []const []bool) , вы могли бы сделать следующее:

 var a = [_]bool{ false, false, true };
var b = [_]bool{ false, true, false };

const map = [_][]bool{
    a[0..], // Make it a slice using slice syntax
    amp;b,     // Or make it a slice by coercing *[N]T to []T
};

var c: []const []bool = map[0..]; // Pass it as a slice of slices
printMap(c);
  

Для создания массивов многомерных фрагментов произвольных размеров вам потребуется несколько буферов для хранения данных.
Вы можете использовать некоторую статическую память или выделять ее по мере необходимости, один из подходов может быть таким:

 fn buildMap(x: u8, y: u8, allocator: *std.mem.Allocator) ![][]bool {
    var map: [][]bool = undefined;
    map = try allocator.alloc([]bool, x);
    for (map) |*row| {
        row.* = try allocator.alloc(bool, y);
    }
    return map;
}
  

С чем следует работать printMap(map: []const []bool) .

Другим подходом было бы использовать одномерный массив / буфер и соответствующим образом индексировать его, но это не совсем отвечает на ваш вопрос. Я довольно новичок в языке, поэтому могут быть тонкости, которые я пропустил.

Комментарии:

1. Рад помочь, я все еще играю с Zig сам, поэтому не могу обещать, что это лучший способ сделать это = D