2011-02-10 11 views
6

CでIteratorのサポートを提供しようとした人は誰ですか? 正確なC++ STL :: Iteratorを探しているわけではありません。C言語のイテレータ

私はstlのようなコンテナライブラリを開発していますが、最小限のサポートで、このような機能が必要です。

(STLに似た)アルゴリズムインターフェイスの特定のセットを定義するのを楽しみにしています。ソートは、イテレーターの開始と終了を取り、任意のコンテナーで動作するはずです。

+5

は、ポインタと呼ばれるCのイテレータではありませんか? – AShelly

+1

@AShellyのソートですが、通常イテレータには、ポインタにはない別の値があるかどうかの概念があります。 –

答えて

2

プロジェクトでGPLコードを使用することが許されている場合は、ホイールを再発明する代わりにGLibを見てください。 GLibはまた、ソースコードレベルでかなり移植可能な方法で開発することを可能にします。これを使用する場合は、GPLの下でもコードをリリースする必要があることに注意してください。

リストにイテレータの機能を実装するg_list_first()g_list_next()を見てください。でもg_list_foreach() `

http://library.gnome.org/devel/glib/stable/glib-Doubly-Linked-Lists.html

+0

glib LGPL、i.d.ではありません。あなたは非GPLコードから(動的に)それにリンクできませんか? – delnan

+0

@delnan、あなたは完全に正しいです!そして私はいつもそれがGPLの下にあると思っていました... LGPLは絶対にうまいですが、動的にしかリンクしていません。 – jdehaan

1

標準化された方法で、イテレータを増分する必要があります。 C++では、それはちょうどオーバーロードされたoperator++()です。コンテナには、次の要素へのポインタを返す関連する関数が必要です。このインクリメント関数は、ライブラリ内のイテレータを受け入れることができる汎用ルーチンへのポインタとして渡す必要があります。例えば、私はコンテナから最大要素を返す関数を書きたい場合は、私は比較関数(operator<()に相当)だけでなく、必要とする、私はイテレータインクリメント機能(と同等のものを

が必要operator++())。

したがって、増分関数へのポインタを受け入れることが重要です。

+0

はいこれは次のインターフェイスで置き換えることができます – Avinash

+0

なぜその複雑さ、chrisaycockのレベルに行くのですか?イテレータデータ構造体を定義するモジュールは、単に現在のイテレータのアドレスを取るインクリメント関数を持つだけです。 – Sniggerfardimungus

+0

@ user30997 [OK]を、私はそれをより良い説明のために編集しました。 – chrisaycock

3

は、リンクリストを見てみましょあります。それは、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 */ 
} 

:ノードは、1つは、C++のイテレータと同様に、リストを反復するために使用することができ、「次」ポインタを含みますこれはC.で

+2

あなたは詰まっている。リンクされたリストは配列のように、データ構造です。 OPはイテレータを要求しています。イテレータは異なるデータ構造を一様に反復するために使用できます。 – delnan

+0

私はアナロジーを提供しています。 Cで直接利用できるものはありません。そのようなことがどのように機能するかを示すために、リンクされたリストの類推が提供されています。 –

10

ポインタはこの機能を果たすことができます。 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)の呼び出しによって状態が更新された構造体へのポインタです)。

+4

この基本的なスケルトンは、単純なイテレータを開始するのに最適なポイントです。しかし 'array_next'関数は、' i ++ 'は' i'を返し、実際には次の項目には移動しないので、 '(i + 1)'または '++ i'を返すべきです。 –

+0

良いキャッチ。一定。 – AShelly

0

C言語でSTLを実装しているオープンソースプロジェクトが1つ見つかりました。

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は、私たちのプロジェクトの接頭辞である:

http://sourceforge.net/projects/tstl2cl/

1

これは私が思いついたものです。 コンテナのような辞書(文字列マップ)が必要でした。