情報基礎演習 b 後半第5回
DESCRIPTION
情報基礎演習 B 後半第5回. 担当 岩村 TA 谷本君. 前回の復習1. 構造体 新しい変数の型を定義する メンバの参照 ドットを用いる. 変数名 . メンバ. 前回の復習2. ファイルポインタの宣言 FILE *fp; ファイルのオープン fp=fopen(“ ファイル名” , “ モード” ); モード r: 読み込み(ファイルがなければエラー) w: 書き込み(既にファイルがあれば破棄して上書き) a: 追加(ファイルがあれば。なければwと同じ) ファイルのクローズ fclose(fp);. 先週の課題. - PowerPoint PPT PresentationTRANSCRIPT
情報基礎演習 B後半第5回
担当 岩村TA 谷本君
前回の復習1 構造体
新しい変数の型を定義する
メンバの参照 ドットを用いる
変数名 . メンバ
前回の復習2 ファイルポインタの宣言 FILE *fp; ファイルのオープン fp=fopen(“ ファイル名” , “ モード” );
モード r: 読み込み(ファイルがなければエラー) w: 書き込み(既にファイルがあれば破棄して上書き) a: 追加(ファイルがあれば。なければwと同じ)
ファイルのクローズ fclose(fp);
先週の課題 任意の人数の名前、身長、体重をファイル
から読み込み、 BMI を計算して出力するプログラムを作成しなさい名前、身長、体重、 BMI を扱う構造体を使うデータファイルは用意してあるものを使う
データファイルの構造 人数、 ( 1人目の ) 名前、身長、体重、 ( 2人目
の ) 名前、身長、体重… ただし身長の単位は cm 、体重は kg
課題の解答
後半の予定1. 関数2. ポインタ(前半)3. ポインタ(後半) & メモリの動的確保4. 構造体 & ファイルの入出力5. プリプロセッサ & 復習 +α
( おまけ ) 文字列処理 & コマンドライン引数の処理
プリプロセッサ コンパイル前にプログラムを書き換える
処理例)
#include <stdio.h> #define N 50
ファイルの挿入( #include )
/* stdio.h */
printf の定義…fprintf の定義…scanf の定義…fscanf の定義…
int main(void){ printf(“hello!!\n"); return(0);}
/* stdio.h */
printf の定義…fprintf の定義…scanf の定義…fscanf の定義…
関数は使う前に定義が必要
#include<stdio.h>
int main(void){ printf(“hello!!\n"); return(0);}
コンパイル前にプログラムを修正
修正後のプログラム
マクロ定義 (#define)
1. 文字列の置き換え #define N 50
2. マクロの定義 #define wa(a,b) a+b
副作用があるので注意が必要
文字列の置き換え コンパイル前に文字列を置き換える 書式
#define 置き換える文字列 置き換えられる文字列 例
#define N 50#define FILENAME “data.txt”
効能後で数値やファイル名などを変えたいとき、一括して
変えられる
マクロの定義 コンパイル前に文字列を置き換えて、関数の
ような処理を行う例)#define wa(a,b) a+b
printf("wa(x,y) = %f\n",wa(x,y));
文字列の置き換えによってwa(x,y)x+y
を実現
マクロの定義と関数の違い 関数との違い
変数の型がない 単にソースコードを変更しただけなので
余計な処理時間がかからない 普通関数を呼び出すと多少時間がかかる マクロは単にソースコードを変更しただけ
注意しないと意図した動作をしない場合がある(副作用)
マクロの定義の副作用 プログラム#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)
括弧がない!
これまでの復習 +α
ポインタについて アドレスを扱う変数 関数の呼び出し方法の違い
1. 値を渡す2. アドレスを渡す ( 配列を渡す )
配列の先頭のアドレスを関数に渡せば、配列を関数に渡したことになる
ポインタ アドレスを扱う変数
具体的には、変数が格納されているメモリの先頭番地を記憶する
動的な配列の確保( malloc ) ポインタを用意すれば、 malloc が配列を確保してくれ
る関数の先頭でなくてもよい配列の大きさはプログラムの実行後に決定可能
一方、配列だと…関数の先頭でないと宣言できない配列の大きさはコンパイル時に決定(定数のみ)
配列でよくある間違いint n;
int a[n];
nは変数!これは malloc でしか実現できない
動的な配列の確保( malloc )の動作
動的でない配列( int a[3] )
a自体がポインタみたいなもの
関数への値の渡し方
int wa(int x, int y) { int z; z=x+y; return z;}
void wa(int *z, int x, int y) { *z=x+y;}
…sum=wa(a, b);…
…wa(&sum, a, b);…
main関数関数 wa
a,b の値を x,y にコピー
関数 wa (参照渡し version ) main関数
zの値を sumにコピー
sum のアドレスを z にコピー
sumの中身を変更
配列を関数へ渡す方法
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 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);…
int a[5] で配列を確保した場合
malloc で配列を確保した場合