Como Converter String para Número e Vice-versa em Zig

Como Converter String para Número e Vice-versa em Zig

Converter entre strings e números é uma das tarefas mais comuns em programação. Em Zig, a biblioteca padrão fornece funções robustas para realizar essas conversões com segurança, usando o sistema de tratamento de erros da linguagem.

Nesta receita, você aprenderá a converter strings para inteiros e floats, e também a transformar números de volta para representações textuais.

Converter String para Inteiro

A função std.fmt.parseInt é usada para converter uma string (ou slice de bytes) em um valor inteiro. Ela aceita a base numérica como parâmetro e retorna um erro caso a conversão falhe.

const std = @import("std");

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

    // Converter string decimal para inteiro
    const texto_decimal = "42";
    const numero = try std.fmt.parseInt(i32, texto_decimal, 10);
    try stdout.print("Decimal: \"{s}\" -> {d}\n", .{ texto_decimal, numero });

    // Converter string hexadecimal para inteiro
    const texto_hex = "FF";
    const hex_valor = try std.fmt.parseInt(u32, texto_hex, 16);
    try stdout.print("Hexadecimal: \"{s}\" -> {d}\n", .{ texto_hex, hex_valor });

    // Converter string binária para inteiro
    const texto_bin = "11010";
    const bin_valor = try std.fmt.parseInt(u32, texto_bin, 2);
    try stdout.print("Binário: \"{s}\" -> {d}\n", .{ texto_bin, bin_valor });

    // Converter string octal para inteiro
    const texto_oct = "77";
    const oct_valor = try std.fmt.parseInt(u32, texto_oct, 8);
    try stdout.print("Octal: \"{s}\" -> {d}\n", .{ texto_oct, oct_valor });

    // Números negativos
    const texto_negativo = "-123";
    const negativo = try std.fmt.parseInt(i32, texto_negativo, 10);
    try stdout.print("Negativo: \"{s}\" -> {d}\n", .{ texto_negativo, negativo });
}

Saída esperada:

Decimal: "42" -> 42
Hexadecimal: "FF" -> 255
Binário: "11010" -> 26
Octal: "77" -> 63
Negativo: "-123" -> -123

Converter String para Float

Para converter strings em números de ponto flutuante, use std.fmt.parseFloat.

const std = @import("std");

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

    // Converter string para f32
    const texto_float = "3.14159";
    const pi = try std.fmt.parseFloat(f64, texto_float);
    try stdout.print("Float: \"{s}\" -> {d:.5}\n", .{ texto_float, pi });

    // Notação científica
    const texto_cientifico = "1.5e10";
    const cientifico = try std.fmt.parseFloat(f64, texto_cientifico);
    try stdout.print("Científico: \"{s}\" -> {d}\n", .{ texto_cientifico, cientifico });

    // Número negativo com decimais
    const texto_neg = "-273.15";
    const negativo = try std.fmt.parseFloat(f64, texto_neg);
    try stdout.print("Negativo: \"{s}\" -> {d:.2}\n", .{ texto_neg, negativo });
}

Saída esperada:

Float: "3.14159" -> 3.14159
Científico: "1.5e10" -> 15000000000
Negativo: "-273.15" -> -273.15

Converter Número para String

Para converter números em strings, use std.fmt.bufPrint que escreve a representação formatada em um buffer fornecido por você.

const std = @import("std");

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

    // Converter inteiro para string
    var buf: [64]u8 = undefined;
    const numero: i32 = 42;
    const resultado = try std.fmt.bufPrint(&buf, "{d}", .{numero});
    try stdout.print("Inteiro para string: {d} -> \"{s}\"\n", .{ numero, resultado });

    // Converter float para string com precisão
    var buf2: [64]u8 = undefined;
    const pi: f64 = 3.14159265;
    const resultado_pi = try std.fmt.bufPrint(&buf2, "{d:.4}", .{pi});
    try stdout.print("Float para string: {d:.8} -> \"{s}\"\n", .{ pi, resultado_pi });

    // Converter para hexadecimal
    var buf3: [64]u8 = undefined;
    const valor: u32 = 255;
    const hex_str = try std.fmt.bufPrint(&buf3, "{x}", .{valor});
    try stdout.print("Hex: {d} -> \"{s}\"\n", .{ valor, hex_str });

    // Converter para binário
    var buf4: [64]u8 = undefined;
    const bin_str = try std.fmt.bufPrint(&buf4, "{b}", .{valor});
    try stdout.print("Binário: {d} -> \"{s}\"\n", .{ valor, bin_str });
}

