プログラミング基礎覚え書き⑩(共用体unionと列挙enum)

参考文献:高橋麻奈著『やさしいC第5版』

共用体型(union構文)
複数の変数でひとつのメモリ領域を共有するもの。
共用体のメンバーはメモリをシェアしているため一つの値しか記憶させることができない。
宣言は構造体に似ているが、機能はかなり違う。
共用体型は次のような構文を書いて宣言する。

union 共用体名

型名 識別子;
型名 識別子;
・・・・・・


構造体Carと構造体Busを含むVehicle共用体
とりあえずストラクト・カーもストラクト・バスもユニオン・ビークルもtypedef構文であだ名をつけている。
乗用車にはナンバーと排気量のデータが、バスにはナンバーと乗車定員のデータが入っており、これらを収める共用体のデータのサイズは、収められたメンバーの中で最もサイズが大きい値と一致する。

#include

typedef struct Car {
int num; //ナンバー
double gas; //ガソリン
} Car; //乗用車構造体

typedef struct Bus {
int num; //ナンバー
int capacity; //乗車定員
} Bus; //バス構造体

//------------------------------
//ここにVehicle共用体を宣言

typedef union Vehicle{
Car car;
Bus bus;
} Vehicle;

//------------------------------

int main(void)
{
Car c = {1234, 25.5};
Bus b = {4567, 50};

Vehicle v;

v.car = c;
printf("v.car.num=%d, v.car.gas=%.1f\n", v.car.num, v.car.gas);
v.bus = b;
printf("v.bus.num=%d, v.bus.capacity=%d\n", v.bus.num, v.bus.capacity);

return 0;
}

列挙型(enum構文)
列挙型は識別子の値を格納できる型。
識別子の値(一般的に全て大文字で記述する)は、普通に文章で記述できるので、ソースコードが分かりやすいという利点もある。

列挙型は次のような構文を書いて宣言する。

enum 列挙型名 {識別子1, 識別子2, 識別子3 ・・・};

ちなみに{ }の中にない識別子は除外するという機能もある。

列挙型Week
enum Week{SUN,MON,TUE,WED,THU,FRI,SAT};

また、これらの識別子は、C言語のプログラムにおいては自動的に0からの数字に置き換えられて処理される。

enum Week{SUN,MON,TUE,WED,THU,FRI,SAT};

SUN・・・0
MON・・・1
TUE・・・2
WED・・・3
THU・・・4
FRI・・・5
SAT・・・6

さらに、識別子の数字を自分で指定することもできる。
enum Week{SUN,MON=0,TUE=5,WED,THU,FRI,SAT};

この場合は
SUN・・・0
MON・・・0
TUE・・・5
WED・・・6
THU・・・7
FRI・・・8
SAT・・・9
と、数字を重複させたり、スキップさせることができる。

列挙の識別子をswitch文のcaseにしたコード
今まではcaseは数字だったが、case CARなどと文章(=識別子名)で行けるので、人間の文章としてかなり読みやすい。

#include

//------------------------------
//ここにVType列挙を宣言

typedef enum VType{CAR, BUS} VType;

//------------------------------

int main(void)
{
int i;
VType vehicles[] = {BUS, CAR, BUS, BUS, CAR};

for (i=0;i<5;i++) {
switch (vehicles[i]) {
case CAR: printf("%d番目は乗用車です.\n",i); break;
case BUS: printf("%d番目はバスです.\n",i); break;
}
}

return 0;
}

花の列挙型Flower
ここでは、アイリス、チューリップ、ユリ、タンポポの4つの種類の識別子を格納している。

#include

typedef enum Flower_t {
IRIS,
TULIP,
LILY,
DANDELION
} Flower;

int main(void)
{
int i;
Flower flowers[] = {2, 3, 0, 1};

for (i=0;i<4;i++) {
switch(flowers[i]) {
case IRIS:
printf("アヤメ\n");
break;
case TULIP:
printf("チューリップ\n");
break;
case LILY:
printf("ユリ\n");
break;
case DANDELION:
printf("タンポポ\n");
break;
}
}

return 0;
}

構造体の中に共用体と列挙を含んだコード
全部乗せみたいなコード。

#include

typedef struct Car {
int num; //ナンバー
double gas; //ガソリン
} Car; //乗用車構造体

typedef struct Bus {
int num; //ナンバー
int capacity; //乗車定員
} Bus; //バス構造体

typedef enum VType {CAR,BUS} VType; //VType列挙

//------------------------------
//ここにVehicle構造体を宣言

typedef struct Vehicle{

VType type;
union{Car car;Bus bus;}data;

} Vehicle;

//Vehicle構造体の中にVType列挙とdata共用体が入っている!
※dataは構造体でもいいが、一回の処理でCarかBusのどちらか一方しか扱わないので、データのサイズを落とすために共用体がよい。

//------------------------------

int main(void)
{
int t;
Vehicle v;

printf("乗用車(0)ですか?バス(1)ですか?: ");
scanf("%d", &t);
if (t==CAR) {
v.type=CAR;
printf("ナンバーは?: ");
scanf("%d",&v.data.car.num);
printf("ガソリンは?: ");
scanf("%lf",&v.data.car.gas);
} else if (t==BUS) {
v.type=BUS;
printf("ナンバーは?: ");
scanf("%d",&v.data.bus.num);
printf("乗車定員は?: ");
scanf("%d",&v.data.bus.capacity);
}

switch(v.type) {
case CAR:
printf("乗用車:num=%d, gas=%.1f\n",
v.data.car.num,v.data.car.gas);
break;
case BUS:
printf("バス:num=%d, capacity=%d\n",
v.data.bus.num,v.data.bus.capacity);
break;
}

return 0;
}

配列の全てのデータを表示するコード
先ほどのVehicle構造体のコードを改造したもの。

#include

typedef struct Car {
int num; //ナンバー
double gas; //ガソリン
} Car; //乗用車構造体

typedef struct Bus {
int num; //ナンバー
int capacity; //乗車定員
} Bus; //バス構造体

typedef enum VType {CAR,BUS} VType;

//--------------------------------------------------
//ここにVehicle構造体を宣言

typedef struct Vehicle{

VType type;
union{Car car;Bus bus;}data;

} Vehicle;

//--------------------------------------------------

int main(void)
{
int i;
Car c1 = {1234,25.5};
Car c2 = {4567,52.2};
Bus b1 = {6789,50};
Vehicle vs[3];

vs[0].type = CAR;
vs[0].data.car = c1;
vs[1].type = CAR;
vs[1].data.car = c2;
vs[2].type = BUS;
vs[2].data.bus = b1;

//----------------------------------------
//ここに配列内の全ての要素を表示する処理
表示させたいデータの変数が(vs[i].data.車種.ナンバーなど,)と、非常に長くなるのに注意。

for(i=0; i<3; i++){

switch(vs[i].type){

case CAR:
printf("乗用車:num=%d, gas=%.1f\n",
vs[i].data.car.num, vs[i].data.car.gas);
break;

case BUS:
printf("バス:num=%d, capacity=%d\n",
vs[i].data.bus.num, vs[i].data.bus.capacity);
break;
}

}

//----------------------------------------

return 0;
}
Calendar
<< June 2020 >>
SunMonTueWedThuFriSat
 123456
78910111213
14151617181920
21222324252627
282930
search this site.
tags
archives
recent comment
recent trackback
others
にほんブログ村 科学ブログへ にほんブログ村 科学ブログ 恐竜へ カウンター
admin
  • 管理者ページ
  • 記事を書く
  • ログアウト