Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
C言語入門 第17週 (補講)
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ,
情報処理言語Ⅰ(実習を含む。)
1
期末試験問題
2
C言語のプログラム
• コンパイラにより実行形式に変換する
.c ファイル
.h ファイル .h ファイル
.h ファイル
.c ファイル .c ファイル
Source files
C compiler
Preprocessor
linker
.o ファイル
Object files
.o ファイル .o ファイル
実行ファイル
Executable file
3 第1週資料p.7.
いつもgccやbcc32がやってく
れている処理の範囲
問1はいつものコン
パイル手順を思い出してみると良い
アセンブラ
• 教科書p.17
• 第2週講義資料 pp.25-26.
4
初期化・更新処理付きループ (for 文)
• 真偽値による繰り返し
5
for(式1; 式2; 式3) { // 式2が真の場合の処理 };
式2
式1
真
偽
問2-1は、forループの処理手順を自分で確かめれば良い
処理
式3
第3週資料p.92.
問2-2
• y軸のカウントダウン(y--)が出来てない人が多数いた。
• 境界値の間違いが多数いた
• <, <=, >=, > の違い
• 例えば代表値を代入して確認してみる
• 例: (x,y) = (0,0) や (7,7) 等
6
(b) $ ./a 7 . . . . . . . # 6 . . . . . . # # 5 . . . . . # # # 4 . . . . # # # # 3 . . . # # # # # 2 . . # # # # # # 1 . # # # # # # # 0 # # # # # # # # y x 0 1 2 3 4 5 6 7
(b) $ ./a 7 . . . . . . . # 6 . . . . . . # # 5 . . . . . # # # 4 . . . . # # # # 3 . . . # # # # # 2 . . # # # # # # 1 . # # # # # # # 0 # # # # # # # # y x 0 1 2 3 4 5 6 7
問2-3
• 問2-1同様、1つ1つの手順に値を入れて自分で手順を確認してみれば良い。
• 実は処理を1つ1つ確認しなくても選択ソートのアルゴリズム(=処理手順)を知っていれば分かる問題
• 未処理の先頭値と、未処理の最小値を交換する
7
選択ソートの進捗 $ gcc exam_q2_3.c && ./a 0 3 13 2 7 17 11 19 5 1 2 13 3 7 17 11 19 5 2 2 3 13 7 17 11 19 5 3 2 3 5 7 17 11 19 13 4 2 3 5 7 17 11 19 13 5 2 3 5 7 11 17 19 13 6 2 3 5 7 11 13 19 17 7 2 3 5 7 11 13 17 19
赤字: 処理済み 青字: 未処理の先頭 橙字: 未処理の最小値
問3-1
• double なのに int にしている人が多数いた
• 関数呼び出し時に & を付けない人が多数いた(ポインタ渡しにしないと、呼び出し元の変数の内容を変更出来ない)
8
問3-2
• double tmp; と宣言しなければいけないので tmp は double 型であってポインタではない。
• ポインタでない変数 tmp の前に間接参照の単項演算子 '*' を付けているのでエラーとなった。
• tmp の前の '*' を除去して *b = tmp とすれば良い。
9
問4
• 以下の何れか
• int factorize(int x, int a[], int n);
• int factorize(int x, int *a, int n);
• 末尾が ; 出ない人が多数いた
• 適切に型を与えていない(intと書いていない人)も多数いた
• a が a[] や *a 出ない人が多数いた
10
問5
• ポインタ変数 p の使い方
• p : 代入したアドレスそのもの
• *p : 代入したアドレスに格納されている値
• 例:
• p = &a なら
• p は a のアドレス(つまり &a)
• *p は a の値(つまり a)
11
問5
• ポインタ変数 p の計算
• p + 1 は?
• *p の次の要素のアドレス
• つまりpに入っているアドレスにsizeof(*p)を加算した値
• 例:
• p = &a が 0 で sizeof(*p) が 4 なら
• p + 1 は 4
12
問6-1
• 関数 main
• s の先頭からサイズ-1(終端文字¥0の手前)までを処理している
• s の内容を1つづず q6_1 に与えて戻り値を文字コードとして扱い、対応する文字を1文字表示
• 関数 q6_1
• abc~xyz が zyx~cba に入れ替わる
• アルファベットの小文字以外はそのまま
13
問6-2
• 配列の初期化
• 第3週資料p.73-83.を参照
14
期末試験実技課題
15
統計
• 母集団のすべての標本値 𝑥𝑖が𝑖 = 0~𝑛 − 1までの𝑛個あるとした場合 • (母集団の)平均 (AVR: AVeRage)
𝑥 =1
𝑛 𝑥𝑖
𝑛−1
𝑖=0
• (母集団の)分散 (VAR: VARiance)
𝜎2 =1
𝑛 𝑥𝑖 − 𝑥
2
𝑛−1
𝑖=0
• (母集団の)標準偏差 (STDEV: STandard DEViation)
𝜎 =1
𝑛 𝑥𝑖 − 𝑥
2
𝑛−1
𝑖=0
16
各値 −平均 2の平均
分散の平方根
値の合計値
件数
統計
• (母集団の)平均 (AVR: AVeRage)
𝑥 =1
𝑛 𝑥𝑖
𝑛−1
𝑖=0
17
値の合計値
件数
for による積算 sum = 0; for (i = 0; i < n; i++) { sum += x[i]; } avr = sum / n; 値の合計値
件数
値の積算
積算用変数の初期化
ここではsumがdouble型なので暗黙の算術変換(第5週資料p.49)が適用されるが、「整数型 / 整数型」の場合は(double)等のキャストを行わないと結果が整数になる
統計
• (母集団の)分散 (VAR: VARiance)
𝜎2 =1
𝑛 𝑥𝑖 − 𝑥
2
𝑛−1
𝑖=0
18
各値 −平均 2の平均
for文による積算 var = 0; for (i = 0; i < n; i++) { var += (x[i] - avr) * (x[i] - avr); } var /= n; 値の合計値
件数
値の積算
積算用変数の初期化
訂正: 2014-08-18 19:50 誤: (x[i] - var) 正: (x[i] - avr)
統計
• (母集団の)標準偏差 (STDEV: STandard DEViation)
𝜎 =1
𝑛 𝑥𝑖 − 𝑥
2
𝑛−1
𝑖=0
19
分散の平方根
平方根の計算 stdev = sqrt(var);
課題1: calcscore.c
全てまとめると完成
20
calcscore.c: 追記部分 sum = 0; for (i = 0; i < n; i++) { sum += score[i]; } avr = sum / n; var =0; for (i = 0; i < n; i++) { var += (score[i] - avr) * (score[i] - avr); } var = var / n; stdev = sqrt(var);
素因数分解
正整数𝑥を因数分解するには
1. 整数𝑦を2以上𝑥未満まで順に増やしながら手順2の処理を繰り返す。
2. 𝑥が𝑦で割り切れるなら𝑥 = 𝑦 × 𝑧として𝑦を素因数として保存し𝑧を新たな𝑥とする事を繰り返す。(12 = 2 × 2 ×3の同じ素因数を複数個取り得るため)
3. 最後に残った𝑥も素因数として保存する。ただし、 𝑥=1の場合、かつ保存した素因数が1個以上ある場合𝑥を素因数として保存してはいけない。(4 = 2 ×2 × 1のようになるため)
例: 1 = 1 2 = 2 3 = 3 4 = 2 * 2 12 = 2 * 2 * 3
21
なおyを2~x未満とした場合 x=7をy=6で割るのは明らかに無駄だが ここでは手順の簡素化を優先している。
素因数分解
1. 整数𝑦を2以上𝑥未満まで順に増やしながら手順2の処理を繰り返す。
for文を使って単純に繰り返せばよい
22
手順1のループ for (y = 2; y < x; y++) { // y を 2 以上 x 未満まで増やす };
素因数分解
2. 𝑥が𝑦で割り切れるなら𝑥 = 𝑦 × 𝑧として𝑦を素因数として保存し𝑧を新たな𝑥とする事を繰り返す。
ここも繰り返しなので手順1と手順2で2重ループとなる
素因数の保存は配列に追加して行けば良い
保存済みの素因数をn個とした時
nは配列の最大要素数を超えてはいけないから
エラー処理も必要になる
23
手順2のループ while (x % y == 0) { // ここでyを保存 x = x / y; //zを新たなxにする }
手順1のループ中で 処理する必要がある
素因数分解
2. 𝑥が𝑦で割り切れるなら𝑥 = 𝑦 × 𝑧として𝑦を素因数として保存し𝑧を新たな𝑥とする事を繰り返す。
ここも繰り返しなので手順1と手順2で2重ループとなる
素因数の保存は配列に追加して行けば良い
保存済みの素因数をn個とした時
nは配列の最大要素数を超えてはいけないから
エラー処理も必要になる
24
手順2におけるyの保存処理 if (nmax <= n) return -1; a[n] = y; n++;
素因数分解
2. 𝑥が𝑦で割り切れるなら𝑥 = 𝑦 × 𝑧として𝑦を素因数として保存し𝑧を新たな𝑥とする事を繰り返す。
ここも繰り返しなので手順1と手順2で2重ループとなる
素因数の保存は配列に追加して行けば良い
保存済みの素因数をn個とした時
nは配列の最大要素数を超えてはいけないから
エラー処理も必要になる
25
手順2の処理 while (x % y == 0) { if (nmax <= n) return -1; a[n] = y; n++; x = x / y; }
手順1のループ中で 処理する必要がある
素因数分解
3. 最後に残った𝑥も素因数として保存する。ただし、 𝑥=1の場合、かつ保存した素因数が1個以上ある場合𝑥を素因数として保存してはいけない。
if 文で条件分岐させれば良い 条件は「𝑥=1かつ保存した素因数が1個以上ある」以外
の場合𝑥も素因数として保存するとも言い換えることが出来る。
素因数の保存とエラー処理については 手順2と同じ
26
手順3の処理 if (!(x == 1 && 0 < n)) { if (nmax <= n + 1) return -1; a[n] = x; n++; }
課題2: factorize.c
• 全てまとめると完成
27
factoraize.c int factorize(int x, int *a, int nmax) { int y, z, n = 0; if (x <= 0) return -1; for (y = 2; y < x; y++) { while (x % y == 0) { z = x / y; if (nmax <= n) return -1; a[n] = y; n++; x = z; } } if (!(x == 1 && 0 < n)) { if (nmax <= n + 1) return -1; a[n] = x; n++; } return n; }
factoraize.h #ifndef FACTORIZE_H #define FACTORIZE_H int factorize(int x, int *a, int nmax); #endif