前期試験 ・ 2012 年 8 月 2 日 4 時限実施 ・ ページ
授業 科目 |
計算機実習 I | 学生番号 | 学科 | 学年 | 組 | 番 | フリ ガナ |
評点 | ||||||||
氏名 | ||||||||||||||||
担当者 | DÜRST, Martin J., 松田、斉藤 |
プログラミング一般やプログラミング言語 C/C++ において使われる次の英語の用語の日本語訳と説明を書きなさい。日本語訳ではできるだけ片仮名を使わないようにしてください。
declaration
宣言; ものの存在、名前、型だけを知らせ (実態の中身は後で定義)
compound statement
複文; {} 内で囲まれる複数の文が一つの文とみなされる
derived type
派生型; 基本的な型から派生された型、例: 配列、ポインタ、構造体、関数
actual parameter
実引数; 関数の呼出し時に実際に関数に渡される値
heap
ヒープ; メインメモリの中、同的メモリの確保に使わらる領域
loop invariant
繰り返しの普遍条件; 繰り返しにおいて、常に保たれる条件、動作を証明するために使われる
regression test
退行テスト/回帰テスト/再帰テスト; プログラムの部分的変更の影響を感知するテスト
syntax
構文; 文や式などの書き方 (例: if (条件) 文)
standard output
標準出力; 画面やリダイレクトのファイルへの出力
printf
書式指定文字列内の文字の意味 (16 点)下記の printf
等で使われる書式指定文字列内の文字の意味を説明しなさい。
例: d
: 符号付き整数を 10進法に変換
s
: 文字列を (ナル文字が来るまでに) 出力
x
: 符号無し整数を 16進法に変換、a-f を使用
f
: 浮動小数点数の表示 (E, 指数無し)
-
: 左揃えを指定するフラグ
c
: 整数を一文字 (バイト) として出力
+
: 正でも符号を必ず出力するフラグ
p
: ポインタの出力 (16 進法)
*
: フィールド幅や精度をその場ではなく、変数を使って指定できる
前期試験 ・ 2012 年 8 月 2 日 4 時限実施 ・ ページ
C のプログラムの中には、正しく動作しても読みやすさなどの面でまだまだ改善できるものも多い。
下記のそれぞれのプログラム断片について、一番改善につながる変更を簡単に説明しなさい。(「...
」 はプログラム断片の省略場所を示します。)
番号 | プログラム断片 | 改善の提案とその理由 |
---|---|---|
例 | for (i=0; i<50; i++) { if (i%5 ==0) printf ("\n"); } |
プログラムの構造が一瞬で把握できるため、字下げ (インデント) と改行を徹底的に修正 |
i = 0; while (i<20) { printf(...); i = i+1; } |
while 文の直前にループ変数の初期化、その最後にループ変数の変更があるので、while 文を for 文に変更 | |
int a[10]; a[0] = 27; a[1] = 33; a[2] = 67; a[3] = 0; a[4] = 77; a[5] = 73; ... |
コードが短くなって、値が簡単に確認できるため、配列の初期化を使用 | |
for (...) { goukei += a; sqr_tot += a*a; CbT += a*a*a; } |
変数名を分かりやすくし、書式と自然言語を統一 (できれば英語を使用) | |
if (a[12]==0 || a[12]==4 || a[12]==15) b = 27; else if (a[12]==13 || a[12]==3) d = 17; ... else e = 12; |
比較する値 (a[12]) が毎回同じで、整数値なので、if 文を switch 文に変更 | |
char array[15][100]; for (i=0; i<15; i++) gets(array[i]); |
関数 gets はメモリの不正な使用につながる可能性が高いので、安全な fgets に置き換えるべき | |
for ( ; i+k > 20; ) { i = k-2; k = i+1; } |
for 文の機能が全く活かされてないので、 while 文に変更 | |
if (m==1) return "January"; else if (m==2) return "February"; else if (m==3) return "March"; ... |
if 文の中のデータをデータ構造 (文字列の配列) にし、範囲チェックの上で配列からデータを取り出す。 | |
int string_length (char *string) { int length = 0; while (*string++) length++; return length; } |
この関数は文字列の長さを計算しますが、もうすでに標準ライブラリに strlen 関数がありますので、そちらを使用すべき (#include <string.h> が必要) |
前期試験 ・ 2012 年 8 月 2 日 4 時限実施 ・ ページ
授業 科目 |
計算機実習 I | 学生番号 | 学科 | 学年 | 組 | 番 | フリ ガナ |
評点 | ||||||||
氏名 | ||||||||||||||||
担当者 | DÜRST, Martin J., 松田、斉藤 |
下記のプログラムは二つの点の x座標と y座標を読み込み、その二点の中点を求めるプログラムである。空欄を埋めなさい。
#include <stdio.h> typedef struct { double x; double y; } Point ; void inputPoint (Point *p) { scanf("%lf", &p->x); scanf("%lf", &p->y); } Point middlePoint (Point *p) { Point m; m.x = (p->x + (p+1)->x) / 2; m.y = (p->y + (p+1)->y) / 2; return m ; } int main (void) { Point p[2]; Point m; int i; for (i=0; i<2; i++){ inputPoint( p+i ); } m = middlePoint( p ); printf("Middle point x:%.2lf y:%.2lf\n", m.x, m.y); return 0; }
inputPoint
の引数の型の変更 (2 点)上記の関数 inputPoint
の引数の型を (Point p)
に変更したとする。
下記の空欄を埋めて、コンパイルエラーが生じないように修正した inputPoint
関数を作成しなさい。
void inputPoint (Point p) {
scanf("%lf", &p.x); scanf("%lf", &p.y);
}
上記修正に加え、main
関数での呼び出し部分も修正することで、
引数の型を変更しても、コンパイルエラーの無い実行可能なプログラムが作成できます。
しかしながら、そのプログラムは期待されたようには動作しない。
その理由を、専門用語を使って説明しなさい。
元のプログラムは、ポインタを利用した参照渡しのため、 inputPoint 関数内で読み込んだ値を、main 関数内でも利用できる。 しかし、修正したプログラムでは、値渡しのため、 scanfで読み込んだ値は inputPoint 関数内でしか参照できず、 中点の計算には利用できない。
前期試験 ・ 2012 年 8 月 2 日 4 時限実施 ・ ページ
整数を 10個標準入力から読み込んで、その最小値を求め、標準出力に書き出すプログラムを作成しなさい。エラー処理は無視してかまわない。
#include <stdio.h> int main (void) { int i, n, min; scanf("%d", &min); for (i=1; i<10; i++) { scanf("%d", &n); if (min > n) { min = n; } } printf("%d\n", min); return 0; }
次の質問 (一部省略) が Q & A フォーラムにだされたので答えなさい。
前期試験 ・ 2012 年 8 月 2 日 4 時限実施 ・ ページ
授業 科目 |
計算機実習 I | 学生番号 | 学科 | 学年 | 組 | 番 | フリ ガナ |
評点 | ||||||||
氏名 | ||||||||||||||||
担当者 | DÜRST, Martin J., 松田、斉藤 |
次のテーブルの式の値を計算しなさい。(ヒント: + が << より優先)
番号 | 式 | 値 | 番号 | 式 | 値 |
例 | 2+3*5 |
17 |
例 | 2+3*5 |
17 |
~ - 1 |
0 |
3 + 2 << 5 - 3 |
20 |
||
19 & 15 |
3 |
~ (3 | ~ 15) |
12 |
||
4 > 2 ? 13 : 9 |
13 |
0x3F - 0x24 |
27 |
||
55 / 8 |
6 |
53 % 7 |
4 |
||
15 >= 7 < 1 |
0 |
(int) 1350000E-5 |
13 |
||
15 ^ 27 |
20 |
20, 42, 37 |
37 |
オブジェクト指向においてのカプセル化を C++ を例に使って詳しく説明しなさい。
カプセル化はオブジェクト指向の一番基本的な特徴。
カプセル化は、オブジェクトの持つデータ (メンバ変数)
は他のクラスからアクセスや変更ができないことである。
C++ では class で、struct と違って、メンバ変数は普通 private となる。
カプセル化によりプログラムのそれぞれの部分はお互い独立性が上り、変更が簡単になる。
次の変数の宣言を書きなさい。
例: 実数 a
: double a;
10個の整数の配列 b
:
int b[10];
80バイト分の文字列 12個の配列 c
:
char c[12][80];
整数 16個の配列へのポインタ e
:
int (*e)[16];
実数のポインタ 7個の配列 f
:
double *f[7];
整数二つを引数にとり、実数を返す関数 (へのポインタ) 5個の配列 d
:
double (*d[5])(int, int);
この授業で一番分かりにくかったことを書きなさい。(何か書いたら 3 点)
@@@@
この授業で一番勉強になったことを簡単に説明しなさい。(何か書いたら 3 点)
@@@@
前期試験 ・ 2012 年 8 月 2 日 4 時限実施 ・ ページ
フィボナッチ関数 F(n)
は次のように定義されている:
F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2) (n
>≥2 のとき)
下記の 2つのプログラムは、どちらも標準入力から整数を 1つ読み込み、その整数に対応するフィボナッチ関数を計算し、表示する。 左側のプログラム (A) は関数の再帰呼び出しを利用して実装され、右側のプログラム (B) は再帰呼び出しを使わずに実装されている。
/* プログラム(A) */ #include <stdio.h> long fibonacci (int n) { if ( n < 1 (@)) return 0; else if ( n == 1 (@@)) return 1; else return fibonacci(n-1) + fibonacci(n-2); } int main(void) { int n; if (scanf("%d", &n) == 1) printf("%ld\n", fibonacci(n)); else printf("整数値を正しく読み込めません。\n"); return 0; } |
/* プログラム(B) */
#include <stdio.h>
long fibonacci (int n) {
int i;
int fn2 = 0; // F(n-2)
int fn1 = 1; // F(n-1)
int fn; // F(n)
if (/* (@) の欄と同じ */)
return 0;
else if (/* (@@) の欄と同じ */)
return 1;
for (i=1; i<n; i++) {
fn = fn1 + fn2;
fn2 = fn1;
fn1 = fn;
}
return fn ;
}
int main(void) {
/* プログラム (A) と同じ、省略 */
}
|
5
を入力すると、プログラム (A)、(B) ともに
5 が計算結果として表示される。3
を入力した場合、fibonacci という関数は
5 回呼び出される。5
を入力した場合、fibonacci という関数は
15 回呼び出される。3
を入力した場合、fibonacci という関数は
1 回呼び出される。5
を入力した場合、fibonacci という関数は
1 回呼び出される。前期試験 ・ 2012 年 8 月 2 日 4 時限実施 ・ ページ
授業 科目 |
計算機実習 I | 学生番号 | 学科 | 学年 | 組 | 番 | フリ ガナ |
評点 | ||||||||
氏名 | ||||||||||||||||
担当者 | DÜRST, Martin J., 松田、斉藤 |
以下のプログラム断片で、関数 structCopy
は、構造体 St
の配列 array
と要素数
asize
を渡すと、動的にメモリを確保したあと、
array の先頭から asize
個をコピーし、複製したメモリの先頭アドレスを返す。
空欄を適切に埋め、関数を完成させなさい。 (10 点)
typedef struct {
int num;
char str[100];
} St;
St *structCopy(St array[] , int asize)
{
St *p, *head;
if (!(head = (St * ) malloc (sizeof(St) * asize)))
fprintf(stderr, "Not enough memory!\n"), exit(1);
p = head;
while (p - head < asize ) {
p->num = array->num;
strcpy(p->str, array->str);
array++;
p++;
}
return head;
}
上記の関数 structCopy
を使う際に、注意すべき点を述べなさい。(5 点)
structCopy
で確保した領域が不要になったとき、
関数 free
を使って、
その領域を解放し、
メモリリークを防止すべき点。
次の表を埋めなさい。(10 点)
名前 | 定数の書き方 | 型 |
---|---|---|
実数のゼロ | 0.0 | double |
空の文字列 | "" | char * |
ナル文字 | '\0' | char |
整数のゼロ | 0 | int |
ナルポインタ | NULL | void * |
上記の表の定数を上記の表の型の変数へ代入するとき、エラーの場合と警告の場合を列挙しなさい。(4 点)
エラー: char * と void * から double へ、またはその逆
警告: char * と void * から int と char へ
上記の五種類のゼロの仲間のうち、偽とみなされるものはどれですか。(2 点)
空の文字列以外、全てのものが偽とみなされる。