鹿児島大学 プログラミング基礎演習 第8回 関数(2) 独立性 半田利弘 鹿児島大学 大学院理工学研究科 物理・宇宙専攻 理化学研究所 関数の独立性 ▶ 関数の定義と引用 ■ ■ 引数の順位だけで対応 型が合っていないとまずい ▶ 関数内部の変数は呼び出し元には影響なし ■ 関数の内外は引数と戻り値でしか関連しない 理化学研究所 関数の独立性 ▶ C言語ではメモリー空間は関数ごとに独立 ■ 引数は呼び出し元と関数内では別アドレス 呼び出し時に値をコピーしている 関数内で変数値を変えても呼び出し元は変わらない 理化学研究所 プログラムで確かめる ▶ List8-2の引数 ■ 違う変数名でも引数位置が同じなら同じ値になる #include <stdio.h> float calc(float xx); int main(void); float calc(float price) /* 割引価格を求める */ { float waribki; waribiki=price*0.7; return(waribki); } int main(void) { float xx,yy; xx=10000.0; yy=calc(xx); printf("通常価格%.0f円のところ",xx); printf("今回は特別に%.0f円でご提供\n",yy);理化学研究所 return(0); } プログラムで確かめる ▶ 関数内外では同じ変数名でも無関係 #include <stdio.h> float calc(float xx); int main(void); float calc(float price) /* 割引価格を求める */ { float waribki; waribiki=price*0.7; return(waribki); } int main(void) { float xx,yy,waribiki; xx=10000.0; yy=calc(xx); waribiki=3.0; printf("通常価格%.0f円のところ",xx); printf("今回は特別に%.0f割引で",waribiki); printf("%.0f円でご提供\n",yy); 理化学研究所 return(0); } 関数の独立性(advanced) ▶ C言語ではメモリー空間は関数ごとに独立 ■ 関数が終了すると変数値は保存しない 保存したい場合は、変数をstaticで宣言する ▶ 自動(auto)変数と静的(static)変数 ■ ■ auto:ブロックが終了するとOSに返してしまう static:プログラムが終了するまでメモリを確保 ソースのファイルが異なると別のメモリに割付られる ■ 大域(global)変数というのもあるが使うべきでない 理化学研究所 頭を使えば99%回避できる プログラムで確かめる List8-3改2 #include <stdio.h> void print_graph(int xx); int main(void); void print_graph(int xx) /* 棒グラフを*で書く */ { int ii; printf("ii=%d\n",ii); for(ii=0;ii<xx;ii++) { printf("*"); } printf("\n"); return; } int main(void) { int xx: xx=10; print_graph(xx); print_graph(5); return(0); } 理化学研究所 プログラムで確かめる List8-3改3 #include <stdio.h> void print_graph(int xx); int main(void); void print_graph(int xx) /* 棒グラフを*で書く */ { static int ii; printf("ii=%d\n",ii); for(ii=0;ii<xx;ii++) { printf("*"); } printf("\n"); return; } 関数が終わっても覚えておく int main(void) { int xx: xx=10; print_graph(xx); print_graph(5); return(0); } 理化学研究所 staticはどんなときに使う?(1) ▶ 呼び出した回数で内容が変わる時 #include <stdio.h> void print_graph(int xx); int main(void); void print_graph(int xx) { static nankai=0; int ii; char mark; if(nankai>1) mark='o'; else mark='*'; for(ii=0;ii<xx;ii++) { printf("%c",mark); } printf("\n"); nankai++; return; } int main(void) { int xx: xx=10; print_graph(xx); print_graph(xx*2); print_graph(5); return(0); } 理化学研究所 staticはどんなときに使う?(2) ▶ 前の結果を次の呼び出しで使いたい時 #include <stdio.h> void print_graph(int xx); int main(void); void print_graph(int xx) { static int last_xx=0; int ii; char mark; for(ii=0;ii<xx;ii++) { printf("%c",mark); } printf("\n"); if(last_xx>5) mark='o'; else mark='*‘; last_xx=xx; return; } int main(void) { int xx: xx=10; print_graph(xx); print_graph(xx*2); print_graph(5); return(0); } 理化学研究所 複数変数の関数 ■ List8-4(教科書p.192) #include <stdio.h> int GetPower(int xx, int nn); int main(void); int GetPower(int xx, int nn) /* 整数のべき乗を得る */ { int ii, jj=1; for(ii=0;ii<nn;ii++) { yy=yy*xx; } return(yy); } 引数とその型宣言を「,」区切 りで並べて書く int main(void) { int zz; zz=GetPower(8,2); printf("%d\n",zz); return(0); } 引数を「,」区切り で並べて書く 理化学研究所 main関数 ▶ 1つのプログラムの最上位となる関数 ▶ 先頭のおまじない int main(void) ■ ■ ■ main関数の定義宣言だった 「void」は引数がないことの明示 実は、int main(int argc, char **argv)とすべき 「char **」ってなに?→後でね ▶ 呼び出し元はOS 理化学研究所 ゲームに必須の関数 ▶ 乱数(でたらめな数)を返す、サイコロを振る ▶ int rand(void); ■ ■ ■ #include <stdlib.h> “種”から乱数もどきを作る 0~RAND_MAXの間の整数値 RAND_MAXの値はコンパイラーによる 必要な最大値で割ったあまりを使う 理化学研究所 乱数発生関数 ▶ 使用例 ListA-1.c #include <stdio.h> #include <stdlib.h> int main(void); int main(void) { saidaiで割って切り捨て int xx, yy, saidai=10; saidaiで割った最少倍数 xx=rand(); printf("xx=%d\n",xx); yy=(xx/saidai)*saidai; yy=xx-yy; printf("yy=%d\n",yy); return(0); } 理化学研究所 saidaiで割った余り 疑似乱数の実行 ▶ ListA-1.cをコンパイルして実行 ▶ あれ、いつも同じ数… 理化学研究所 疑似乱数の“疑似”とは ▶ いつでも同じ種だと同じ順に数値が出る ■ “種”を変えないといつも同じ ▶ void srand(unsigned int ii); ■ ■ ■ #include <stdlib.h> rand()に種seedを与える関数 種はどうやって与えても良い プレーヤーの年齢 プレーヤーの名前の文字コードとか ゲームを始めた時刻とか 理化学研究所 現在時刻を得る関数 ▶ time_t time(void); ■ ■ #include <time.h> 現在時刻を返す 値:1970年1月1日0時からの通算秒数 time_tがlong型だと、そろそろ桁あふれするので注意 2038年問題 理化学研究所 現在時刻を疑似乱数の種に… ▶ time()の戻り値を疑似乱数の種にする ▶ main関数の先頭近くで ■ srand((unsigned int)time()); ▶ を実行すれば良い。 理化学研究所 乱数発生 ▶ 改良版ListA-2.c #include <stdio.h> #include <stdlib.h> #include <time.h> int std_rand(int saidai); int main(void); int std_rand(int saidai) { int xx, yy; xx=rand(); yy=(xx/saidai)*saidai; yy=xx-yy; return(yy); } int main(void) { int xx, ii; /* 乱数の初期化 */ srand((unsigned int)time(NULL)); for(ii=0;ii<15;ii++) { xx=std_rand(10); printf("%d, ",xx); } printf("\n"); return(0); } 理化学研究所 期末課題 ▶ 最終回の授業で自作ゲームの紹介 ■ ■ ■ ■ ■ 個人またはチームごとで1作、1チーム1~3名 全員、いずれかのチームに所属すること C言語で作成する 主な動作とプログラムで工夫した部分の解説 発表は5分、質疑応答3分を想定 理化学研究所
© Copyright 2024 ExpyDoc