Transcript 情報基礎演習B
情報基礎演習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の定義…
/* stdio.h */
#include<stdio.h>
int main(void){
printf(“hello!!\n");
return(0);
}
コンパイル前に
プログラムを修正
printfの定義…
fprintfの定義…
scanfの定義…
fscanfの定義…
int main(void){
printf(“hello!!\n");
return(0);
}
マクロ定義 (#define)
1.
文字列の置き換え
2.
#define N 50
マクロの定義
#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自体がポインタみたいなもの
関数への値の渡し方
関数wa
main関数
a,bの値をx,yにコピー
int wa(int x, int y) {
int z;
…
z=x+y;
sum=wa(a, b);
return z;
…
zの値をsumにコピー
}
関数wa(参照渡しversion)
void wa(int *z, int x, int y) {
*z=x+y;
} sumの中身を変更
main関数
…
wa(&sum, a, b);
…
sumのアドレスをzにコピー
配列を関数へ渡す方法
mallocで配列を確保した場合
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);
…