プログラミングⅠ

プログラミングⅠ
Report#5
提出期限 : 6月19日(木)
所属 : 情報工学科
学籍番号 : 085762K
氏名 : 谷津 和平
目次
1:サンプルファイルの分析
P1~2
2:makeを使う下準備として1つのプログラムの中に3つの関数を使用したプログラ
ム
P2~4
3:makeコマンドを使い、プログラムを翻訳単位に分けて同様なプログラムを作る
P4~7
4:平均からの差でA,B,C,D,Fの評価をつけるプログラム
P7~8
5:変数のスコープと記憶域クラスについて考察せよ
P9
感想&参考文献
P10
1. 次のプログラムは外部変数に定義され、初期化された10個のint型データ
の平均を求め、各データと平均との差を表示するプログラムである。このプロ
グラムを以下のような関数の翻訳単位にファイルを分け、同様な動作をするプ
ログラムを作成せよ。
型
����� �float
�������void
関数名
������ get_ave
print_data
引数・パラメータ
なし
配列の添字、平均
値
機能
平均値を求め表
示
1つのデータと平均
値との差を求め表
示
戻り値
平均値
なし
【サンプルソースコード;average.c】
______________________________________________________________________
1
/*
2
program
: average.c
3
comments : 結合(linkage)を用いて、平均・差を求める。
4
*/
5
6
#include <stdio.h>
7
8
int score[10]={3,5,8,9,10,6,7,9,8,3};
9
10 int main(){
11 int
i;
12 float ave = 0.0, dif;
13
14
for(i=0; i<10; i++) ave = ave + (float)score[i];
15
ave = ave / 10.0;
16
printf("ave = %3.1f\n",ave);
17
18
for(i=0; i<10; i++){
19
dif = score[i] - ave;
20
printf("score[%02d]=%2d Difference from average =
%4.1\n",i,score[i],dif);
21
}
22
23
return(0);
24 }
______________________________________________________________________
~~~~~ 【実行結果
; average.c】~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[yatsu-wahei-no-macbook:~] yatsukazuhei% cc average.c
[yatsu-wahei-no-macbook:~] yatsukazuhei% ./a.out
ave = 6.8
score[00]= 3 Difference from average = -3.8
score[01]= 5 Difference from average = -1.8
score[02]= 8 Difference from average = 1.2
score[03]= 9 Difference from average = 2.2
score[04]=10 Difference from average = 3.2
score[05]= 6 Difference from average = -0.8
score[06]= 7 Difference from average = 0.2
score[07]= 9 Difference from average = 2.2
score[08]= 8 Difference from average = 1.2
score[09]= 3 Difference from average = -3.8
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
【解説 ; average.c】
●int型の変数scoreを作り、[10]で一つの箱に0~9の10個の引き出しを作っている。
●11~12行目では、int型変数iとfloat型変数ave=0.0、 dif を作っている。
●14行目のfor文は変数iが0から+1ずつしていき、10より大きくなったら終了するようになっている。
●14~15行目では変数aveについても計算されていて、変数scoreの引き出しの中の数字をすべて足し
て、10.0で割るように計算されている。
●16行目は幅3マスで小数第1位までの指定で変数aveが表示されるようになっている。
●19行目は変数 dif をscoreの各々の引き出しに入っている数字からaveで引いて求められるように
している。
●20行目はscoreを[]の中は0詰めの幅2マス指定で変数iを表示、 =の後は幅2マス指定だけで変数
scoreの引き出しから順序よく数字を表示するようにしている。
2. average.cのプログラムの意味が分かった。makeを使用する準備として1
つのプログラムの中に3つの関数を使用した。
【ソースコード ; average01.c】
______________________________________________________________________
1
/*
2
program : average01.c
3
comments : 3つの関数を使用して、平均・差を求める。
4
5
6
7
8
9
10
11
12
*/
#include <stdio.h>
int score[10]={3,5,8,9,10,6,7,9,8,3};
float ave =0.0;
float get_ave();
void print_data();
13
14
/*main関数*/
15
16
17
18
19
20
21
22
23
int main(){
24
25
26
27
28
29
30
31
32
33
34
float get_ave(){
int i;
get_ave();
print_data(score,ave);
return(0);
}
/*float型get_ave関数*/
for(i=0; i<10; i++){ ave = ave + (float)score[i];
ave = ave / 10.0;
printf("ave = %3.1f\n",ave);
}
return(ave);
}
/*void型print_data関数*/
35 void print_data(){
36 float dif;
37
int i;
38
39
for(i=0; i<10; i++){
40
dif = score[i] - ave;
41
printf("score[%02d]=%2d difference from average =
%4.1\n",i,score[i],dif);
42 }
43
return;
44 }
______________________________________________________________________
~~~~~ 【実行結果
; average01.c】~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[yatsu-wahei-no-macbook:~] yatsukazuhei% cc average01.c
[yatsu-wahei-no-macbook:~] yatsukazuhei% ./a.out
ave = 6.8
score[00]= 3 difference from average = -3.8
score[01]= 5 difference from average = -1.8
score[02]= 8 difference from average = 1.2
score[03]= 9 difference from average = 2.2
score[04]=10 difference from average = 3.2
score[05]= 6 difference from average = -0.8
score[06]= 7 difference from average = 0.2
score[07]= 9 difference from average = 2.2
score[08]= 8 difference from average = 1.2
score[09]= 3 difference from average = -3.8
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
【解説 ; average01.c】
●8~9行目では、int型変数scoreとfloat型変数aveを宣言する。
●11~12行目で、main関数で使用するための、get_ave()とprint_data()を宣言しておく。
●14行目からmain関数。get_ave()-->print_data()-->returnの順序で実行していく。
●23~32行目は get_ave関数。 for文を使い、i=0で初期化して1回の処理ごとにi++し、i<10に
なった時点でプログラムが終了するようにした。そして、aveにave + (float)score[i]の値を
代入。aveを10で割る。
●29行目でprintf関数でaveの値を浮動小数点型、つまり小数第一位まで出力するようにした。
●34~44行目は print_data関数。for文を使い、i=0で初期化して1回の処理ごとにi++し、i<10
になった時点でプログラムが終了するようにした。difにscore[i] - aveの値を代入。
●41行目でprintf関数でscore[]を10進数で、Difference from averageを浮動小数点型、
小数点第一まで出力するようにした。
【考察 ; average01.c】
●実行結果より、まず平均が6.8点{=(3+5+8+9+10+6+7+9+8+3)/10}となっている。さらに一つ
一つのscoreが出力されており、それらの平均からの差が出力されている。
●1つのプログラムに3つの関数を入れるのは、自分的にはとてもみやすい。
●ここまでのプログラムを実行した結果、float型の関数や、void型の関数の使い方が分かった。
3. makeコマンドを使用した、プログラムを翻訳単位に分けて同様なプログラ
ムを作成した。
【ソースコード ; average02.c】 ***main関数を使用したプログラム***
______________________________________________________________________
1
/*
2
program : average02.c
3
comments : main関数の分割ファイル
4
5
6
*/
7
8
9
10
11
12
13
float get_ave();
void print_data(int i,float ave);
14
15
16
17
18
int main(){
float ave=0.0;
ave=get_ave();
print_data(i,ave);
/*変数宣言*/
int score[10]={3,5,8,9,10,6,7,9,8,3};
int i;
/*main関数*/
19
return(0);
20 }
______________________________________________________________________
【解説 ; average02.c】
●10~11行目で宣言しているint型変数scoreとiは後でexternを使用するためにmain関数の外で宣
言している。
●13~20行目はmain関数。float型の関数 ave を作り、それにget_ave()を代入している。その
後、print_data()を実行してプログラムが終了している。
【ソースコード ; get_ave.c】
***get_ave()を使用し、int型変数
scoreの平均を出すようにするプログラム***
______________________________________________________________________
1
/*
2
program : get_ave.c
3
comments : scoreの平均値を求めるプログラムである。
4
5
6
7
8
*/
#include <stdio.h>
extern int score[10]
float get_ave(){
/*get_ave関数*/
9
10
int i;
11
float ave = 0.0;
12
13
for(i=0; i<10; i++) ave = ave + (float) score[i];
14
ave = ave / 10.0;
15
printf("ave = %3.1f\n",ave);
16
17
return(ave);
18 }
______________________________________________________________________
【解説 ; get_ave.c】
●5行目で#include <stdio.h>を入力したのは、printf関数を使用するためである。
●6行目でexterunをつかい、average#2.cファイルのmain関数の外にあったint型変数 score
を。
●10行目に int型変数iを宣言した。
externは外部変数を参照するときに使う記憶クラスである。
●8行目からはget_ave()を宣言。
●11行目で float型変数 ave = 0.0を宣言。
●13~15行目でscoreの平均を出し、出力するようにしている。
【ソースコード ; print_data.c】 ***print_data()を使用し、それぞれ
のscoreから平均の値を引いた値を出すプログラム***
______________________________________________________________________
1 /*
2
program : print_data.c
3
comments : score - 平均 = ? を求める。
4 */
5
6 #include <stdio.h>
7 extern int score[10];
8
9 void print_data(void){
10
int i;
11
float dif = 0.0, ave;
12
for(i=0; i<10; i++){
13
dif = score[i] - ave;
14
15 printf("score[%02d]=%2d Difference from average = %4.1
16
\n",i,score[i],dif);
17 }
18 return;
19 }
______________________________________________________________________
【解説;print_data.c】
●7行目でexternを使用して、外部変数のscoreを使用する。
●9行目は void型関数print_dataの宣言。
●11~14行目でそれぞれのスコアから平均の値を引いた数が出力されるようになっている。
【makefile】 average02.o と get_ave.o と print_data.o のファイルをmakeを使い、互い
に依存させ合うプログラム。
______________________________________________________________________
1 average02: average02.o get_ave.o print_data.o
2
gcc -o average02 average02.o get_ave.o print_data.o
3
4
5 average02.o: average02.c
6
gcc -c average02.c
7
8 get_ave.o: get_ave.c
9
gcc -c get_ave.c
10
11 print_data: print_data.c
gcc -c print_data.c
______________________________________________________________________
【解説;makefile】
●1~2行目で実行可能ファイルaverage02は、3つのオブジェクトファイル
(average02.o、get_ave.o、print_data.o)に依存しているという意味である。
●4~5行目では、average02.oファイルはC言語のソースファイルaverage02.cに依存しているとい
う意味である。
●7~8行目では、get_ave.oファイルはC言語のソースファイルget_ave.cに依存しているという意
味である。
●10~11行目では、print_data.oファイルはC言語のソースファイルprint_data.cに依存してい
るという意味 である。
~~~~~ 【コンパイル;average02.c】~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[nw0862:~] yatsukazuhei% make
cc -c average02.c
cc -c get_ave.c
cc -c print_data.c
cc -o average02 average02.o get_ave.o print_data.o
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~ 【実行結果;average02.c】~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[nw0862:~] yatsukazuhei% ./average02
ave = 6.8
score[00]= 3 Difference from average = -3.8
score[01]= 5 Difference from average = -1.8
score[02]= 8 Difference from average = 1.2
score[03]= 9 Difference from average = 2.2
score[04]=10 Difference from average = 3.2
score[05]= 6 Difference from average = -0.8
score[06]= 7 Difference from average = 0.2
score[07]= 9 Difference from average = 2.2
score[08]= 8 Difference from average = 1.2
score[09]= 3 Difference from average = -3.8
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
【考察;average02.c】
●ユーザ関数のプロトタイプ宣言をmain関数の前に記述する。
●これをしっかりしないとコンパイルのときエラーがでる。
●その後、別のファイルでそれぞれユーザ関数の記述をするのだが、それぞれのファイルでも、使用する
変数を定義しないと行けないことに気づく。
●makefileをを使ってのコンパイルは、かなり使いやすい。それは、makeとコマンドを実行するだけ
実行可能ファイルを作成してくれるからである。
●結果より、無事に出力ができてることが証明されている。
●externの他にもauto,static,register,typedefなど記憶クラスがある。
4. 平均からの差でA,B,C,D,Fの評価を付けるプログラムをつくる。
【ソースコード;print_data#custom.c】
______________________________________________________________________
1 /*
2
program : print_data#custom.c
3
comments : 評価をつけてみる。
4 */
5
6 #include <stdio.h>
7
8 #define A 3.0
9 #define B 1.0
10 #define C 0.0
11 #define D 1.0
12 #define F 4.0
13
14 int score[10]={3,5,8,9,10,6,7,9,8,3};
15 int main(){
16
17 int i;
18 float ave = 0.0, dif;
19
20 for(i=0; i<10; i++) ave = ave + (float)score[i];
21 ave = ave / 10.0;
22 printf("ave = %3.1f\n",ave);
23
24 for(i=0; i<10; i++){
25
dif = score[i] - ave;
26
27
printf("score[%02d]=%2d Difference from average =
%4.1\n",i,score[i],dif);
28
29
if (A <= dif)
30
printf("Very good(A評価)");
31
32
else if (B <= dif)
printf("Good(B評価)");
33
34
else if (C <= dif)
printf("Normal(C評価)");
35
36
else if (D <= dif)
printf("Bad(D評価)");
37
38
else if (F <= dif)
printf("Very bad(F評価)");
39
printf("\n");
40
41 }
42
return;
43 }
______________________________________________________________________
【解説;print_data#custom.c】
●8~12行目に#defineで成績の値を定義した。3.0ならA、1.0ならB、0.0ならC、-1.0なら
D、-4.0ならFと定義した。
●29~38行目までは、if文による条件分け。平均値との差(dif)が3.0以上ならA、1.0以上なら
B、0.0以上ならC、−1.0 以上ならD、-4.0以上ならFを出力するようにしている。
~~~~~ 【実行結果;print_data#custom.c】~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[nw0862:~] yatsukazuhei% ./a.out
ave = 6.8
score[00]= 3 Difference from average = -3.8
Very bad(F評価)
score[01]= 5 Difference from average = -1.8
Very bad(F評価)
score[02]= 8 Difference from average =
Good(B評価)
1.2
score[03]= 9 Difference from average =
Good(B評価)
2.2
score[04]=10 Difference from average =
Very good(A評価)
3.2
score[05]= 6 Difference from average = -0.8
Bad(D評価)
score[06]= 7 Difference from average =
Normal(C評価)
0.2
score[07]= 9 Difference from average =
Good(B評価)
2.2
score[08]= 8 Difference from average =
Good(B評価)
1.2
score[09]= 3 Difference from average = -3.8
Very bad(F評価)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
【考察;print_data#custom.c】
●成績を出力するプログラムである。
●数字をみて条件分けできる。
●このプログラムは条件に入るならしっかり値を返すので事務処理などに役立つと思う。if文は使い慣れ
てきた気がする。
●#defineとif文の組み合わせは様々なパターンに使えそうだ。
5. 変数のスコープと記憶域クラスについて考察せよ。
【変数のスコープ(範囲)】
●まず変数には2つの種類がある。そしてそれぞれ通用する範囲が異なる。
(1) ローカル変数
(2) グローバル変数
●(1)は関数内で定義され、その関数でのみ使用されるもの。
なので毎回記述しなければならない。
●(2)は関数外で定義され、定義以降はどの関数からでも使用できる。
●しかし、変数を混同してしまう可能性がある。
例えば(1)で変数Vを記述したが、(2)で先に変数Vを宣言していた為に
関数内外で変数の衝突が起きるなんてこともある。
そこで通常はローカル変数のみを用い、関数間のやりとりは引数で行ったほうがよい。
【記憶域クラス】
●記憶域クラスは3つに分けられる。
(1) 自動変数
(2) 外部変数
(3) 静的変数
●(1)はローカル変数であり、関数実行中のみメモリが確保され、実行終了するとメモリが解放される。
関数が呼ばれるたびに初期化する。はっきりと初期化しないと初期値は不安定になる。
省略可できる。(auto int i => int i)
●(2)はグローバル変数であり、プログラム開始処理の前に一度だけ初期化を行う。
プログラム実行中は常に同じ場所に配置され値を保持する。
さらに初期化を明示的にしないと初期値は 0 になる。
●(3)は(1)同様、ローカル変数である。
●また(2)同様、プログラム実行中は常に同じ場所に配置され値を保持する。
●さらにプログラム開始処理の前に一度だけ初期化を行い、初期化を明示的にしないと初期値は 0 にな
る。
●どの変数の初期化もはっきりさせないといけない。結局変わらないのであれば初期化しよう。
●いつも使用している変数が自動変数という発見には驚いた。
【感想】
今回の課題では、makefileを作るときにエラーがしょっちゅうでて大変だったが、インターネットな
どで調べたりしてなんとか乗り越えられた。
float型関数や void型関数など、これからも多くのプログラムを作成するのに必要になったりすると
思うので、覚えておきたいです。
【参考文献】
●http://www9.plala.or.jp/sgwr-t/ 初心者のためのポイント学習C言語
●http://homepage3.nifty.com/mmgames/c_guide/ 苦しんで覚えるC言語