Cheatsheet: Strings em Zig
Em Zig, strings são simplesmente slices de bytes ([]const u8). Não existe um tipo String especial. Esta cheatsheet cobre todas as operações comuns com strings.
Tipos de String
// String literal — array de bytes com sentinela null
const literal: *const [5:0]u8 = "Hello";
// Slice de string (mais comum)
const slice: []const u8 = "Hello";
// String mutável
var buffer: [100]u8 = undefined;
var str: []u8 = buffer[0..5];
// String com sentinela (compatível com C)
const c_str: [*:0]const u8 = "Hello";
const sentinel_slice: [:0]const u8 = "Hello";
Comparação de Strings
const std = @import("std");
const a = "hello";
const b = "hello";
const c = "world";
// Comparar igualdade
const iguais = std.mem.eql(u8, a, b); // true
const diferentes = std.mem.eql(u8, a, c); // false
// Comparação ordenada
const ordem = std.mem.order(u8, a, c); // .lt, .eq ou .gt
const menor = std.mem.lessThan(u8, a, c); // true ("hello" < "world")
Busca em Strings
const texto = "Hello, World! Hello, Zig!";
// Encontrar substring
const pos = std.mem.indexOf(u8, texto, "World"); // ?usize = 7
const ultima = std.mem.lastIndexOf(u8, texto, "Hello"); // ?usize = 14
// Encontrar caractere
const virgula = std.mem.indexOfScalar(u8, texto, ','); // ?usize = 5
// Verificar prefixo e sufixo
const comeca = std.mem.startsWith(u8, texto, "Hello"); // true
const termina = std.mem.endsWith(u8, texto, "Zig!"); // true
// Contar ocorrências
const count = std.mem.count(u8, texto, "Hello"); // 2
// Verificar se contém
const contem = std.mem.indexOf(u8, texto, "World") != null; // true
Fatiamento (Slicing)
const texto = "Hello, World!";
const hello = texto[0..5]; // "Hello"
const world = texto[7..12]; // "World"
const resto = texto[7..]; // "World!"
// Obter último caractere
const ultimo = texto[texto.len - 1]; // '!'
// Iterar sobre caracteres
for (texto) |byte| {
std.debug.print("{c}", .{byte});
}
// Iterar com índice
for (texto, 0..) |byte, i| {
std.debug.print("[{}]={c} ", .{ i, byte });
}
Divisão (Split)
const std = @import("std");
const csv = "nome,idade,cidade";
// Split por delimitador
var it = std.mem.splitSequence(u8, csv, ",");
while (it.next()) |campo| {
std.debug.print("Campo: {s}\n", .{campo});
}
// Saída: "nome", "idade", "cidade"
// Split por caractere único
const path = "/usr/local/bin";
var it2 = std.mem.splitScalar(u8, path, '/');
while (it2.next()) |parte| {
if (parte.len > 0) {
std.debug.print("Parte: {s}\n", .{parte});
}
}
// Tokenize (ignora delimitadores consecutivos)
const texto = " hello world ";
var tok = std.mem.tokenizeScalar(u8, texto, ' ');
while (tok.next()) |token| {
std.debug.print("Token: '{s}'\n", .{token});
}
// Saída: "hello", "world"
Concatenação
const std = @import("std");
// Em comptime (concatenação de literais)
const saudacao = "Olá, " ++ "mundo!"; // "Olá, mundo!"
// Repetição em comptime
const tracos = "-" ** 20; // "--------------------"
// Em runtime com allocator
const allocator = std.heap.page_allocator;
const resultado = try std.mem.concat(allocator, u8, &.{ "Hello", " ", "World" });
defer allocator.free(resultado);
// Com std.fmt.allocPrint
const nome = "Zig";
const msg = try std.fmt.allocPrint(allocator, "Olá, {s}! Versão {d}", .{ nome, 13 });
defer allocator.free(msg);
Formatação
const std = @import("std");
// Formatar em buffer fixo
var buf: [256]u8 = undefined;
const resultado = try std.fmt.bufPrint(&buf, "Valor: {d}, Hex: 0x{x}", .{ 42, 255 });
// resultado é []u8 contendo "Valor: 42, Hex: 0xff"
// Especificadores comuns
// {s} — string ([]const u8)
// {d} — decimal
// {x} — hexadecimal minúsculo
// {X} — hexadecimal maiúsculo
// {b} — binário
// {o} — octal
// {e} — notação científica
// {c} — caractere (u8)
// {any} — qualquer tipo (debug)
// {} — formato padrão
// Preenchimento e alinhamento
const alinhado = try std.fmt.bufPrint(&buf, "|{s:>10}|", .{"zig"});
// "| zig|"
const esquerda = try std.fmt.bufPrint(&buf, "|{s:<10}|", .{"zig"});
// "|zig |"
const centro = try std.fmt.bufPrint(&buf, "|{s:^10}|", .{"zig"});
// "| zig |"
// Zeros à esquerda
const zeros = try std.fmt.bufPrint(&buf, "{d:0>5}", .{42});
// "00042"
Trim (Remover Espaços)
const std = @import("std");
const texto = " Hello, World! ";
// Trim ambos os lados
const trimmed = std.mem.trim(u8, texto, " "); // "Hello, World!"
// Trim à esquerda
const ltrimmed = std.mem.trimLeft(u8, texto, " "); // "Hello, World! "
// Trim à direita
const rtrimmed = std.mem.trimRight(u8, texto, " "); // " Hello, World!"
// Trim de múltiplos caracteres
const dados = "\n\t dados \n\t";
const limpo = std.mem.trim(u8, dados, &[_]u8{ ' ', '\n', '\t' }); // "dados"
Substituição
const std = @import("std");
const allocator = std.heap.page_allocator;
const texto = "Hello World Hello Zig";
// Substituir todas as ocorrências
const resultado = try std.mem.replaceOwned(u8, allocator, texto, "Hello", "Olá");
defer allocator.free(resultado);
// "Olá World Olá Zig"
Conversão Maiúsculas/Minúsculas
const std = @import("std");
const texto = "Hello World";
var buf: [100]u8 = undefined;
// Para minúsculas
const lower = std.ascii.lowerString(buf[0..texto.len], texto);
// "hello world"
// Para maiúsculas
const upper = std.ascii.upperString(buf[0..texto.len], texto);
// "HELLO WORLD"
// Verificar se caractere é letra, dígito, etc.
const eh_alpha = std.ascii.isAlphabetic('A'); // true
const eh_digit = std.ascii.isDigit('5'); // true
const eh_space = std.ascii.isWhitespace(' '); // true
Conversão Número ↔ String
const std = @import("std");
// String → Inteiro
const num = try std.fmt.parseInt(i32, "42", 10); // 42
const hex = try std.fmt.parseInt(u32, "FF", 16); // 255
const bin = try std.fmt.parseInt(u8, "1010", 2); // 10
// String → Float
const pi = try std.fmt.parseFloat(f64, "3.14159"); // 3.14159
// Inteiro → String
var buf: [20]u8 = undefined;
const str = try std.fmt.bufPrint(&buf, "{d}", .{42}); // "42"
ArrayList como String Builder
const std = @import("std");
pub fn construirString(allocator: std.mem.Allocator) ![]u8 {
var lista = std.ArrayList(u8).init(allocator);
defer lista.deinit();
try lista.appendSlice("Olá");
try lista.appendSlice(", ");
try lista.appendSlice("mundo!");
try lista.append('!');
// Transferir propriedade para o chamador
return lista.toOwnedSlice();
}
UTF-8
const std = @import("std");
const texto = "Olá, São Paulo!";
// Zig trata strings como bytes UTF-8
// Para iterar sobre code points Unicode:
var view = std.unicode.Utf8View.initUnchecked(texto);
var it = view.iterator();
while (it.nextCodepoint()) |cp| {
std.debug.print("U+{X:0>4}\n", .{cp});
}
// Validar UTF-8
const valido = std.unicode.utf8ValidateSlice(texto); // true
// Comprimento em code points (não em bytes)
const byte_len = texto.len; // número de bytes
var cp_len: usize = 0;
var iter = std.unicode.Utf8View.initUnchecked(texto).iterator();
while (iter.nextCodepoint()) |_| {
cp_len += 1;
}
Tabela de Referência Rápida
| Operação | Função |
|---|---|
| Comparar | std.mem.eql(u8, a, b) |
| Buscar substring | std.mem.indexOf(u8, str, sub) |
| Começa com | std.mem.startsWith(u8, str, prefix) |
| Termina com | std.mem.endsWith(u8, str, suffix) |
| Dividir | std.mem.splitSequence(u8, str, delim) |
| Trim | std.mem.trim(u8, str, chars) |
| Concatenar | std.mem.concat(alloc, u8, slices) |
| Formatar | std.fmt.bufPrint(&buf, fmt, args) |
| Parse int | std.fmt.parseInt(T, str, base) |
| Parse float | std.fmt.parseFloat(T, str) |
| Minúsculas | std.ascii.lowerString(buf, str) |
Veja Também
- Sintaxe Básica — Literais de string
- Arrays e Slices — Operações com arrays
- Formatação — Especificadores de formato detalhados
- I/O — Leitura e escrita de texto
- Interop com C — Strings terminadas em null