Como Comparar Strings em Zig

Como Comparar Strings em Zig

Em Zig, strings são slices de bytes ([]const u8) e não podem ser comparadas diretamente com ==. Em vez disso, a biblioteca padrão fornece funções especializadas para diferentes tipos de comparação.

Comparação de Igualdade com std.mem.eql

A função std.mem.eql compara se dois slices contêm exatamente os mesmos bytes.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    const a = "Zig";
    const b = "Zig";
    const c = "zig";
    const d = "Rust";

    try stdout.print("\"Zig\" == \"Zig\": {}\n", .{std.mem.eql(u8, a, b)});
    try stdout.print("\"Zig\" == \"zig\": {}\n", .{std.mem.eql(u8, a, c)});
    try stdout.print("\"Zig\" == \"Rust\": {}\n", .{std.mem.eql(u8, a, d)});

    // Comparar com slice vazio
    const vazio = "";
    try stdout.print("\"\" == \"\": {}\n", .{std.mem.eql(u8, vazio, "")});
    try stdout.print("\"Zig\" == \"\": {}\n", .{std.mem.eql(u8, a, "")});
}

Saída esperada:

"Zig" == "Zig": true
"Zig" == "zig": false
"Zig" == "Rust": false
"" == "": true
"Zig" == "": false

Comparação Lexicográfica (Ordenação)

Use std.mem.order para determinar a ordem lexicográfica entre duas strings.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    // order retorna .lt, .eq ou .gt
    const resultado1 = std.mem.order(u8, "abc", "abd");
    try stdout.print("\"abc\" vs \"abd\": {}\n", .{resultado1});

    const resultado2 = std.mem.order(u8, "xyz", "xyz");
    try stdout.print("\"xyz\" vs \"xyz\": {}\n", .{resultado2});

    const resultado3 = std.mem.order(u8, "banana", "abacaxi");
    try stdout.print("\"banana\" vs \"abacaxi\": {}\n", .{resultado3});

    // Comparações com tamanhos diferentes
    const resultado4 = std.mem.order(u8, "abc", "abcd");
    try stdout.print("\"abc\" vs \"abcd\": {}\n", .{resultado4});

    // Usar para verificar se uma string vem antes de outra
    const nome1 = "Maria";
    const nome2 = "João";
    if (std.mem.order(u8, nome1, nome2) == .gt) {
        try stdout.print("\"{s}\" vem depois de \"{s}\"\n", .{ nome1, nome2 });
    }
}

Saída esperada:

"abc" vs "abd": math.Order.lt
"xyz" vs "xyz": math.Order.eq
"banana" vs "abacaxi": math.Order.gt
"abc" vs "abcd": math.Order.lt
"Maria" vem depois de "João"

Comparação Case-Insensitive

Para comparar strings ignorando maiúsculas e minúsculas, use std.ascii.eqlIgnoreCase.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    // Comparação ignorando caso (case-insensitive)
    try stdout.print("\"Zig\" =~ \"zig\": {}\n", .{std.ascii.eqlIgnoreCase("Zig", "zig")});
    try stdout.print("\"HELLO\" =~ \"hello\": {}\n", .{std.ascii.eqlIgnoreCase("HELLO", "hello")});
    try stdout.print("\"ABC\" =~ \"abd\": {}\n", .{std.ascii.eqlIgnoreCase("ABC", "abd")});

    // Exemplo prático: validar comando de usuário
    const comando = "SAIR";
    if (std.ascii.eqlIgnoreCase(comando, "sair") or
        std.ascii.eqlIgnoreCase(comando, "exit") or
        std.ascii.eqlIgnoreCase(comando, "quit"))
    {
        try stdout.print("Comando de saída reconhecido: \"{s}\"\n", .{comando});
    }
}

Saída esperada:

"Zig" =~ "zig": true
"HELLO" =~ "hello": true
"ABC" =~ "abd": false
Comando de saída reconhecido: "SAIR"

