Presentation is loading. Please wait.

Presentation is loading. Please wait.

情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.

Similar presentations


Presentation on theme: "情報基礎演習B 後半第5回 担当 岩村 TA 谷本君."— Presentation transcript:

1 情報基礎演習B 後半第5回 担当 岩村 TA 谷本君

2 前回の復習1 構造体 新しい変数の型を定義する メンバの参照 ドットを用いる 変数名.メンバ

3 前回の復習2 ファイルポインタの宣言 FILE *fp; ファイルのオープン fp=fopen(“ファイル名”, “モード”);
r: 読み込み(ファイルがなければエラー) w: 書き込み(既にファイルがあれば破棄して上書き) a: 追加(ファイルがあれば。なければwと同じ) ファイルのクローズ fclose(fp);

4 先週の課題 任意の人数の名前、身長、体重をファイルから読み込み、BMIを計算して出力するプログラムを作成しなさい
データファイルは用意してあるものを使う データファイルの構造  人数、(1人目の)名前、身長、体重、 (2人目の)名前、身長、体重… ただし身長の単位はcm、体重はkg

5 課題の解答

6 後半の予定 関数 ポインタ(前半) ポインタ(後半) & メモリの動的確保 構造体 & ファイルの入出力 プリプロセッサ & 復習+α
  (おまけ)文字列処理 & コマンドライン引数の処理

7 プリプロセッサ コンパイル前にプログラムを書き換える処理 例) #include <stdio.h> #define N 50

8 ファイルの挿入(#include) 関数は使う前に定義が必要 /* stdio.h */ printfの定義… fprintfの定義…
修正後のプログラム /* stdio.h */ printfの定義… fprintfの定義… scanfの定義… fscanfの定義… /* stdio.h */ printfの定義… fprintfの定義… scanfの定義… fscanfの定義… #include<stdio.h> int main(void){ printf(“hello!!\n"); return(0); } int main(void){ printf(“hello!!\n"); return(0); } コンパイル前に プログラムを修正

9 マクロ定義 (#define) 文字列の置き換え マクロの定義 #define N 50 #define wa(a,b) a+b
副作用があるので注意が必要

10 文字列の置き換え コンパイル前に文字列を置き換える 書式 例 効能 #define 置き換える文字列 置き換えられる文字列
#define N 50 #define FILENAME “data.txt” 効能 後で数値やファイル名などを変えたいとき、一括して変えられる

11 マクロの定義 コンパイル前に文字列を置き換えて、関数のような処理を行う 例) #define wa(a,b) a+b
printf("wa(x,y) = %f\n",wa(x,y)); 文字列の置き換えによって wa(x,y)x+y を実現

12 サンプルプログラム1(マクロの定義) #define wa(a,b) a+b #include<stdio.h>
int main(void){ float x, y; printf("x: "); scanf("%f", &x); printf("y: "); scanf("%f", &y); printf("wa(x,y) = %f\n",wa(x,y)); return(0); }

13 マクロの定義と関数の違い 関数との違い 変数の型がない 余計な処理時間がかからない 注意しないと意図した動作をしない場合がある(副作用)
単にソースコードを変更しただけなので 余計な処理時間がかからない 普通関数を呼び出すと多少時間がかかる マクロは単にソースコードを変更しただけ 注意しないと意図した動作をしない場合がある(副作用)

14 マクロの定義の副作用 プログラム #define kake(a,b) a*b
printf("wa(x,y) = %f\n",kake(x,y+10)); マクロの展開 kake(x,y+10)x*y+10 ≠x*(y+10) 括弧がない!

15 これまでの復習+α ポインタについて アドレスを扱う変数 関数の呼び出し方法の違い 値を渡す アドレスを渡す(配列を渡す)
配列の先頭のアドレスを関数に渡せば、配列を関数に渡したことになる

16 ポインタ アドレスを扱う変数 具体的には、変数が格納されているメモリの先頭番地を記憶する

17 動的な配列の確保(malloc) ポインタを用意すれば、mallocが配列を確保してくれる 一方、配列だと… 関数の先頭でなくてもよい
配列の大きさはプログラムの実行後に決定可能 一方、配列だと… 関数の先頭でないと宣言できない 配列の大きさはコンパイル時に決定(定数のみ) 配列でよくある間違い int n; int a[n]; nは変数! これはmallocでしか実現できない

18 動的な配列の確保(malloc)の動作

19 動的でない配列(int a[3]) a自体がポインタみたいなもの

20 関数への値の渡し方 関数wa main関数 a,bの値をx,yにコピー int wa(int x, int y) { int z;
z=x+y; return z; } sum=wa(a, b); zの値をsumにコピー 関数wa(参照渡しversion) main関数 void wa(int *z, int x, int y) { *z=x+y; } wa(&sum, a, b); sumの中身を変更 sumのアドレスをzにコピー

21 サンプルプログラム(関数へ配列を渡す) a = (int *)malloc(sizeof(int)*n); ポインタを渡す=配列を渡す
#include <stdio.h> int wa_all(int n, int *a) { int i, t=0; for (i=0; i<n; i++) { t += a[i]; } return(t); int main(void) { int *a, n=5, total, i; a = (int *)malloc(sizeof(int)*n); if (a==NULL) { printf("Cannot allocate memory\n"); exit(1); } for (i=0; i<n; i++) { a[i] = i; total = wa_all(n, a); printf("Total: %d\n", total); free(a); return(0); ポインタを渡す=配列を渡す

22 配列を関数へ渡す方法 mallocで配列を確保した場合 int a[5]で配列を確保した場合
int wa_all(int n, int *a) { int i, t=0; for (i=0; i<n; i++) { t += a[i]; } return(t); int *a, n=5, total; a = (int *)malloc(sizeof(int)*n); total = wa_all(n, a); free(a); int a[5]で配列を確保した場合 int wa_all(int n, int a[]) { int i, t=0; for (i=0; i<n; i++) { t += a[i]; } return(t); int a[5], n=5, total; total = wa_all(n, a);


Download ppt "情報基礎演習B 後半第5回 担当 岩村 TA 谷本君."

Similar presentations


Ads by Google