第16章 構造体

第16章
構造体
16.1 構造体の定義と構造体変数
16.2 構造体の配列
今日のポイント

構造体の定義と宣言のしかた

タグとは何か、メンバーとは何か

構造体変数の宣言と理解

メンバーの理解と使い方

構造体配列とその使い方
Structures
16.1 構造体の定義
タグ名
struct point {
double x;
double y;
};
セミコロンを
忘れないこと!
メンバーの宣言
左の表記で構造体の構成を決めている.
この例では、2つのdouble型をパックした
詰め合わせセットを定義した.
x 座標
y 座標
「2つのdouble型から成る構造体に
point という名前のブランドタグを
つけよう」
…という感じ
構造体=ユーザーが定義した(複合的な)オリジナルの型
=詰め合わせセットを独自ブランドとして登録したもの
16.1 構造体の定義と構造体変数
プログラム例 16.1.1
2点の中点の座標を求めるプログラム
#include <stdio.h>
struct point {
「point というタグがついた構造体は
double x;
2つの実数から構成される」という意味
double y;
};
int main(void)
{
point というタグがついた構造体を2つ用意
struct point p1, p2;
double xm, ym;
各構造体の中のメンバーに
メンバーの指定
p1.x = 3.8; p1.y = 5.6;
それぞれ異なる値を代入
にはメンバー
p2.x = 8.4; p2.y = 18.2;
演算子(ピリオド)
xm = (p1.x + p2.x) / 2.;
中身を取り出して加工
を使用
ym = (p1.y + p2.y) / 2.;
printf("(%.2f, %.2f)と(%.2f,%.2f)の中点の座標は(%.2f, %.2f)\n",
p1.x, p1.y, p2.x, p2.y, xm, ym);
return 0;
}
正誤表(改訂前の教科書用)
訂正のサイト
http://www.info.kindai.ac.jp/C-Book/Correction.html
①
②
③
④
p.152, 下から3行目
誤: 構造体中の各変数 p1, p2 は,メンバー(member)と呼ばれ…
正: 構造体中の各変数 x, y は,メンバー(member)と呼ばれ…
p.152, 下から3行目
誤: メンバー変数
正: メンバー
p.153, 1行目から2行目まで
誤: …のようにタグとメンバー変数名とで指定する.タグとメンバー変数名の間にはメ
ンバー演算子(member operator)(.) を付ける.他の演算子 と違って,タグ,メン
バー演算子,変数の間には…
正: …のように構造体変数名 (structure variable name) とメンバーとで指定する.構
造体変数名とメンバーの間にはメンバー演算子 (member operator)(.)を付ける.
他の演算子と違って,構造体変数名,メンバー演算子,メンバーの間には…
p.153, プログラム例 16.1.2 の2行目
#include <string.h> を追加
新たに追加したい修正
教科書 p.152 の説明に間違った記述があるので注意
①
p.152, 下から7行目
誤: typedef point float_float
正: typedef struct point float_float
16.1 構造体を新しい型として定義
プログラム例 16.1.1 改
2点の中点の座標を求めるプログラム
#include <stdio.h>
ex16_1_1a.c
struct point {
タグを使わずに定義する方法
double x;
typedef struct {
double y;
double x;
};
double y;
typedef struct point double_double;
} double_double;
int main(void)
{
struct point を新しい型
double_double p1, p2;
double_double として定義
double xm, ym;
p1.x = 3.8; p1.y = 5.6;
p.152 の下から
p2.x = 8.4; p2.y = 18.2;
10行目~4行目
xm = (p1.x + p2.x) / 2.;
ym = (p1.y + p2.y) / 2.;
printf("(%.2f, %.2f)と(%.2f,%.2f)の中点の座標は(%.2f, %.2f)\n",
p1.x, p1.y, p2.x, p2.y, xm, ym);
return 0;
}
16.1 構造体の代入

