演習課題「ループ処理で値を取り出す」
コードエリアにはスタックを実現するプログラムがあります。
スタックの各要素は char* 型として定義されており、main 関数でいくつかの値を追加しています。
コードを修正し、ループ処理でスタックから各要素を取り出してメッセージを出力してください。
プログラムを実行して、正しく出力されれば演習課題クリアです!
期待する出力値
勇者はルビーを手に入れた
勇者は薬草を手に入れた
勇者は盾を手に入れた
勇者は剣を手に入れた
#04:スタックを使った宝箱
このチャプターでは、スタックを使った例として、宝箱の中身を出力するプログラムを作成します。
#include <stdio.h>
#define N 10
typedef int data_t;
data_t stack[N];
int size;
void init(void)
{
size = 0;
}
void push(data_t x)
{
if (size >= N) {
printf("stack overflow\n");
return;
}
stack[size] = x;
size++;
}
void pop(data_t *x)
{
if (size <= 0) {
printf("stack underflow\n");
return;
}
*x = stack[size - 1];
size--;
}
int main(void)
{
}
スタックの要素のデータ型は data_t として宣言していました。
typedef のところを変更すれば、このデータ型を変更できます。// スタックの要素を char* 型にする
typedef char* data_t;
◯ スタックに追加する char item1[] = "鋼鉄の剣";
char item2[] = "木の盾";
char item3[] = "回復薬";
char item4[] = "クリスタル";
push(item1);
push(item2);
push(item3);
push(item4);
item1 〜 item4 は文字列の先頭の文字へのポインタになっています。
そのため、push(item1) などとすれば、文字列として使えるポインタを追加できます。
◯ スタックから取り出す char *p;
pop(&p);
printf("%s\n", p);
char* 型のデータを取り出すには、char*型の変数 p を使う必要があります。
pop の引数に &p を指定して、p の値をスタックから取り出した値に書き換えています。
取り出した値はアドレスなので、そのまま文字列として出力できます。
※ 文字列とポインタについては「C 言語入門編 5 #06:ポインタの配列を理解しよう」で説明しています。
https://paiza.jp/works/c/primer/beginner-c5/23606
pop 関数に戻り値を設定すれば、pop に成功したかどうかを判定できます。int pop(data_t *x)
{
if (size <= 0) {
return 1;
}
*x = stack[size - 1];
size--;
return 0;
}
関数の戻り値は、
・関数の処理が成功したとき 0
・関数の処理が失敗したとき 0 以外
にすることが多いので、この例では、
・pop が成功したとき 0
・pop が失敗したとき 1
にしています。
このチャプターで作成したコードです。// スタックを使った宝箱
#include <stdio.h>
#define N 10
typedef char* data_t;
data_t stack[N];
int size;
void init(void)
{
size = 0;
}
void push(data_t x)
{
if (size >= N) {
printf("stack overflow\n");
return;
}
stack[size] = x;
size++;
}
int pop(data_t *x)
{
if (size <= 0) {
return 1;
}
*x = stack[size - 1];
size--;
return 0;
}
int main(void)
{
char item1[] = "鋼鉄の剣";
char item2[] = "木の盾";
char item3[] = "回復薬";
char item4[] = "クリスタル";
push(item1);
push(item2);
push(item3);
push(item4);
char *p;
printf("宝箱を開けた!\n");
while (pop(&p) == 0) {
printf("%sを手に入れた!\n", p);
}
}
pop 関数と同様に、push 関数にも戻り値を設定できます。int push(data_t x)
{
if (size >= N) {
return 1;
}
stack[size] = x;
size++;
return 0;
}
戻り値を設定すると、関数が処理に成功したかどうかを知ることができて便利です。
スタックの実装 - C言語/C++入門講座 ツナサーモン
https://tunasalmon.com/2017/09/24/スタックの実装/
【ワレコのコラム】正常終了した関数の戻り値はゼロで良いか? - われこ われこ
https://www.wareko.jp/blog/should-return-value-of-normally-terminated-function-be-zero