Padrão Iterator
Parte da seção Object Oriented Programming do Journey de C da Coddy — lição 56 de 61.
O padrão Iterator fornece uma maneira de acessar elementos de uma coleção sequencialmente sem expor sua estrutura subjacente. Em vez de dar aos usuários acesso direto a um array, você fornece a eles um objeto que sabe como percorrer os dados um elemento por vez.
Um iterador normalmente precisa de duas informações: uma referência para a coleção e a posição atual. Em C, criamos uma struct para manter esse estado:
typedef struct {
int* data; // ponteiro para o array
int size; // número total de elementos
int current; // posição atual
} IntIterator;O iterador expõe duas funções principais. has_next() verifica se há mais elementos para ler, e next() retorna o elemento atual e avança a posição:
int has_next(IntIterator* it) {
return it->current < it->size;
}
int next(IntIterator* it) {
return it->data[it->current++];
}Usar o iterador parece limpo e esconde os detalhes do array:
IntIterator it = create_iterator(numbers, 5);
while (has_next(&it)) {
printf("%d\n", next(&it));
}O chamador nunca precisa saber que numbers é um array ou como a indexação funciona. Essa abstração torna fácil alterar a estrutura de dados subjacente mais tarde — de um array para uma lista encadeada, por exemplo — sem alterar o código que utiliza o iterador.
Desafio
FácilVamos construir um iterador NumberList — uma abstração limpa que permite percorrer uma coleção de inteiros sem expor a estrutura do array subjacente.
Você organizará seu código em três arquivos:
iterator.h: Defina uma structIntIteratorque contém um ponteiro para um array de inteiros, o tamanho total da coleção e a posição atual. Declare três funções:create_iterator(recebe um ponteiro de array e o tamanho, retorna um iterador inicializado),has_next(verifica se restam mais elementos) enext(retorna o elemento atual e avança a posição). Não se esqueça dos include guards!iterator.c: Implemente suas funções de iterador. A funçãocreate_iteratordeve retornar umIntIteratorpor valor com a posição atual definida como 0. A funçãohas_nextretorna 1 se houver mais elementos para ler, 0 caso contrário. A funçãonextretorna o elemento na posição atual e, em seguida, incrementa a posição.main.c: Leia o número de elementos e, em seguida, leia cada valor inteiro para um array. Crie um iterador para este array e use um loop while comhas_nextenextpara percorrer e imprimir cada elemento em sua própria linha.
Seu programa receberá:
- O número de elementos no array
- Cada valor inteiro em uma linha separada
Use o padrão iterator para imprimir todos os elementos — nada de indexação direta de array no seu loop de percurso!
Exemplo de saída quando as entradas são 4, depois 10, 20, 30, 40:
10
20
30
40Exemplo de saída quando as entradas são 3, depois -5, 0, 100:
-5
0
100Exemplo de saída quando as entradas são 1, depois 42:
42O iterador oculta como os dados são armazenados — seu loop principal simplesmente pergunta "há mais?" e "dê-me o próximo" sem saber nada sobre índices de array ou layout de memória.
Folha de consulta
O padrão Iterator fornece uma maneira de acessar elementos de uma coleção sequencialmente sem expor sua estrutura subjacente.
Uma struct de iterador mantém a referência da coleção, o tamanho e a posição atual:
typedef struct {
int* data; // ponteiro para o array
int size; // número total de elementos
int current; // posição atual
} IntIterator;O iterador expõe duas funções principais:
int has_next(IntIterator* it) {
return it->current < it->size;
}
int next(IntIterator* it) {
return it->data[it->current++];
}O uso do iterador oculta os detalhes de implementação do array:
IntIterator it = create_iterator(numbers, 5);
while (has_next(&it)) {
printf("%d\n", next(&it));
}Esta abstração permite alterar a estrutura de dados subjacente sem modificar o código do cliente.
Experimente você mesmo
#include <stdio.h>
#include "iterator.h"
int main() {
int n;
scanf("%d", &n);
int arr[n];
// TODO: Leia n valores inteiros para dentro do array
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// TODO: Crie um iterator para o array
// TODO: Use um loop while com has_next e next para percorrer
// e imprimir cada elemento em sua própria linha
// NÃO use indexação direta de array no seu loop de percurso!
return 0;
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Object Oriented Programming
1Fundamentos da Programação Modular
Arquivos de CabeçalhoInclude GuardsArquivos-FonteFunções EstáticasRecapitulação: Calculadora Modular4Encapsulamento
Conceito de Ponteiros OpacosDefinindo Structs OpacasGetters e SettersValidação em SettersRecapitulação: Caixa Secreta2Objetos e Métodos
Structs como ObjetosO Ponteiro 'Self'Const CorrectnessPonteiro vs ValorMétodos AuxiliaresRecapitulação: Point Manager5Projeto: Conta Bancária Simples
Configuração do ProjetoImplementação da Conta3Ciclo de Vida de Objetos
Padrão de ConstrutorPadrão de DestrutorInicialização na StackCópia ProfundaRecapitulação: String Wrapper6Herança via Composição
Incorporação de StructsA Regra do Primeiro MembroAcessando Membros PaiUpcastingRecapitulação: Hierarquia de Formas9Projeto: Desenhador de Formas
Visão Geral do ProjetoImplementação do Círculo