p.154 の下から
10行目~3行目
構造体のメンバーの値をすべてコピーするには
代入演算子"="が使える
#include <stdio.h>
ex16_1_1b.c
struct point {
double x;
double y;
};
int main(void)
{
struct point p1, p2;
p1.x = 12.; p1.y = 18.;
p2 = p1;
printf("p1 = (%.2f, %.2f)\n", p1.x, p1.y);
printf("p2 = (%.2f, %.2f)\n", p2.x, p2.y);
return 0;
}
16.1 構造体の定義
タグ名
struct grade {
char name[15];
int subject1;
int subject2;
int subject3;
double average;
};
セミコロンを
忘れないこと!
メンバーの宣言
左の表記で構造体の構成を決めている.
この例では、文字列と3つの整数と1つの
実数からなる詰め合わせセットを作った.
氏 名
科目1の点数
科目2の点数
科目3の点数
平均点
「こういう構成から成る構造体に
grade という名前のブランド
タグをつけよう」
という感じ
ユーザーが定義したオリジナルの型
=独自ブランドとして登録
16.1 構造体の定義と構造体変数
プログラム例 16.1.3
3科目の平均点を出力するプログラム
#include <stdio.h>
「grade というタグがついた構造体は、この
struct grade {
5つのメンバーから構成される」という意味
char name[15];
int subject1;
構造体宣言部
int subject2;
「Smith は grade というタグのつ
int subject3;
いた構造体で、初期値は{ … }」と
double average;
};
いう意味
構造体変数 Smith の宣言と初期値代入
int main(void)
{
struct grade Smith = {"John Smith", 90, 80, 35, 0};
Smith.average = (Smith.subject1 + Smith.subject2
平均点計算
+ Smith.subject3) / 3.;
printf("name: %s¥n", Smith.name);
printf("科目1: %d 科目2: %d 科目3: %d¥n",
Smith.subject1, Smith.subject2, Smith.subject3);
printf("平均: %f¥n", Smith.average);
return 0;
}
16.1 構造体の定義と構造体変数
プログラム例 16.1.3 の一部
int main(void)
{
struct grade Smith = {"John Smith", 90, 80, 35, 0};
Smith.average = (Smith.subject1 + Smith.subject2
+ Smith.subject3) / 3.;
printf("name: %s¥n", Smith.name);
平均点の計算
printf("科目1: %d 科目2: %d 科目3: %d¥n",
Smith.subject1, Smith.subject2, Smith.subject3);
printf("平均: %f¥n", Smith.average);
return 0;
}
構造体の中のメンバーを指す時(アクセスする時)は
構造体変数名.メンバー
ピリオド(メンバー演算子)
例: Smith.name
16.2 構造体の配列
世の中で扱われるデータの例: 成績データ
氏 名
科目1
科目2
科目3
John Smith
90
70
50
Ken Ohta
65
85
75
Chen Bien
77
89
97
平均点
氏名と科目1、科目2、科目3の点数と平均点を
1セットのデータとして扱いたい.
→ 「構造体」というデータ構造で表現
→ データ全体は「構造体の配列」
16.2 構造体の配列
プログラム例 16.2.1 のサブセット
3人各々について3科目の
平均点を出力するプログラム
#include <stdio.h>
struct grade {
char name[15]; int subject1; int subject2; int subject3;
double average;
};
int main(void)
{
struct grade student[]
= {{"John Smith", 90, 70, 50, 0},
各人の平均点計算と表示を
{"Ken Ohta",
65, 85, 75, 0},
for ループで3人分回す
{"Chen Bien", 77, 89, 97, 0}};
int i, ndata = 3;
for (i = 0; i < ndata; i++) {
student[i].average = (student[i].subject1 + student[i].subject2
+ student[i].subject3) / 3.;
printf("name: %s¥n", student[i].name);
printf("科目1: %d 科目2: %d 科目3: %d¥n",
student[i].subject1, student[i].subject2, student[i].subject3);
printf("平均: %.2f¥n\n", student[i].average);
}
return 0;
}
スキルアップタイム1
以下の4名の成績データについて、* のセルを埋めるプログラム
を作れ(プログラム例 16.2.1 のサブセット を参考にする).
氏 名
科目1
科目2
科目3
科目4
平均点
John Smith
90
70
50
74
*
Ken Ohta
65
85
75
92
*
Chen Bien
77
89
97
50
*
Naomi Kanda
81
57
92
60
*
科目毎の平均点
総合平均点
スキルアップタイム1のヒント
#include <stdio.h>
struct grade {
char name[15];
int subject1; int subject2; int subject3; ??? ????????;
double average;
};
int main(void)
{
struct grade student[]
= {{"John Smith", 90, 70, 50, 74, 0},
...
{?????????????? ??? ??? ??? ??? ?}};
int i, ndata = ?;
for (i = 0; i < ndata; i++) {
student[i].average = (student[i].subject1 + student[i].subject2
+ student[i].subject3 + ???????????????????) / ??;
printf("name: %s¥n", student[i].name);
printf("科目1: %d 科目2: %d 科目3: %d ?????? ??¥n",
student[i].subject1, student[i].subject2,
student[i].subject3, ???????????????????);
printf("平均: %.2f¥n\n", student[i].average);
}
return 0;
}
スキルアップタイム2
以下の4名の成績データについて、* のセルを埋めるプログラム
を作れ(プログラム例 16.2.1 (教科書)の後半を参考にする).
氏 名
科目1
科目2
科目3
科目4
平均点
John Smith
90
70
50
74
71.0
Ken Ohta
65
85
75
92
79.3
Chen Bien
77
89
97
50
78.3
Naomi Kanda
81
57
92
60
72.5
科目毎の平均点
*
*
*
*
総合平均点
スキルアップタイム2のヒント
#include <stdio.h>
struct grade {
...
};
int main(void)
{
struct grade student[]
= {{"John Smith", 90, 70, 50, 74, 71.0},
...
{?????????????? ??? ??? ??? ??? ????}};
int i, ndata = ?;
int total1, total2, total3, total4;
double average1, average2, average3, average4;
total1 = total2 = total3 = total4 = 0;
for (i = 0; i < ndata; i++) {
total1 += student[i].subject1;
...
}
average1 = (double)total1 / ndata;
...
printf("各科目の平均点\n");
printf("科目1: %.2f 科目2: %.2f 科目3: %.2f ?????? ????¥n",
average1, average2, average3, ????????);
return 0;
}
スキルアップタイム3
スキルアップタイム2 までできた人は 演習問題16.1 を
やってみよう.
1.
2.
3.
4.
5.
"Author", "Title", "Pub", 1999, "0-11-111111-1", 1000, 20010101
"著者", "書名", "出版社", 2007, "4-9999-9999-9", 20000, 20070707
"Kernighan", "C", "Prentice", 1988, "0-13-110362-8", 3000, 20040506
"カーニハン", "言語C", "共立", 1989, "4-320-02692-6", 2800, 20030303
"熊谷", "C言語", "近代科学", 2001, "4-7649-0289-3", 2200, 20070401
スキルアップタイム3のヒント
#include <stdio.h>
struct database {
char author[80]; char title[80]; char publisher[80];
int year; char isbn[20]; int price; int date;
};
int main(void)
{
struct database textbook[5]
= {{"Author","Title","Pub", 1999,"0-11-111111-1", 1000, 20000101},
...
{"熊谷","C言語","近代科学", 2001,"4-7649-0289-3", 2200, 20070401}};
int i, ndata = ?, total = 0;
for (i = 0; i < ndata; i++) {
printf("著者: %s¥n", textbook[i].author);
printf("署名: %s\n", textbook[i].title);
...
printf("購入年月日: %d¥n\n", textbook[i].date);
total += textbook[i].price;
}
printf("total = %d\n", total);
return 0;
}