前回の関数のまとめ (1) プログラムは main() 関数の先頭から実行される 関数は main() 関数または他の関数から呼び出されて実行される. 関数を呼び出す側の実引数の値が関数内の仮引数 ( 変数 ) にコピーされる 関数内で求めた値は return 文によって関数値として呼び出し側に戻される. 関数の定義 スタートポイント 関数の呼び出し #include <stdio.h> 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); a, b: 仮引数仮引数もローカル変数 関数内でのみ有効 x,y: 実引数 復習
menseki() 関数内のローカル変数 a と b #include ローカル変数 (1) <stdio.h> float menseki(float a, float b) float s; s = a * b / 2; return s; main() 関数内のローカル変数 a と b int main(void) float a, b, kekka; menseki() 関数 ローカル変数同じ変数名 a, b でも, 関数が違うと, 別の変数と見なされる 赤色 a,b と青色 a,b は別の変数 main() 関数 printf(" 底辺は?"); scanf(" %f ", &a); printf(" 高さは?"); scanf(" %f ", &b); kekka = menseki(); printf(" 面積は %f です. n", kekka); 復習
void キーワード 復習 void は返却値が無いことを宣言 返却値を持たない ( 関数値のない ) 関数の定義 void kansu(float a, float b)... 何も返さないので,return 式 ; return; とは書かない. return 文の省略も可能! int main(void) int x; x = kansu(3, 4); printf("x=%d, %d", x, kansu(2,5)); void 宣言された関数の返却値を利用しようとするとエラー 引数として void と書くと, 引数が無いことを宣言 int func(void) return 5; int main(void) printf(" 値は %d", func());
main() 関数 int main(void) int x = 12; mul10(x); printf("x = %d", x); x = 12 main() 関数 引数の値渡し mul10() 関数 void mul10(int a) a = a * 10; return; 原則引数は関数からコピーバックされない. 呼び出し側の変数 ( 実引数 ) は変化しない. 値渡し (call by value) 関数呼び出し 引数を 10 倍する関数 復習 mul10() 関数 変数 12 x 引数のコピー 引数のコピーバック 120 a 局所変数ローカル変数 return 文実行 例外ポインタ引数, 配列引数 参照渡し (call by reference)
n 個のデータの値を 10 倍する関数 #include <stdio.h> 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; 配列引数 ( 参照渡し ) を用いた関数 データの個数 (n 個 ) を引数とする 理由 : この関数を再利用することを想定. データの個数はいつも 30 個とは限らないので, ループ回数を 30 回に固定したくない 復習 配列引数 : かっこ [ ] のみつける. 要素数を空欄にした配列 data[n] data[0] data 理由 : コンパイラから見たら普通の変数に見えるので 理由 : 配列全体でなく要素を指定しているので 配列引数は参照渡しであるため, 呼び出し側の配列の値が変化する! // 配列 aa に 30 個のデータを入力する for (i = 0; i < 30; i++) printf("%d 番のデータ :", i); scanf("%d", &aa[i]); mul10(aa,30); printf(" データを全て 10 倍すると "); // データの表示 ( 省略 ) 関数内のローカル配列変数 data を変化すると, 呼び出し側の配列 aa も変化 配列を引数とした関数呼び出し配列名のみ書く.([ ] は不要 ) 理由 1: 配列全体を引数としているのでインデックス付けない理由 2: コンパイラはすでに aa が配列であることを知っている 有効なデータの個数は 30 個
配列引数 ( 参照渡し ) における実引数と仮引数 復習 #include <stdio.h> 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]); 実引数配列 aa aa[0] aa[1] aa[2] 仮引数配列 data data[0] data[1] data[2] mul10(aa,30); printf(" データを全て 10 倍すると "); // データの表示 ( 省略 ) aa[29] 配列の実体 data[29] 配列の別名
関数のデバッグ [A] ツールバーでデバッグを始める手順 (1) ツールボタンで右クリックして, デバッグを選ぶ (2) デバッグツールバーからボタンを選ぶ (3) (2) (1) (1) ステップオーバー 次の行を実行 (2) ステップイン 関数内部に入る (3) ステップアウト 関数内部から出る (3) デバッグの中止 デバッグをやめる [B] メニューでデバッグを始める手順 デバッグメニューで, ステップオーバーを選ぶ ステップインは関数内部に入って 1 行づつ実行する ステップアウトは関数内部から呼び出し元にもどる プログラムが長い場合に非常に便利 [C] プログラムの実行を止めたい場所のソースプログラムをポイントして, カーソル行の前まで実行 メニューを使う
プログラミング技術の発達 初期の時代暗黒時代. モジュール化困難. 理解しやすいプログラム, 再利用可能なプログラムができなかった. 初期のFORTRAN, 初期のBASIC,etc... 構造化プログラミングループ制御, 選択制御の整理. ローカル変数の導入 モジュール化が容易. 理解しやすいプログラム, 再利用しやすいプログラムができるようになった. C 言語,Pascal,etc... オブジェクト指向プログラミング一度作成したモジュールの徹底した再利用が可能. プログラミングの考え方の整理 C++,Java,C#,Objective-C 数値計算シミュレーション機械制御 ( ロボット ) 科目名基礎プログラミング応用プログラミング実習 現代のプログラミング技術 グラフィカルユーザーインターフェース (GUI) アプリケーション ( アプリ ) 人工知能 科目名プログラミングプロジェクト演習
オブジェクト指向 オブジェクトを中心としたプログラムの考え方オブジェクト = 物, 全ての事物 事象 オブジェクトの例 人間 機械 人間を表わす要素性別, 名前, 年齢, 身長,,etc. 機械を表わす要素名前, 重さ, 部品の数, 値段 実験データ実験データを表わす要素データ値の個数, データの値
構造体ーオブジェクト指向の第一歩 いくつかの変数をまとめて新しい変数型を作る 例えば 複素数型実部と虚部の float 型の 2 変数からできている 日付型年, 月, 日を表す int 型の 3 変数からできている 学生身体データ型学籍番号 (int 型変数 ) 名前 ( 文字列変数 ) 誕生日 ( 日付型構造体 ) 身長 (float 型変数 ) 体重 (float 型変数 )
例えば, 課題が A 君の誕生日を a,b 君の誕生日を b とし, どちらが早く生まれたか比べなさい 日付 a や日付 b を表す変数があると便利 実際には日付は複数の変数でできている 普通の変数 ( ここでは年 月 日 ) 構造体変数 1999 year 12 month 箱のイメージ 5 day 構造体変数 ( ここでは日付 ) 構造体変数 a の中の year プログラム中では a.year ピリオド 構造体変数 b の中の year プログラム中では b.year year month day a year month day b 引き出しのイメージ ピリオド 同じ構造をした 引き出し 変数を構造体変数と呼ぶ
キーワード struct 構造体変数 a を b に代入 #include <stdio.h> struct Date int year; int month; int day; ; void main() Date a, b; 構造体のプログラム例 (1) ー日付型 Date 型の構造体変数 a と b の宣言 構造体内の変数をメンバ変数と呼ぶ Date 型の構造体の定義 a.year は構造体変数 a のメンバ変数 year を意味する a.year = 2015; a.month = 7; a.day = 1; b = a; b.day = 2; b.day は構造体変数 bのメンバ変数 dayを意味する printf(" 初めの日付は %d 年 %d 月 %d 日,", a.year, a.month, a.day); printf(" 次の日付は %d 年 %d 月 %d 日 n", b.year, b.month, b.day); 初めの日付は 2015 年 7 月 1 日, 次の日付は 2015 年 7 月 2 日 b Date は変数ではなく設計図 a year 2015 month 7 day 1 代入 2015 7 12 year month day
構造体のプログラム例 (2) struct Date int year; int month; int day; ; 構造体変数を宣言すると同時に初期化 void main() Date a = 1998, 6, 28; Date b; b = 1998, 6, 29; Date c[20]; c[15].year = 1998; c[15].month = 6; c[15].day = 28; 同時ではないのでダメエラー Date 型構造体の配列の宣言 Date 型構造体配列のインデックス 15 の要素に値を代入 printf(" 今日は %d 年 %d 月 %d 日 n", c[15].year, c[15].month, c[15].day); この例では配列の添え字 15 には特に意味はない
#include <stdio.h> 構造体のプログラム例 (4) Student 型構造体 s を仮引数とする関数の定義 引き出しの内容 ( 情報 ) を丸ごと引数として受け取るイメージ struct Date int year; int month; int day; ; struct Student ; Student 型構造体のメンバとして文字列を指定 int number; // 学籍番号 char name[20]; // 名前 float height; // 身長 float weight; // 体重 Date birthday; // 誕生日 Student 型構造体のメンバとして Date 型構造体変数を指定 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 型構造体の変数 s の内容を画面表示 注意! s.number number Student 型構造体変数 matsu を実引数とした関数呼び出し
構造体のプログラム例 (5) #include <stdio.h> 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) 注意! a.weight printst(a); weight if (a.weight + 110 > 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() 関数の定義はこの例では省略しているが実際は必要