Menu
Coddy logo textTech

Patrón Iterator

Parte de la sección Object Oriented Programming del Journey de C de Coddy — lección 56 de 61.

El patrón Iterator proporciona una forma de acceder a los elementos de una colección de manera secuencial sin exponer su estructura subyacente. En lugar de dar a los usuarios acceso directo a un array, se les proporciona un objeto que sabe cómo recorrer los datos de elemento en elemento.

Un iterador normalmente necesita dos piezas de información: una referencia a la colección y la posición actual. En C, creamos un struct para mantener este estado:

typedef struct {
    int* data;      // puntero al arreglo
    int size;       // número total de elementos
    int current;    // posición actual
} IntIterator;

El iterador expone dos funciones clave. has_next() comprueba si hay más elementos para leer, y next() devuelve el elemento actual y avanza la posición:

int has_next(IntIterator* it) {
    return it->current < it->size;
}

int next(IntIterator* it) {
    return it->data[it->current++];
}

El uso del iterador se ve limpio y oculta los detalles del array:

IntIterator it = create_iterator(numbers, 5);
while (has_next(&it)) {
    printf("%d\n", next(&it));
}

El llamador nunca necesita saber que numbers es un array o cómo funciona la indexación. Esta abstracción facilita el cambio de la estructura de datos subyacente más adelante — de un array a una lista enlazada, por ejemplo — sin cambiar el código que utiliza el iterador.

challenge icon

Desafío

Fácil

Vamos a construir un iterador NumberList — una abstracción limpia que te permite recorrer una colección de enteros sin exponer la estructura del arreglo subyacente.

Organizarás tu código en tres archivos:

  • iterator.h: Define una estructura IntIterator que contenga un puntero a un arreglo de enteros, el tamaño total de la colección y la posición actual. Declara tres funciones: create_iterator (toma un puntero al arreglo y el tamaño, devuelve un iterador inicializado), has_next (verifica si quedan más elementos) y next (devuelve el elemento actual y avanza la posición). ¡No olvides los include guards!
  • iterator.c: Implementa las funciones de tu iterador. La función create_iterator debe devolver un IntIterator por valor con la posición actual establecida en 0. La función has_next devuelve 1 si hay más elementos por leer, 0 en caso contrario. La función next devuelve el elemento en la posición actual y luego incrementa la posición.
  • main.c: Lee el número de elementos, luego lee cada valor entero en un arreglo. Crea un iterador para este arreglo, luego usa un bucle while con has_next y next para recorrer e imprimir cada elemento en su propia línea.

Tu programa recibirá:

  1. El número de elementos en el arreglo
  2. Cada valor entero en una línea separada

¡Usa el patrón iterador para imprimir todos los elementos — nada de indexación directa del arreglo en tu bucle de recorrido!

Ejemplo de salida cuando las entradas son 4, luego 10, 20, 30, 40:

10
20
30
40

Ejemplo de salida cuando las entradas son 3, luego -5, 0, 100:

-5
0
100

Ejemplo de salida cuando las entradas son 1, luego 42:

42

El iterador oculta cómo se almacenan los datos — tu bucle principal simplemente pregunta "¿hay más?" y "dame el siguiente" sin saber nada sobre los índices del arreglo o el diseño de la memoria.

Hoja de referencia

El patrón Iterator proporciona una forma de acceder a los elementos de una colección de manera secuencial sin exponer su estructura subyacente.

Una estructura de iterador contiene la referencia a la colección, el tamaño y la posición actual:

typedef struct {
    int* data;      // pointer to the array
    int size;       // total number of elements
    int current;    // current position
} IntIterator;

El iterador expone dos funciones clave:

int has_next(IntIterator* it) {
    return it->current < it->size;
}

int next(IntIterator* it) {
    return it->data[it->current++];
}

El uso del iterador oculta los detalles de implementación del array:

IntIterator it = create_iterator(numbers, 5);
while (has_next(&it)) {
    printf("%d\n", next(&it));
}

Esta abstracción permite cambiar la estructura de datos subyacente sin modificar el código del cliente.

Pruébalo tú mismo

#include <stdio.h>
#include "iterator.h"

int main() {
    int n;
    scanf("%d", &n);
    
    int arr[n];
    
    // TODO: Leer n valores enteros en el arreglo
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }
    
    // TODO: Crear un iterador para el arreglo
    
    // TODO: Usar un bucle while con has_next y next para recorrer
    // e imprimir cada elemento en su propia línea
    // ¡NO uses indexación directa del arreglo en tu bucle de recorrido!
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Object Oriented Programming