物理情報処理基礎実習II 第13回

http://www.phys.ynu.ac.jp/labs/cosmic/shibata/jisshu/
物理情報処理基礎実習II
第13回
ポインタ
ファイル入出力
(原 [email protected])
柴田 [email protected]
石川 [email protected]
§課題11aプログラム(データ処理)
script コマンドが 2006年01月13日 (金) 17時07
分13秒 で起動されました。
aplsrvky01% cat kadai11a.c
1. #include <stdio.h>
2. main()
3. {
4.
int i,k;
5.
int n=0;
/* no. of student n=30; */
6.
int wrk1; /* work variable */
7.
int stid[100],stpt[100];/* id & point */
8.
/* read data */
9.
for(i=0;i<100;i++){
10.
if(scanf("%d %d",&stid[i],&stpt[i])!=2)
11.
break;
12.
}
13.
n=i;
/* number of student */
14.
15. /* sort */
16. for(i=0;i<n-1;i++){
17.
for(k=i+1;k<n;k++){
18.
if(stpt[k]>stpt[i]){
19.
wrk1=stpt[i];
20.
stpt[i]=stpt[k];
21.
stpt[k]=wrk1;
22.
wrk1=stid[i];
23.
stid[i]=stid[k];
24.
stid[k]=wrk1;
25.
}
26.
}
27. }
28. /* print */
29. printf(" No. student id point\n");
30. for(i=0;i<n;i++){
31.
printf("%3d) %07d %5d\n",i+1,
32.
stid[i],stpt[i]);
33. }
34. }
§課題11a解答例 (データ処理)
aplsrvky01% cc kadai11a.c -o kadai11a
aplsrvky01% ./kadai11a < seiseki.d
No. student id point
1) 0945012 100
2) 0945030 85
3) 0945028 71
4) 0945019 70
5) 0945001 69
6) 0945004 63
7) 0945027 63
8) 0945029 62
9) 0945008 61
10) 0945026 61
11) 0945021 56
12) 0945003 55
13) 0945011 55
14) 0945022 52
15) 0945015 51
16) 0945005 49
17) 0945002 48
18) 0945007 46
19) 0945025 43
20) 0945009 43
21) 0945018 42
22) 0945006 42
23) 0945017 41
24) 0945014 37
25) 0945010 33
26) 0945024 32
27) 0945023 28
28) 0945013 27
29) 0945016 18
30) 0945020 6
aplsrvky01% exit
aplsrvky01%
§課題11bプログラム(talor展
開)
aplsrvky01% cat kadai11b.c
printf("%5.2lf %13.10lf %13.10lf\n",xi,ex,pn);
}
#include <stdio.h>
}
#include <math.h>
main()
別解
{
main()
{
int i,m,n=6; /* order of talor series */
int i,n=6;
/* order of talor series */
double xi,ex,pn;
double xi,ex,pn;
double b;
printf(" x exp(x)
polunomial\n");
printf(" x exp(x)
polunomial\n");
for(xi=0.0;xi<=1.0001;xi+=0.05){
for(xi=0.0;xi<=1.0001;xi+=0.05){
ex=exp(xi);
/* intrinsic function */
ex=exp(xi); /* intrinsic function */
pn=1.0+xi/n;
/* talor series */
pn=1.0; m=1; b=1./* talor series */
for(i=n-1;i>0;i--){
for(i=1;i<=n;i++){
pn=1.0+pn*xi/i;
}
m=m*i;
/* print */
b=b*xi;
printf("%5.2lf %13.10lf %13.10lf\n",xi,ex,pn);
pn=pn+b/m;
}
}
}
§課題11b解答例 (talor展開)
aplsrvky01% cat kadai11b.c
0.55 1.7332530179
aplsrvky01% cc kadai11b.c -lm -o kadai11b 0.60 1.8221188004
aplsrvky01% ./kadai11b
0.65 1.9155408290
x exp(x)
polunomial
0.70 2.0137527075
0.00 1.0000000000 1.0000000000
0.75 2.1170000166
0.05 1.0512710964 1.0512710964
0.80 2.2255409285
0.10 1.1051709181 1.1051709181
0.85 2.3396468519
0.15 1.1618342427 1.1618342424
0.90 2.4596031112
0.20 1.2214027582 1.2214027556
0.95 2.5857096593
0.25 1.2840254167 1.2840254042
1.00 2.7182818285
0.30 1.3498588076 1.3498587625
aplsrvky01% exit
0.35 1.4190675486 1.4190674151
0.40 1.4918246976 1.4918243556
0.45 1.5683121855 1.5683114002
0.50 1.6487212707 1.6487196181
1.7332497761
1.8221128000
1.9155302511
2.0137348181
2.1169708252
2.2254947556
2.3395757901
2.4594963625
2.5855527292
2.7180555556
§課題12フローチャート(5角形の面積)
main 5角形の面積
プロトタイプ宣言
出力/終了
辺と対角線データセット
引数
△ABCの面積
△ACEの面積
関数 3角形の面積
3角形の面積
S=ヘロンの公式
△CDEの面積
5角形△ABCDE
の面積
戻り値 S
終了
3角形の3辺
§アドレス
プログラム(ソフトウェア)は、
計算機(ハードウェア)のメモリに複製されて※、
実際の動作をすることになる。
※この動作をロードという
つまり、プログラム内の変数は、
計算機のメモリのどこかにあり、
この場所をメモリアドレスという。
実際にいくつか、は知らなくても問題ないが、
変数に代入して使えると非常に便利になる。
注)アドレスと変数の説明図
§ポインタ
C言語では、
メモリアドレスをポインタという概念で扱える。
ポインタ型変数
メモリアドレス専用の変数。
指し示す変数によって~型へのポインタという。
宣言方法
変数の型 *ポインタ変数名
そのメモリアドレスが示す変数の型ごとに宣言
ex.) double *p
配列(文字列含む)へのポインタ
配列名がそのままポインタになる。
ex.) int s[3] → s は、配列s[ ]へのポインタ
§ポインタに関する演算子
アドレス演算子&
変数のアドレスの求める演算子。
ex.) 変数 a のアドレス → &a
※実はscanfとかで既に使ってる。
※条件式の&&と間違えないように!
※更に言うと、ビット演算子&とも紛らわしい!
間接演算子*
ポインタ型変数の指す変数の値を求める演算子。
ex.) ポインタ p の指す変数の値 → *p
※乗算の*とは違う(やっぱり紛らわしい)
§ポインタを使用する
ポインタ型変数を使うときは、
必ず、指し示す先の変数を用意すること!
ex.)
int d ;
※整数型で d を宣言
int *p ;
※整数型へのポインタ p を宣言
p = &d ;
※ d のアドレスを p に代入
※これでpは、d へのポインタとなる(図参照)。
※ int *p=&d と、宣言時に初期化しても良い。
ポインタ型変数の演算
ここでは詳解しない(難しい割に使い道が…)。
教科書p.176を参照のこと
§値渡しと参照渡し
実用性が高いポインタの使用方法
→ 関数への参照渡し
値渡しと参照渡し
→ 値渡し
引数は値だけ複製されて使用される
引数をアドレスにする → 参照渡し
引数を直接変化させることが出来てしまう
※今まで使ってきたのは殆ど値渡し。
引数は変数そのもの
参照渡しの良いところ
関数内での計算結果が複数の数値になるとき。
関数の引数が配列である(先週やったよ)。
引数をそのまま計算結果に置き換えられる。
§値渡しと参照渡しの違い
 値渡しの例
