このドキュメントは http://edu.net.c.dendai.ac.jp/ 上で公開されています。
座標のように、複数の値を一つのものとして扱いたい場合があります。 C 言語では構造体という仕組みで扱うことができます。 まず、構造体の型の名前を宣言し、その型のメンバー変数を宣言します。 型を宣言するには struct 宣言 をします。 struct の後に、構造体の名前を指定し、その後にメンバーの宣言のブロック({} で括られたもの)が来て、最後にセミコロン(;)で終了します。 メンバーの宣言は変数宣言と同じ形になりますが、変数が宣言されるわけでは ないことに注意が必要です。 例えば座標の構造体の型は次のように宣言されます。これは変数宣言ではなく、 型の宣言です。 従ってこれだけで変数が使用できるわけではありません。
struct point {
double x;
double y;
};
このようにすると point という構造体の型だけが作られます。 point は構造体の型であって、変数ではありません。 point 型の変数 p と q を宣言するには次のようにします。
struct point p,q;
これで p と q という point 型の変数ができました。 宣言した変数は次のように使います。
p.x=1.0;
printf("%f\n",p.y);
このように変数名の後にピリオドをつけ、その後にメンバ
名をつけます。
こうすると通常の変数と同様に使用することができます。
この場合、型はメンバを宣言した型になります。
q=p;
printf("%f\n",q.x);
同じ型であれば単なる代入文で全てのメンバの値がコピーされます。
struct point p={1.0,2.0};
/* p という変数が作られ、 p.x に 1.0, p.y に 2.0 が代入される */
但し、プログラム実行中はできない。
なお、二つの構造体の変数が一致しているかどうかは == で調べられませんの で、一つ一つ要素を比べるしかありません。
構造体 A という型を宣言しても、変数宣言は struct A x;
と
struct を書く必要があります。
(C++ ではちゃんと A x; と書けますが……)
そのため、 struct を書かなくて済むように typedef という宣言があります。
typedef struct point {
double x;
double y;
} POINT;
と宣言すると、この宣言以降、 struct point の代わりに POINT と書けば済 むようになります。 変数宣言は次のようになります。
POINT p,q;
/* point 型の変数 p と q が宣言される */
POINT r={1.0,2.0};
/* point 型の変数 r が宣言され、 r.x に 1.0, r.y に 2.0 が代入される。 */
なお、複数のファイルで構造体を使う場合、ファイル毎に構造体の宣言がそれ ぞれ必要です。 そのため、構造体の宣言はヘッダファイルに入れると便利です。
構造体のポインタの宣言は通常のポインタと同様です。
POINT *p;
POINT q={1.0,2.0};
q の番地を p に入れるのも同様です。
p=&q;
但し、p の指す構造体の要素をアクセスする場合、 (*p).x
と
も書けますが、これを p->x
と書くこともできます。
構造体の配列の取り扱いは、通常の配列の取り扱いと同様です。
POINT p[5];
int i;
for(i=0; i<5 ; i++){
p[i].x=0.0;
p[i].y=1.0;
}
構造体は普通の変数と同様に関数と値をやりとりできます。 つまり、特にポインタなどを使用しなくてもよいということです。
---------------p.h----------------typedef struct p { int x; int y; } POINT; POINT sub(POINT p);
---------------sub.c--------------#include "p.h" POINT sub(POINT p){ p.x--; p.y++; return p; }
---------------main.c------------- #include <stdio.h> #include "p.h" int main(void){ POINT p={1,2},q; q=sub(p); printf("%d\n%d\n",p.x,p.y); printf("%d\n%d\n",q.x,q.y); return 0; }
構造体 POINT を次のように定義します。
typedef struct point {
double x;
double y;
} POINT;
POINT 型の引数をもらい、原点からの距離を double 型で返す関数 distance を作りなさい。 そして、以下の main 関数によりその関数をテストしなさい。
----point.h----typedef struct point { double x; double y; } POINT; double distance(POINT p);
----main.c---- #include <stdio.h> #include "point.h" int main(void){ POINT p={3.0,4.0}; printf("点 %f, %f と原点の距離は %f です。\n",p.x,p.y,distance(p)); return 0; } ----distance.c----#include "point.h" double distance(POINT p){ /* この部分を書く (必要ならヘッダファイルを追加する)*/ }
POINT 型のポインタを引数とし、その引数の x 座標、y 座標とも 1/2 にする
関数 void halve(POINT *p)
を作りなさい。
そして、以下の main 関数によりその関数をテストしなさい。
----point.h----typedef struct point { double x; double y; } POINT; void halve(POINT *p);
----main.c---- #include <stdio.h> #include "point.h" int main(void){ POINT p={6.0,8.0}; printf("最初の点は %f, %f です。",p.x,p.y); halve(&p); printf("半分の位置は %f, %f です。",p.x,p.y); return 0; } ----halve.c----#include "point.h" void halve(POINT *p){ /* この部分を書く */ }