構造体

Last-modified: 2022-04-19 (火) 12:02:14
 

目的

構造体について理解し、使用できるようになること。

構造体とは

配列は同じ型のデータを複数個まとめて扱うための方法でした。
構造体を使うと、違う型のデータをまとめて、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 当選

補足

実行例の名前はフィクションです。