---
title: "Como Dividir (Split) Strings por Delimitador em Zig"
url: "https://ziglang.com.br/receitas/como-dividir-split-strings-por-delimitador-em-zig/"
markdown_url: "https://ziglang.com.br/receitas/como-dividir-split-strings-por-delimitador-em-zig.MD"
description: "Aprenda a dividir strings em Zig usando delimitadores com std.mem.splitScalar, splitSequence e tokenizeScalar. Exemplos práticos."
date: "2026-02-21"
author: "Zig Brasil"
---

# Como Dividir (Split) Strings por Delimitador em Zig

Aprenda a dividir strings em Zig usando delimitadores com std.mem.splitScalar, splitSequence e tokenizeScalar. Exemplos práticos.


# Como Dividir (Split) Strings por Delimitador em Zig

Dividir strings por um delimitador é uma operação fundamental para parsing de dados, processamento de texto e análise de formatos como CSV. Zig oferece várias funções na biblioteca padrão para fazer isso de forma eficiente e sem alocação de memória.

## Split vs Tokenize

Zig oferece duas famílias de funções para dividir strings:

- **split**: mantém campos vazios quando delimitadores consecutivos são encontrados
- **tokenize**: ignora campos vazios (semelhante ao comportamento de `strtok` em C)

## Dividir por Caractere Único com splitScalar

A função `std.mem.splitScalar` divide uma string usando um único caractere como delimitador.

```zig
const std = @import("std");

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

    // Dividir por vírgula
    const csv = "João,25,São Paulo,Brasil";
    var iter = std.mem.splitScalar(u8, csv, ',');

    try stdout.print("Campos do CSV:\n", .{});
    while (iter.next()) |campo| {
        try stdout.print("  -> \"{s}\"\n", .{campo});
    }

    // Dividir caminho por /
    try stdout.print("\nPartes do caminho:\n", .{});
    const caminho = "/home/usuario/documentos/arquivo.txt";
    var iter2 = std.mem.splitScalar(u8, caminho, '/');
    while (iter2.next()) |parte| {
        try stdout.print("  -> \"{s}\"\n", .{parte});
    }
}
```

**Saída esperada:**
```
Campos do CSV:
  -> "João"
  -> "25"
  -> "São Paulo"
  -> "Brasil"

Partes do caminho:
  -> ""
  -> "home"
  -> "usuario"
  -> "documentos"
  -> "arquivo.txt"
```

Note que `splitScalar` preserva campos vazios (como o primeiro campo vazio antes de `/home`).

## Dividir por Sequência de Caracteres

Use `std.mem.splitSequence` para dividir por uma sequência de múltiplos caracteres.

```zig
const std = @import("std");

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

    // Dividir por " -> "
    const fluxo = "início -> processamento -> validação -> fim";
    var iter = std.mem.splitSequence(u8, fluxo, " -> ");

    try stdout.print("Etapas do fluxo:\n", .{});
    while (iter.next()) |etapa| {
        try stdout.print("  [{s}]\n", .{etapa});
    }

    // Dividir por quebra de linha "\r\n"
    try stdout.print("\nLinhas:\n", .{});
    const texto = "Linha 1\r\nLinha 2\r\nLinha 3";
    var iter2 = std.mem.splitSequence(u8, texto, "\r\n");
    while (iter2.next()) |linha| {
        try stdout.print("  \"{s}\"\n", .{linha});
    }
}
```

**Saída esperada:**
```
Etapas do fluxo:
  [início]
  [processamento]
  [validação]
  [fim]

Linhas:
  "Linha 1"
  "Linha 2"
  "Linha 3"
```

## Tokenizar Strings (Ignorar Vazios)

Use `std.mem.tokenizeScalar` quando quiser ignorar campos vazios resultantes de delimitadores consecutivos.

```zig
const std = @import("std");

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

    // Tokenizar por espaço (ignora espaços múltiplos)
    const texto = "  Olá    Mundo   Zig  ";
    var tokens = std.mem.tokenizeScalar(u8, texto, ' ');

    try stdout.print("Tokens (espaço):\n", .{});
    while (tokens.next()) |token| {
        try stdout.print("  \"{s}\"\n", .{token});
    }

    // Comparação: split mantém vazios
    try stdout.print("\nSplit (espaço) - com vazios:\n", .{});
    var split = std.mem.splitScalar(u8, texto, ' ');
    while (split.next()) |parte| {
        try stdout.print("  \"{s}\"\n", .{parte});
    }
}
```

