Como Remover Espaços (Trim) de Strings em Zig
Remover espaços em branco do início e/ou fim de strings é uma operação fundamental para limpeza de dados de entrada, parsing de arquivos e normalização de texto. Em Zig, as funções de trim trabalham com slices e não fazem alocação de memória.
Trim Básico com std.mem.trim
A função std.mem.trim remove caracteres específicos do início e do fim de um slice.
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// Remover espaços em branco
const texto = " Olá Mundo ";
const limpo = std.mem.trim(u8, texto, " ");
try stdout.print("Original: \"{s}\"\n", .{texto});
try stdout.print("Trimmed: \"{s}\"\n", .{limpo});
// Remover tabs e espaços
const com_tabs = "\t\t Dados importantes \t\n";
const limpo2 = std.mem.trim(u8, com_tabs, " \t\n\r");
try stdout.print("\nOriginal: \"{s}\"", .{com_tabs});
try stdout.print("Trimmed: \"{s}\"\n", .{limpo2});
// Remover caracteres personalizados
const com_barras = "///caminho/para/recurso///";
const limpo3 = std.mem.trim(u8, com_barras, "/");
try stdout.print("\nOriginal: \"{s}\"\n", .{com_barras});
try stdout.print("Trimmed: \"{s}\"\n", .{limpo3});
}
Saída esperada:
Original: " Olá Mundo "
Trimmed: "Olá Mundo"
Original: " Dados importantes
"
Trimmed: "Dados importantes"
Original: "///caminho/para/recurso///"
Trimmed: "caminho/para/recurso"
Trim Apenas à Esquerda ou Direita
Use std.mem.trimLeft e std.mem.trimRight para remover caracteres de apenas um lado.
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
const texto = " Olá Mundo ";
// Remover apenas do início
const sem_esquerda = std.mem.trimLeft(u8, texto, " ");
try stdout.print("trimLeft: \"{s}\"\n", .{sem_esquerda});
// Remover apenas do fim
const sem_direita = std.mem.trimRight(u8, texto, " ");
try stdout.print("trimRight: \"{s}\"\n", .{sem_direita});
// Remover zeros à esquerda de um número
const numero = "000042";
const sem_zeros = std.mem.trimLeft(u8, numero, "0");
try stdout.print("\nNúmero: \"{s}\" -> \"{s}\"\n", .{ numero, sem_zeros });
// Remover nova linha do fim (comum ao ler arquivos)
const linha = "conteúdo da linha\n";
const sem_newline = std.mem.trimRight(u8, linha, "\n\r");
try stdout.print("Linha: \"{s}\" -> \"{s}\"\n", .{ linha, sem_newline });
}
Saída esperada:
trimLeft: "Olá Mundo "
trimRight: " Olá Mundo"
Número: "000042" -> "42"
Linha: "conteúdo da linha
" -> "conteúdo da linha"
Trim de Whitespace Completo
Defina uma constante com todos os caracteres de espaço em branco para uso recorrente.
const std = @import("std");
const WHITESPACE = " \t\n\r";
fn trimWhitespace(texto: []const u8) []const u8 {
return std.mem.trim(u8, texto, WHITESPACE);
}
fn trimLeftWhitespace(texto: []const u8) []const u8 {
return std.mem.trimLeft(u8, texto, WHITESPACE);
}
fn trimRightWhitespace(texto: []const u8) []const u8 {
return std.mem.trimRight(u8, texto, WHITESPACE);
}
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
const entradas = [_][]const u8{
" normal ",
"\ttabulação\t",
"\n\nnova linha\n\n",
" \t\n misto \n\t ",
"sem_espacos",
};
for (entradas) |entrada| {
const limpo = trimWhitespace(entrada);
try stdout.print("\"{s}\" -> \"{s}\" (len: {d} -> {d})\n", .{
entrada, limpo, entrada.len, limpo.len,
});
}
}
Exemplo Prático: Processar Entrada de Usuário
Um exemplo comum é limpar dados de entrada antes de processá-los.
const std = @import("std");
const WHITESPACE = " \t\n\r";
const Campo = struct {
chave: []const u8,
valor: []const u8,
};
fn parseConfig(linha: []const u8) ?Campo {
const limpa = std.mem.trim(u8, linha, WHITESPACE);
if (limpa.len == 0) return null;
// Ignorar comentários
if (limpa[0] == '#') return null;
// Dividir por '='
const sep = std.mem.indexOf(u8, limpa, "=") orelse return null;
return Campo{
.chave = std.mem.trim(u8, limpa[0..sep], WHITESPACE),
.valor = std.mem.trim(u8, limpa[sep + 1 ..], WHITESPACE),
};
}
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
const config =
\\# Configuração do servidor
\\ host = localhost
\\ porta = 8080
\\
\\ nome = Meu Servidor
\\ debug = true
\\# fim
;
try stdout.print("Configurações parseadas:\n", .{});
var linhas = std.mem.splitScalar(u8, config, '\n');
while (linhas.next()) |linha| {
if (parseConfig(linha)) |campo| {
try stdout.print(" {s} = \"{s}\"\n", .{ campo.chave, campo.valor });
}
}
}
Saída esperada:
Configurações parseadas:
host = "localhost"
porta = "8080"
nome = "Meu Servidor"
debug = "true"
Normalizar Espaços Internos
Para normalizar espaços dentro de uma string (colapsar múltiplos espaços em um só), combine trim com tokenize.
const std = @import("std");
fn normalizarEspacos(allocator: std.mem.Allocator, texto: []const u8) ![]u8 {
var tokens = std.mem.tokenizeScalar(u8, texto, ' ');
var resultado = std.ArrayList(u8).init(allocator);
defer resultado.deinit();
var primeiro = true;
while (tokens.next()) |token| {
if (!primeiro) {
try resultado.append(' ');
}
try resultado.appendSlice(token);
primeiro = false;
}
return resultado.toOwnedSlice();
}
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const texto = " Olá Mundo Zig é legal ";
const normalizado = try normalizarEspacos(allocator, texto);
defer allocator.free(normalizado);
try stdout.print("Original: \"{s}\"\n", .{texto});
try stdout.print("Normalizado: \"{s}\"\n", .{normalizado});
}
Saída esperada:
Original: " Olá Mundo Zig é legal "
Normalizado: "Olá Mundo Zig é legal"
Referência Rápida
| Função | Descrição |
|---|---|
std.mem.trim(u8, str, chars) | Remove chars de ambos os lados |
std.mem.trimLeft(u8, str, chars) | Remove chars do início |
std.mem.trimRight(u8, str, chars) | Remove chars do fim |
Todas as funções retornam um sub-slice da string original, sem alocação de memória. O resultado aponta para a mesma memória que a string original.
Veja Também
- Dividir (Split) Strings — Divida após limpar
- Comparar Strings — Limpe antes de comparar
- Substituir Texto em Strings — Substitua espaços por outros caracteres
- Ler Arquivo Linha por Linha — Faça trim ao processar linhas