情報処理Ⅱ
2006年12月15日(金)
前回の補足1
ライブラリ関数の分類
標準ライブラリ関数(標準関数,ANSI準拠の関数)
• この科目で使用するのは,この範囲だけ
POSIX準拠の関数
• 情報ネットワーク演習で使用する
その他(サードパーティライブラリ)
• OpenGL(ビジュアル情報演習で使用する)
関数・定数・独自型などをまとめて,他のプログラムから利用
できるよう部品化したものを「ライブラリ」という.
ANSI: American National Standard Institute
POSIX: Portable Operating System Interface for UNIX
2
前回の補足2
複雑な式も,木構造(構文木)
で表現できる.
コンパイラは,ソースコード(文
字列)をこの種の木構造で表
現し,それから計算機が実行
できるコード(オブジェクトコー
ド)に変換する.処理の中で,
再帰呼び出しが用いられるこ
とがある.
「s != NULL && *s != '\0'」の
構文木
&&
!=
s
!=
NULL
*
'\0'
s
3
授業の進め方
構造体
プリプロセッサ
指令
その他の型
ライブラリ関数
自分の思う通りに,適切な形で,プ
ログラムとして表現する.
識別子
算術型
制御文
演算子
2年以降で
さらに学習・習熟
ファイル入出力
配列・文字列
ポインタ
関数
変数の
有効範囲
再帰呼び出し
プログラムの作成・
コンパイル・実行
4
本日学ぶこと
いくつかの型
なぜ「型」にこだわるか?
typedef
列挙型(enum型)
構造体
プログラムを書きやすく
読みやすくする…定性的
なメリット
実行時のコスト(メモリ使用量な
ど)を見積もることができ,そこか
らプログラムの改善が期待できる
…定量的なメリット
処理対象のデータを効果的・効率的に取り扱える
既存の機能をもとに,便利な機能を創れる
以下を読む上での注意
この色とこの色は型名を表す.
この色は変数名を表す.
5
typedef
独自に型(type)を定義(define)できる.
例
typedef signed char schar;
schar c; ⇒ signed char c; と同じ
typedef unsigned char uchar;
uchar c, *p; ⇒ unsigned char c, *p; と同じ
typedef char *String;
String s, t; ⇒ char *s, *t; と同じ
typedef char c5[5];
c5 x, y, z; ⇒ char x[5], y[5], z[5]; と同じ
構造体の型名定義によく用いられる.
6
typedefの考え方
変数の定義
char c5[5]; は,変数c5を定義し,その型はchar [5]型
とする.
型の定義
typedef char c5[5]; は,c5型を定義し,その型は
char [5]型と同一とみなす.
7
列挙型(enumeration)とは
「ラベル」を格納・参照・比較したいときに使う.
変数に格納される具体的な値には関心がない.
実際には,ラベルに整数値が割り当てられる.これを積極的に
活用することもある.
構文: enum タグ名 { 列挙子並び };
「enum タグ名」型が定義される.
列挙子は「,」で区切る.
8
列挙型の使用例
例
0
1
enum Boolean {FALSE, TRUE};
enum Boolean p = TRUE, q = FALSE, r = p||q;
13
enum month {
Jan = 1, Feb, Mar, ..., Dec, MONTH_END
} mloop;
型と変数を同時に定義
int rain[100][MONTH_END];
for (mloop = Jan; mloop < MONTH_END;
mloop++) {
rain[6][mloop] = ...;
}
年月単位の降水量を格納する
9
汎整数型
整数型(char,int,long など)と列挙型を合わせて,
汎整数型(integral type)という.
列挙型は,計算時にはint型とみなされる.
ただし,利用は代入,比較,範囲内の増分・減分にとどめておく.
10
構造体(structure)
複数のオブジェクトを取りまとめて一つのオブジェクトとして
扱うための機構
構造体で表現するとよいもの
(x,y)
(2次元,3次元などの)座標上の点
複素数
行列(行数と列数と各成分)
所持金
学生情報
500
100
100
100
50
10
学生番号:0001
氏名:あいうえお
情処Ⅰの点数:80
情処Ⅱの点数:75
修得単位数: 52
11
構造体の構文と定義の例(1)
構文: struct タグ名 { メンバ宣言子並び };
「struct タグ名」型が定義される.
例
struct point {
この x と y を,
double x;
point構造体の
double y;
メンバという.
};
struct point p = {1, -1};
セミコロンを忘れない
ように
p:
x=1
y = -1
配列と同じ書式で
初期化可能
12
構造体の定義の例(2)
構造体宣言と変数定義を一つの文で
struct point {
double x;
double y;
} p;
構造体宣言と型定義を一つの文で
typedef struct point {
double x, y;
} point;
point p;
struct point型と
point型が定義される
13
構造体の定義の例(3)
無名構造体
struct {
double x;
double y;
} p;
typedef struct {
double x, y;
} point;
point p;
14
構造体の定義の例(4)
行列(行数,列数とも10まで)
struct matrix {
int row, column;
double element[10][10];
};
•
•
row
column
element
…
行列(成分はポインタ)
struct matrix {
int row, column;
double **element;
};
row
•
column
•
element
15
構造体の定義の例(5)
自己参照構造体
struct node {
graph
int value;
struct node *next;
value = 1
};
next
struct node graph[100];
graph[0].value = 1;
graph[0].next = graph + 1;
graph[1].value = 99;
graph[1].next = NULL;
•
•
value = 99
…
next = NULL
16
構造体の参照と代入(1)
前提
struct point {
double x, y;
};
struct point p, *pp = &p;
メンバへのアクセス方法
p:
pp
x
y
× *pp.x
構造体オブジェクトpのメンバxは p.x と書いて
参照・代入ができる.
構造体オブジェクトのポインタppについては,(*pp).x もしく
は pp->x と書けばよい.
• . と -> は演算子であり,最上位の優先順位を持つ.
17
構造体の参照と代入(2)
構造体オブジェクトの代入
struct matrix a, b; (aを初期化) b = a; とすると,
bにはaのコピーが格納される.
構造体の中に配列があっても,コピーされる.
構造体の中のポインタは,ポインタ値がコピーされる.
構造体渡し
関数の引数や戻り値の授受でも,構造体オブジェクトが代入
(コピー)される.
しかし,構造体はしばしばポインタで渡される(参照渡し).
• 関数処理で,構造体オブジェクトの中の値を変えたいとき
• 大きなサイズの構造体オブジェクトをスタックに置きたくない
とき
18
両替問題の仕様(1)
両替機の両替部分をシミュレート(模擬)する.
入金に対して,どの紙幣・貨幣を何枚出せばいいかを出力す
る.
「崩す」(一万円札を千円札10枚にするなど)のは考えない.
金額に関する情報
一万円,五千円,千円の各紙幣(bill)の枚数
500円,100円,50円,10円,5円,1円の各硬貨(coin)の
枚数
合計金額(amount) ⇒ 構造体のメンバ?
100
100
100
100
50
10 10 10
5 5 5 5
500
19
両替問題の考え方
知りたい情報,行いたい操作
紙幣・貨幣がそれぞれ何枚ある(入金された,出金しないとい
けない)かを知る
合計金額を求める
両替する
• 両替前の「紙幣・貨幣の枚数の情報」に対して,
両替後の「紙幣・貨幣の枚数の情報」を求める
20
両替問題のプログラミング(1)
金銭構造体
struct money {
int bill_10000, bill_5000, bill_1000;
int coin_500, coin_100, coin_50, coin_10,
coin_5, coin_1;
};
•
•
21
両替問題のプログラミング(2)
定義した関数
void print_money(struct money *moneyp);
• 枚数と総額を出力する
• 構造体のポインタを引数にとる
int calc_amount(struct money *moneyp);
• 総額を求める
• 構造体のポインタを引数にとる
struct money change_money(struct
money money_in);
• 両替する
• 構造体オブジェクトを引数にとり,構造体オブジェクトを返す
22
その他の話題
構造体と配列の使い分け
sizeof(構造体)
構造体とプログラミング
してはいけないこと
独自の型はどこで定義する?
23
構造体と配列の使い分け
配列
構造体
同一の型の集まり
各要素に番号がついている
ループなどを使って順番に処理する
様々な型の集まり(ただし,同一の型の集まりでもよい)
各要素に付けられた名前を使ってアクセスする
「配列を含む構造体」や「構造体の配列」もよく利用される.
24
sizeof(構造体)
sizeof(構造体) は,構造体の各メンバのサイズの合計
以上になる.
構造体オブジェクトの中で使用されない領域もあり得る.「パ
ディング」という.
s:
c
struct s {
char c;
int i;
};
パディング
i
sizeof(char) == 1
sizeof(int) == 4
でも sizeof(struct s) != 5
25
構造体とプログラミング
さまざまな種類の情報を持つ「実体」を一つのオブジェクトと
して処理したいとき,
まず,「何に処理をしたいか?」を考える.
• そのオブジェクトの型を構造体で定義する.
• 座標上の点,学生情報,ノード(節点),など.
次に,「何の処理をしたいか?」を考える.
• 構造体を引数にとって処理する関数を定義する.
• 引数・戻り値ともに,型は構造体そのものにすべきか,
構造体のポインタにすべきか,そのつど検討する.
26
してはいけないこと
× 関数内のauto変数を指し示すポインタを,戻り値とする.
struct money *create_money(void)
{
struct pocket money = {
0, 0, 0, 0, 0, 0, 0, 0, 0
};
return &money;
}
コンパイルエラーにはならないが,実行時に支障をきたす.
関数処理が終わると,moneyの領域が破棄される
⇒ *(&money)が不定!
27
独自の型はどこで定義する?
一般には,グローバル区間で定義し,複数の関数間で利用
できるようにする.
#include文の後,関数プロトタイプの前に書く.
ブロックの中で定義してもよい.
有効範囲は,そのブロックの終わりまで.
28
まとめ
独自の型(typedef,列挙型,構造体)を定義することで,
変数に持たせる意味がより明確になる.
構造体により,複数のデータからなる「システム」を創ること
ができる.
構造体を対象とする関数を定義するとき, (引数・戻り値の)
型は構造体そのものにすべきか,構造体のポインタにすべ
きか,そのつど検討する.
29
予告
次回授業終了後すぐ,授業Webページにて,第2回レポート
課題を掲示します.
30
© Copyright 2026 ExpyDoc