表紙 <戻 進> i-mobile

   異なる型の変数をまとめる   

  1. 第1項:まとめてデータを扱いたい場合
  2. 第2項:構造体の使い方
  3. 第3項:構造体変数自体の処理
  4. 第4項:構造体の簡潔な宣言

[1]まとめてデータを扱いたい場合


第13章では、同じ型の複数の変数をまとめて扱う配列を説明しました。
しかし、場合によっては、異なる型もまとめて扱いたい場合があります。
また、各要素を番号で区別するよりも、名前で区別した方が便利なこともあります。

例えば、学校で生徒の身体測定の結果を保存しておきたい場合には、
各生徒につき、クラス、学年、出席番号、名前、身長、体重、などのデータが必要です。
これを、素直に変数で用意した場合、次のようになります。


int year;	/* 学年 */
int clas;	/* クラス */
int number;	/* 出席番号 */
char name[64];	/* 名前 */
double stature;	/* 身長 */
double weight;	/* 体重 */

clas は class が正しいスペルなのですが、
C++では class が予約語になっているので、あえて clas にしています。
気に入らなければ group でも良いでしょう。
身長と体重は、小数第1位まで表現することが多いので、実数型にしています。

当然、これでも、生徒のデータとして十分機能します。
しかし、これらのデータは、全て関連したデータであるにもかかわらず、
1つ1つが別の変数として宣言されているため、あまりわかりやすくありません。

この様な場合に、複数の異なる型の変数を1つにまとめて取り扱う方法として、
構造体という機能が用意されています。


[  構造体  ]
複数の異なる型をまとめて作られた型のこと。
構造体では、複数の型をまとめた新しい型を作り出すことが出来ます。
例えば、生徒のデータを新しい型の構造体として作るには、次のようにします。

struct student {
	int year;	/* 学年 */
	int clas;	/* クラス */
	int number;	/* 出席番号 */
	char name[64];	/* 名前 */
	double stature;	/* 身長 */
	double weight;	/* 体重 */
};
構造体の型を宣言する時には、始めにstruct(ストラクト)をつけます。
その次には、変数と同じルールの元、新しく宣言する構造体の型名をつけます。
この型名を特に、構造体タグ名と呼ぶことがあります。

[  構造体タグ名  ]
作成した構造体それ自体の名前。
厳密には型名ではないので注意するように。
今回は、生徒と言う意味の、studentという名前をつけています。
後は、{}で囲んだ中に、まとめたい変数の型と名前を宣言していきます。

この様にして、新しい構造体の型を作ることが出来ますが、
これだけでは、単に型を宣言しただけなので、実際に使うことは出来ません。
実際に使うためには、構造体の型の変数を宣言する必要があります。
構造体の型の変数を宣言するには、次のようにします。


struct student data;
この例では、student構造体タグの、data構造体変数を宣言しています。
構造体タグの変数を宣言する場合、始めにstructをつけます。
次に、構造体の型名、最後に、構造体変数の名前を指定します。
今後、構造体の型を構造体タグ、構造体タグで宣言された変数を構造体変数と呼びます。

[  C++では  ]
C言語の拡張版であるC++では
structをつけなくても構造体変数を宣言出来ます。
現在のコンパイラはほとんどがC++用なので、
structをつけなくても宣言出来てしまいます。
この様にして、構造体タグと構造体変数を宣言することが出来ます。
次のプログラムは、構造体タグと構造体変数を宣言する例です。

struct student {
	int year;	/* 学年 */
	int clas;	/* クラス */
	int number;	/* 出席番号 */
	char name[64];	/* 名前 */
	double stature;	/* 身長 */
	double weight;	/* 体重 */
};

int main(void)
{
	struct student data;
	return 0;
}
この例のように、構造体タグは、関数よりも先に宣言するのが普通です。
何故なら、そうすれば、後に登場する全ての関数でこの構造体が使えるからです。

目次に戻る


[2]構造体の使い方

前項では、構造体タグと構造体変数の宣言について説明しましたが、
いくら宣言しても、実際に使ってみないことには意味がありません。

構造体変数は、元となった構造体タグで宣言されていた全ての型を持っています。
配列の時には、同じ型の変数を番号によって区別していましたが、
構造体変数では、型に関係なく、全ての要素を名前によって区別します。
構造体変数の持つ1つの要素にアクセスするには、次のようにします。


構造体変数名.要素名
ここで、. とは、小数点記号のことです。カンマではありません。
この様にして、個々の要素にアクセスすることが出来ます。
次のプログラムは、先ほどの構造体の、year要素を使う例です。

#include <stdio.h>

struct student {
	int year;	/* 学年 */
	int clas;	/* クラス */
	int number;	/* 出席番号 */
	char name[64];	/* 名前 */
	double stature;	/* 身長 */
	double weight;	/* 体重 */
};

int main(void)
{
	struct student data;
	
	data.year = 10;	/* year要素にアクセス */
	printf("%d\n",data.year);

	return 0;
}
このプログラムの実行結果は次の通りになります。

10
この例では、student構造体タグのdata構造体変数のyear要素を使っています。
この様にしてアクセスした場合、もはや普通の変数と全く同じです。
また、同様にして、配列にアクセスすることも出来ます。
次のプログラムは、先ほどの構造体の、name要素にアクセスする例です。

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