Verificar Prefixo e Sufixo

Use std.mem.startsWith e std.mem.endsWith para verificar como uma string começa ou termina.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    const url = "https://www.exemplo.com.br/pagina";

    // Verificar prefixo
    try stdout.print("Começa com https: {}\n", .{std.mem.startsWith(u8, url, "https://")});
    try stdout.print("Começa com http: {}\n", .{std.mem.startsWith(u8, url, "http://")});

    // Verificar sufixo
    const arquivo = "relatorio.pdf";
    try stdout.print("Termina com .pdf: {}\n", .{std.mem.endsWith(u8, arquivo, ".pdf")});
    try stdout.print("Termina com .txt: {}\n", .{std.mem.endsWith(u8, arquivo, ".txt")});

    // Exemplo prático: classificar arquivos por extensão
    const arquivos = [_][]const u8{ "foto.jpg", "doc.pdf", "video.mp4", "texto.txt", "imagem.png" };
    try stdout.print("\nArquivos de imagem:\n", .{});
    for (arquivos) |arq| {
        if (std.mem.endsWith(u8, arq, ".jpg") or
            std.mem.endsWith(u8, arq, ".png"))
        {
            try stdout.print("  {s}\n", .{arq});
        }
    }
}

Saída esperada:

Começa com https: true
Começa com http: false
Termina com .pdf: true
Termina com .txt: false

Arquivos de imagem:
  foto.jpg
  imagem.png

Comparação Personalizada para Ordenação

Crie funções de comparação personalizadas para usar com std.mem.sort.

const std = @import("std");

fn compararStringsIgnorandoCaso(_: void, a: []const u8, b: []const u8) bool {
    // Retorna true se a < b (ignorando caso)
    for (a, 0..) |char_a, i| {
        if (i >= b.len) return false;
        const lower_a = std.ascii.toLower(char_a);
        const lower_b = std.ascii.toLower(b[i]);
        if (lower_a < lower_b) return true;
        if (lower_a > lower_b) return false;
    }
    return a.len < b.len;
}

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    // Ordenar strings ignorando caso
    var nomes = [_][]const u8{ "carlos", "Ana", "beatriz", "Daniel", "alice" };
    std.mem.sort([]const u8, &nomes, {}, compararStringsIgnorandoCaso);

    try stdout.print("Nomes ordenados (case-insensitive):\n", .{});
    for (nomes) |nome| {
        try stdout.print("  {s}\n", .{nome});
    }
}

Saída esperada:

Nomes ordenados (case-insensitive):
  alice
  Ana
  beatriz
  carlos
  Daniel

Verificar se String Contém Outra

Use std.mem.indexOf para verificar se uma string contém outra (mais detalhes na receita de busca de substrings).

const std = @import("std");

fn contem(haystack: []const u8, needle: []const u8) bool {
    return std.mem.indexOf(u8, haystack, needle) != null;
}

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    const texto = "A linguagem Zig é eficiente e segura";
    try stdout.print("Contém \"Zig\": {}\n", .{contem(texto, "Zig")});
    try stdout.print("Contém \"Rust\": {}\n", .{contem(texto, "Rust")});
    try stdout.print("Contém \"eficiente\": {}\n", .{contem(texto, "eficiente")});
}

Saída esperada:

Contém "Zig": true
Contém "Rust": false
Contém "eficiente": true

Resumo das Funções

FunçãoDescrição
std.mem.eql(u8, a, b)Igualdade exata
std.mem.order(u8, a, b)Ordenação lexicográfica
std.ascii.eqlIgnoreCase(a, b)Igualdade case-insensitive
std.mem.startsWith(u8, str, prefix)Verifica prefixo
std.mem.endsWith(u8, str, suffix)Verifica sufixo
std.mem.indexOf(u8, hay, needle)Verifica se contém

Veja Também

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.