← Volver al listado de tecnologías

Control de Flujo en Zig

Por: Artiko
zigcontrol-flujoifwhileforswitch

Control de Flujo

Condicionales (if)

const std = @import("std");

pub fn main() void {
    const numero = 42;

    // If básico
    if (numero > 0) {
        std.debug.print("Positivo\n", .{});
    } else if (numero < 0) {
        std.debug.print("Negativo\n", .{});
    } else {
        std.debug.print("Cero\n", .{});
    }

    // If como expresión
    const signo: i32 = if (numero >= 0) 1 else -1;
    std.debug.print("Signo: {d}\n", .{signo});
}

If con Optionals

fn buscar(arr: []const i32, valor: i32) ?usize {
    for (arr, 0..) |elem, i| {
        if (elem == valor) return i;
    }
    return null;
}

pub fn main() void {
    const numeros = [_]i32{ 1, 2, 3, 4, 5 };

    // Captura del valor optional
    if (buscar(&numeros, 3)) |indice| {
        std.debug.print("Encontrado en índice: {d}\n", .{indice});
    } else {
        std.debug.print("No encontrado\n", .{});
    }
}

Bucle While

const std = @import("std");

pub fn main() void {
    // While básico
    var i: u32 = 0;
    while (i < 5) {
        std.debug.print("{d} ", .{i});
        i += 1;
    }
    // Output: 0 1 2 3 4

    // While con continue expression
    var j: u32 = 0;
    while (j < 10) : (j += 1) {
        if (j % 2 == 0) continue;
        std.debug.print("{d} ", .{j});
    }
    // Output: 1 3 5 7 9

    // While con else
    var k: u32 = 0;
    const resultado = while (k < 5) : (k += 1) {
        if (k == 3) break k * 10;
    } else @as(u32, 0);
    std.debug.print("\nResultado: {d}\n", .{resultado}); // 30
}

Bucle For

const std = @import("std");

pub fn main() void {
    const numeros = [_]i32{ 10, 20, 30, 40, 50 };

    // For básico
    for (numeros) |num| {
        std.debug.print("{d} ", .{num});
    }

    // For con índice
    for (numeros, 0..) |num, i| {
        std.debug.print("\n[{d}] = {d}", .{ i, num });
    }

    // Iterar sobre rangos
    for (0..5) |i| {
        std.debug.print("{d} ", .{i});
    }

    // For sobre strings
    const texto = "Hola";
    for (texto) |char| {
        std.debug.print("{c} ", .{char});
    }
}

Switch

const std = @import("std");

const Color = enum { rojo, verde, azul, otro };

fn nombreColor(c: Color) []const u8 {
    return switch (c) {
        .rojo => "Rojo",
        .verde => "Verde",
        .azul => "Azul",
        .otro => "Desconocido",
    };
}

fn clasificarNumero(n: i32) []const u8 {
    return switch (n) {
        0 => "cero",
        1, 2, 3 => "bajo",
        4...10 => "medio",
        else => "alto",
    };
}

pub fn main() void {
    std.debug.print("Color: {s}\n", .{nombreColor(.verde)});
    std.debug.print("5 es: {s}\n", .{clasificarNumero(5)});
    std.debug.print("100 es: {s}\n", .{clasificarNumero(100)});
}

Switch con Capturas

const std = @import("std");

const Operacion = union(enum) {
    sumar: i32,
    multiplicar: i32,
    reset,
};

fn aplicar(valor: i32, op: Operacion) i32 {
    return switch (op) {
        .sumar => |n| valor + n,
        .multiplicar => |n| valor * n,
        .reset => 0,
    };
}

test "operaciones con switch" {
    var valor: i32 = 10;

    valor = aplicar(valor, .{ .sumar = 5 });
    try std.testing.expectEqual(@as(i32, 15), valor);

    valor = aplicar(valor, .{ .multiplicar = 2 });
    try std.testing.expectEqual(@as(i32, 30), valor);

    valor = aplicar(valor, .reset);
    try std.testing.expectEqual(@as(i32, 0), valor);
}

Break y Continue con Labels

const std = @import("std");

pub fn main() void {
    // Break con label
    const resultado = outer: for (0..10) |i| {
        for (0..10) |j| {
            if (i * j > 50) break :outer i * j;
        }
    } else @as(usize, 0);

    std.debug.print("Resultado: {d}\n", .{resultado});
}

fn buscarEnMatriz(matriz: []const []const i32, objetivo: i32) ?struct { fila: usize, col: usize } {
    for (matriz, 0..) |fila, i| {
        for (fila, 0..) |valor, j| {
            if (valor == objetivo) {
                return .{ .fila = i, .col = j };
            }
        }
    }
    return null;
}

Testing de Control de Flujo

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

fn esPositivo(n: i32) bool {
    return if (n > 0) true else false;
}

fn factorial(n: u32) u32 {
    var resultado: u32 = 1;
    var i: u32 = 1;
    while (i <= n) : (i += 1) {
        resultado *= i;
    }
    return resultado;
}

fn sumarArray(arr: []const i32) i32 {
    var suma: i32 = 0;
    for (arr) |num| {
        suma += num;
    }
    return suma;
}

fn clasificar(n: i32) []const u8 {
    return switch (n) {
        std.math.minInt(i32)...-1 => "negativo",
        0 => "cero",
        1...std.math.maxInt(i32) => "positivo",
    };
}

test "condicionales" {
    try testing.expect(esPositivo(5));
    try testing.expect(!esPositivo(-3));
    try testing.expect(!esPositivo(0));
}

test "factorial con while" {
    try testing.expectEqual(@as(u32, 1), factorial(0));
    try testing.expectEqual(@as(u32, 1), factorial(1));
    try testing.expectEqual(@as(u32, 120), factorial(5));
    try testing.expectEqual(@as(u32, 3628800), factorial(10));
}

test "suma con for" {
    const arr1 = [_]i32{ 1, 2, 3, 4, 5 };
    try testing.expectEqual(@as(i32, 15), sumarArray(&arr1));

    const arr2 = [_]i32{ -1, 1 };
    try testing.expectEqual(@as(i32, 0), sumarArray(&arr2));

    const vacio = [_]i32{};
    try testing.expectEqual(@as(i32, 0), sumarArray(&vacio));
}

test "switch clasificación" {
    try testing.expectEqualStrings("negativo", clasificar(-100));
    try testing.expectEqualStrings("cero", clasificar(0));
    try testing.expectEqualStrings("positivo", clasificar(42));
}

test "for con índice" {
    const datos = [_]i32{ 10, 20, 30 };
    var suma_indices: usize = 0;
    var suma_valores: i32 = 0;

    for (datos, 0..) |val, idx| {
        suma_indices += idx;
        suma_valores += val;
    }

    try testing.expectEqual(@as(usize, 3), suma_indices); // 0+1+2
    try testing.expectEqual(@as(i32, 60), suma_valores);   // 10+20+30
}

test "while con break" {
    var contador: u32 = 0;
    const resultado = while (contador < 100) : (contador += 1) {
        if (contador == 7) break contador;
    } else @as(u32, 999);

    try testing.expectEqual(@as(u32, 7), resultado);
}

Ejercicios

  1. Implementa FizzBuzz usando control de flujo
  2. Crea una función que encuentre el número más grande en un array
  3. Implementa búsqueda binaria con while

Resumen