Saída esperada:

Inteiro para string: 42 -> "42"
Float para string: 3.14159265 -> "3.1416"
Hex: 255 -> "ff"
Binário: 255 -> "11111111"

Converter Número para String com Alocador

Quando você precisa de uma string alocada dinamicamente (por exemplo, para retornar de uma função), use std.fmt.allocPrint.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Criar string formatada alocada dinamicamente
    const numero: i32 = 12345;
    const texto = try std.fmt.allocPrint(allocator, "O valor é: {d}", .{numero});
    defer allocator.free(texto);
    try stdout.print("Alocado: \"{s}\"\n", .{texto});

    // Formatar múltiplos valores
    const x: f64 = 1.5;
    const y: f64 = 2.5;
    const ponto = try std.fmt.allocPrint(allocator, "({d:.1}, {d:.1})", .{ x, y });
    defer allocator.free(ponto);
    try stdout.print("Ponto: \"{s}\"\n", .{ponto});
}

Saída esperada:

Alocado: "O valor é: 12345"
Ponto: "(1.5, 2.5)"

Tratando Erros de Conversão

É fundamental tratar os erros que podem ocorrer durante a conversão. A conversão pode falhar se a string contiver caracteres inválidos ou se o valor estiver fora do intervalo do tipo numérico.

const std = @import("std");

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

    // Tentativa com string inválida
    const invalido = std.fmt.parseInt(i32, "abc", 10);
    if (invalido) |valor| {
        try stdout.print("Valor: {d}\n", .{valor});
    } else |err| {
        try stdout.print("Erro ao converter 'abc': {}\n", .{err});
    }

    // Overflow: valor muito grande para o tipo
    const overflow = std.fmt.parseInt(u8, "300", 10);
    if (overflow) |valor| {
        try stdout.print("Valor: {d}\n", .{valor});
    } else |err| {
        try stdout.print("Erro ao converter '300' para u8: {}\n", .{err});
    }

    // Conversão segura com valor padrão
    const texto = "não_é_número";
    const valor = std.fmt.parseInt(i32, texto, 10) catch |_| 0;
    try stdout.print("Valor com fallback: {d}\n", .{valor});
}

Saída esperada:

Erro ao converter 'abc': error.InvalidCharacter
Erro ao converter '300' para u8: error.Overflow
Valor com fallback: 0

Função Utilitária: Conversão Segura

Aqui está uma função utilitária que encapsula a conversão com um valor padrão.

const std = @import("std");

fn parseIntOuPadrao(comptime T: type, texto: []const u8, padrao: T) T {
    return std.fmt.parseInt(T, texto, 10) catch padrao;
}

fn parseFloatOuPadrao(comptime T: type, texto: []const u8, padrao: T) T {
    return std.fmt.parseFloat(T, texto) catch padrao;
}

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

    const idade = parseIntOuPadrao(u32, "25", 0);
    try stdout.print("Idade: {d}\n", .{idade});

    const invalido = parseIntOuPadrao(u32, "xyz", 0);
    try stdout.print("Inválido com padrão: {d}\n", .{invalido});

    const temperatura = parseFloatOuPadrao(f64, "36.6", 0.0);
    try stdout.print("Temperatura: {d:.1}\n", .{temperatura});
}

Saída esperada:

Idade: 25
Inválido com padrão: 0
Temperatura: 36.6

Resumo das Funções

FunçãoDescrição
std.fmt.parseInt(T, str, base)String para inteiro com base especificada
std.fmt.parseFloat(T, str)String para ponto flutuante
std.fmt.bufPrint(&buf, fmt, args)Número para string em buffer fixo
std.fmt.allocPrint(alloc, fmt, args)Número para string alocada dinamicamente

Veja Também

Continue aprendendo Zig

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