CプログラミングⅡ
構造体の基礎 構造体配列
構造体とは
複数の異なる型(int型,double型,char型など)を 1つの新しい型にまとめる
x y name int main(void)
{
int x;
double y;
char name[10];
return 0;
}
複数の変数を宣言するとき それらを格納するための箱は
それぞれ独立したものとなる
x y name
構造体型で宣言すると
変数ごとに格納場所を区切られた ひとまとまりの箱として扱える
構造体型の宣言
新しい構造体型を宣言するときには struct を用いる
struct List { int age;
double tall;
char name[10];
};
age tall name 構造体型の宣言
struct 構造体型名 { 型名 識別子;
型名 識別子;
: };
List型
この宣言は main関数の外で行う
List型構造体の宣言
yama
構造体変数の宣言
構造体型を宣言したら,その型の変数を宣言する ことでプログラムコード中で使用することができる
int main(void) {
struct List yama;
}
構造体変数の宣言
struct 構造体型名 構造体変数名;
List型変数yama
List型構造体の宣言
age tall name
yama
メンバへのアクセス
構造体型変数を宣言すると,その中の変数(例では,
age や tall,name)に値を格納することができる
age や tall,name をメンバという
int main(void) {
struct List yama;
yama.age = 37;
yama.tall = 174.5;
strcpy(yama.name,"yamamoto");
}
構造体のメンバへのアクセス 構造体変数名.メンバ;
List型変数yama
List型変数yamaのメンバへの値格納 構造体変数名とメンバを区切る
" . " をドット演算子という
37 174.5 "yamamoto"
age tall name
メンバの値の出力
構造体型変数に格納されている値を出力するときは,
必ずどのメンバの値を出力するのか指定する
int main(void) {
struct List yama;
yama.age = 37;
yama.tall = 174.5;
strcpy(yama.name, "yamamoto");
printf("氏名は %s です.¥n", yama.name );
printf("年齢は %d です.¥n", yama.age );
printf("身長は %lf です.¥n", yama.tall );
return 0;
}
メンバの型に合った変換仕様を 指定する
氏名はyamamotoです.
年齢は37です.
身長は174.50000です.
メンバの値の入力
構造体型変数に格納されている値を入力するときも,
必ずどのメンバの値を出力するのか指定する
int main(void) {
struct List yama;
scanf(" %d ", &yama.age );
scanf(" %lf ", &yama.tall );
scanf(" %s ", yama.name );
printf("氏名は %s です.¥n", yama.name );
printf("年齢は %d です.¥n", yama.age );
printf("身長は %lf です.¥n", yama.tall );
return 0;
}
先頭に & をつける
メンバが文字列の場合には 先頭に & をつけない
43[Enter]
175.0[Enter]
takahiro[Enter]
氏名はtakahiroです.
年齢は43です.
身長は175.00000です.
typedefによる構造体型名の宣言
typedef を用いて構造体型を宣言すると,その変数を
宣言するときに省略した形で宣言できる
typedefを用いた構造体型の宣言
typedef struct 構造体型名 { 型名 識別子;
型名 識別子;
: } 型名;
typedef struct List { int age;
double tall;
char name[10];
} List;
構造体型名を省略した宣言 typedef struct {
型名 識別子;
型名 識別子;
: } 型名;
typedef struct { int age;
double tall;
char name[10];
} List;
typedefによる構造体型名の宣言
typedef struct List { int age;
double tall;
char name[10];
} List ;
int main(void) {
List yama;
yama.age = 37;
yama.tall = 174.5;
strcpy(yama.name, "yamamoto");
…
return 0;
}
"struct List yama; " と書いたのと同じ
"struct List" の型名を "List" 置き換える
構造体型変数の初期化
構造体型変数を宣言するときにメンバの値を格納 することができる
typedef struct List { int age; ①
double tall; ②
char name[10]; ③
} List ;
int main(void) {
List yama = { 37, 174.5, "yamamoto" };
…
return 0;
}
配列の各要素の初期化と同じように メンバの値を " , " で並べて { } で囲む
並べる順番は,List型を定義したときの メンバの宣言順序と同じにする
① ②
③
構造体型変数の代入
同じ構造体型の別の変数にメンバの値を代入するとき には,変数同士の代入文だけでよい
int main(void) {
List yama = { 37, 174.5, "yamamoto" };
List taka;
taka = yama;
printf("氏名は %s です.¥n", taka.name );
printf("年齢は %d です.¥n", taka.age );
printf("身長は %lf です.¥n", taka.tall);
return 0;
}
同じList型の 変数takaを宣言 yamaのメンバの値をすべて
takaのメンバにコピーする
taka.age = yama.age;
taka.tall = yama.tall;
strcpy(taka.name, yama.name);
としなくてよい
yama
37 174.5 "yamamoto"
taka
37 174.5 "yamamoto"
age tall name
age tall name
関数の引数・戻り値に構造体を使う
構造体型変数を関数の引数・戻り値に用いる
typedef struct Data { int x;
int y;
} Data;
Data keisan(Data c);
int main(void) {
Data a = { 30, 20 }, b;
b = keisan( a );
printf("メンバの和 = %d¥n", b.x );
printf("メンバの差 = %d¥n", b.y );
return 0;
}
a の値が keisan関数の
仮引数 c に 渡される
a x
30
Data keisan(Data c) {
Data d;
d.x = c.x + c.y;
d.y = c.x – c.y;
return d;
}
y 20
c
x y
d
x y
b
x y
50 10
main関数
keisan関数
30 20
10 50
計算
d の値が main関数の b に返される Data型変数を引数にもち,
Data型変数の(メンバ)値を 返す関数の
メンバの和 = 50 メンバの差 = 10
構造体の配列
一般の型の配列と同様,構造体の配列も作成できる
typef struct Data { int x;
int y;
} Data;
int main(void) {
int i;
Data a[3];
a[0].x = 10; a[0].y = 20;
a[1].x = 30; a[1].y = 10;
a[2].x = 20; a[2].y = 30;
for(i = 0; i < 3; i++){
printf("a[%d].x = %d¥n", i, a[i].x);
printf("a[%d].y = %d¥n", i, a[i].y );
} }
配列要素の 各メンバに 値を代入する
a[0]
x 10
y 20
それぞれの配列要素が メンバ x,y をもつ
a[1]
x 30
y 10
a[2]
x 20
y 30 構造体の配列の例
a[0].x = 10 a[0].y = 20 a[1].x = 30 a[1].y = 10 a[2].x = 20 a[2].y = 30
構造体配列の初期化
構造体配列の各要素のメンバの値を,宣言と同時に 初期化する
typef struct Data { int x;
int y;
} Data;
int main(void) {
int i;
Data a[3] = { {10, 20}, {30, 10}, {20, 30}};
for(i = 0; i < 3; i++){
printf("a[%d].x = %d¥n", i, a[i].x);
printf("a[%d].y = %d¥n", i, a[i].y);
}
return 0;
}
配列要素ごとに メンバの値を{ }で囲む
a[0].x = 10 a[0].y = 20 a[1].x = 30 a[1].y = 10 a[2].x = 20 a[2].y = 30
構造体配列を関数の引数として用いる
typedef struct Data { int x;
int y;
} Data;
void fnc(int n, Data p[]);
int main(void) {
Data a[3] = {{10, 20}, {30, 10}, {20, 30}};
fnc( 3, a );
return 0;
}
関数に構造体配列を渡すときは 配列名だけ記述する
main関数
fnc関数
添字演算子を用いてData型配列p[ ]として main関数のData型配列a[ ]を受け取る
a[0]
x 10
y 20
a[1]
x 30
y 10
a[2]
x 20
y 30
void fnc(int n, Data p[] ) {
int i
for(i = 0; i < n; i++){
printf("a[%d].x = %d¥n", i, p[i].x );
printf("a[%d].y = %d¥n", i, p[i].y );
} }
p[0]
x 10
y 20
p[1]
x 30
y 10
p[2]
x 20
y 30