nota: questo è stato inizialmente chiesto su SO .
Parte del mio progetto attuale riguarda l'iterazione su sequenze che non esistono necessariamente. Ad esempio, ho in memoria qualcosa di simile a un database relazionale, quindi diciamo che ho tre array
typedef struct { size_t car_index, size_t part_index } car_part_t;
car_ * cars;
part_t * parts;
car_part * car_parts;
Voglio essere in grado di scorrere tutte le parti di una determinata macchina, per esempio. Voglio in particolare part
e non car_part
. La mia soluzione attuale è
typedef struct {
size_t car_index;
size_t part_index;
size_t m_car_part_index; // keeps progress
} car_part_iterator_t;
e per avere due funzioni
car_part_iterator_t car_part_first(size_t car_index);
che restituisce un iteratore impostato in modo che it.part_index
sia l'indice della parte in parts
, it.car_index
è l'auto selezionata dal primo parametro e it.m_car_part_index
è una variabile 'privata' usata per tracciare progresso nella lista car_parts
.
Ho quindi una funzione simile per ottenere il prossimo
bool car_part_next(car_part_iterator_t * it);
che passa alla prossima parte della macchina e torna se l'iteratore è ancora valido. Finalmente per completezza ho
bool car_part_valid(car_part_iterator it);
per verificare se l'iteratore corrente è ancora valido. Quindi può essere usato in un ciclo for come
for (car_part_iterator_t it = car_part_first(car_index);
car_part_valid(it); car_part_next(&it))
{
// use it.part_index ...
}
Per me, questa sembra una buona soluzione alla quale sono arrivato dopo alcune prove ed errori. Ho anche sperimentato una funzione che restituisce un iteratore prima del primo risultato, quindi la prossima 'funzione restituirebbe il primo risultato, da utilizzare nei cicli while.
Questo è un buon modello? Presumo uno conosciuto. ha un nome? Ci sono insidie che non vedo?
note:
Su SO la questione è stata messa in dubbio sulla generalità (cioè può essere resa più generale), ma così com'è non sono troppo preoccupato per questo.
È stato anche sottolineato che la funzione valid
non è strettamente necessaria per il ciclo, ma consente un ciclo for
più naturale ed è talvolta utile anche al di fuori dei loop.