Menu
Coddy logo textTech

イテレータパターン

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を使用するコードを変更する必要はありません。

challenge icon

チャレンジ

簡単

NumberList iterator を作りましょう。これは、基になる array の構造を公開せずに、integer の collection を走査できる、すっきりとした抽象化です。

コードを 3 つのファイルに分けて構成します。

  • iterator.h: integer array への pointer、collection の合計サイズ、現在の position を保持する IntIterator struct を 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_iterator function は、current position が 0 に設定された IntIterator を値として返します。has_next function は、読み取る more elements がある場合は 1、otherwise は 0 を返します。next function は current position にある element を返し、その後 position を increments します。
  • main.c: elements の number を読み取り、次に各 integer value を array に読み込みます。この array 用の iterator を Create し、その後 has_nextnext を使う while loop で走査し、各 element をそれぞれ別の line に print します。

プログラムは次の入力を受け取ります。

  1. array 内の elements の number
  2. それぞれ別の line にある各 integer value

iterator pattern を使用してすべての elements を print してください。走査用の loop で direct な array indexing は使用しないでください。

入力が 4、続いて 10203040 の場合の出力例:

10
20
30
40

入力が 3、続いて -50100 の場合の出力例:

-5
0
100

入力が 1、続いて 42 の場合の出力例:

42

iterator は 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;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Cオンラインコンパイラ