★構造体(基礎2)★


とりあえず構造体に慣れてもらうことから始めましょう。

まずは次の構造体を作ってみてください。

 タグ名   Card

 メンバ変数 int型でnumberとsuit

 実体名   card

宣言を書いて、main関数で実体を作りましょう。









































解答例です。


<sample program 101-01>

#include <stdio.h>

struct Card
{
    int number;
    int suit;
};

int main(void)
{
    struct Card card;

    return 0;
}

ここから、値を代入して単純に中身を表示するプログラムにしてみます。

numberを1に、suitを2に設定し表示します。

<sample program 101-02>

#include <stdio.h>

struct Card
{
    int number;
    int suit;
};

int main(void)
{
    struct Card card;

    card.number = 1;

    card.suit = 2;

    printf("number = %d\n", card.number);

    printf("suit = %d\n", card.suit);

    return 0;
}

<実行結果>

number = 1
suit = 2
続行するには何かキーを押してください・・・

変数や配列の場合、実体の作成時に初期値が代入できました。

<変数>

int a = 3;

<一次元配列>

int a[2] = { 1, 2 };

<二次元配列>

int a[3][2] = {
    { 1, 2 },
    { 3, 4 },
    { 5, 6 },
};

構造体も同じように初期値を代入できます。


<sample program 101-03>

#include <stdio.h>

struct Card
{
    int number;
    int suit;
};

int main(void)
{
    struct Card card = { 1, 2 };

    printf("number = %d\n", card.number);

    printf("suit = %d\n", card.suit);

    return 0;
}

<実行結果>

number = 1
suit = 2
続行するには何かキーを押してください・・・

宣言時に書いたメンバ変数の順番に数値を入れておけば良いです。


さて、この構造体はカード1枚分のデータを入れることが出来ます。

このカードが52枚あればトランプのデッキが作れそうです。

そこで、Card構造体を配列にしてみます。

初期値や表示も変更しなければならないので、まずは実体を作るところまで書きましょう。

トランプの枚数52は#defineで定義したいところですが、コラム「#defineの罠」で書いたように定義してみましょう。


<sample program 101-04>

#include <stdio.h>

#define NUMBER 13
#define SUIT 4
#define CARD (NUMBER * SUIT)

struct Card
{
    int number;
    int suit;
};

int main(void)
{
    struct Card deck[CARD];

    return 0;
}

一種類のスートにつき1から13までの数がありますから52枚としています。

deckは配列ですから、メンバ変数にアクセスするには、

 deck[0].number

 deck[5].suit

などと指定します。


さて、初期値を代入してカードのデッキを作ってみましょう。

numberには1から13をsuitには0から3を入れることにします。

  <suit>
 0 スペード
 1 ハート
 2 ダイヤ
 3 クラブ

上でやったような初期値の代入は厳しそうですね。

一応、実体の作成と同時に初期値を入れる方法を書いておきますが、あまり良くない方法だと思います。


<sample program 101-05>

#include <stdio.h>

#define NUMBER 13
#define SUIT 4
#define CARD (NUMBER * SUIT)

struct Card
{
    int number;
    int suit;
};

int main(void)
{
    struct Card deck[CARD] = {
        {  1, 0 },
        {  2, 0 },
        {  3, 0 },
        {  4, 0 },
        {  5, 0 },
        {  6, 0 },
        {  7, 0 },
        {  8, 0 },
        {  9, 0 },
        { 10, 0 },
        { 11, 0 },
        { 12, 0 },
        { 13, 0 },
        {  1, 1 },
        {  2, 1 },
        {  3, 1 },
        {  4, 1 },
        {  5, 1 },
        {  6, 1 },
        {  7, 1 },
        {  8, 1 },
        {  9, 1 },
        { 10, 1 },
        { 11, 1 },
        { 12, 1 },
        { 13, 1 },
        {  1, 2 },
        {  2, 2 },
        {  3, 2 },
        {  4, 2 },
        {  5, 2 },
        {  6, 2 },
        {  7, 2 },
        {  8, 2 },
        {  9, 2 },
        { 10, 2 },
        { 11, 2 },
        { 12, 2 },
        { 13, 2 },
        {  1, 3 },
        {  2, 3 },
        {  3, 3 },
        {  4, 3 },
        {  5, 3 },
        {  6, 3 },
        {  7, 3 },
        {  8, 3 },
        {  9, 3 },
        { 10, 3 },
        { 11, 3 },
        { 12, 3 },
        { 13, 3 },
    };

    return 0;
}