#include <stdio.h>
2. void func(int) ;
3. main(){
4.
int a = 1 ;
5.
printf(“%d\n”,a) ;
6.
func(a) ;
7.
printf(“%d\n”,a) ;
8. }
9. void func(int x){
10.
x=2;
11. }
1.
 aは1のまま。
 参照渡しの例
#include <stdio.h>
2. void func(int *) ;
3. main(){
4.
int a = 1 ;
5.
printf(“%d\n”,a) ;
6.
func(&a) ;
7.
printf(“%d\n”,a) ;
8. }
9. void func(int *x){
10.
*x = 2 ;
11. }
1.
 aは2になる!
§配列を引数とすると参照渡し

配列が引数の例
1. #include <stdio.h>
2. void func(int [],int) ;
3. main(){
4.
int a[2]={0,1};
5.
printf("a[0]=%d a[1]=%d\n",a[0],a[1]);
6.
func(a,2) ;
7.
printf(“a[0]=%d a[1]=%d\n”,a[0],a[1]) ;
8. }
9. void func(int v[],int n){
10.
int i;
11.
for(i=0;i<n;i++){v[i]=(i+1)*5;}
12. }
 最初は a[0]=0 a[1]=1;
2番目は a[0]=5 a[1]=10;
§ファイル入出力
cf. 教科書p.212~
ファイルアクセス
ライブラリ関数を使う。
このため、OSごとに使い方が多少違う可能性がある。
ファイルへのアクセス手順
ファイルを開く
読んだり書いたりする
ファイルを閉じる
※結局、Windowsとかで文章書くのと一緒。
§ファイルを開く
まず、ファイル専用のポインタを宣言しておく。
FILE *fp ;
※上記は例、ポインタは当然fp以外でも良い。
※構造体FILEを使用するが、ここでは解説を省く。
次に関数fopenを用いてファイルを開く
fp = fopen(“ファイル名”, “モード”) ;
モードは以下のどれかを使う
 “r”
