Page 15 構造体

構造体とは

これまで、int、double、charなど、数字/文字の変数を扱ってきました。

構造体はこれらの変数型を組み合わせて作る、ユーザ定義型です。

例えば、RPGをつくるとして、主人公キャラの名前と各パラメータをまとめて扱えると便利です。

char Name[30];
int LV;
int HP;
int MP;
int Str;
int Def;

このままだとバラバラですが、構造体を使用すると、この情報をひとまとめにできます。

struct 構造体名{

        構造体の中身

};

{}で囲まれた部分が構造体の中身になります。実際に使うと下のようになります。

struct Character{
        char Name[30];
        int LV;
        int HP;
        int MP;
        int Str;
        int Def;
};

これで構造体Characterができました。

ここまででやったことは型の定義だけなので、実体を作成しないと使えません。

struct Character MyCharacter;

MyCharacterが構造体の実体になります。

構造体の中身にアクセスするには「構造体名.要素名」でアクセスします。「主人公が5のダメージを受けた」ですと、「MyCharacter.HP -= 5;」でOKです。

/* 主人公のパラメータを設定し、出力するプログラム */
#include <stdio.h>

int main(int argc, char* argv[]){
        /* 構造体定義 */        
        struct Character{
                char Name[30];
                int LV;
                int HP;
                int MP;
                int Str;
                int Def;
        };
        struct Character MyCharacter;
        
        /* パラメータのセット */
        snprintf(MyCharacter.Name, 30, "Taro");
        MyCharacter.LV = 1;
        MyCharacter.HP = 100;
        MyCharacter.MP = 50;
        MyCharacter.Str = 20;
        MyCharacter.Def = 10;

        /* パラメータの表示 */
        printf("%s\n",MyCharacter.Name);
        printf("LV:  %d\n",MyCharacter.LV);
        printf("HP:  %d\n",MyCharacter.HP);
        printf("MP:  %d\n",MyCharacter.MP);
        printf("STR: %d\n",MyCharacter.Str);
        printf("DEF: %d\n",MyCharacter.Def);

        return 0;
}

構造体配列

構造体も配列にできます。下のようにすれば4人パーティのできあがりです。

struct Character MyCharacter[4];

メンバに対するアクセスは、配列の番号の指定が増えるだけです。

MyCharacter[0].LV = 1;
MyCharacter[1].LV = 5;
MyCharacter[3].HP = 100;
などなど

構造体へのポインタ

構造体もポインタが使えます。使い方も通常の変数とほぼ変わりません。

struct Character MyCharacter[4];
struct Character *CharPointer;
CharPointer = &MyCharacter[0];

CharPointerがMyCharacter[0]のアドレスなので、CharPointer+1はMyCharacter[1]のアドレスとなります。この辺は通常の変数と変わりありません。ただし、構造体のメンバにアクセスする場合は、少し注意が必要です。ポインタが示しているのはMyCharacter[0]のアドレスなので、

CharPointer == &MyCharacter[0]
*CharPointer == MyCharacter[0]
(*CharPointer).LV == MyCharacter[0].LV

と、ポインタの位置がわかりづらく、間違えやすくなります。さらに、構造体のなかに構造体があり、それがポインタで結び付いているという状態になると、ポインタの位置がより一層難しくなります。そのため、構造体のポインタを使った構造体メンバにアクセスする方法として、よりシンプルな「->」が使われます。アロー演算子とか呼ばれます。

CharPointer->LV == (*CharPointer).LV == MyCharacter[0].LV

MyCharacter[1].LVにアクセスするには(CharPointer + 1)->LVにアクセスすればよく、構造体へのポインタが簡単に活用できます。

/* 主人公のパラメータを設定し、出力するプログラム その2 */
#include <stdio.h>

int main(int argc, char* argv[]){
        /* 構造体定義 */        
        struct Character{
                char Name[30];
                int LV;
                int HP;
                int MP;
                int Str;
                int Def;
        };
        struct Character MyCharacter;
        struct Character *p;
        p = &MyCharacter;
        /* パラメータのセット */
        snprintf(p->Name, 30, "Taro");
        p->LV = 1;
        p->HP = 100;
        p->MP = 50;
        p->Str = 20;
        p->Def = 10;

        /* パラメータの表示 */
        printf("%s\n",p->Name);
        printf("LV:  %d\n",p->LV);
        printf("HP:  %d\n",p->HP);
        printf("MP:  %d\n",p->MP);
        printf("STR: %d\n",p->Str);
        printf("DEF: %d\n",p->Def);

        return 0;
}

戻る