プログラミング演習I

プログラミング演習II
2004年12月 14日(第7回)
理学部数学科・木村巌
前回までの復習





関数ポインタ
教科書10.5から(p. 337~348)
スタックというデータ構造と、配列を使ったス
タックの実現
逆ポーランド記法
逆ポーランド記法計算機の実装例(+, -のみ)
今日学ぶこと




構造体
typedef
構造体のサイズ
構造体の応用



関数の引数に構造体を使う
関数の引数に構造体へのポインタを使う
構造体の配列
新しい型を決める

これまで学んだのは、





char, int, floatなどの基本型
それらの配列
それらを指すポインタ、など
基本型や、それらの配列など派生型を一まと
めにすることができる……構造体(structure)
ひとつの意味を持たせることができる
構造体(structure)



異なる型の値をまとめて、新しい型を定義す
る
配列は、同じ型の値をまとめることしかできな
かった
例:車のナンバー(int型)、ガソリン量
(double)などを一つにまとめ、「車」をあらわ
す型が定義できる
構造体の宣言


構造体形の宣言……structというキーワード
を使う
構文
struct 構造体型名 {
型名 識別子;
型名 識別子;
…
};
例


例:車をあらわすCarという構造体の定義
struct Car {
int num; /* number */
double gas; /* gas */
};
これで、struct Car型という新たな型が定義さ
れた
構造体変数を宣言する

構文


たとえば、先の例のstruct Car型については


構造体型名 構造体変数名;
struct Car car1;
car1は、struct Car型の値を格納する変数とな
る
メンバへのアクセス



構造体型の変数(単に構造体ともいう)を宣
言すると、そのメンバへのアクセスが可能に
なる
struct Car car1; と宣言すると、car1のナンバー
をあらわすnumやガソリン量をあらわすgasな
どのメンバにアクセスできる
メンバにアクセスするには、ドット演算子をつ
かう
メンバにアクセスする(続)

構文


たとえば、



構造体変数名.メンバ
car1.num = 1234; /* ナンバーをあらわすnumに1234を代入
car1.gas = 25.5; /* ガソリン量をあらわすgasに25.5を代入 */
*/
Sample1.c (p. 353)、Sample2.c(p.355)を打ち
込んで、コンパイル・実行してみよう
構造体の記述の仕方



typedefにより名前を割り当てることができる
struct Carという長い型名に対して、typedefに
より別名を割り当てることができる
構文

typedef 型名 識別子;
Typedefで名前を割り当てる

例
typedef struct Car {
int num;
double gas;
} Car;
とすることで、Car car1; とCar型の変数car1を宣言できる



Sample3.c (p. 357)を打ち込んで、コンパイル・実行
してみよう
注:構造体型名と、typedefで割り当てる識別子は異
なっていても良い
Typedefで名前を割り当てる(続)



typedefで名前を割り当てるのは、長い構造体
型名を短縮するという用途よりも、ある型(例えば、
struct Car型)が、実際にどのように定義されている
か(この場合、構造体であること)を隠蔽するという用途の
方が実際的
抽象データ型(abstract data type, ADT)
typedefは、構造体の型名に別名を割り当て
る以外にも使える
構造体の初期化



構造体を宣言したあと、ドット演算子を使って各メン
バを初期化する
もうひとつのやり方は、宣言と同時にメンバの所期
かも行ってしまうもの
例




Car car1 = {1234, 25.5};
カンマで区切った順に、メンバが初期化される
昔のCでは出来なかった
Sample4.cを入力し、コンパイル・実行してみよう
構造体を構造体へ代入する




構造体のメンバに値を代入する方法は上に
見てきたとおり
同じ構造体型の構造体変数に、構造体を代
入することが出来る
通常の変数への代入と同じ書き方
Sample5.cを入力して、コンパイル・実行して
みよう
構造体のサイズ




sizeof演算子で、構造体型のサイズ(メモリに
占める領域)をバイト単位で知ることが出来る
各メンバの型のサイズの総和に等しいか、大
きくなることがある
sizeof (構造体) >= sizeof(メンバ1)+sizeof(メ
ンバ2) + …… + sizeof (メンバn)
Sample6.cを入力し、コンパイル・実行してみ
よう
構造体のサイズと
構造体へのポインタのサイズ



Sample6.cでは、構造体そのもののサイズと、
その構造体へのポインタのサイズを見ている
後者のほうが、一般的には小さい
ビットフィールドの話は省略
構造体の応用



関数の引数として構造体を使う
Sample8.cを打ち込んで、コンパイル・実行し
てみよう
引数は値渡し


各メンバがコピーされて、そのコピーが関数に渡
される
関数側で引数の構造体を変更しても、元の構造
体には反映されない
構造体へのポインタを引数に



構造体を関数の引数とすると、関数呼び出し
のたびに構造体のコピーが行われる
構造体が巨大な場合、無視できない処理時
間がかかる
構造体へのポインタを引数として使うとよい


構造体より、そのポインタの方が小さいのだった
ポインタ渡しだと、それが指す構造体を変更する
ことも出来る
構造体へのポインタを引数に(続)


構造体へのポインタから、メンバにアクセス
アロー演算子 -> を使う



構造体へのポインタ->構造体メンバ
「(*構造体へのポインタ).構造体メンバ」と同じ
Sample9.cを入力し、コンパイル・実行してみ
よう
構造体の配列



構造体型も他の型と同じように、配列をなす
ことができる
typedefによって、Car型が作られたとすると
Car cars[3]; /* Carの配列 cars[] */
Sample10.cを入力し、コンパイル・実行してみ
よう
更に進んだ話題(次回予告)




構造体のポインタから、typedefによって別の
型を作る
各メンバへのアクセスは、関数、もしくはマク
ロを使う
このようにして、ある型が、実際にはどのよう
に実装されているのかを隠蔽する
抽象データ型(Abstract Data Type, ADT)



スタックも(構造体は使っていないが)その例
初期化して、push, popするのみ
使う人は、配列であることを意識しなくてよい
今日学んだこと




構造体
typedef
構造体のサイズ
構造体の応用



関数の引数に構造体を使う
関数の引数に構造体へのポインタを使う
構造体の配列
レポート課題
typedef struct Book {
char author[31];
char title[63];
char isbn[10];
} Book;
により、Book型を定義する.Sample10.c(教科書
p. 373)を参考に、本5冊について、著者名、
表題、ISBNを管理するプログラムを作成せ
よ.
レポート課題(続)



締め切り:2004年12月20日一杯(日本時間
で)
提出:メールで木村([email protected])まで.
感想などあると木村が喜びます
試験通知

中間試験を、2005年1月11日に行います



中間試験の範囲は、それまでやったところすべて
形式は、筆記試験.持ち込み可
期末試験を、2005年2月1日に行う予定です

期末試験の範囲は、後期にやったところすべて