イテレータパターン
CoddyのCジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 56/61。
イテレータパターンは、基盤となる構造を公開せずに、collection の elements に順番にアクセスする方法を提供します。ユーザーに array への direct なアクセスを与える代わりに、data を一度に 1 つの element ずつ進める方法を知っているオブジェクトを渡します。
イテレーターには通常、2つの情報が必要です。コレクションへの参照と現在の位置です。Cでは、この状態を保持するためにstructを作成します。
typedef struct {
int* data; // 配列へのポインタ
int size; // 要素の総数
int current; // 現在の位置
} IntIterator;iterator は2つの主要な functions を公開します。has_next() は読み取るべき more の elements があるかを checks し、next() は current の element を返して position を advances します。
int has_next(IntIterator* it) {
return it->current < it->size;
}
int next(IntIterator* it) {
return it->data[it->current++];
}iterator を使うとすっきりし、array の詳細が隠されます。
IntIterator it = create_iterator(numbers, 5);
while (has_next(&it)) {
printf("%d\n", next(&it));
}呼び出し側は、numbersが配列であることや、indexingがどのように機能するかを知る必要はまったくありません。この抽象化により、たとえば配列から連結リストへと後から基盤となるデータ構造を簡単に変更できます。その際、iteratorを使用するコードを変更する必要はありません。
チャレンジ
簡単NumberList iterator を作りましょう。これは、基になる array の構造を公開せずに、integer の collection を走査できる、すっきりとした抽象化です。
コードを 3 つのファイルに分けて構成します。
iterator.h: integer array への pointer、collection の合計サイズ、現在の position を保持するIntIteratorstruct を Define します。3 つの functions を Declare します。create_iterator(array pointer とサイズを受け取り、initialized された iterator を返す)、has_next(more elements が残っているか checks する)、next(current element を返し、position を advances する)です。include guards も忘れないでください。iterator.c: iterator functions を Implement します。create_iteratorfunction は、current position が 0 に設定されたIntIteratorを値として返します。has_nextfunction は、読み取る more elements がある場合は 1、otherwise は 0 を返します。nextfunction は current position にある element を返し、その後 position を increments します。main.c: elements の number を読み取り、次に各 integer value を array に読み込みます。この array 用の iterator を Create し、その後has_nextとnextを使う while loop で走査し、各 element をそれぞれ別の line に print します。
プログラムは次の入力を受け取ります。
- array 内の elements の number
- それぞれ別の line にある各 integer value
iterator pattern を使用してすべての elements を print してください。走査用の loop で direct な array indexing は使用しないでください。
入力が 4、続いて 10、20、30、40 の場合の出力例:
10
20
30
40入力が 3、続いて -5、0、100 の場合の出力例:
-5
0
100入力が 1、続いて 42 の場合の出力例:
42iterator は data がどのように格納されているかを隠します。main の loop は、array の indices や memory layout について何も知らなくても、単に "is there more?" と "give me the next one" を尋ねるだけです。
自分で試してみよう
#include <stdio.h>
#include "iterator.h"
int main() {
int n;
scanf("%d", &n);
int arr[n];
// TODO: n個の整数値を配列に読み込む
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// TODO: 配列のイテレータを作成する
// TODO: has_next と next を使った while ループで走査する
// そして各要素をそれぞれ1行に出力する
// 走査ループ内で配列の直接インデックス参照を使用しないでください!
return 0;
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Cオンラインコンパイラ