有没有人尝试过为 C 中的迭代器提供支持。 我并不是在寻找精确的 C++ STL::Iterator,但对某些想法的最小支持对我来说是个好点。
我正在开发与 stl 相同的容器库,但支持很少,所以我需要在这些容器中提供这种功能。
我期待定义某些算法接口集(类似于STL)。例如 sort ,它将采用开始和结束迭代器,并且应该适用于任何容器。
指针可以起到这个作用。
container.begin()
很简单,而且 container.end()
不需要太多工作。
考虑
Value array[N];
typedef Value* iterator;
iterator array_begin(Value a[]){ return &a[0];}
iterator array_end(Value a[], int n){ return &a[n];}
iterator array_next(iterator i) { return ++i;}
iterator it = array_begin(a);
iterator end = array_end(a,N);
for (;it < end; it=array_next(it))
{
Value v = *it;
}
对于列表等其他容器,可以使用 NULL 作为结束。 对于树来说也是如此,但是
next
函数需要维护状态。 (或者迭代器是指向结构体的指针,其状态通过调用 next(it)
进行更新)。
看一下链表。节点包含一个“下一个”指针,可用于以类似于 C++ 迭代器的方式迭代列表:
typedef struct Node {
...
struct Node *next;
} Node;
...
Node *iter, *firstNode, *nodeList;
/* set firstNode and populate nodeList */
for (iter = firstNode; iter != NULL; iter = iter->next) {
/* iterate through list */
}
它不是 C++ 迭代器,但希望这能提供一种在 C 中实现此目的的方法。
如果您被允许在项目中使用 LGPL 代码,请查看 GLib,而不是重新发明轮子。 GLib 还允许在源代码级别以相当可移植的方式进行开发。
看看
g_list_first()
和 g_list_next()
,它们实现了列表上迭代器的功能。甚至还有一个 g_list_foreach()`
http://library.gnome.org/devel/glib/stable/glib-Doubly-Linked-Lists.html
您需要一种标准化的方法来“递增”迭代器。在 C++ 中,这只是重载的 operator++()
。您的容器需要一个关联的函数来返回指向下一个元素的指针。这个递增函数需要作为指针传递给任何可以接受库中迭代器的通用例程。
例如,如果我想编写一个从容器返回max
元素的函数,我不仅需要比较函数(相当于operator<()
),还需要一个迭代器递增函数(相当于
) operator++()
)。因此,确保我可以接受指向您的递增函数的指针是关键要求。
typedef struct PWDict PWDict;
typedef struct PWDictIterator PWDictIterator;
typedef struct PWDictImplementation
{
PWDict *(*create)(const struct PWDictImplementation *impl, size_t elements);
void (*destroy)(PWDict *dict);
unsigned int (*size)(const PWDict *dict);
unsigned int (*sizeInBytes)(const PWDict *dict);
int (*get)(const PWDict *dict, const char *key, char *output, size_t size);
int (*set)(PWDict *dict, const char *key, const char *value);
PWDictIterator *(*iteratorCreate)(const PWDict *dict);
void (*iteratorBegin)(PWDictIterator *it);
void (*iteratorEnd)(PWDictIterator *it);
void (*iteratorDestroy)(PWDictIterator *it);
const char *(*iteratorGetKey)(const PWDictIterator *it);
const char *(*iteratorGetValue)(const PWDictIterator *it);
int (*iteratorSetValue)(PWDictIterator *it, const char *value);
void (*iteratorNext)(PWDictIterator *it);
}
PWDictImplementation;
struct PWDict
{
PWDictImplementation *impl;
};
struct PWDictIterator
{
PWDict *dict; /* get iterator implementation from the dict implementation */
};
PW是我们的项目前缀。 我们只需要一个像容器一样的字典(字符串-字符串映射)。
typedef struct Iter Iter;
struct Iter { void *adr; size_t elt, cnt, cur; }
void * IterCur(Iter const *);
void * IterNext(Iter *);
void * IterPrev(Iter *);
# define ITER(a) (Iter){a, sizeof *a, sizeof a / sizeof *a, 0}
# define ITER_N(a, n) (Iter){a, sizeof *a, n , 0}
这样使用:
for (iter = ITER(objs), obj = IterCur(&iter); obj; obj = IterNext(&iter)) {
...
}
IterNext
和其他的实现是微不足道的。如果有元素,我会得到一个指针,否则
NULL
。可以迭代静态或动态分配的数组,甚至作为边缘情况的空数组。如果我需要使用公共标头迭代不同的结构,则特别有用,因为它会自动处理大小差异。当然,它的效率比烘焙偏移要低。