16.3 関数と構造体 構造体ポインタ 地底探査ゲーム

Slides:



Advertisements
Similar presentations
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
Advertisements

情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング入門2 第10回 動的な領域確保 情報工学科 篠埜 功.
第13回構造体.
課題解説: 関数の引数にポインタを使って2数を入れ替える
データ構造とアルゴリズム 第10回 mallocとfree
第12回構造体.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
第14章 ファイル操作 (コマンドプロンプト版)
第13回 プログラミングⅡ 第13回
Excelによる3-D/等高線グラフの描画 2変数関数の描画 Excel によるグレイスケールマップ風描画
Excelによる3-D/等高線グラフの描画 2変数関数の描画 Excel によるグレイスケールマップ風描画
第8回 プログラミングⅡ 第8回
構造体.
16.3 関数と構造体 ■ 乱数の発生 ■ 制御コード ■ 列挙型 ■ system関数
第16章 構造体 16.1 構造体の定義と構造体変数 16.2 構造体の配列.
第16章 構造体 16.1 構造体の定義と構造体変数 16.2 構造体の配列.
第3回 配列,構造体,ポインタ ~ データ構造について学ぶための基礎~
第10回 プログラミングⅡ 第10回
第16章 構造体 16.1 構造体の定義と構造体変数 16.2 構造体の配列.
岩村雅一 知能情報工学演習I 第8回(後半第2回) 岩村雅一
情報工学科 3年生対象 専門科目 システムプログラミング 第5回、第6回 ヒアドキュメント レポート課題 情報工学科 篠埜 功.
C言語講座 第3回 ポインタ、配列.
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング論 ファイル入出力
関数とポインタ 値呼び出しと参照呼び出し swapのいろいろ 関数引数 数値積分
16.3 関数と構造体 ■ 乱数の発生 ■ 制御コード ■ 列挙型 ■ system関数
関数と配列とポインタ 1次元配列 2次元配列 配列を使って結果を返す 演習問題
マインスイーパの概要 マインスイーパの準備 マインスイーパの完成 マインスイーパの改良
関数の定義.
第10回関数 Ⅱ (ローカル変数とスコープ).
第11回 宿題 出題日:12月21日 締切日:1月7日(木).
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第2回 ファイル処理 情報・知能工学系 山本一公
プログラミング 4 記憶の割り付け.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第9回関数Ⅰ (簡単な関数の定義と利用) 戻り値.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
第14章 ファイル操作 (コマンドプロンプト版)
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング論 ファイル入出力
16.3 関数と構造体 ■ 乱数の発生 ■ 制御コード ■ 列挙型 ■ system関数
第11回 プログラミングⅡ 第11回
関数の再帰呼び出しとは ハノイの塔 リダイレクト レポート課題
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
配列変数とポインタ 静的確保と動的確保 ポインタ配列 2次元配列 時間計測 第1回レポートの課題
疑似乱数, モンテカルロ法によるシミュレーション
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
プログラミング入門2 第9回 ポインタ 情報工学科 篠埜 功.
Excelによる3-D/等高線グラフの描画 2変数関数の描画 Excel によるグレイスケールマップ風描画
11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 11.5 関数引数
第5回 プログラミングⅡ 第5回
cp-15. 疑似乱数とシミュレーション (C プログラミング演習,Visual Studio 2019 対応)
岩村雅一 知能情報工学演習I 第12回(後半第6回) 岩村雅一
モバイルプログラミング第2回 C言語の基礎 (1).
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
プログラミング演習II 2003年12月10日(第7回) 木村巌.
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
プログラミング入門2 第5回 配列 変数宣言、初期化について
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
Presentation transcript:

16.3 関数と構造体 構造体ポインタ 地底探査ゲーム 第16章 構造体 16.3 関数と構造体 構造体ポインタ 地底探査ゲーム

今日のポイント 構造体、タグ名、メンバーとそれらの 使い方を思い出す! 構造体のデータを関数間でやりとり する場合の仮引数・実引数の使い方  使い方を思い出す! 構造体のデータを関数間でやりとり する場合の仮引数・実引数の使い方 関数値を構造体で戻す方法