**Saída esperada:**
```
Tokens (espaço):
  "Olá"
  "Mundo"
  "Zig"

Split (espaço) - com vazios:
  ""
  ""
  "Olá"
  ""
  ""
  ""
  "Mundo"
  ""
  ""
  "Zig"
  ""
  ""
```

## Tokenizar por Múltiplos Delimitadores

Use `std.mem.tokenizeAny` para dividir por qualquer caractere de um conjunto.

```zig
const std = @import("std");

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

    // Tokenizar por múltiplos delimitadores (espaço, vírgula, ponto-e-vírgula)
    const entrada = "maçã, banana; laranja  uva,melão";
    var tokens = std.mem.tokenizeAny(u8, entrada, " ,;");

    try stdout.print("Frutas:\n", .{});
    while (tokens.next()) |fruta| {
        try stdout.print("  - {s}\n", .{fruta});
    }
}
```

**Saída esperada:**
```
Frutas:
  - maçã
  - banana
  - laranja
  - uva
  - melão
```

## Coletar Resultados em ArrayList

Para armazenar os resultados do split em uma lista, use `ArrayList`.

```zig
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();

    const csv = "nome,idade,cidade,profissão";
    var iter = std.mem.splitScalar(u8, csv, ',');

    // Coletar em ArrayList
    var campos = std.ArrayList([]const u8).init(allocator);
    defer campos.deinit();

    while (iter.next()) |campo| {
        try campos.append(campo);
    }

    try stdout.print("Total de campos: {d}\n", .{campos.items.len});
    for (campos.items, 0..) |campo, i| {
        try stdout.print("  Campo {d}: \"{s}\"\n", .{ i, campo });
    }
}
```

**Saída esperada:**
```
Total de campos: 4
  Campo 0: "nome"
  Campo 1: "idade"
  Campo 2: "cidade"
  Campo 3: "profissão"
```

## Exemplo Prático: Parser de CSV Simples

Veja um exemplo mais completo que faz parsing de um conteúdo CSV.

```zig
const std = @import("std");

const Pessoa = struct {
    nome: []const u8,
    idade: u32,
    cidade: []const u8,
};

fn parseLinhaCsv(linha: []const u8) !Pessoa {
    var campos = std.mem.splitScalar(u8, linha, ',');

    const nome = campos.next() orelse return error.CampoAusente;
    const idade_str = campos.next() orelse return error.CampoAusente;
    const cidade = campos.next() orelse return error.CampoAusente;

    const idade = try std.fmt.parseInt(u32, idade_str, 10);

    return Pessoa{
        .nome = nome,
        .idade = idade,
        .cidade = cidade,
    };
}

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

    const dados =
        \\Ana,30,São Paulo
        \\Carlos,25,Rio de Janeiro
        \\Maria,35,Belo Horizonte
    ;

    var linhas = std.mem.splitScalar(u8, dados, '\n');

    try stdout.print("Pessoas cadastradas:\n", .{});
    while (linhas.next()) |linha| {
        if (linha.len == 0) continue;
        const pessoa = try parseLinhaCsv(linha);
        try stdout.print("  {s}, {d} anos, {s}\n", .{ pessoa.nome, pessoa.idade, pessoa.cidade });
    }
}
```

**Saída esperada:**
```
Pessoas cadastradas:
  Ana, 30 anos, São Paulo
  Carlos, 25 anos, Rio de Janeiro
  Maria, 35 anos, Belo Horizonte
```

## Referência Rápida

| Função | Delimitador | Campos Vazios |
|--------|-------------|---------------|
| `splitScalar` | Caractere único | Mantém |
| `splitSequence` | Sequência de chars | Mantém |
| `splitAny` | Qualquer de um conjunto | Mantém |
| `tokenizeScalar` | Caractere único | Remove |
| `tokenizeSequence` | Sequência de chars | Remove |
| `tokenizeAny` | Qualquer de um conjunto | Remove |

## Veja Também

- [Concatenar Strings](/receitas/zig-concatenar-strings/) — Operação inversa: juntar strings
- [Buscar Substrings](/receitas/zig-buscar-substring/) — Encontre texto antes de dividir
- [Converter String para Número](/receitas/zig-converter-string-numero/) — Converta campos numéricos após o split
- [Ler Arquivo Linha por Linha](/receitas/zig-ler-arquivo-linha-por-linha/) — Combine com leitura de arquivos
