note: this was originally asked on SO.
Part of my current project involves iterating over sequences that don't necessarily exist. For example, I have something similar to a relational database in memory, so say I have three arrays
typedef struct { size_t car_index, size_t part_index } car_part_t;
car_ * cars;
part_t * parts;
car_part * car_parts;
I want to be able to iterate over all the parts in a given car, for example. I specifically want the part
and not the car_part
. My current solution is
typedef struct {
size_t car_index;
size_t part_index;
size_t m_car_part_index; // keeps progress
} car_part_iterator_t;
and to have two functions
car_part_iterator_t car_part_first(size_t car_index);
which returns an iterator set up such that it.part_index
is the index of the part in parts
, it.car_index
is the car selected by the first parameter, and it.m_car_part_index
is a 'private' variable used to track progress in the car_parts
list.
I then have a similar function for getting the next one
bool car_part_next(car_part_iterator_t * it);
which moves to the next car part, and returns if the iterator is still valid. Finally for completeness I have
bool car_part_valid(car_part_iterator it);
to check if the current iterator is still valid. So it can be used in a for loop like
for (car_part_iterator_t it = car_part_first(car_index);
car_part_valid(it); car_part_next(&it))
{
// use it.part_index ...
}
To me, this sounds like a good solution that I came to after some trial and error. I also experimented with a function that returns an iterator before the first result, so the next` function would return the first result, for use in while loops.
Is this a good pattern? I assume a known one. Does it have a name? Are there pitfalls I'm not seeing?
notes:
On SO the generality of this was questioned (ie it can be made more general), but as it stands I'm not too bothered about that.
It was also pointed out that the valid
function isn't strictly needed for the loop, but it allows for a more natural for
loop, and is also sometimes useful outside of loops.