欢迎访问yhm138的博客园博客, 你可以通过 [RSS] 的方式持续关注博客更新

MyAvatar

yhm138

HelloWorld!

Zig语言编程示例

部分代码非本人编写。
以下部分Zig代码可以在AttemptThisOnline运行。

推荐些阅读材料

Zig by Example
官方文档
Zig中文教程,非官方

Zig语言简介

Zig 是一种命令式、通用、静态类型、编译的系统编程语言,由 Andrew Kelley 设计。 它旨在替代C编程语言,其目标是更小,编程更简单,同时还提供现代功能,新的优化和各种安全机制, 同时不像其他语言那样对运行时安全性的要求。

语言简单性的改进与流控制、函数调用、库导入、变量声明和 Unicode 支持有关。 此外,该语言不使用宏或预处理器指令。从现代语言中采用的功能包括添加编译时泛型类型, 允许函数处理各种数据,以及一小组新的编译器指令,以允许使用反射访问有关这些类型的信息。 Zig 还旨在提高代码的安全性,它不提供垃圾回收(GC),但是使用可选类型代替 null ,这避免了空指针的出现。

在线执行Zig的平台

有很多

以下列出了,可以在线执行 zig 的平台:

zig-playground
zig-play

debug-print

const std = @import("std");
std.debug.print("z={},d={},n={},k={}\n", .{z, d, n, k});

函数返回类型

看起来pub fn main() !void 要比pub fn main() void好用。
这是联合错误类型,该语法将会告诉 zig 编译器会返回错误或者值,此处的意思是如果有返回值,一定是一个错误。

pub fn main() !void {
    const result = try generateSequence(5, 13);
    for (result) |item| {
        std.debug.print("{}, ", .{item});
    }
    std.debug.print("\n", .{});
}

allocator有哪些

std.heap.page_allocator

const allocator = std.heap.page_allocator;

const memory = try allocator.alloc(u8, 100);
defer allocator.free(memory);

try expect(memory.len == 100);
try expect(@TypeOf(memory) == []u8);

std.heap.FixedBufferAllocator

var buffer: [1000]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buffer);
const allocator = fba.allocator();

const memory = try allocator.alloc(u8, 100);
defer allocator.free(memory);

try expect(memory.len == 100);
try expect(@TypeOf(memory) == []u8);

std.heap.page_allocator

const byte = try std.heap.page_allocator.create(u8);
defer std.heap.page_allocator.destroy(byte);
byte.* = 128;

std.heap.GeneralPurposeAllocator


var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer {
        const deinit_status = gpa.deinit();
        //fail test; can't try in defer as defer is executed after we return
        if (deinit_status == .leak) expect(false) catch @panic("TEST FAIL");
}

const bytes = try allocator.alloc(u8, 100);
defer allocator.free(bytes);

for-loop和while-loop

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

pub fn main() !void {
    var array = [_]u32{ 1, 2, 3 };

    for (array) |elem| {
        print("by val: {}\n", .{elem});
    }

    for (&array) |*elem| {
        elem.* += 100;
        print("by ref: {}\n", .{elem.*});
    }

    for (array, &array) |val, *ref| {
        _ = val;
        _ = ref;
    }

    for(0..4) |my_index| {
       print("index: {}\n", .{my_index});
    }

    for (0.., array) |i, elem| {
        print("{}: {}\n", .{ i, elem });
    }

    for (array) |_| {}

    var a: usize = 0;
    var b: usize = 0;
    var c: usize = 0;
    var d: usize = 0;

    while (a < 2) {
        print("a: {}\n", .{a});
        a += 1;
    }

    while (b < 2) : (b += 1) {
        print("b: {}\n", .{b});
    }

    while (c < 4) : ({
        c += 1;
        c += 1;
    }) {
        print("c: {}\n", .{c});
    }

    while (true) {
        break;
    }

    while (true) : (d += 1) {
        if (d < 2) {
            print("d: {}\n", .{d});
            continue;
        }

        break;
    }
}

ArrayList

const std = @import("std");
const expect = std.testing.expect;

const eql = std.mem.eql;
const ArrayList = std.ArrayList;
const test_allocator = std.heap.page_allocator;

pub fn main() !void {
    var list = ArrayList(u8).init(test_allocator);
    defer list.deinit();
    try list.append('H');
    try list.append('e');
    try list.append('l');
    try list.append('l');
    try list.append('o');
    try list.appendSlice(" World!");

    try expect(eql(u8, list.items, "Hello World!"));
}

Arrays

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

pub fn main() !void {

    const a = [3]i32{ 1, 2, 3 };

    const b = [_]i32{ 4, 5, 6 };

    const c: [3]i32 = .{ 7, 8, 9 };

    var d: [3]i32 = undefined;
    d[0] = 10;
    d[1] = 11;
    d[2] = 12;

    print("len: {}\n", .{c.len});

    print("repeat: {any}\n", .{a ** 2});

    print("concat: {any}\n", .{a ++ b});

    for (d) |elem| {
        print("elem: {}\n", .{elem});
    }



    //var array1:  [8]u8       = .{ 1,2,3,4,5,6,7,8 };
    //var array2d: [2][4]u8    = .{ .{1,2,3,4}, .{5,6,7,8} };
    //var array3d: [2][2][2]u8 = .{ .{ .{1,2}, .{3,4} }, .{ .{5,6}, .{7,8} } };
    const mat4x4 = [4][4]f32{
       [_]f32{ 1.0, 0.0, 0.0, 0.0 },
       [_]f32{ 0.0, 1.0, 0.0, 1.0 },
       [_]f32{ 0.0, 0.0, 1.0, 0.0 },
       [_]f32{ 0.0, 0.0, 0.0, 1.0 },
    };

    for (mat4x4) |row| {
       for(row) |elem| {
          print("elem: {}\n", .{elem});
       }
    }
}

实战——变长二维数组

下面这份Zig代码我写了一个多小时。

const std = @import("std");
const allocator = std.heap.page_allocator;

pub fn main() !void {
    const result = try generateSequence(5, 13);
    for (result) |item| {
        std.debug.print("{}", .{item});
    }
    std.debug.print("\n", .{});
}

fn generateSequence(_k: i32, _n: i32) ![]i32 {
    var k=_k; var n=_n;

    var s = std.ArrayList(std.ArrayList(i32)).init(allocator);

    for (0..@as(usize, @intCast(n))) |i| {
        var innerList = std.ArrayList(i32).init(allocator);
        if (i < k) {
            try innerList.append(1);
        } else {
            try innerList.append(0);
        }
        try s.append(innerList);
    }

    var d:i32 = n-k;  
    n = @max(k, d);
    k = @min(k, d);
    var z = d;

    while (z > 0 or k > 1) {
        for (0..@as(usize, @intCast(k))) |i| {
            var lastList = s.items[s.items.len - 1 - i];
            for (lastList.items) |item| {
                try s.items[i].append(item);
            }
        }
        s.shrinkRetainingCapacity(s.items.len - @as(usize, @intCast(k)));
        z -= k;
        d = n - k;
        n = @max(k, d);
        k = @min(k, d);
    }

    var result = std.ArrayList(i32).init(allocator);

    for (s.items) |sublist| {
        for (sublist.items) |item| {
            try result.append(item);
        }
    }
    return result.toOwnedSlice();
}
posted @ 2024-02-05 14:28  yhm138  阅读(88)  评论(0编辑  收藏  举报