問題の番号などが見えるようには最新のブラウザ (例えば Opera) が必要。 回答 (例) を見るにはスタイルシートを切り替える必要がある。
前期試験 ・ 2006 年 7 月 20 日 4 時限実施 ・ ページ
授業 科目 |
計算機実習 I | 学生番号 | 学科 | 学年 | 組 | 番 | フリ ガナ |
評点 | ||||||||
氏名 | ||||||||||||||||
担当者 | DÜRST, Martin J. |
次の関数が入力用の関数、出力用の関数、標準入出力用の関数、ファイル入出力用の関数、文字入出力用の関数、バイナリ入出力用の関数である場合に各欄に○、そうでない場合に×を記入しなさい。
番号 | 関数 | 入力用 | 出力用 | 標準入出力用 | ファイル入出力用 | 文字入出力用 | バイナリ入出力用 |
putc |
× | ○ | × | ○ | ○ | × | |
scanf |
○ | × | ○ | × | ○ | × | |
fopen |
○ | ○ | × | ○ | ○ | ○ | |
pow |
× | × | × | × | × | × | |
fseek |
○ | ○ | × | ○ | × | ○ | |
gets |
○ | × | ○ | × | ○ | × | |
printf |
× | ○ | ○ | × | ○ | × | |
fwrite |
× | ○ | × | ○ | × | ○ | |
fgets |
○ | × | × | ○ | ○ | × |
次の用語を簡単に説明しなさい。
番号 | 用語 | 説明 |
配列 | 同じ型の要素をある一定の数納められるデータ型の種類 | |
宣言 | 変数や関数の存在、名前、型を知らせる | |
メンバ | 構造体の「部品」 | |
ヒープ | 動的メモリに使われるメイン・メモリの部分 | |
関数 | 引数を与えて呼び出すと決まった仕事をして、結果を戻り値で返すもの | |
定義 | 変数や関数の実際のメモリの用意、そして場合によって初期化 | |
スタック | 関数の引数、局所変数などに使われるメイン・メモリの部分 | |
グローバル変数 | プログラムの度の部分からでも使える変数 |
次のプログラムは実行すると A
という文字を出力する。空欄をコメントを参考にして埋めなさい。
#include <stdio.h> int main (void) { char c; char *p ; /* ポインタの宣言 */ c = 'A'; p = &c ; /* ポインタの値の設定 */ printf("%c\n", *p); /* ポインタの指す値を表示 */ return 0; }
前期試験 ・ 2006 年 7 月 20 日 4 時限実施 ・ ページ
あるプログラムの想定されている出力は次のとおりである。表の中身はパスカルの三角形を横倒ししたもの。
0 1 2 3 4 5 6 7 8 9 10 0 1 1 1 1 1 1 1 1 1 1 1 1 1 2 3 4 5 6 7 8 9 10 11 2 1 3 6 10 15 21 28 36 45 55 66 3 1 4 10 20 35 56 84 120 165 220 286 4 1 5 15 35 70 126 210 330 495 715 1001 5 1 6 21 56 126 252 462 792 1287 2002 3003 6 1 7 28 84 210 462 924 1716 3003 5005 8008 7 1 8 36 120 330 792 1716 3432 6435 11440 19448 8 1 9 45 165 495 1287 3003 6435 12870 24310 43758 9 1 10 55 220 715 2002 5005 11440 24310 48620 92378 10 1 11 66 286 1001 3003 8008 19448 43758 92378 184756
このプログラムは以下のとおりであるが、現在 12 個のエラーがある。入れ代えなどは一つのエラーと数える。エラーを見つけて直接プログラムに書き込んで修正しなさい。
#include <stdio.h> double fac (int n) { retaurn n<2!? 1 : n * fact(n-1); } int main (void) { int i, j=0; printf (" "); for (i=0; i≤<=10; i++) printf (" %56d", i); printf ("\n"); for (; j<11;ij++) { printf ("%2d'", j); for (i=0; i<11; i++) printf (" %6gd", (int)(fac(i+j)/fac(i)/fac(j))); printf ("\n");}} }
上記のエラー探しの問題で fac
関数 (階乗関数) の戻り値の型は double
である。その理由を簡単に説明しなさい。
階乗の引数が少しでも増えると戻り値が猛スピードで増える。機械によっては int
,
long
など整数は4バイトしか使わないが、double
はそれ以上の精密度を持っています。表の計算で割り算もあって、最終的にはそれほど大きい数字にはならないので、そこで
int
に戻すことができる。
次のテーブルの式の値を計算しなさい。(優先度: + が << より優先)
番号 | 式 | 値 | 番号 | 式 | 値 |
例 | 2+3*5 |
17 |
例 | 2+3*5 |
17 |
3<<2 + 5 |
384 |
(int) 7.1e5 |
710000 |
||
200 / 20/5 |
2 |
(int)(6.03*6.99) |
42 |
||
'G'-'N' |
-7 |
5678 ^ ~5678 |
-1 |
||
3 >= 12 && 7.5 < 7.7 |
0 |
4 > 3.7 ? 2.3 : 7 |
2.3 |
前期試験 ・ 2006 年 7 月 20 日 4 時限実施 ・ ページ
授業 科目 |
計算機実習 I | 学生番号 | 学科 | 学年 | 組 | 番 | フリ ガナ |
評点 | ||||||||
氏名 | ||||||||||||||||
担当者 | DÜRST, Martin J. |
次のプログラムは学生情報が記載された構造体データを値渡しと参照渡しの二とおりで関数に渡して表示する。出力は次のようになる:
値渡し: 15800000 例題花子 76.5 参照渡し: 15800000 例題花子 76.5
このプログラムの空欄を埋めなさい。
#include <stdio.h> typedef struct { /* 学生情報 */ int no; /* 学生番号 */ char name[20]; /* 氏名 */ double average; /* 平均点 */ } Student; void disp1 (Student st) { printf(" 値渡し: %d %s %f\n", st.no, st.name, st.average); } void disp2 ( Student *st ) { printf("参照渡し: %d %s %f\n", st->no , st->name , st->average ); } int main (void) { Student seito = {15800000, "例題花子", 76.5}; disp1(seito); /* 値渡しで学生情報を渡して表示 */ disp2( &seito ); /* 参照渡しで学生情報を渡して表示 */ return 0; }
左下のプログラムを実行した場合の右下の実行結果について空欄を記入しなさい。
#include <stdio.h> int main(void){ int a=3, b, c; ++a; b = ++a; printf("a = %d, b = %d\n", a, b); a = 3; a++; c = a++; printf("a = %d, c = %d\n", a, c); return 0; }
実行結果
a = 5 , b = 5 a = 5 , c = 4
前期試験 ・ 2006 年 7 月 20 日 4 時限実施 ・ ページ
左下のプログラムを実行すると右下の実行結果になる。
#include <stdio.h> typedef struct { char c; int i; short s; } Test; int main () { Test a, b; printf ("Address of a.c: %p\n", &a.c); printf ("Address of a.i: %p\n", &a.i); printf ("Address of a.s: %p\n", &a.s); printf ("Address of b.c: %p\n", &b.c); return 0; }
実行結果
Address of a.c: 0x22eeb0 Address of a.i: 0x22eeb4 Address of a.s: 0x22eeb8 Address of b.c: 0x22eea0
変数 a
と b
の全てのメンバのメモリ配置表を作成しなさい。(各枠に使われていたら使っているメンバー (例: b.i
)、使われなかったら -
を記入しなさい。)
xxx0 | xxx1 |
xxx2 | xxx3 |
xxx4 | xxx5 |
xxx6 | xxx7 |
xxx8 | xxx9 |
xxxA | xxxB |
xxxC | xxxD |
xxxE | xxxF |
|
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0022eeay |
b.c | - | - | - | b.i | b.i | b.i | b.i | b.s | b.s | - | - | - | - | - | - |
0022eeby |
a.c | - | - | - | a.i | a.i | a.i | a.i | a.s | a.s | - | - | - | - | - | - |
構造体 Test
をメモリがもっと効率よく使われるように書き直しなさい (3点)。
typedef struct { int i; short s; char c; } Test;
新しく定義した構造体 Test
の場合に想定されるメモリ配置を書きなさい (5点)。
xxx0 | xxx1 |
xxx2 | xxx3 |
xxx4 | xxx5 |
xxx6 | xxx7 |
xxx8 | xxx9 |
xxxA | xxxB |
xxxC | xxxD |
xxxE | xxxF |
|
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0022eeay |
b.i | b.i | b.i | b.i | b.s | b.s | b.c | - | a.i | a.i | a.i | a.i | a.s | a.s | a.c | - |
0022eeby |
- | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
ポインタの五つの用途を述べ、簡単に説明しなさい (例を使ってもよい)。
番号 | 用途 | 説明 |
低レベルのアドレス操作 | デバイス割り当てなどに使う。 | |
動的メモリの管理 | malloc などでメモリを用意し、そのアドレスをポインタで取っておく。 | |
配列の処理の効率化 | 配列の a[i] の代わりに移動するポインタを使う。 | |
参照 | 例えば引数の関数への参照渡し。 | |
間接 | 例えば複数の並び換えを前もって作っておいて、データをコピーしなくてポインタを使う。 |
前期試験 ・ 2006 年 7 月 20 日 4 時限実施 ・ ページ
授業 科目 |
計算機実習 I | 学生番号 | 学科 | 学年 | 組 | 番 | フリ ガナ |
評点 | ||||||||
氏名 | ||||||||||||||||
担当者 | DÜRST, Martin J. |
次のプログラムの部分を「使用禁止」欄の演算子,予約語又は関数を使わずに記述しなさい。
(「...」は任意の部分を
表す。a
、b
は int
型の変数で、p
は int *
型の変数。)
番号 | 変更前 | 使用禁止 | 答え |
例 | i++; |
++ |
i += 1; |
while (a > 12) { ...; } |
while |
for ( ; a > 12; ) { ...; } |
|
if (a || b ) { ...; } |
|| |
if (a) { ...; } else if (b) { ...; } |
|
p[b] |
[ ] |
*(p+b) |
|
a * 64 |
* |
a << 6 |
|
b * 65 |
* |
(b<<6) + b |
|
a = getchar(); |
getchar |
a = getc(stdin); |
|
*p |
* |
p[0] |
|
if (a>b) i=6; else i=5; |
> |
if (a<=b) i=5; else i=6; |
入力関数の場合、入力や使い方によってプログラムの不具合や暴走、そしてウィルスの侵入につながる恐れのある危険な関数がある。この関数やその使い方を列挙し、危険性の理由を説明し、対策を述べなさい。
危険な関数は gets (標準入力から一行読み込む) と scanf である。scanf の場合に危険なのは %s です。入力用に用意されたメモリの長さが関数に伝わらないので、そのメモリを超えて別のところに書き込むことになる可能性がある。それによってプログラムの急な停止 (segmentation fault)、 暴走、ウィルスの侵入もあり得ますので、絶対使わない方がよい。その代わりに fgets を使った方がよい。
C のプログラム中によく次の一句が見える (array
は int
型へのポインタ):
if (!(array = (int *) malloc(sizeof(int) * 10))) printf("Not enough memory!\n"), exit(1);
この句の一つ一つの部分を説明しなさい。
番号 | 部分 | 説明 |
if (!( |
メモリが足りるかのテスト | |
array = |
新しいメモリへのポインタの代入 | |
(int *) |
適切なポインタ型への変換 | |
sizeof(int) * 10 |
必要なメモリの大きさの計算 | |
printf 関数の呼び出し |
メモリが足りなかったことを書き出す | |
exit 関数の呼び出し |
メモリが足りなかったのでプログラムを終了 |
前期試験 ・ 2006 年 7 月 20 日 4 時限実施 ・ ページ
下記のプログラムの一部に、
の行にそれぞれの文を当てはめたとき、それぞれの出力結果を答えなさい。
int i, sum;
sum = 0;
for (i=0; i<10; i++) {
}
print ("%d\n", sum);
番号 | の一行の文 | 出力 |
例 | sum; |
0 |
sum++; |
10 | |
sum += i; |
45 | |
sum += i/2; |
20 | |
sum += i/2.0; |
20 | |
sum += sum+i; |
1013 |
2つの整数の最大公約数を求めるにはユークリッドの互助法がある。これは次の再帰的な定義に基づく方法である。2つの整数 m と n の最大公約数は次の通りになる:
次の最大公約数を計算する関数 gcd
の空欄を埋めて完成しなさい。
int gcd (int m, int n) { if (m == n) return m; else if ( m > n ) return gcd(n, m-n); else return gcd(m, n-m); }
次の表を穴埋めしなさい。
番号 | a |
b |
c |
a & b |
a | c |
c << a |
(a | b) & (c>>1) |
---|---|---|---|---|---|---|---|
例 | 2 |
4 |
5 |
0 |
7 |
20 |
2 |
3 |
5 |
9 |
1 |
11 |
72 |
4 |
|
6 |
17 |
63 |
0 |
63 |
4032 |
23 |
|
4 |
0 |
128 |
0 |
132 |
2048 |
0 |
前期試験 ・ 2006 年 7 月 20 日 4 時限実施 ・ ページ
授業 科目 |
計算機実習 I | 学生番号 | 学科 | 学年 | 組 | 番 | フリ ガナ |
評点 | ||||||||
氏名 | ||||||||||||||||
担当者 | DÜRST, Martin J. |
左下のプログラムを実行すると右下の実行結果のようにそれぞれの単語がその文字数と共に出力される。空欄を埋めなさい。
#include <stdio.h> int main ( void ){ char *name[10] = { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten" }; char **p, **endp; int i; p = name; endp = name+10; for (p = name; p < endp; p++) { for (i=0; (*p)[j] != '\0'; i++) ; printf("%s %d\n", *p, i); } return 0; }
実行結果
One 3 Two 3 Three 5 Four 4 Five 4 Six 3 Seven 5 Eight 5 Nine 4 Ten 3