第16章 構造体 16.1 構造体の定義と構造体変数 16.2 構造体の配列
今日のポイント 構造体の定義と宣言のしかた タグとは何か、メンバーとは何か 構造体変数の宣言と理解 メンバーの理解と使い方 構造体配列とその使い方
16.1 構造体の定義 point タグ名 メンバーの宣言 struct point { double x; double y; }; 16.1 構造体の定義 タグ名 メンバーの宣言 struct point { double x; double y; }; 左の表記で構造体の構成を決めている. この例では、2つのdouble型をパックした詰め合わせセットを定義した. 「2つのdouble型から成る構造体に point という名前のブランドタグをつけよう」 という感じ セミコロンを 忘れないこと! x 座標 y 座標 point 構造体=ユーザーが定義した(複合的な)オリジナルの型 =詰め合わせセットを独自ブランドとして登録したもの
point というタグがついた構造体を2つ用意 16.1 構造体の定義と構造体変数 プログラム例 16.1.1 2点の中点の座標を求めるプログラム #include <stdio.h> struct point { double x; double y; }; int main(void) { 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; } 「point というタグがついた構造体は 2つの実数から構成される」という意味 point というタグがついた構造体を2つ用意 各構造体の中のメンバーに それぞれ異なる値を代入 中身を取り出して加工
正誤表(改訂前の教科書用) 教科書 pp.152〜153 の説明に間違った表現があるので注意 訂正のサイト http://www.info.kindai.ac.jp/C-Book/Correction.html p.152, 下から3行目 誤: 構造体中の各変数 p1, p2 は,メンバー(member)と呼ばれ… 正: 構造体中の各変数 x, y は,メンバー(member)と呼ばれ… 誤: メンバー変数 正: メンバー p.153, 1行目から2行目まで 誤: …のようにタグとメンバー変数名とで指定する.タグとメンバー変数名の間にはメンバー演算子(member operator)(.) を付ける.他の演算子 と違って,タグ,メンバー演算子,変数の間には… 正: …のように構造体変数名 (structure variable name) とメンバーとで指定する.構造体変数名とメンバーの間にはメンバー演算子 (member operator)(.)を付ける.他の演算子と違って,構造体変数名,メンバー演算子,メンバーの間には…
16.1 構造体を新しい型として定義 プログラム例 16.1.1 改 2点の中点の座標を求めるプログラム 16.1 構造体を新しい型として定義 プログラム例 16.1.1 改 2点の中点の座標を求めるプログラム #include <stdio.h> struct point { double x; double y; }; typedef struct point double_double; int main(void) { double_double 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; } ex16_1_1a.c タグを使わずに定義する方法 typedef struct { double x; double y; } double_double; struct point を新しい型 double_double として定義 p.152 の下から10行目~4行目
16.1 構造体の代入 構造体のメンバーの値をすべてコピーするには代入演算子"="が使える p.154 の下から10行目~3行目 16.1 構造体の代入 p.154 の下から10行目~3行目 構造体のメンバーの値をすべてコピーするには代入演算子"="が使える #include <stdio.h> 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; } ex16_1_1b.c
16.1 構造体の定義 grade タグ名 メンバーの宣言 struct grade { char name[15]; 16.1 構造体の定義 タグ名 メンバーの宣言 struct grade { char name[15]; int subject1; int subject2; int subject3; double average; }; 左の表記で構造体の構成を決めている. この例では、文字列と3つの整数と1つの実数からなる詰め合わせセットを作った. 氏 名 科目1の点数 科目2の点数 科目3の点数 平均点 grade 「こういう構成から成る構造体に grade という名前のブランドタグをつけよう」 という感じ セミコロンを 忘れないこと! ユーザーが定義したオリジナルの型 =独自ブランドとして登録
構造体変数 student の宣言と初期値代入 16.1 構造体の定義と構造体変数 プログラム例 16.1.3 3科目の平均点を出力するプログラム #include <stdio.h> struct grade { char name[15]; int subject1; int subject2; int subject3; double average; }; 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; } 「grade というタグがついた構造体は、この 5つのメンバーから構成される」という意味 構造体宣言部 「Smith は grade というタグのついた構造体で、初期値は{ … }」という意味 構造体変数 student の宣言と初期値代入 平均点計算
16.1 構造体の定義と構造体変数 プログラム例 16.1.3 の一部 構造体変数名.メンバー 例: Smith.name 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 構造体の配列 世の中で扱われるデータの例: 成績データ 16.2 構造体の配列 世の中で扱われるデータの例: 成績データ 氏名と科目1、科目2、科目3の点数と平均点を1セットのデータとして扱いたい. → 「構造体」というデータ構造で表現 → データ全体は「構造体の配列」
16.2 構造体の配列 プログラム例 16.2.1 のサブセット 3人各々について3科目の 平均点を出力するプログラム 16.2 構造体の配列 3人各々について3科目の 平均点を出力するプログラム プログラム例 16.2.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, 0}, {"Ken Ohta", 65, 85, 75, 0}, {"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; 各人の平均点計算と表示を for ループで3人分回す
スキルアップタイム1 以下の4名の成績データについて、* のセルを埋めるプログラムを作れ(プログラム例 16.2.1 のサブセット を参考にする).
スキルアップタイム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 (教科書)の後半を参考にする).
スキルアップタイム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 を やってみよう. "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;