復習:ジェネリック配列
CoddyのCジャーニー「Object Oriented Programming」セクションの一部 — レッスン 53/61。
チャレンジ
簡単void* ポインタを使用して、同じコレクション内に整数と文字列を混在させて保持できる柔軟なデータ構造である GenericArray コンテナを構築しましょう。
コードは以下の3つのファイルに分けて構成します:
generic_array.h: 3つのメンバ(ポインタを保持するvoid**配列、現在の要素数を示すint、および容量を示すint)を持つGenericArray構造体を定義します。配列の作成、要素の追加、インデックスによる要素の取得、および配列の解放を行うための関数プロトタイプを宣言します。generic_array.c: コンテナの機能を実装します:create_array— 指定された初期容量で GenericArray を割り当て、count を 0 に初期化します。add_element— 次の利用可能なスロットにvoid*ポインタを格納し、count をインクリメントします(容量は十分であると仮定します)。get_element— 指定されたインデックスにあるvoid*を返します。free_array— items 配列と GenericArray 構造体自体を解放します。
main.c: 整数と文字列の両方を格納することで、ジェネリック配列の実演を行います。追加する要素の数を読み取り、各要素について型インジケータ(整数の場合はi、文字列の場合はs)に続いて値を読み取ります。すべての要素を追加した後、配列を反復処理して各値を出力します。整数の場合は数値を直接出力し、文字列の場合はテキストを直接出力します。
プログラムは以下を受け取ります:
- 追加する要素の数
- 各要素について:型インジケータ(
iまたはs)と、それに続く値
整数を追加するときは、int 用のメモリを割り当ててポインタを格納します。文字列を追加するときは、メモリを割り当てて文字列をコピーします。取得するときは、適切な型にキャストし直して出力します。
重要: 出力時に型を追跡するために、main 内で型インジケータの単純な並列配列を使用するか、各要素と一緒に型インジケータ文字を保存することができます。
入力が 3、次に i 42、s Hello、i 100 の場合の出力例:
42
Hello
100入力が 4、次に s World、s Generic、i -5、s Arrays の場合の出力例:
World
Generic
-5
Arraysヘッダーファイルではインクルードガードを使用することを忘れないでください。コンテナ自体は、自分が何を格納しているかを知る必要はありません。単に void* ポインタを保持するだけです。型を把握する責任は、要素を追加および取得するコード側にあります。
自分で試してみよう
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "generic_array.h"
int main() {
int n;
scanf("%d", &n);
// TODO: 容量 n の GenericArray を作成する
// TODO: 型を追跡するための並列配列(サイズ n の char 配列)を作成する
// TODO: 各要素について:
// - 型インジケーター(i または s)を読み込む
// - 値を読み込む
// - 整数(int)の場合:int 用のメモリを割り当て、値を格納し、配列に追加する
// - 文字列(string)の場合:文字列用のメモリを割り当て、値をコピーし、配列に追加する
// - 型インジケーターを並列配列に格納する
// TODO: 配列を反復処理し、各要素を出力する
// - 並列配列から型を確認する
// - void* を適切な型にキャストし直して出力する
// TODO: すべての割り当て済みメモリ(整数、文字列、および配列)を解放する
return 0;
}