目的
構造体について理解し、使用できるようになること。
構造体とは
配列は同じ型のデータを複数個まとめて扱うための方法でした。
構造体を使うと、違う型のデータをまとめて、1つの型として扱うことができます。
構造体の例
たとえば、学生のデータを扱うことを考えてみます。
学生のデータと言っても様々ですが、今回は名前と年齢と学籍番号を扱うことにします。
今までのやり方では、以下のようにそれぞれ別々に確保していました。
char name[256]; // 名前
int age; // 年齢
int id; // 学籍番号
これをまとめて、1つの型として扱おうというのが構造体です。
構造体を使うと、次のように書くことができます。
Student s; // 学生型を宣言
このとき、Student という型は、以下のように構造体を使って定義します。
typedef struct {
char name[256];
int age;
int id;
} Student;
構造体を使わなくてもプログラムは作れます。
しかし、構造体を使うことで、プログラムを綺麗に分かりやすく書くことができます。
構造体の定義
構造体を使うには、構造体を定義する必要があります。
構造体を定義するには、次の2種類の方法があります。
- 形式1
struct 構造体名 { 型 変数名; ... };
- 形式2
typedef struct { 型 変数名; ... } 構造体の別名;
構造体の定義は、どのような変数を含むかを定義しているだけで、そこに変数が存在するわけではありません。
実際に使うには、構造体の型で変数宣言をし、変数として生成しなくてはいけません。
それぞれ、プログラムでは次のように変数宣言をします。
struct 構造体名 a; // 形式1
構造体の別名 b; // 形式2
構造体は、一般的にグローバル (関数の外側) で宣言します。
形式2は、形式1に別名を与えて、形式1より短く記述できるようにした形式です。
どちらを利用するかは好みで構いません。
変数を宣言する形式が異なるだけで、利用方法は異なりません。
なお、このページでは形式2を利用して記述していきます。
ここで、typedef 文 は型に別名をつける働きをしています。
typedef 文についての詳細な解説は、ここでは省略します。
構造体の使い方
次のように定義された構造体があるとします。
typedef struct {
int a, b;
} T;
上の構造体は、以下のように使用します。
T x; // 構造体 T の変数を宣言
x.a = 10; // x の a に代入
scanf("%d", &x.b); // x の b に入力
構造体を使う際は、上のように変数名と構造体のメンバ名をドット . で結びます。
また、構造体を以下のように配列として利用することもできます。
T x[10];
x[0].a = 27;
x[0].b = 18;
もちろん、関数に引数として渡すこともできます。
#include <stdio.h>
typedef struct {
int a, b;
} T;
void func(T x){
printf("%d %d\n", x.a, x.b); // 12 34
}
int main(){
T x;
x.a = 12;
x.b = 34;
func(x);
return 0;
}
課題
課題1
2次元座標が整数で2つ与えられます。
2点間の距離を求めなさい。
ただし、以下に指定される構造体と関数を定義して、使用しなさい。
次の座標を表す構造体を定義しなさい。
typedef struct {
int x, y;
} Point;
また、2点間の距離を求めるための、以下のプロトタイプ宣言で表される関数を定義しなさい。
double distance(Point a, Point b);
入力形式
2行に渡って、以下の形式で座標が入力されます。
x1 y1
x2 y2
出力形式
(x1, y1), (x2, y2) の距離を小数で表示しなさい。
実行例
./a.out 0 0 1 1 1.41
./a.out 6 2 -4 5 10.44
./a.out 0 0 0 0 0
課題2
選挙の当選者を判定するプログラムを作成しなさい。
入力として、当選人数、候補者の名前、得票数が入力されます。
当選人数と得票数に応じて当選者を決め、一覧を出力してください。
候補者の名前は、ローマ字 20 字以内であり、人数は最大でも 10 人です。
当選人数は、1 以上の整数、得票数は 0 以上の整数です。
得票数の重複はないと仮定してよい。
また、候補者の名前と得票数を最低限含む構造体を定義し、使用しなさい。
構造体の名前や、メンバ名は特に定めないものとする。
入力形式
1行目に、候補者の人数 n と、当選者数 m が与えられます。
2行目 ~ (n + 1) 行目に、候補者の名前 name と得票数 num が空白区切りで与えられます。
n m name1 num1 name2 num2 ...
出力形式
入力された順に、候補者を出力しなさい。
また、当選した候補者の一番右には「当選」と出力しなさい。
見やすくするために、出力の前に、1つ改行を出力すること。
name1 num1 name2 num2 当選 ...
実行例
./a.out 2 1 Yamagiwa 972652 Mendori 827462
Yamagiwa 972652 当選 Mendori 827462
./a.out 5 2 Iwata 428978 Sakamoto 572965 Shimizu 876294 Takata 624915 Shinomori 877264
Iwata 428978 Sakamoto 572965 Shimizu 876294 当選 Takata 624915 Shinomori 877264 当選
./a.out 1 1 Fukumoto 0
Fukumoto 0 当選
補足
実行例の名前はフィクションです。