Zig estructuras y enums

En el lenguaje de programación Zig, las estructuras (struct) y las enumeraciones (enum) son dos tipos de datos básicos.

Las estructuras y los enums son dos formas principales de definir y utilizar tipos de datos personalizados.

Las estructuras y los enums proporcionan una organización de datos y una seguridad de tipos de mayor nivel, adecuados para diferentes escenarios de programación.

  • Estructura (Struct): se utiliza para agrupar variables relacionadas en un tipo de datos compuesto. Las estructuras pueden contener campos y métodos, y son adecuadas para organizar datos complejos.
  • Enumeración (Enum): se utiliza para definir un conjunto de constantes con nombre, que pueden ser enums sin valor o con valor. Los enums son adecuados para representar un conjunto finito de valores discretos.

Estructura (Struct)

Una estructura es un tipo de datos compuesto que permite combinar varios elementos de datos de diferentes tipos en un único tipo.

La sintaxis de las estructuras en Zig es la siguiente:

const structName = struct {
    field1: FieldType1,
    field2: FieldType2,
    // 其他字段
};

En el siguiente código, MyStruct es un tipo de estructura que tiene tres campos: field1 es un entero de 32 bits, field2 es un número de coma flotante de doble precisión y field3 es un puntero a un array de bytes.

struct MyStruct {
    field1: i32,
    field2: f64,
    field3: []const u8,
}

Ejemplo

const std = @import("std");

// Define una estructura
const Person = struct {
    name: []const u8,
    age: u32,
};

pub fn main() void {
    // Crear una instancia de la estructura
    const person = Person{
        .name = "Alice",
        .age = 30,
    };

    // Acceder a los campos de la estructura y formatear correctamente
    std.debug.print("Name: {s}\n", .{person.name}); // Usar {s} para formatear el slice
    std.debug.print("Age: {}\n", .{person.age});
}

Compile y ejecute el código anterior, el resultado es:

Name: Alice
Age: 30

Para modificar los campos de una estructura, asegúrate de usar var para definir la instancia de la estructura, de modo que puedas modificar los valores de los campos. Si usas const para definir la instancia de la estructura, no podrás modificar sus valores de campo.

Ejemplo

const std = @import("std");

// Define una estructura
const Person = struct {
    name: []const u8,
    age: u32,
};

pub fn main() void {
    // Crear una instancia de la estructura
    var person = Person{
        .name = "Alice",
        .age = 30,
    };

    // Imprimir el valor inicial
    std.debug.print("Initial Name: {s}\n", .{person.name});
    std.debug.print("Initial Age: {}\n", .{person.age});

    // Modificar el valor del campo de la estructura
    person.name = "Bob";
    person.age = 35;

    // Imprimir el valor modificado
    std.debug.print("Modified Name: {s}\n", .{person.name});
    std.debug.print("Modified Age: {}\n", .{person.age});
}

Compile y ejecute el código anterior, el resultado es:

Initial Name: Alice
Initial Age: 30
Modified Name: Bob
Modified Age: 35

Métodos

En Zig, los métodos de una estructura se definen mediante la palabra clave fn, similar a los métodos de clase en otros lenguajes de programación.

Ejemplo

const std = @import("std");

const Rectangle = struct {
    width: u32,
    height: u32,

    // Método para calcular el área
    fn area(self: Rectangle) u32 {
        return self.width * self.height;
    }
};

pub fn main() void {
    var rect = Rectangle{
        .width = 10,
        .height = 5,
    };

    // Llamar al método de la estructura
    std.debug.print("Area: {}\n", .{rect.area()});
}

Compile y ejecute el código anterior, el resultado es:

Area: 50

Enumeración (Enum)

Una enumeración es un tipo de datos que consiste en un conjunto fijo de valores constantes.

La sintaxis de las enumeraciones en Zig es la siguiente:

const enumName = enum {
    Variant1,
    Variant2,
    // 其他变体
};

En el siguiente código, MyEnum es un tipo de enumeración que tiene tres valores posibles: Option1, Option2 y Option3.

enum MyEnum {
    Option1,
    Option2,
    Option3,
}

Ejemplo

const std = @import("std");

// Define una enumeración
const Color = enum {
    Red,
    Green,
    Blue,
};

pub fn main() void {
    // Usar la enumeración
    const favoriteColor = Color.Green;

    switch (favoriteColor) {
        Color.Red => std.debug.print("Red\n", .{}),
        Color.Green => std.debug.print("Green\n", .{}),
        Color.Blue => std.debug.print("Blue\n", .{}),
    }
}

Compile y ejecute el código anterior, el resultado es:

Green

Enums con valores

Zig permite asignar un valor concreto a cada variante de la enumeración, lo que puede usarse para representar más información o para realizar comparaciones.

Ejemplo

const std = @import("std");

// Define una enumeración con valores
const Status = enum(u32) {
    Pending = 1,
    InProgress = 2,
    Completed = 3,
};

pub fn main() void {
    const taskStatus = Status.InProgress;

    switch (taskStatus) {
        Status.Pending => std.debug.print("Pending\n", .{}),
        Status.InProgress => std.debug.print("InProgress\n", .{}),
        Status.Completed => std.debug.print("Completed\n", .{}),
    }
}

Compile y ejecute el código anterior, el resultado es:

InProgress

Usar enums como campos

Los enums pueden usarse como campos de una estructura, lo que hace que la estructura sea más flexible y potente.

Ejemplo

const std = @import("std");

const Status = enum {
    Active,
    Inactive,
    Suspended,
};

const User = struct {
    name: []const u8,
    status: Status,
};

pub fn main() void {
    // Crear una instancia de User
    const user = User{
        .name = "Alice",
        .status = Status.Active,
    };

    // Imprimir el campo name de User
    std.debug.print("User: {s}\n", .{user.name}); // Usar {s} para formatear el slice

    // Usar la sentencia switch para imprimir diferentes estados según status
    switch (user.status) {
        Status.Active => std.debug.print("Status: Active\n", .{}),
        Status.Inactive => std.debug.print("Status: Inactive\n", .{}),
        Status.Suspended => std.debug.print("Status: Suspended\n", .{}),
    }
}

Compile y ejecute el código anterior, el resultado es:

User: Alice
Status: Active
Otras extensiones