中点を求めて出力する関数 center_point のプロトタイプ宣言 16.3 関数と構造体 構造体、タグ名、メンバーとは何だったか? x 座標 y 座標 point プログラム例 16.3.2 から タグ名 struct point { double x; double y; }; 「2つのdouble型から成る構造体に point という名前のブランドタグをつけよう」      という感じ メンバーの宣言 void center_point(struct point p1, struct point p2); 中点を求めて出力する関数 center_point のプロトタイプ宣言 p1, p2 は point というタグがついた構造体変数

構造体とメンバーのアドレス p1 p1.x → 1310568 3.8 p1.y → 1310576 5.6 #include <stdio.h> struct point {double x,y;}; int main(void) { struct point p1; p1.x = 3.8; p1.y = 5.6; printf("%g, %g, (%g, %g)\n", p1.x, p1.y, p1); printf("%u, %u, %u\n", &p1.x, &p1.y, &p1); return 0; } 同じ型ならまとめて書いても良い p1 p1.x → 1310568 3.8 p1.y → 1310576 5.6 メンバーを省略すると 先頭から順にメンバーの 数だけ出力しようとする (VC++の場合)

構造体の配列の構造 #include <stdio.h> struct point {double x,y;}; int main(void) { struct point p[2]; p[0].x = 3.8; p[0].y = 5.6; p[1].x = 7.4; p[1].y = 9.2; printf("(%g, %g), (%g, %g)\n", p[0].x, p[0].y, p[1].x, p[1].y); printf("%u, %u, %u\n", &p[0].x, &p[0].y, &p[0]); printf("%u, %u, %u\n", &p[1].x, &p[1].y, &p[1]); return 0; } p[0] p[0].x → 1310560 3.8 p[0].y → 1310568 5.6 p[1] p[1].x → 1310576 8.4 p[1].y → 1310584 18.2

16.3 関数と構造体 プログラム例 16.3.2 構造体データの引渡し #include <stdio.h> 16.3 関数と構造体 プログラム例 16.3.2 構造体データの引渡し #include <stdio.h> struct point {double x, y;}; void center_point(struct point p1, struct point p2); int main(void) { struct point p1, p2; p1.x = 3.8; p1.y = 5.6; p2.x = 8.4; p2.y = 18.2; center_point(p1, p2); return 0; } 構造体の実引数を関数に引き渡す

16.3 関数と構造体 プログラム例 16.3.2 構造体データの引渡し 16.3 関数と構造体 プログラム例 16.3.2 構造体データの引渡し 仮引数が構造体である関数の定義 void center_point(struct point p1, struct point p2) { double xm, ym; xm = (p1.x + p2.x) / 2.; ym = (p1.y + p2.y) / 2.; printf("(%g, %g) と (%g, %g) の中点の座標は (%g, %g)\n", p1.x, p1.y, p2.x, p2.y, xm, ym); } メンバーを用いて計算 出力はメンバーで

構造体変数 p3 のアドレスを関数に引き渡して結果を受け取る 16.3 関数と構造体 関数から結果を構造体で 受け取る → 構造体ポインタ プログラム例 16.3.2改 #include <stdio.h> struct point {double x, y;}; void center_point(struct point p1, struct point p2, struct point *p3); int main(void) { struct point p1, p2, p3; p1.x = 3.8; p1.y = 5.6; p2.x = 8.4; p2.y = 18.2; center_point(p1, p2, &p3); printf("(%g, %g) と (%g, %g) の中点の座標は (%g, %g)\n", p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); return 0; } 結果を受け取る構造体 p3 を用意 構造体変数 p3 のアドレスを関数に引き渡して結果を受け取る 出力はメンバーで

