std.fmt.parseInt / parseFloat — Conversão de Strings para Números
As funções std.fmt.parseInt e std.fmt.parseFloat convertem representações textuais de números em valores numéricos tipados. Elas são as equivalentes do atoi/strtol do C e do parseInt/parseFloat do JavaScript, mas com segurança de tipos verificada em tempo de compilação e tratamento explícito de erros.
Visão Geral
const std = @import("std");
const fmt = std.fmt;
Assinaturas
// Converte string para inteiro em qualquer base
pub fn parseInt(comptime T: type, buf: []const u8, base: u8) !T
// Converte string para float
pub fn parseFloat(comptime T: type, buf: []const u8) !T
// Versão unsigned-only
pub fn parseUnsigned(comptime T: type, buf: []const u8, base: u8) !T
Parâmetros
T: O tipo numérico de destino (i32,u64,f32,f64, etc.)buf: O slice de bytes contendo a representação textualbase: A base numérica (2, 8, 10, 16, ou 0 para detecção automática)
Erros Possíveis
// parseInt pode retornar:
error.InvalidCharacter // Caractere inválido para a base
error.Overflow // Valor excede o range do tipo
// parseFloat pode retornar:
error.InvalidCharacter // Formato inválido
Funções Relacionadas
// Converte inteiro para string
pub fn formatInt(value: anytype, base: u8, case: Case, options: FormatOptions, writer: anytype) !void
// bufPrint para converter número em string
pub fn bufPrint(buf: []u8, comptime format: []const u8, args: anytype) ![]u8
Exemplo 1: Parsing Básico de Inteiros e Floats
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// parseInt — base 10
const idade = try std.fmt.parseInt(u32, "25", 10);
try stdout.print("Idade: {d}\n", .{idade});
// parseInt — base 16 (hexadecimal)
const cor = try std.fmt.parseInt(u24, "FF8000", 16);
try stdout.print("Cor: 0x{x:0>6}\n", .{cor});
// parseInt — base 2 (binário)
const flags = try std.fmt.parseInt(u8, "10110011", 2);
try stdout.print("Flags: {d} (0b{b:0>8})\n", .{ flags, flags });
// parseInt — base 0 (detecção automática)
const auto_dec = try std.fmt.parseInt(i32, "42", 0);
const auto_hex = try std.fmt.parseInt(i32, "0x2A", 0);
const auto_bin = try std.fmt.parseInt(i32, "0b101010", 0);
try stdout.print("Auto: dec={d}, hex={d}, bin={d}\n", .{
auto_dec, auto_hex, auto_bin,
}); // Todos são 42
// parseFloat
const pi = try std.fmt.parseFloat(f64, "3.14159");
try stdout.print("Pi: {d:.5}\n", .{pi});
// Números negativos
const negativo = try std.fmt.parseInt(i32, "-100", 10);
try stdout.print("Negativo: {d}\n", .{negativo});
// Notação científica
const cientifico = try std.fmt.parseFloat(f64, "6.022e23");
try stdout.print("Avogadro: {e}\n", .{cientifico});
}
Exemplo 2: Tratamento de Erros na Conversão
const std = @import("std");
fn converterParaInt(texto: []const u8) !i32 {
return std.fmt.parseInt(i32, texto, 10);
}
fn tentarConverter(texto: []const u8, stdout: anytype) !void {
if (std.fmt.parseInt(i32, texto, 10)) |valor| {
try stdout.print(" '{s}' -> {d}\n", .{ texto, valor });
} else |err| {
switch (err) {
error.InvalidCharacter => {
try stdout.print(" '{s}' -> ERRO: caractere inválido\n", .{texto});
},
error.Overflow => {
try stdout.print(" '{s}' -> ERRO: overflow para i32\n", .{texto});
},
}
}
}
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
try stdout.writeAll("Conversões de string para i32:\n");
const testes = [_][]const u8{
"42",
"-100",
"0",
"abc",
"12.5",
"999999999999",
"",
" 42",
"2147483647",
"2147483648",
};
for (testes) |teste| {
try tentarConverter(teste, stdout);
}
}
Exemplo 3: Parser de Argumentos Numéricos
const std = @import("std");
const Configuracao = struct {
porta: u16 = 8080,
threads: u8 = 4,
timeout: f64 = 30.0,
verbose: bool = false,
};
fn parseConfigFromArgs(args: []const []const u8) Configuracao {
var config = Configuracao{};
var i: usize = 0;
while (i < args.len) : (i += 1) {
const arg = args[i];
if (std.mem.eql(u8, arg, "--porta") and i + 1 < args.len) {
i += 1;
config.porta = std.fmt.parseInt(u16, args[i], 10) catch 8080;
} else if (std.mem.eql(u8, arg, "--threads") and i + 1 < args.len) {
i += 1;
config.threads = std.fmt.parseInt(u8, args[i], 10) catch 4;
} else if (std.mem.eql(u8, arg, "--timeout") and i + 1 < args.len) {
i += 1;
config.timeout = std.fmt.parseFloat(f64, args[i]) catch 30.0;
} else if (std.mem.eql(u8, arg, "--verbose")) {
config.verbose = true;
}
}
return config;
}
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// Simula argumentos de linha de comando
const args = [_][]const u8{
"--porta", "3000",
"--threads", "8",
"--timeout", "60.5",
"--verbose",
};
const config = parseConfigFromArgs(&args);
try stdout.writeAll("Configuração:\n");
try stdout.print(" Porta: {d}\n", .{config.porta});
try stdout.print(" Threads: {d}\n", .{config.threads});
try stdout.print(" Timeout: {d:.1}s\n", .{config.timeout});
try stdout.print(" Verbose: {}\n", .{config.verbose});
}
Padrões Comuns
Valor Padrão com catch
const porta = std.fmt.parseInt(u16, texto, 10) catch 8080;
Validação de Range
fn parsePorta(texto: []const u8) !u16 {
const valor = try std.fmt.parseInt(u16, texto, 10);
if (valor < 1024) return error.PortaReservada;
return valor;
}
Conversão de Número para String
var buf: [20]u8 = undefined;
const texto = try std.fmt.bufPrint(&buf, "{d}", .{valor});
Módulos Relacionados
- std.fmt — Visão geral do módulo de formatação
- std.fmt Format Strings — Sintaxe de format strings
- std.json — Parsing de JSON
- std.mem — Operações com strings/slices