二次元配列の初期化と似ています。

ただ、こんな風に書きたくは無いですよね。

よく見ると一定の法則で数字が並んでいますので、プログラムを使ってスマートに設定したいところです。

分かった方は自分で作ってみてください。


まずは簡単そうなスートの方を考えてみましょう。

52枚のトランプを順番にみると、最初の13枚は0、次の13枚は1という具合に13ごとに1増えています。

方法は色々ありますが、52枚のカードの設定をするため、52回繰り返すプログラムを追加してみます。


<sample program 101-06>

#include <stdio.h>

#define NUMBER 13
#define SUIT 4
#define CARD (NUMBER * SUIT)

struct Card
{
    int number;
    int suit;
};

int main(void)
{
    struct Card deck[CARD];

    int i;

    for (i = 0; i < CARD; i++) {

    }

    return 0;
}

変数iが0から51まで変化しますので、それを利用してスートを初期化します。

対応させなければならない数値は以下のようになります。

※法則を見て、式を考えるという癖を身につけてください。

i  suit
0   0
1   0
2   0
3   0
4   0
5   0
6   0
7   0
8   0
9   0
10   0
11   0
12   0
13   1
14   1
15   1
16   1
17   1
18   1
19   1
20   1
21   1
22   1
23   1
24   1
25   1
26   2
27   2
28   2
29   2
30   2
31   2
32   2
33   2
34   2
35   2
36   2
37   2
38   2
39   3
40   3
41   3
42   3
43   3
44   3
45   3
46   3
47   3
48   3
49   3
50   3
51   3


iの値が、

  0〜12までの場合 suitは0
  13〜25までの場合 suitは1
  26〜38までの場合 suitは2
  39〜51までの場合 suitは3

さて、どういった式を作ればiの値からsuitが導き出せるでしょうか?

考えてください。









































解答例です。


 i / 13 (小数点以下切り捨て)

i
0 / 13 = 0.000
1 / 13 = 0.077
2 / 13 = 0.154
3 / 13 = 0.231
4 / 13 = 0.308
5 / 13 = 0.385
6 / 13 = 0.462
7 / 13 = 0.538
8 / 13 = 0.615
9 / 13 = 0.692
10 / 13 = 0.769
11 / 13 = 0.846
12 / 13 = 0.923
13 / 13 = 1.000
14 / 13 = 1.077
15 / 13 = 1.154
16 / 13 = 1.231
17 / 13 = 1.308
18 / 13 = 1.385
19 / 13 = 1.462
20 / 13 = 1.538
21 / 13 = 1.615
22 / 13 = 1.692
23 / 13 = 1.769
24 / 13 = 1.846
25 / 13 = 1.923
26 / 13 = 2.000
27 / 13 = 2.077
28 / 13 = 2.154
29 / 13 = 2.231
30 / 13 = 2.308
31 / 13 = 2.385
32 / 13 = 2.462
33 / 13 = 2.538
34 / 13 = 2.615
35 / 13 = 2.692
36 / 13 = 2.769
37 / 13 = 2.846
38 / 13 = 2.923
39 / 13 = 3.000
40 / 13 = 3.077
41 / 13 = 3.154
42 / 13 = 3.231
43 / 13 = 3.308
44 / 13 = 3.385
45 / 13 = 3.462
46 / 13 = 3.538
47 / 13 = 3.615
48 / 13 = 3.692
49 / 13 = 3.769
50 / 13 = 3.846
51 / 13 = 3.923

何度も説明していますが、int型の割り算は小数点以下切り捨てです。

整数部分だけを見ると、ちゃんとスートの数字になっています。


それでは、この式を使ってスートの初期値設定をしましょう。

13は#defineでNUMBERと定義されていますよね。


<sample program 101-07>

#include <stdio.h>

#define NUMBER 13
#define SUIT 4
#define CARD (NUMBER * SUIT)

struct Card
{
    int number;
    int suit;
};

