Menu
Coddy logo textTech

ジェネリックスタック

CoddyのCジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 60/61。

challenge icon

チャレンジ

簡単

スタックは、Last-In-First-Out(LIFO)原則に従う基本的なデータ構造です。つまり、最後に追加された要素が最初に削除されます。皿の積み重ねをイメージしてください。上から追加し、上から削除します。

Generic Stackを作成しましょう。これは、void* pointersを使用して任意の型のデータを格納できる汎用的なデータ構造です。このスタックは、すべての essential なoperationを備えたLast-In-First-Out原則に従います。

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

  • stack.h:3つのmembersを持つStack structを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が続くpushpop、またはpeekです。capacity 10でスタックをCreateします。pushでは、heap上にintegerをAllocateし、そのpointerをpushします。popでは、itemを取得し、そのvalueを出力してintegerをFreeします。peekでは、削除せずにvalueを出力します。emptyなスタックに対してpopまたはpeekが呼び出された場合は、emptyを出力します。すべてのoperationの後、残っているitemとスタックをFreeします。

プログラムには次の入力が与えられます。

  1. operationの数
  2. 各operationを別々の行に記述したもの(push Xpop、またはpeek

入力が5、続いてpush 10push 20peekpoppopの場合の出力例:

20
20
10

入力が3、続いてpoppush 42peekの場合の出力例:

empty
42

入力が4、続いてpush 5push 15poppopの場合の出力例:

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オンラインコンパイラ