C プログラミング Ⅱ
演習 2-1(a) BMI による判定 文字列, 身長 height(double 型 ), 体重 weight (double 型 ) をメンバとする構造体 Data を定義し, それぞれのメンバの値をキーボードから入力した後, BMI を計算するプログラムを作成しなさい BMI の計算は関数化すること ( ) [ ] [ ] [ ] BMI = 体重 kg 身長 m 身長 m BMI 計算後,18.5 BMI < 25 のとき " 標準 ", それ以外のとき " 標準ではない " と出力するようにすること
演習 2-1(a) BMI による判定 BMIの計算プログラムの構造例 1: #include <stdio.h> 3: typedef struct 4: char [21]; 5: double height, weight; 6: Data; 7: 8: double calbmi(data p); 9: 10: int main(void) 11: 1 Data person; 13: 14: /* personの各メンバを入力 */ 15: double bmi; 16: 17: bmi = calbmi(person); 18: 19: printf("%sのbmi 判定 :", person.); 20: /* bmiの判定 */ 21: 2 return 0; 23: 24: BMI の計算プログラムの構造例 ( 続き ) 25: 26: 27: 28: 29: 30: 31: 3 double avecal(data p) double bmi; /* p のメンバ height,weight から BMI 計算 */ return bmi;
演習 2-1(b) ベクトルの内積, 合成 2 つの 3 次元ベクトルについて, それらの内積と合成ベクトル ( ベクトルの和 ) を計算するプログラムを作成しなさい ベクトルのデータを格納するための構造体として, ベクトル要素 x,y,z (double 型 ) をメンバとする構造体 Vec3 を定義すること 内積を計算する処理を関数化すること Vec3 型変数 a,b を仮引数とし, それらの内積を double 型で返す 合成ベクトル ( ベクトルの和 ) を計算する処理も関数化すること Vec3 型変数 a,b を仮引数とし, それらの和を Vec3 型で返す
演習 2-1(b) ベクトルの内積, 合成 ベクトルの内積, 合成プログラムの構造例 1: #include <stdio.h> 3: typedef struct 4: double x, y, z; 5: Vec3; 6: 7: double innervec(vec3 a, Vec3 b); 8: Vec3 compvec(vec3 a, Vec3b); 9: 10: int main(void) 11: 1 Vec3 vec1, vec2, vec3; 13: double invec; 14: 15: printf("vec1.x ="); 16: scanf("%lf", &vec1.x); 17: printf("vec1.y ="); 18: scanf("%lf", &vec1.y); 19: printf("vec1.z ="); 20: scanf("%lf", &vec1.z); 21: 2 /* vec2の入力 */ 23: ベクトルの内積, 合成プログラムの構造例 ( 続き ) 24: 25: 26: 27: 28: 29: 30: 31: 3 33: 34: 35: 36: 37: 38: 39: 40: 41: 4 43: invec = innervec(vec1, vec2); vec3 = coompvec(vec1, vec2); printf(" 内積 :%lf n", invec); printf(" 合成ベクトル :"); printf("(%lf, %lf, %lf) n", vec3.x, vec3.y, vec3.z); return 0; double innervec(vec3 a, Vec3 b) /* 内積の計算 */ Vec3 compvec(vec3 a, Vec3 b) /* 合成ベクトルの計算 */
演習 2-2(a) 構造体配列の要素の検索 氏名 ( 文字列 ), 身長 tall(int 型 ) をメンバとする構造体 List を定義し,List 型配列 x[ ] に格納されているデータの中から, キーボードから入力した と一致するメンバ を持つ要素を検索するプログラムを作成しなさい x[0] x[1] x[2] x[3] x[4] tall tall tall tall tall 福岡太郎 175 福岡次郎 164 博多三郎 182 博多四郎 168 九州五郎 170 key tall 博多四郎 -1 x[i]. と key. を比較 一致したときの x[i].tall を key.tall に代入 キーボードから入力 見つからない場合を考えて -1 を入れておく
演習 2-2(a) 構造体配列の要素の検索 検索処理は関数化すること 関数名を srch とする データ数 ( 配列要素数 ) n(int 型 ),List 型配列 px[ ], 検索したい ( 文字列 ) を仮引数とする 検索したい と一致したメンバを持つ要素を,List 型変数 found に格納して return 文で返すようにすること ポインタを用いた形でプログラミングしてもよい 文字列が一致しているかどうかの判定は, 標準関数の strcmp 関数を用いること ヘッダファイル string.h をインクルードすること 二つの文字列 str1,str2 を引数とし, それらが同じ文字列の場合は 0 を返すようになっている
演習 2-2(a) 構造体配列の要素の検索 検索プログラムの構造例 1: 3: 4: 5: 6: 7: 8: 9: 10: 11: 1 13: 14: 15: 16: 17: 18: 19: 20: 21: 2 23: 24: 25: 26: 27: 28: 29: #include <stdio.h> typedef struct char [10]; int tall; List; List srch(int n, List px[], char []); int main(void) List x[5] = " 福岡太郎 ", 175, " 福岡次郎 ", 164, " 博多三郎 ", 182, " 博多四郎 ", 168, " 九州五郎 ", 170 ; List y; char [21]; printf(" 検索氏名 :"); scanf("%s", ); y = srch(5, x, ); if(y.tall!= -1) printf("%s の身長 :%d n",, y.tall); else printf("%s はデータにありません. n"); return 0; 検索プログラムの構造例 ( 続き ) 30: 31: 3 33: 34: 35: 36: 37: 38: 39: List srch(int n, List px[], char []) int i; List found; /* と一致するメンバを持つ */ /* 配列 px[] の要素の検索 */ return found;
演習 2-2(a) 構造体配列の要素の検索 二つの文字列の比較 1: 3: 4: 5: 6: 7: 8: 9: 10: 11: 1 13: 14: 15: 16: 17: 18: 19: #include <stdio.h> #include <string.h> /* strcmp 関数を利用する場合,string.h を include する必要がある */ int main(void) char str1[21], str2[21]; printf( 一人目の名前 : ); printf( 二人目の名前 : ); scanf("%s", str1); scanf("%s", str2); if(strcmp(str1, str2) == 0) /* 文字列 str1 と str2 が一致していれば,strcmp 関数は 0 を返す */ printf(" 二人の名前は一致 n"); else printf(" 二人の名前は不一致 n"); return 0;
演習 2-2(b) 構造体配列の要素の並べ替え 氏名 ( 文字列 ), 点数 score(int 型 ) をメンバとする構造体 score を定義し,score 型配列 x[ ] を以下のように初期化したとき, x[ ] をメンバ tall の値が高い順 ( 降順 ) に並べ替えるプログラムを作成しなさい 構造体 score 型の定義および score 型配列 x[] の初期化 並べ替え前 並べ替え後 1: 3: 4: 5: 6: 7: 8: 9: 10: 11: 1 13: 14: 15: #include<stdio.h> #define N 5 typedef struct char [10]; int ; score; int main(void) score x[n] = " 福岡太郎 ", 82, " 福岡次郎 ", 64, " 博多三郎 ", 98, " 博多四郎 ", 75, " 九州五郎 ", 57 ; x[0] x[1] x[2] x[3] x[4] 福岡太郎 82 福岡次郎 64 博多三郎 98 博多四郎 75 九州五郎 57 博多三郎 98 福岡太郎 82 博多四郎 75 福岡次郎 64 九州五郎 57
演習 2-2(b) 構造体配列の要素の並べ替え int 型配列要素の並べ替え ( 昇順 ) のプログラムの例 ( バブルソート ) 1: 3: 4: 5: 6: 7: 8: 9: 10: 11: 1 13: 14: 15: 16: 17: 18: 19: 20: 21: 2 23: #include <stdio.h> #define N 5 int main(void) int a[n] = 88, 67, 100, 56, 25; int i, j, t; for(i = 0; i < N - 1; i++) for(j = 0; j < N - 1 - i; j++) if(a[j] > a[j + 1]) t = a[j]; a[j] = a[j + 1]; a[j + 1] = t; for(i = 0; i < N; i++) printf("a[%d] = %d n", i, a[i]); return 0; a[0] a[1] a[2] a[3] a[4] 初期状態 88 67 100 56 25 i = 0 のとき ( 最大値が右側に ) j=0のとき 87 67 100 56 25 67 88 100 56 25 j=1のとき 67 88 100 56 25 j=2のとき 67 88 100 56 25 67 88 56 100 25 j=3のとき 67 88 56 100 25 67 88 56 25 100
演習 2-2(b) 構造体配列の要素の並べ替え int 型配列要素の並べ替え ( 昇順 ) のプログラムの例 ( バブルソート ) 1: 3: 4: 5: 6: 7: 8: 9: 10: 11: 1 13: 14: 15: 16: 17: 18: 19: 20: 21: 2 23: #include <stdio.h> #define N 5 int main(void) int a[n] = 88, 67, 100, 56, 25; int i, j, t; for(i = 0; i < N - 1; i++) for(j = 0; j < N - 1 - i; j++) if(a[j] > a[j + 1]) t = a[j]; a[j] = a[j + 1]; a[j + 1] = t; for(i = 0; i < N; i++) printf("a[%d] = %d n", i, a[i]); return 0; i = 1 のとき (2 番目に大きい値が右側に ) j=0のとき 67 88 56 25 100 j=1のとき 67 88 56 25 100 67 56 88 25 100 j=2のとき 67 56 88 25 100 67 56 25 88 100 i = 2 のとき (3 番目に大きい値が右側に ) i = 3 のとき (4 番目に大きい値が右側に )
演習 2-2(b) 構造体配列の要素の並べ替え int 型配列要素の並べ替え ( 昇順 ) のプログラムの例 ( バブルソート ) 1: 3: 4: 5: 6: 7: 8: 9: 10: 11: 1 13: 14: 15: 16: 17: 18: 19: 20: 21: 2 23: #include <stdio.h> #define N 5 int main(void) int a[n] = 88, 67, 100, 56, 25; int i, j, t; for(i = 0; i < N - 1; i++) for(j = 0; j < N - 1 - i; j++) if(a[j] > a[j + 1]) t = a[j]; a[j] = a[j + 1]; a[j + 1] = t; for(i = 0; i < N; i++) printf("a[%d] = %d n", i, a[i]); return 0; すなわち, x[j].tall と x[j+1].tall を比較し, ( 課題は降順にするので ) x[j].tall の方が小さかったら, x[j] と x[j+1] を入れ替えるという処理を行うようにプログラミングすればよい
演習 2-3(a) 簡単な統計処理 ( 回帰分析 ) n 個のデータ x[i],y[i] (i = 0, 1,..., n-1) について回帰分析を行うプログラムを作成しなさい データはファイル regression.txt から読み込むようにする ファイルは授業用ホームページからダウンロードすること データの並びに注意すること 無関係な文字列なども入っているので, 読み込み手順を工夫すること 以下の値を出力すること ( 出力先は画面でよい ) データの平均値 データの偏差平方和, 偏差積和 回帰直線の傾き, 切片 相関係数
演習 2-3(a) 簡単な統計処理 ( 回帰分析 ) 回帰分析 回帰分析 ( 単回帰分析 ) は, ある変数 y とそれに影響を及ぼす考えられる変数 x との関係式を直線 y = ax + b で表すことを目的としたもの 変数 y および x について観測されたデータをもとに, 直線の傾き a と切片 b を最小二乗法で求める 相関係数 r により, データ x と y が求めた直線式にどれだけ従うかを評価することができる 計算手順 ファイルからデータを読み込み, 平均値を計算する. [ データ ] [ 平均値 ] x x x x i i 0 1 n 1 y y y y 0 1 n 1 n 1 n 1 1 1 x = x, y = y n i i= 0 n i= 0 i
演習 2-3(a) 簡単な統計処理 ( 回帰分析 ) 計算手順 ( 続き ) 次に,x[i],y[i] についての偏差平方和, およびそれらの偏差積和を計算する. [ 偏差平方和 ] [ 偏差積和 ] n 2 n 2 ( ), ( ) S = x x S = y y xx i yy i i= 1 i= 1 n ( )( ) S = x x y y xy i i i= 1 直線式のパラメータ, および相関係数を計算する. Sxy a=, b= y a x S xx [ 直線式のパラメータ ] [ 相関係数 ] r = S S xx xy S yy
演習 2-3(b) 文字数のヒストグラム テキストファイル abstract.txt に含まれるアルファベットの各文字数をカウントし, そのヒストグラムを出力するプログラムを作成しなさい 大文字, 小文字を区別せずにカウントすることヒストグラムについては, たとえば文字数 2 個につき * を 1 個出力するようにすればよい int hist [26] : ヒストグラムデータ hist [0] : a もしくは A の文字数 hist [1] : b もしくは B の文字数 hist [2] : c もしくは C の文字数 : : hist [25] : z もしくは Z の文字数
演習 2-3(b) 文字数のヒストグラム 英単語中のアルファベット文字のカウント 1: #include <stdio.h> 3: int main(void) 4: 5: char engstr[21] = "aabbbcddddeee"; 6: int i, hist[26]; 7: 8: for(i = 0; i < 26; i++) hist[i] = 0; 9: 10: i = 0; 11: while(str[i]!= NULL) 1 if(str[i] >= 'a' && str[i] <= 'z') 13: hist[str[i] 'a']++; 14: else ifif(str[i] >= 'A' && str[i] <= 'Z') 15: hist[str[i] 'A']++; 16: else 17: i++; 18: 19: アルファベット文字以外は 20: return 0; 21: カウントしない ( 何もしない ) 今見ている文字 str[i] に 'b' が格納されていたとき, 'b' - 'a' = 1 なので hist[1] に +1 される 今見ている文字 str[i] に 'B' が格納されていたとき, 'B' - 'A' = 1 なので hist[1] に +1 される
演習 2-3(b) 文字数のヒストグラム ヒストグラムの出力例 1: #include <stdio.h> 3: int main(void) 4: 5: int i, j, hist[26]; 6: 7: 8: 9: for(i = 0; i < 26; i++) 10: 11: 1 13: 14: 15: 16: 17: 18: return 0; 19: /* hist[] にカウント数が格納されていたとする * printf("%c および %c は %3d 文字 :", 'a' + i, 'A' + i); for(j = 0; j < hist[i]; j += 2) printf("*"); printf(" n"); a および A は 60 文字 :****************************** b および B は 19 文字 :********* c および C は 34 文字 :***************** : : : y および Y は 10 文字 :***** z および Z は 0 文字 :