16.3 関数と構造体 プログラム例 16.3.2改 関数から結果を構造体で 受け取る → 構造体ポインタ 16.3 関数と構造体 関数から結果を構造体で 受け取る → 構造体ポインタ プログラム例 16.3.2改 void center_point(struct point p1, struct point p2, struct point *p3) { (*p3).x = (p1.x + p2.x) / 2.; (*p3).y = (p1.y + p2.y) / 2.; } 仮引数が構造体ポインタである関数の定義 メンバーを用いて計算 構造体ポインタの場合、選択演算子(アロー演算子) "->" でメンバーを指定 (*p3).x p3 -> x (*p3).y p3 -> y p3 -> x = (p1.x + p2.x) / 2.; p3 -> y = (p1.y + p2.y) / 2.; は に書き換えて

16.3 関数と構造体 プログラム例 16.3.2改 関数から結果を構造体で 受け取る → 構造体ポインタ 16.3 関数と構造体 関数から結果を構造体で 受け取る → 構造体ポインタ プログラム例 16.3.2改 void center_point(struct point p1, struct point p2, struct point *p3) { p3 -> x = (p1.x + p2.x) / 2.; p3 -> y = (p1.y + p2.y) / 2.; printf("p3 -> x = %g, p3 -> y = %g\n", p3 -> x, p3 -> y); printf("(*p3).x = %g, (*p3).y = %g\n", (*p3).x, (*p3).y); printf("&p3 -> x = %u, &p3 -> y = %u\n", &p3 -> x, &p3 -> y); printf("&(*p3).x = %u, &(*p3).y = %u\n", &(*p3).x, &(*p3).y); } 仮引数が構造体ポインタである関数の定義 メンバーを用いて計算 優先順位はポインタ演算子よりもメンバー演算子のほうが高いことに注意 *p3.x は *(p3.x) と解釈されるので、p3 がポインタの場合は間違いとなる。

16.3 関数と構造体 プログラム例 16.3.2改2 関数から結果を構造体で 受け取るもう1つの方法 16.3 関数と構造体 関数から結果を構造体で 受け取るもう1つの方法 プログラム例 16.3.2改2 #include <stdio.h> struct point {double x, y;}; struct point center_point(struct point p1, struct point p2); int main(void) { struct point p1, p2, p3; p1.x = 3.8; p1.y = 5.6; p2.x = 8.4; p2.y = 18.2; p3 = center_point(p1, p2); printf("(%g, %g) と (%g, %g) の"中点の座標は (%g, %g)\n", p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); return 0; } 戻り値が構造体であることを宣言 結果を受け取る構造体 p3 を用意 結果の構造体を関数から戻り値で受け取る 出力はメンバーで

16.3 関数と構造体 プログラム例 16.3.2改2 関数から結果を構造体で 受け取るもう1つの方法 16.3 関数と構造体 関数から結果を構造体で 受け取るもう1つの方法 プログラム例 16.3.2改2 戻り値が構造体である関数の定義 struct point center_point(struct point p1, struct point p2) { struct point p; p.x = (p1.x + p2.x) / 2.; p.y = (p1.y + p2.y) / 2.; return p; } 結果を入れる構造体を用意 メンバーを用いて計算 結果を構造体で返す

地底探検ゲーム(undergnd.c) ■■ ■ ■ ■ ■ ■ ■ ■☆ ■ ■ ■ 距離 0 m: 4←→6 ↓=2 ギブアップ=0: 10 ■■ ■     ■ ■   ■    ■ ■  ■☆    ■ ■        ■ 距離 0 m: 4←→6 ↓=2 ギブアップ=0: 現在地 4 ブロック もぐった距離 テンキーで入力 左右にブロックを避けながら下にすすんでいき、進めなくなったところまでの距離(スコア)を競うゲーム

地底探検ゲーム(undergnd.c) 講義資料のWebページからダウンロード #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* 地面を格納する構造体の宣言 */ struct ground { int block[10]; // 地下情報を格納する配列の宣言 char blockStr[21]; // 地下ブロックパターン }; 乱数発生に必要 乱数初期化に必要 g[0].block = {1, 0, 0, 1, 0, 0, 0, 1, 0, 1} g[0].blockstr ■__■___■_■ 2バイト文字なので倍のサイズが必要 + \0 → 21バイト

