1. 構造体配列のポインタ表現
構造体配列をポインタで扱う手順は、一般の配列をポインタで扱う場合と全く同じです。ポインタの使用手順を忘れてしまった人は「10-2.配列とポインタ」を確認してください。
ただし、構造体へのポインタを参照するためには、「構造体->メンバ名」のようにアロー演算子(->)を使う点に注意して下さい。
#include <stdio.h>
struct seiseki {
int no; // 番号
char name[20]; // 名前
double avg; // 平均点
};
int main(void)
{
struct seiseki seito[20] = {
{ 1, "SAKURAI", 78.6 },
{ 2, "NAGANO", 57.3 },
{ 3, "TAKESHITA", 66.4 },
};
/* ポインタの宣言:構造体でポインタを使うよと宣言する */
struct seiseki *sp;
/* ポインタの値設定:
ポインタに構造体の配列の先頭要素のアドレスを設定 */
sp = seito;
/* 相対的なポインタの参照:
ポインタの値を変えずに相対的にポインタ+i番目のデータを参照 */
for (int i = 0; i < 3; i++) {
printf("%d %s %.1f\n",
(sp+i)->no, (sp+i)->name, (sp+i)->avg);
}
/* 絶対的なポインタの参照:
ポインタの値を変え、絶対的にポインタでデータを参照 */
for (int i = 0; i < 3; i++) {
printf("%d %s %.1f\n",
sp->no, sp->name, sp->avg);
sp++;
}
return 0;
}
【実行結果例】
1 SAKURAI 78.6
2 NAGANO 57.3
3 TAKESHITA 66.4
1 SAKURAI 78.6
2 NAGANO 57.3
3 TAKESHITA 66.4
2. 入れ子の構造体の場合
入れ子の構造体をポインタを使って指定する場合は、一見「syomu->kyu->kihon」のようにアロー演算子を続けて用いそうですが、これは間違いです。 syomu のメンバである kyu はポインタではないのでアロー演算子ではなく、ドット演算子で結んでやらなければなりません。 ですから、「syomu->kyu.kihon」が正解となります。
15-2 で示した例をポインタを使って書きかえると下のようになります。
#include <stdio.h>
struct kyuuyo { // 給与
int kihon; // 基本給
int jyutaku; // 住宅手当
int kazoku; // 家族手当
int sikaku; // 資格手当
} kyu;
struct syain_dt { // 社員情報
int no; // 社員番号
char name[20]; // 氏名
char yaku[20]; // 役職
int nensu; // 勤続年数
struct kyuuyo kyu; // 給与
};
int main(void)
{
struct syain_dt syomu[20]= { // 庶務課
{78027, "神保直樹", "課長", 21, {446780, 50000, 30000, 20000}},
{84004, "相原彰子", "主任", 15, {363640, 50000, 20000, 20000}},
{87022, "本郷幸子", "", 12, {308760, 50000, 10000, 20000}},
{93042, "三上葵", "", 6, {286530, 30000, 0, 10000}},
{95005, "佐々木翠", "", 4, {276700, 0, 0, 20000}},
{99009, "長崎宏美", "", 1, {250140, 0, 0, 0}},
{0, "", "", 0, {0, 0, 0, 0} },
};
struct syain_dt *syomu_p = syomu;
for (int i = 0; syomu_p->no != 0; i++) {
printf("%-10s 総支給額 = %d\n",
syomu_p->name,
syomu_p->kyu.kihon + syomu_p->kyu.jyutaku +
syomu_p->kyu.kazoku + syomu_p->kyu.sikaku);
syomu_p++;
}
return 0;
}
【実行結果例】
神保直樹 総支給額 = 546780
相原彰子 総支給額 = 453640
本郷幸子 総支給額 = 388760
三上葵 総支給額 = 326530
佐々木翠 総支給額 = 296700
長崎宏美 総支給額 = 250140
〇 演習問題
問1
次に示す生徒情報を構造体として作成し、それぞれの科目の平均点を構造体のポインタを用いて求めなさい。繰り返し処理は生徒番号が0で終了する。
生徒番号 | 国語 | 数学 | 理科 | 社会 |
1001 | 85 | 74 | 63 | 90 |
1002 | 78 | 65 | 70 | 62 |
1003 | 89 | 92 | 88 | 76 |
1004 | 32 | 48 | 66 | 25 |
1005 | 92 | 76 | 81 | 98 |
-1 | 0 | 0 | 0 | 0 |
【実行結果例】
国語 平均 = 75.20
数学 平均 = 71.00
理科 平均 = 73.60
社会 平均 = 70.20
問2
次の仕様に従って、生徒の科目得点から合計点を求め、 出力フォームのように合計点順に画面表示するプログラムを作成しなさい。
- プログラムに組み込むデータについては、構造体の初期値として与え、メンバは、生徒番号、各科目点数、合計点で、次のとおりとすること。
生徒番号 国語 数学 理科 社会 合計点 1001 85 74 63 90 0 1002 78 65 70 62 0 1003 89 92 88 76 0 1004 32 48 66 25 0 1005 92 76 81 98 0 - 処理手順は、次のとおりとすること。
- 各人の4科目の合計点を求め、構造体に格納すること。
- 合計点の高い順に各人を並べ替えること。
- 結果を出力フォームに従って表示すること。
- 尚、上記の処理はポインタを用いて行うこと。
【実行結果例】 番号 国語 数学 理科 社会 合計 1005 92 76 81 98 347 1003 89 92 88 76 345 1001 85 74 63 90 312 1002 78 65 70 62 275 1004 32 48 66 25 171
解答例
// 問1
#include <stdio.h>
#define NINZU 5 // 学生の人数
#define KAMOKU 4 // 科目数
struct seiseki {
int no;
int kamoku[KAMOKU];
};
int main(void)
{
struct seiseki mycls[NINZU+1] = {
{1001, 85, 74, 63, 90},
{1002, 78, 65, 70, 62},
{1003, 89, 92, 88, 76},
{1004, 32, 48, 66, 25},
{1005, 92, 76, 81, 98},
{ -1, 0, 0, 0, 0} };
char *kname[] = {"国語", "数学", "理科", "社会"};
struct seiseki *my_p = mycls;
for (int j = 0; j < KAMOKU; j++) {
int i = 0;
double heikin = 0.0;
while((my_p + i)->no != -1) {
heikin = heikin + (my_p + i)->kamoku[j];
i++;
}
heikin = heikin / i;
printf("%s 平均 = %6.2f\n", kname[j], heikin);
}
return 0;
}
// 問2
#include <stdio.h>
#define NINZU 5 // 学生の人数
#define KAMOKU 4 // 科目数
struct seiseki { // 成績データ
int no; // 学生番号
int ten[KAMOKU]; // 点数
int goukei; // 合計点
};
int main(void)
{
struct seiseki mycls[NINZU] = {
{1001, 85, 74, 63, 90, 0},
{1002, 78, 65, 70, 62, 0},
{1003, 89, 92, 88, 76, 0},
{1004, 32, 48, 66, 25, 0},
{1005, 92, 76, 81, 98, 0},
};
struct seiseki wk;
struct seiseki *sp = mycls;
printf("番号 国語 数学 理科 社会 合計\n");
for (int i = 0; i < NINZU; i++) {
// 合計点を求める
for (int j = 0; j < KAMOKU; j++) {
(sp + i)->goukei = (sp + i)->goukei + (sp + i)->ten[j];
}
}
// 合計得点順に並べる
for (int i = 0; i < NINZU - 1; i++) {
for (int j = 0; j < NINZU - i - 1; j++) {
if((sp + j)->goukei < (sp + j + 1)->goukei) {
wk = *(sp + j);
*(sp + j) = *(sp + j + 1);
*(sp + j + 1) = wk;
}
}
}
// 結果の表示
for (int i = 0; i < NINZU; i++) {
printf("%4d ", (sp + i)->no);
for (int j = 0; j < KAMOKU; j++)
printf("%4d ", (sp + i)->ten[j]);
printf(" %4d\n", (sp + i)->goukei);
}
return 0;
}
コメント