自己参照する構造体

 前回は、配列を使えば並び順や並び替えという概念もプログラムで実装できますよ、というお話でした。実は、配列より少々難しい概念なのですが、自己参照を構造体に取り入れても、並び順を表現できます。

 以下のプログラムを作成し、実行してみて下さい。

#include <stdio.h>
#include <string.h>

struct person {
    char name[40];          // 名前
    char job[40];           // 職業
    int lv;                 // レベル
    int hp;                 // HP
    int mp;                 // MP
    struct person *next;    // 次のキャラ(後ろにいるキャラ)を指すポインタ
};
typedef struct person character;

void showStatus(character chara) {
    printf("名前:%s\n", chara.name);
    printf("職業:%s\n", chara.job);
    printf("レベル:%d\n", chara.lv);
    printf("HP:%d\n", chara.hp);
    printf("MP:%d\n", chara.mp);
    
    // 次のキャラがいるなら、再帰的に関数を呼び出す
    if(chara.next != NULL) {
        showStatus(*(chara.next));
    }
}

int main(int argc, const char * argv[])
{
    
    // insert code here...
    
    // 戦士「ああああ」
    character aaaa;
    strcpy(aaaa.name, "ああああ");
    strcpy(aaaa.job, "戦士");
    aaaa.lv = 40;
    aaaa.hp = 360;
    aaaa.mp = 0;
    
    // 魔法使い「いいいい」
    character iiii;
    strcpy(iiii.name, "いいいい");
    strcpy(iiii.job, "魔法使い");
    iiii.lv = 38;
    iiii.hp = 250;
    iiii.mp = 230;
    
    //並び順
    aaaa.next = &iiii;
    iiii.next = NULL;
    
    showStatus(aaaa);
    
    return 0;
}

 前回までのプログラムと同じ結果になることを確認して下さい。

 再帰的な関数の呼び出しもあるなど、少々難しいサンプルプログラムかもしれません。ここで、自己参照について解説しますと、簡単に言えば、構造体の要素として、次のキャラの情報が格納されているアドレスを持つポインタを宣言します。上記の例でいえば、「struct person *next;」が、それにあたります。nextのポインタにアドレスが入っていれば、そのキャラの後ろに誰かいますし、空(NULL)であれば、そのキャラが一番後ろだということです。

 これの何が利点かといいますと、配列の場合は、配列内で入れ替えが発生するのに対し、自己参照の場合はポインタの中身のアドレスを書き換えれば済むことになります。例えば、

  • 名前:うううう
  • 職業:僧侶
  • レベル:40
  • HP:280
  • MP:220

 上記の仲間を加えたいとします。防御力等の面が戦士より劣るものの魔法使いより優れているので、隊列の真ん中に入れたいとします。その場合、戦士「ああああ」のnextポインタの中身は、僧侶「うううう」のアドレスになり、僧侶「うううう」のnextポインタの中身は、魔法使い「いいいい」のアドレスになります(「いいいい」のnextポインタは書き換える必要はなく、NULLのままです)。配列と自己参照のどちらが良いかという点に大きな点はありませんので、個人的にやりやすい方で行えば良いかと思います。

■スポンサーリンク

このページの先頭へ