地底探検ゲーム(undergnd.c) /* 地面を作成する関数 */ void makeGround(struct ground *p) { int i; char *wall[] = { " ", "■" }; /* 左の壁 */ p??block[0] = 1; strcpy(p??blockStr, wall[1]); /* 中央のブロックパターン */ for (i = 1; i <= 8; i++) { p??block[i] = rand() % 4 ? 0 : 1; // 確率1/4でブロック発生 strcat(p??blockStr, wall[p??block[i]]); } /* 右の壁 */ p??block[9] = 1; strcat(p??blockStr, wall[1]); 3バイトの文字列2つの配列 "■" 4で割り切れたら0:偽→1, 割り切れなければ1~3:真→0 対応する位置にブロックを置く "■"

地底探検ゲーム(undergnd.c) 現在地記憶用変数 int main(void) { ギブアップチェック用フラグ int i, score = 0, x = 4, key = 1; struct ground g[4]; // 地面の構造体配列(4層分) /* 最初の地面の作成 */ srand(time(NULL) % 100); // 乱数シード:現在時刻の100の剰余 for (i = 0; i < 4; i++) makeGround(g + i); /* メインループ */ while (key) { /* 画面表示 */ strncpy(g[2]?blockStr + x * 2, "☆", 2); for (i = 0; i < 4; i++) printf("%s\n", g[i]?blockStr); strncpy(g[2]?blockStr + x * 2, " ", 2); ギブアップチェック用フラグ 現在地マーク の埋め込み 構造体配列の ポインタで引渡し 4層分の地面を描画 次回の印刷時に前回の☆印が残らないよ うに2バイト分の空白で事前に消しておく

地底探検ゲーム(undergnd.c) /* キー入力 */ printf("距離 %d m: ", score); scanf("%d", &key); /* 移動 */ if (key == 4 && g[2]?block[x - 1] == 0) x--; else if (key == 6 && g[2]?block[x + 1] == 0) x++; else if (key == 2 && g[3]?block[x] == 0) { for (i = 0; i < 3; i++) g[i] = g[i + 1]; makeGround(g + 3); score++; } /* 終了処理 */ printf("スコア: %d メートル!\n", score); return 0; 左に移動 右に移動 下に移動 1段下から 順にコピー 最下層の新規作成

スキルアップタイム1 地底探検ゲーム(undergnd.c)を完成させ、コンパイル・実行して動作を確認せよ 地面の深さや幅を変えるにはどこを変更すればよいか、検討せよ 地面の深さや幅を変えやすいようにソースを改良し(undergnd1.c)、深さを1、幅を2、増やせ(4→5, 10→12)。 ただし、現在地は常に下から2層目とする

スキルアップタイム2 ファイル入出力関数の利用により、「ハイスコアの表示・保存機能」を付け足せ(保存ファイル名はhighscr.txt) ソース名は"undergnd2.c"とせよ

スキルアップタイム2のヒント int highscore=0; FILE *fp; ... if ((fp = fopen("highscr.txt", "r")) != NULL) { fscanf(fp, "%d", &highscore); fclose(fp); } if (score > highscore) { printf("ハイスコアです!\n"); fp = fopen("highscr.txt", "w"); fprintf(fp, "%d\n", score); } else printf("ハイスコア: %d メートル\n", highscore); ハイスコアの初期値 ハイスコアファイルがある場合に読み込む ハイスコアの場合にファイルに書き込む

第4回レポート(任意) 課題: スキルアップタイム1または2 提出期限: 2010年2月4日(金) 12:50 提出場所: ネットワーク実験室(1)入口の提出箱 以下の項目を入れること(表紙は不要) 学籍番号、氏 名 "undergnd1.c"または"undergnd2.c"のソースリスト 3.実行結果の例(変更したことがわかる部分だけ残し、後は省略してよい)  4.感 想

本日のパズル このプログラムは何を出力するか #include <stdio.h> #define PR(value) printf(#value"=%d ",(value)) #define NL putchar('\n') #define PRINT3(x1,x2,x3) PR(x1),PR(x2),PR(x3),NL int a[2][3] = {{1,2,3},{4,5,6}}; int main(void) { int i; for (i=0; i<2; i++) PRINT3(a[i][2-i], *a[i], *(*(a+i)+i)); return 0; }