前回の関数のまとめ (1) プログラムは main() 関数の先頭から実行される 関数は main() 関数または他の関数から呼び出されて実行される. 関数を呼び出す側の実引数の値が関数内の仮引数 ( 変数 ) に コピーされる 関数内で求めた値は return 文によって関数値として呼び出し側に戻され る. #include float menseki(float a, float b) { return (a * b / 2); } int main(void) { float x, y, kekka; printf(" 底辺は ?"); scanf(" %f ", &x); printf(" 高さは ?"); scanf(" %f ", &y); kekka = menseki(x, y); printf(" 面積は %f です. \n", kekka); } x,y:実引数 a, b: 仮引数 仮引数もローカル変数 → 関数内でのみ有効 関数の定義 関数の呼び出し 復習 スタートポイント
ローカル変数 (1) #include float menseki(float a, float b) { float s; s = a * b / 2; return s; } int main(void) { float a, b, kekka; printf(" 底辺は ?"); scanf(" %f ", &a); printf(" 高さは ?"); scanf(" %f ", &b); kekka = menseki(); printf(" 面積は %f です. \n", kekka); } menseki() 関数 ローカル変数 同じ変数名 a, b でも,関数が違 うと,別の変数と見なされる ⇒赤色 a,b と青色 a,b は別の変数 menseki() 関数 内のローカル変 数 a と b main() 関数 main() 関数内 のローカル変 数 a と b 復習
void キーワード void kansu(float a, float b) {.... return; } 返却値を持たない ( 関数値のない ) 関数の定義 void は返 却値が無 いことを 宣言 何も返さないので, return 式 ; とは書かない. return 文の省略も可能! int main(void) { int x; x = kansu(3, 4); printf("x=%d, %d", x, kansu(2,5)); } void 宣言された 関数の返却値を 利用しようとす るとエラー int func(void) { return 5; } int main(void) { printf(" 値は %d", func()); } 引数として void と書くと, 引数が無いことを宣言 復習
引数の値渡し int main(void) { int x = 12; mul10(x); printf("x = %d", x); } a 12 x main() 関数 変数 mul10() 関数 1212 引数のコピー 120 return 文実行 void mul10(int a) { a = a * 10; return; } 関数呼び出し x = 12 局所変数 ローカル変数 原則 引数は関数からコ ピーバックされない.呼 び出し側の変数 ( 実引数 ) は 変化しない.⇒値渡し (call by value) 例外 ポインタ引数,配列引数 ⇒参照渡し (call by reference) 引数のコピーバック main() 関数 mul10() 関数 引数を 10 倍する関数 復習
配列引数 ( 参照渡し ) を用いた関数 #include void mul10(int data[], int n) { int i; for (i = 0; i < n; i++) { data[i] = data[i]*10; } } int main(void) { int i, aa[30], s; // 配列 aa に 30 個のデータを入力する for (i = 0; i < 30; i++) { printf("%d 番のデータ :", i); scanf("%d", &aa[i]); } mul10(aa,30); printf(" データを全て 10 倍すると "); // データの表示 ( 省略 ) } 配列引数は参照渡しであるため, 呼び出し側の配列の値が変化す る! n 個のデータの値 を 10 倍する関数 データの個数 (n 個 ) を引数とす る 理由:この関数を再利用することを想 定.データの個数はいつも 30 個とは限 らないので,ループ回数を 30 回に固定 したくない 関数内のローカル配列変数 data を変化 すると,呼び出し側の配列 aa も変化 配列引数:かっこ [ ] のみつける.要素数を空欄にした 配列 →data[n]× data[0]× 配列を引数とした関数呼び出 し 配列名のみ書く. 配列全体を引数とするので [ ] は不 要 有効なデータの個数は 30 個 復習
プログラミング技術の発達 初期の時代 暗黒時代.モジュール化困難. 理解しやすいプログラム,再利用可能なプログラムが できなかった. 構造化プログラミング ループ制御,選択制御の整理. ローカル変数の導入 → モジュール化が容易. 理解しやすいプログラム,再利用しやすいプログラム ができるようになった. オブジェクト指向プログラミング 一度作成したモジュールの徹底した再利用が可 能. プログラミングの考え方の整理 現代のプロ グラミング 技術 グラフィカルユーザー インターフェースのプ ログラミングではこれ が必要 C++ 言語, Java 言語, C# 言語, Objective-C 言語
オブジェクト指向 オブジェクトを中心としたプログラムの考え方 オブジェクト = 物,全ての事物・事象 オブジェクトの例 人間 人間を表わす要素 性別,名前,年齢,身長,・・・, etc. 機械 機械を表わす要素 名前,重さ,部品の数,値段 実験データ 実験データを表わす要素 データ値の個数,データの値
構造体 ー オブジェクト指向の第一歩 いくつかの変数をまとめて新しい変数型を作る 例えば 複素数型 実部と虚部の float 型の2変数からできている 日付型 年,月,日を表す int 型の3変数からできている 学生身体データ型 学籍番号 (int 型変数 ) 名前 ( 文字列変数 ) 誕生日 ( 日付型構造体 ) 身長 (float 型変数 ) 体重 (float 型変数 )
構造体変数 1234 x xyz A 普通の変数 ( ここでは座標値 ) 構造体変数 ( ここでは点を表す ) xyz B 14 y 5 z 点 A の x 座標 プログラム中では A.x 点 B の x 座標 プログラム中では B.x 例えば 「 3 次元空間で2点 A と B の 間に線分を引き・・・」 実際には点 A や点 B は座標で 表すので,複数の変数が必 要 例えば 「 3 次元空間で2点 A と B の 間に線分を引き・・・」 実際には点 A や点 B は座標で 表すので,複数の変数が必 要 箱のイメージ 引き出しのイメージ
構造体のプログラム例 (1) ー 日付型 #include struct Date { int year; int month; int day; }; void main() { Date a, b; a.year = 2015; a.month = 7; a.day = 1; b = a; b.day = 2; printf(" 初めの日付は %d 年 %d 月 %d 日, ", a.year, a.month, a.day); printf(" 次の日付は %d 年 %d 月 %d 日 \n", b.year, b.month, b.day); } a.year は構造体変数 a のメ ンバ変数 year を意味する 構造体内の変数をメンバ変数と呼ぶ 初めの日付は 2015 年 7 月 1 日,次の日付は 2015 年 7 月 2 日 Date 型の構造体の定義 キーワード struct b.day は構造体変数 b の メンバ変数 day を意味す る 構造体 変数 a を b に代入 Date 型の構造体変数 a と b の宣言 yearmonthday b yearmonthday a Date は変数ではなく設計図
構造体のプログラム例 (2) struct Date { int year; int month; int day; }; void main() { Date a = {2002, 6, 28}; Date b; b = {2002, 6, 29}; Date c[20]; c[15].year = 6; c[15].month = 6; c[15].day = 28; printf(" 今日は %d 年 %d 月 %d 日 \n", c[15].year, c[15].month, c[15].day); } 構造体変数を宣言す ると同時に初期化 同時ではないのでダメ エラー Date 型構造体の配列の宣言 Date 型構造体の配列要 素 15 に値を代入 ※この例では配列の添え字 15 には特に意味はない
構造体のプログラム例 (4) #include struct Date { int year; int month; int day; }; struct Student { int number; // 学籍番号 char name[20]; // 名前 float height; // 身長 float weight; // 体重 Date birthday; // 誕生日 }; void printSt(Student s) { printf("%d 番 %s(%d 年 %d 月 %d 日生 )", s.number, s.name,s.birthday.year, s.birthday.month, s.birthday.day); return; } void main() { Student matsu = {1020, "matsushima", 163.5, 62.0, {1970, 2, 28}}; printSt(matsu); printf("\n"); } 1020 番 matsushima(1970 年 2 月 28 日生 ) Student 型構造体の内容を表示する関 数 引数は Student 型 構造体の 変数 Student 型構造 体のメンバと して Date 型構 造体変数を指 定 注意 ! s.number ○ number × 注意 ! s.number ○ number × 引き出しの内容 ( 情報 ) を丸ご と引数として受け取るイ メージ Student 型構 造体のメン バとして文 字列を指定
構造体のプログラム例 (5) #include struct Date { int year; int month; int day; }; struct Student { int number; // 学籍番号 char name[20]; // 名前 float height; // 身長 float weight; // 体重 Date birthday; // 誕生日 }; void printSt(Student s); void check(Student a) { printSt(a); if (a.weight > a.height) { printf(" は太りすぎだ! \n"); } else { printf(" はいい感じだ! \n"); } return; } void main() { Student matsu = {1020, "matsushima", 163.5, 62.0, {1970, 2, 28}}; check(matsu); } 1020 番 matsushima(1970 年 2 月 28 日生 ) は太りすぎ だ! printSt() 関数のプロトタイプ宣言 ( 関数定義はこの例では省略しているが実際は 必要 ) 注意 ! a.weight ○ weight × 注意 ! a.weight ○ weight ×
構造体と配列を組み合わせたプログラム例 (1/2) #include struct BaitoKanri // バイト管理構造体 { int id; // バイトの個人番号 char name[20]; // バイトの氏名 ( 文字列 ) int money[12]; //1 ~ 12 月に支払ったバイト料 (1000 円単位 ) }; // バイト一人分の番号,氏名,支払額の表示する関数 void PrintPerson(BaitoKanri baito) { int i; printf("%2d %-10s", baito.id, baito.name); for (i = 0; i < 12; i++) { printf(" %2d", baito.money[i]); } // バイト一人分の 1 年間の支払額を計算する関数 int Sum(BaitoKanri a) { int i, sum = 0; for (i = 0; i < 12; i++) { sum = sum + a.money[i]; } return sum; } 番号 氏名 毎月の給料 ( 単位 : 千円 ) 合計 Matsushima : Noda : Obama : Putin : 169 続行するには何かキーを押してください... 構造体変数の中に配列が含まれ ている場合 ( 配列を含む構造体 ) 構造体変数が配列になっている 場合 ( 構造体変数の配列 ) 構造体変数の中に配列が含まれ ている場合 ( 配列を含む構造体 ) 構造体変数が配列になっている 場合 ( 構造体変数の配列 ) 配列を含む構造体の定義 この構造体にバイト一人あたりの 情報をすべて詰め込んで管理する この関数を使うと構造体 変数 baito の ( 一人分の ) 情 報を画面表示できる この関数は,構造体変数 a の ( 一人分の )1 年間の給 料総額を返す
構造体と配列を組み合わせたプログラム例 (2/2) #include struct BaitoKanri // バイト管理構造体 { int id; // バイトの個人番号 char name[20]; // バイトの氏名 ( 文字列 ) int money[12]; //1 ~ 12 月に支払ったバイト料 ( 単位 1000 円 ) }; int main(void) { BaitoKanri list[4] = { {10, "Matsushima", {10, 15, 12, 10, 15, 20, 20, 15, 11, 15, 12, 10}}, {15, "Noda", {10, 15, 14, 20, 15, 20, 20, 16, 11, 15, 42, 10}}, {16, "Obama", {20, 15, 13, 15, 15, 30, 20, 15, 11, 25, 12, 10}}, {20, "Putin", {12, 15, 12, 20, 15, 20, 10, 17, 11, 15, 12, 10}}, }; printf(" 番号 氏名 毎月の給料 ( 単位 : 千円 ) 合計 \n"); printf(" \n"); int i; for (i = 0; i < 4; i++) { PrintPerson(list[i]); printf(" :%4d\n", Sum(list[i])); } 番号 氏名 毎月の給料 ( 単位 : 千円 ) 合計 Matsushima : Noda : Obama : Putin : 169 続行するには何かキーを押してください... 構造体変数の配列宣言 一人分の情報 ここでは 4 人分の情 報で初期化 list[i] は, i 番目の一人分の 情報 ( 一つの構造体変数 ) これは配列引数ではないこ とに注意 !