第12回:構造体 (6/27)


第11回演習:解答例


先週の課題3をもう一度

氏名と点数がデータとして与えられたとき,各人の名前と平均点を表示する方法を考えよという問題であった。

出席番号 名前  語学   力学 平均点
1 佐藤 65 71
2 鈴木 84 83
3 高橋 74 74
4 田中 90 90
5 渡辺 87 78
6 伊藤 93 95

これまで習った配列では,同じ型のデータをまとめて扱えたが,この問題のように文字列型と整数型があると,一つの文字列では扱えない。

今日の演習で学ぶ「構造体」は,このように 異なる型のデータをまとめて一つの変数として扱うための手法である。 構造体は,新しい変数の「型」を自分で作り出す役割をする。


構造体の使い方

(1)既存の変数を組み合わせて,int や float にあたる新しい型を定義する。

(2)定義した型を利用する変数を定義して利用する。

という,二つの段階が必要になる。


構造体の定義

構造体を利用するには,まず既存の変数を組み合わせて,新しい「型」の構造体を定義する。


#include <stdio.h>

struct seiseki {
    char simei[25];
    int ten_1;
    int ten_2;
};

void main()
{
    ....
}

構造体の定義部分(赤色の箇所)記述は,関数の内側にも外側にも記述することができる。
関数の中で宣言すれば,その関数内のみで有効になる。(ローカル変数と同じ)
以降,何度も登場する struct というキーワードは,「構造体」という意味である。
構造体の中身の変数(ここではsimeiten_1など)の要素一つ一つのことを,構造体のメンバと呼ぶ。

これで,新しい変数の「型」であるseiseki型が定義できた。


定義した構造体型の変数を定義し利用する

(1)まず,定義した構造体型の変数を宣言する。


struct seiseki list2012;    /*  新しく定義した seiseki 型の変数,list2012  */

上で定義したseiseki型が構造体であることを示すために,structキーワードを必ず記する。 これで,成績データを格納する変数 list2012 が,使えるようになる。

(2)次に,構造体のメンバに値を代入する方法と,値を参照する方法をマスターしよう。

(2-a)代入する方法。

基本的には,構造体変数名.メンバ変数名 のように,構造体変数の名前と,メンバの変数の名前を .(ピリオド,ドット)で結ぶ。
変数の名前がlist2012で,メンバ名がsimei, ten_1, ...なので,


strcpy(list2012.simei, "メイジ");    /*  文字列の代入.下の注を参照!  */
 
list2012.ten_1 = 90;
list2012.ten_2 = 80;

また,変数の定義と同時に初期化するときは,配列の場合と同様に


struct seiseki list2012 = {"メイジ", 90, 80};

と,書くこともできる。

(2-b)次に,構造体変数の各メンバの参照。


printf("氏名 = %s 点数1 = %d ¥n", list2012.simei, list2012.ten_1);

とすることで,値を取り出すことができる.


注:文字列の代入

文字列は,文字型の「配列」なので,


char name[25];
name = "meiji"

これは,エラーになる。では,どうやって文字列に代入するかというと,


 
char name[20];
name[0] = 'm';
name[1] = 'e';
....

が,正しい手順であるが,文字数が増えると大変である。そこで,C言語では文字列の代入をする関数が用意されている。


#include <stdio.h>
#include <string.h>   /*  文字列操作関数用のヘッダファイル  */
 
void main()
{
    char name[20];
    strcpy(name, "meiji");   /*  string copy関数.  */
}
 


構造体の配列

成績リストの例では,構造体1つに1人分の名前・成績データなどを格納できた。これを用いて,全員分の名前や点数を一つの変数に保存するために,構造体を配列にすればよさそうである。 構造体変数も,通常の変数同様,配列を宣言することができる。


struct seiseki list2012[100];

この例では,struct seiseki 型の変数を100人分,配列名を list2012にする,という意味である。

構造体の配列の各要素の,メンバへの代入は,例えば配列の先頭の構造体へは


strcpy(list2012[0].simei, "メイジ");    /*  文字列の代入.  */
 
list2012[0].ten_1 = 90;
list2012[0].ten_2 = 80;

とすることができる。配列の添え字用 [ ] と,構造体用のピリオド「.」の順序に注意!
普通の配列同様,添え字を変化させることにより,構造体の配列すべてのメンバを操作することができる。

配列の宣言と同時に,初期化する場合に限り,


struct seiseki list2012[] = {
{"イクタ",10,20},
{"スルガダイ",5,10},
};
 

という記述が可能である。


構造体を関数へ渡す(値参照)

関数に変数を渡すには,値参照とアドレス参照とがあるが,まずは値参照を使ってみる。


#include <stdio.h>
 
struct seiseki {
    char simei[25];
    int ten_1;
    int ten_2;
};
 
/*  構造体のメンバをすべて表示する関数  */
 
void disp_all(struct seiseki list)
{
    printf("氏名=%s¥n", list.simei);
    printf("点数1=%d¥n", list.ten_1);
    printf("点数2=%d¥n", list.ten_2);
}
 
void main()
{
    struct seiseki list2012 = {"メイジ", 90, 80};
    disp_all(list2012);      /*  関数に構造体を渡す  */
}
 
構造体であることを示す struct を記述すること以外は,通常の値参照による関数呼び出しと同じです。

演習課題

課題1 次に示す生徒の情報を構造体として定義・作成し,各内容を画面に表示するプログラムを作成しなさい。

番号 氏名 点数 成績
1 小林 82 A

課題2 次に示す複数の生徒の情報を構造体の配列として作成し,順番に画面に表示するプログラムを作成しなさい。

番号 氏名 点数 成績
1 石山 82 A
2 松村 48 F
3 中島 98 S

課題3 前回の課題3を構造体を用いて書き直しなさい。

課題4 前回の課題4を構造体を用いて書き直しなさい。