ジェネリックスタック
CoddyのCジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 60/61。
チャレンジ
簡単スタックは、Last-In-First-Out(LIFO)原則に従う基本的なデータ構造です。つまり、最後に追加された要素が最初に削除されます。皿の積み重ねをイメージしてください。上から追加し、上から削除します。
Generic Stackを作成しましょう。これは、void* pointersを使用して任意の型のデータを格納できる汎用的なデータ構造です。このスタックは、すべての essential なoperationを備えたLast-In-First-Out原則に従います。
コードを3つのファイルに分けて整理します。
stack.h:3つのmembersを持つStackstructをDefineします。items用のvoid**array、top index(next free slot)用のint、capacity用のintです。スタックを作成する(capacityを受け取る)、itemをpushする、itemをpopする、top itemをpeekする、スタックがemptyか確認する、スタックを解放するためのfunction prototypesをDeclareします。stack.c:Generic StackをImplementします。create_stack:heap上にStackをAllocateし、given capacityでitems arrayをAllocateし、topを0に初期化してpointerを返しますpush:空きがある場合(topがcapacityより小さい場合)にtopへitemを追加しますpop:top itemを削除して返します。スタックがemptyの場合はNULLを返しますpeek:削除せずにtop itemを返します。emptyの場合はNULLを返しますis_empty:スタックにitemがない場合は1、それ以外の場合は0を返しますfree_stack:最初にitems arrayをFreeし、その後Stack struct itselfをFreeします
main.c:実行するoperationの数を読み取ります。次に各operationについて、commandを読み取ります。commandは、integer valueが続くpush、pop、またはpeekです。capacity 10でスタックをCreateします。pushでは、heap上にintegerをAllocateし、そのpointerをpushします。popでは、itemを取得し、そのvalueを出力してintegerをFreeします。peekでは、削除せずにvalueを出力します。emptyなスタックに対してpopまたはpeekが呼び出された場合は、emptyを出力します。すべてのoperationの後、残っているitemとスタックをFreeします。
プログラムには次の入力が与えられます。
- operationの数
- 各operationを別々の行に記述したもの(
push X、pop、またはpeek)
入力が5、続いてpush 10、push 20、peek、pop、popの場合の出力例:
20
20
10入力が3、続いてpop、push 42、peekの場合の出力例:
empty
42入力が4、続いてpush 5、push 15、pop、popの場合の出力例:
15
5スタックはvoid* pointersを格納することに注意してください。実際のデータのAllocateとFreeはcallerの責任です。popするときは、返されたvoid*をint*にcastしてvalueにアクセスします。command stringsを比較するには、<string.h>のstrcmpを使用します。
自分で試してみよう
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stack.h"
int main() {
int n;
scanf("%d", &n);
// TODO: 容量10のスタックを作成する
// TODO: 各操作を処理する
for (int i = 0; i < n; i++) {
char command[10];
scanf("%s", command);
if (strcmp(command, "push") == 0) {
int value;
scanf("%d", &value);
// TODO: ヒープ上に整数を割り当て、そのポインタをプッシュする
}
else if (strcmp(command, "pop") == 0) {
// TODO: アイテムをポップする
// - NULLでない場合、値を出力して整数を解放する
// - NULLの場合(空のスタック)、"empty"を出力する
}
else if (strcmp(command, "peek") == 0) {
// TODO: 先頭のアイテムをピークする
// - NULLでない場合、値を出力する(削除や解放はしない)
// - NULLの場合(空のスタック)、"empty"を出力する
}
}
// TODO: スタック内の残りのアイテムをすべて解放する
// TODO: スタック自体を解放する
return 0;
}
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Cオンラインコンパイラ