int main(void)
{
    struct Card deck[CARD];

    int i;

    for (i = 0; i < CARD; i++) {

        deck[i].suit = i / NUMBER;
    }

    return 0;
}

最後にnumberの設定をします。

分かった方は早速作ってください。


numberも同じループの中で設定します。

変数iと必要な数字の組み合わせは以下の通りです。

i  number
0   1
1   2
2   3
3   4
4   5
5   6
6   7
7   8
8   9
9   10
10   11
11   12
12   13
13   1
14   2
15   3
16   4
17   5
18   6
19   7
20   8
21   9
22   10
23   11
24   12
25   13
26   1
27   2
28   3
29   4
30   5
31   6
32   7
33   8
34   9
35   10
36   11
37   12
38   13
39   1
40   2
41   3
42   4
43   5
44   6
45   7
46   8
47   9
48   10
49   11
50   12
51   13


iの値が、

  0、13、26、39の場合 numberは1
  1、14、27、40の場合 numberは2
  2、15、28、41の場合 numberは3
  ・
  ・
  ・
  12、25、38、51の場合 numberは13

さて、どういった式を作ればiの値からnumberが導き出せるでしょうか?

考えてください。









































解答例です。


 i % 13 + 1

i
0 % 13 = 0 + 1 = 1
1 % 13 = 1 + 1 = 2
2 % 13 = 2 + 1 = 3
3 % 13 = 3 + 1 = 4
4 % 13 = 4 + 1 = 5
5 % 13 = 5 + 1 = 6
6 % 13 = 6 + 1 = 7
7 % 13 = 7 + 1 = 8
8 % 13 = 8 + 1 = 9
9 % 13 = 9 + 1 = 10
10 % 13 = 10 + 1 = 11
11 % 13 = 11 + 1 = 12
12 % 13 = 12 + 1 = 13

13 % 13 = 0 + 1 = 1
14 % 13 = 1 + 1 = 2
15 % 13 = 2 + 1 = 3
16 % 13 = 3 + 1 = 4
17 % 13 = 4 + 1 = 5
18 % 13 = 5 + 1 = 6
19 % 13 = 6 + 1 = 7
20 % 13 = 7 + 1 = 8
21 % 13 = 8 + 1 = 9
22 % 13 = 9 + 1 = 10
23 % 13 = 10 + 1 = 11
24 % 13 = 11 + 1 = 12
25 % 13 = 12 + 1 = 13

26 % 13 = 0 + 1 = 1
27 % 13 = 1 + 1 = 2
28 % 13 = 2 + 1 = 3
29 % 13 = 3 + 1 = 4
30 % 13 = 4 + 1 = 5
31 % 13 = 5 + 1 = 6
32 % 13 = 6 + 1 = 7
33 % 13 = 7 + 1 = 8
34 % 13 = 8 + 1 = 9
35 % 13 = 9 + 1 = 10
36 % 13 = 10 + 1 = 11
37 % 13 = 11 + 1 = 12
38 % 13 = 12 + 1 = 13

39 % 13 = 0 + 1 = 1
40 % 13 = 1 + 1 = 2
41 % 13 = 2 + 1 = 3
42 % 13 = 3 + 1 = 4
43 % 13 = 4 + 1 = 5
44 % 13 = 5 + 1 = 6
45 % 13 = 6 + 1 = 7
46 % 13 = 7 + 1 = 8
47 % 13 = 8 + 1 = 9
48 % 13 = 9 + 1 = 10
49 % 13 = 10 + 1 = 11
50 % 13 = 11 + 1 = 12
51 % 13 = 12 + 1 = 13

13で割った余りは0〜12ですから、それに1を加えることで1〜13になります。


では、numberの設定をしましょう。


<sample program 101-08>

#include <stdio.h>

#define NUMBER 13
#define SUIT 4
#define CARD (NUMBER * SUIT)

struct Card
{
    int number;
    int suit;
};

int main(void)
{
    struct Card deck[CARD];

    int i;

    for (i = 0; i < CARD; i++) {

        deck[i].suit = i / NUMBER;

        deck[i].number = i % NUMBER + 1;
    }

    return 0;
}

トランプの初期値を設定するプログラムを題材にしてみましたが、後々トランプのゲームも作ってみましょう。


次へ

戻る

目次へ