struct student {
	int year;	/* 学年 */
	int clas;	/* クラス */
	int number;	/* 出席番号 */
	char name[64];	/* 名前 */
	double stature;	/* 身長 */
	double weight;	/* 体重 */
};

int main(void)
{
	struct student data;
	
	strcpy(data.name,"MARIO");
	printf("%s\n",data.name);

	return 0;
}
このプログラムの実行結果は次の通りになります。

MARIO
もちろん、[]をつけて、配列の各要素にアクセスすることも可能です。

目次に戻る


[3]構造体変数自体の処理

前項では、構造体の各要素にアクセスする方法を説明しましたが、
これでは、見た目には確かにまとまっているようにも見えるものの、
実際の使い方は、普通の変数と全く同じで、あまり意味がないようにも思えます。

しかし、構造体の場合、構造体変数自体を変数として取り扱うことが出来ます。
例えば、構造体変数同士で、代入を行うことが可能となっています。
次のプログラムは、構造体変数同士で代入を行う例です。


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

struct student {
	int year;	/* 学年 */
	int clas;	/* クラス */
	int number;	/* 出席番号 */
	char name[64];	/* 名前 */
	double stature;	/* 身長 */
	double weight;	/* 体重 */
};

int main(void)
{
	struct student data1,data2;
	
	/* data1 へ代入 */
	data1.year = 3;
	data1.clas = 4;
	data1.number = 18;
	strcpy(data1.name,"MARIO");
	data1.stature = 168.2;
	data1.weight = 72.4;
	
	data2 = data1;	/* data1の内容をdata2へコピー */
	
	/* data1とdata2の内容を表示 */
	printf("data1.year = %d : data2.year = %d\n",data1.year,data2.year);
	printf("data1.clas = %d : data2.clas = %d\n",data1.clas,data2.clas);
	printf("data1.number = %d : data2.number = %d\n",data1.number,data2.number);
	printf("data1.name = %s : data2.name = %s\n",data1.name,data2.name);
	printf("data1.stature = %f : data2.stature = %f\n",data1.stature,data2.stature);
	printf("data1.weight = %f : data2.weight = %f\n",data1.weight,data2.weight);
	
	return 0;
}
このプログラムの実行結果は次の通りになります。

data1.year = 3 : data2.year = 3
data1.clas = 4 : data2.clas = 4
data1.number = 18 : data2.number = 18
data1.name = MARIO : data2.year = MARIO
data1.stature = 168.200000 : data2.stature = 168.200000
data1.weight = 72.400000 : data2.weight = 72.400000
このプログラムでは、まず、data1の各要素に代入を行っています。
そして、data2にdata1を代入しています。
その結果を表示してみると、data1とdata2の中身は同じになっています。

この様に、構造体変数では、全要素を一括して代入することが出来ます。
後で説明することですが、他にも、関数の引数として利用したりなど、
構造体変数はそれ自体を1つの変数として使うことが出来、
1つ1つ代入しなければならなかった配列よりも便利です。


[  構造体変数の比較  ]
構造体変数は、それ自体を1つの変数として使えると説明しましたが、
残念ながら、構造体変数同士での演算や比較は行えません。つまり、

	struct student data1,data2;
	/* data1とdata2に代入 */
	if (data1 == data2) {
		/* 何かの処理 */
	}
のようなプログラムは書けません。
今までは、構造体タグを宣言してから構造体を使用していました。
この場合、構造体を使う時は、必ずstructが必要になります。
しかし、構造体タグを、新しい型として1度に宣言してしまう方法があります。

C言語では、新しい型を宣言するtypedef(タイプデフ)が用意されています。
詳しい説明は後でしますが、次のようにtypedefを使うと新しい型を宣言出来ます。


typedef 新しい型の形 新しい型名
これを利用すると、構造体タグを直接新しい型に出来ます。
次のプログラムは、構造体タグを元に新しい型を作る例です。

struct student_tag {
	int year;	/* 学年 */
	int clas;	/* クラス */
	int number;	/* 出席番号 */
	char name[64];	/* 名前 */
	double stature;	/* 身長 */
	double weight;	/* 体重 */
};

typedef struct student_tag student;
この例では、student_tagタグを、student型にすることが出来ます。
こうすれば、構造体変数を宣言する時に、structが不要になります。
今後、先ほどの方法で宣言された型を、構造体型と呼ぶことにします。

しかし、その為にtypedefを使って型を定義するのは面倒です。
その場合、構造体タグと構造体型を1度に宣言してしまうことが出来ます。


typedef struct student_tag {
	int year;    /* 学年 */
	int clas;    /* クラス */
	int number;    /* 出席番号 */
	char name[64];  /* 名前 */
	double stature;  /* 身長 */
	double weight;  /* 体重 */
} student;
更に、この場合、新しい型を定義出来れば、構造体タグを省略できます。

typedef struct {
	int year;	/* 学年 */
	int clas;	/* クラス */
	int number;	/* 出席番号 */
	char name[64];	/* 名前 */
	double stature;	/* 身長 */
	double weight;	/* 体重 */
} student;
この方法が、1番簡潔に構造体型を宣言することが出来ます。

目次に戻る



<−前に戻る  先頭に戻る  次へ進む−>