読み込みモード(Read only)
ファイルが無ければエラーになる。
 “w” 書き込みモード(Write)
ファイルが無ければ自動で生成され、あれば上書きされる。
 “a” 追加書き込みモード(Append)
ファイルが無ければ自動で生成され、あれば追記される。
§読んだり書いたり閉じたり
ファイルからの読み込み
fscanf(fp,
“%dとか”, 変数アドレスのリスト)
※要するにscanfのファイル版。fpが増えただけ。
ファイルへの書き込み
fprintf(fp,
“%dとか”, 変数リスト)
※要するにprintfのファイル版。fpが増えただけ。
ファイルを閉じる
fclose(fp)
※開くのは面倒だったが、閉じるのはこれだけ。
§ファイル操作例 -I- 書き出し
 0 ~ 10を0.1刻みで生成し、
ファイルkadai13t.txtに出力する。
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
#include <stdio.h>
main(){
char filename[] = “kadai13t.txt”; ※ファイル名の設定
FILE *fp1;
※ファイル構造体の宣言
double x;
fp1 = fopen(filename, “w”);
※ファイルをwモードで開く
for(x=0 ; x<=10 ; x+=0.1){
fprintf(fp1, “%lf\n”, x);
※ファイルに書き出す
}
fclose(fp1);
※ファイルを閉じる
}
§ファイル操作例 -II- 読み込み
 今作ったファイルkadai13t.txtを読み込んで表示。
#include <stdio.h>
2. main(){
3.
char filename[] = “kadai13t.txt”;
4.
FILE *fp2;
5.
double x;
6.
fp2 = fopen(filename, “r”);
※ファイルをrモードで開く
7.
while(fscanf(fp2, “%lf”,&x)!=EOF){ ※終わりまで読む
8.
printf(“%lf\n”, x);
9.
}
10. fclose(fp2);
11. }
1.
§課題13 -I kadai13t.txt を媒介変数tとして読み込み、極
座標で書き表された次の曲線の点座標を、直
交座標に変換し、
ファイル“kadai13xy.txt”に出力せよ。
ただし、座標変換は関数を作って処理すること。
 r  t2t
f ( r , )  
  t
 出力形式は次の様でよい。“%lf %lf\n”,x ,y
 kadai13xy.txt は、来週の授業で使うので消さ
ないこと。
§課題13 -II考え方のポイント(ヒント)
読込と書出で、ファイルは2個開く必要がある。
ファイル構造体も2個定義する必要。
極座標を直交座標に変換する関数を作る。
引数は r とθ、でも戻り値がxとyと2個!?
xとyも参照渡しで関数を作ればよい。
例えば change(r, theta, &x, &y) 等々。
座標変換は関数にする条件があるが、
他に関数はいくつ作ってもかまわない。
おまけ
次回は最終回、
C言語の話から離れて、
「gnuplot」というグラフ作成ソフトの使い方。
今日の課題で作った、
データファイルを描画させたりするよ。