青山学院大学

前期試験 ・ 2011 年 7 月 7 日 4 時限実施 ・ 60分 ・ ページ

授業
科目
計算機実習 I 学生番号 学科 学年 フリ
ガナ
  評点
                   氏名    
担当者 DÜRST, Martin J.,
松田、藤本、斉藤

英語の用語 (12 点)

プログラミング一般やプログラミング言語 C/C++ において使われる次の英語の用語の日本語訳と説明を書きなさい。日本語訳ではできるだけ片仮名を使わないようにしてください。

definition
定義; 宣言と違って名前、型、だけではなく、例えば関数の場合中身も含まれます。

modulo operator
剰余演算子; a を b で割った時の余りを計算する; a%b と書く

derived type
派生型; 基本的な型から派生された型、例: 配列、ポインタ、構造体、関数

actual parameter
実引数; 関数の呼出し時に実際に関数に渡される値

heap
ヒープ; メインメモリの中、同的メモリの確保に使わらる領域

side effect
副作用;プログラムの実行による式の計算以外の結果 (入出力、グローバル変数の変更など)

Q & A フォーラム (10 点)

次の質問 (一部省略) が Q & A フォーラムにだされたので答えなさい。

この警告はどうしたらよいか: incompatible implicit declaration of built-in function 'pow'
必要なヘッダーファイル (この場合 <math.h>) をインクルードしなさい。
program produced an error (Most probably a Segmentation Fault.) と出ました。助けてください。
プログラムの領域外のメモリを使おおとしている。初期化、配列の指数の範囲など確認した方がいいです。
普通に出力したのに Average is nan となってしまった。nan って何ですか。
nan は「not a number」 (数ではない)。浮動小数点数で 0.0 で割るなどの時に出る。
warning: the `gets' function is dangerous and should not be used. とありました。なぜ?
gets はいくら長くても一行を読む。場所が足りなくて、他のデータが上書きされるおそれがある。fgets を使おう。
コンパイラは lvalue required as unary ‘&’ operand と言っているが、何の話でしょうか。
アドレス演算子 & の被演算子は代入の左側に使える "left value" (変数など) でないとおドレスが取得不可能。

授業へのコメント (3 点)

この授業で一番勉強になったことを簡単に説明しなさい。 (決まった正解はありません。)

@@@@

前期試験 ・ 2011 年 7 月 7 日 4 時限実施 ・ ページ

構造体と入出力 (合計 22 点)

プログラムの穴埋め (7 点)

下記は、構造体を利用して、三人の名前と年齢をキーボードから入力し、平均年齢を求めるプログラムです。空欄を正しく埋めなさい。

#include <stdio.h>

typedef struct {
	char name[100];
	int age;
} Person;

int main (void)
{
	Person people[3];
	int i;
	double average = 0.0;

	for(i=0; i<3; i++){
		fgets(people[i].name, 100, stdin);
		scanf("%d", &people[i].age);
		getchar();
	}

	for(i=0; i<3; i++){
		average += people[i].age;
	}
	printf("average age = %.2lf\n", average/3.0);

	return 0;
}

getchar の挙動 (2 点)

上記プログラムにおいて、 getchar(); が読み込む文字を書きなさい。

改行コード ('\n')

getchar の必要性 (4 点)

上記プログラムにおいて、 getchar がなぜ必要か、fgetsscanf の違いを踏まえて説明しなさい。

fgetsは改行も含めて読み込むが、scanfは改行を読み込まない。
そのため、scanfの後にgetcharで改行を取り除かないと、
次のfgetsが単なる空行を読み込んでしまい、期待したように動作しない。

バイナリ出力の書式 (5 点)

File *binout; がバイナリ出力のために開かれたことを前提に、上記のプログラム変数 people をバイナリ出力する関数の呼出しを書きなさい。

fwrite(&people, sizeof(Person), 3, binout);

バイナリ出力の利点と欠点 (4 点)

バイナリ出力の利点と欠点を二つずつ列挙しなさい。

利点: 速さ、関数の呼出しが少なくて簡単; 欠点: 機種への依存、人間に読めない

青山学院大学

前期試験 ・ 2011 年 7 月 7 日 4 時限実施 ・ ページ

授業
科目
計算機実習 I 学生番号 学科 学年 フリ
ガナ
  評点
                   氏名    
担当者 DÜRST, Martin J.,
松田、藤本、斉藤

ポインタ (合計 13 点)

文字列とポインタ (6 点)

次のプログラムの出力内容を書きなさい。

#include <stdio.h>
#include <string.h>

int main (void)
{
    char *str = "This is a pen.";
    char *p;

    for (p = str + strlen(str) - 1; p != str; --p) {
        if (*p == ' ') {
	    *p = '\0';
	    printf("%s\n", str);
        }
    }

    return 0;
}

(出力内容)

This is a
This is
This

間違い探し (7 点)

次のプログラムについて、正しければ ○ と出力内容を書き、間違っているならば × と間違っている箇所と理由を書きなさい。

#include <stdio.h>
#define MAX 5

int main (void)
{
    double array[MAX+1];
    double *p;

    for (p = array; p - array < MAX; p++)
	printf("%d ", (int)(p - array));

    return 0;
}

(○×の解答欄)

(出力内容または理由)

      0 1 2 3 4
    

前期試験 ・ 2011 年 7 月 7 日 4 時限実施 ・ ページ

関数の書式と利用 (合計 20 点)

プログラムの間違い探し (10 点)

下記のプログラムは入力した値を1辺の長さとする立方体の体積 (=長さの3乗) を計算し、 小数点以下第4桁目まで出力する目的で書かれたが、正しく動作しない。 計算結果を正しく表示するためにどこをどのように訂正すれば良いか,答えなさい。 正しい結果を出力させるために複数箇所の修正が必要な場合は、全て答えなさい。

訂正箇所 (行番号と詳細) 訂正内容 (修正前 → 修正後)
7行目(main内の最初の宣言) int → double
10行目(scanfの中) length → &length
14行目(printfの中) %4f → %.4f
19行目(関数cubeの戻り値の型) cube(...) → double cube(...)
21行目(cube内の最初の宣言) double length; → 不要
 1) #include <stdio.h>
 2)
 3) double cube(double length);
 4)
 5) int main(void)
 6) {
 7)     int length, volume;
 8)
 9)     printf("Input length: ");
10)     scanf("%lf",length);
11)
12)     volume = cube(length);
13)
14)     printf("Volume: %4f\n", volume);
15)
16)     return 0;
17) }
18)
19) cube(double length)
20) {
21)     double length;
22)     return length*length*length;
23) }

参照渡しと変数のスコープ (10 点)

下記のプログラムは各変数にどの時点でどのような値が代入されているかを確認するために書かれたものである。 プログラム中の2箇所の空欄を埋め、その上で得られる出力の v1 及び v2 の値を書きなさい。

#include <stdio.h>

void subfunc(int *v1, int *v2){
  int a = 3;
  *v1 = 4;
  *v2 = a;

  printf("Output[2]: v1=%d, v2=%d\n", *v1, *v2);
}

int main(void)
{
  int a = 1, b = 2;
  printf("Output[1]: v1=%d, v2=%d\n", a, b);
  subfunc(&a, &b);
  printf("Output[3]: v1=%d, v2=%d\n", a, b);
  return 0;
}

出力結果

Output[1]: v1=1, v2=2
Output[2]: v1=4, v2=3
Output[3]: v1=4, v2=3

青山学院大学

前期試験 ・ 2011 年 7 月 7 日 4 時限実施 ・ ページ

授業
科目
計算機実習 I 学生番号 学科 学年 フリ
ガナ
  評点
                   氏名    
担当者 DÜRST, Martin J.,
松田、藤本、斉藤

文法の変更 (12 点)

次のプログラムの部分を「使用禁止」欄に書いたものを使わずに記述しなさい。「...」は任意の部分を表す。

番号 変更前 使用禁止物 答え
int1 / 16 / int1 >> 4
i++; ++ i += 1;
array[i] [] *(array+i)
person.name . (&person)->name
if (a>b || c==d) ... >||== if (!(a<=b&&c!=d)) ...
while (i<50) { ... } while for ( ; i<50; ) {...}

入力の終了の判断 (8 点)

次の入力の関数それぞれの場合、入力の終了 (EOF) をどうやって判断するのか説明しなさい。

getchar: 戻り値を int 型にし、これを EOF (通常 -1) と同じでしたら入力が終了。

fgets: データがもう一切読み込まれない場合、NULL ポインタを返す

scanf: データが読み込まれる前に入力が終了する場合、戻り値は EOF (通常 -1) になる。

fread: 読み込みたい項目数より戻り値が少ない場合、ファイルの終了の可能性が高い。

DRY 原則の説明 (合計 18 点)

DRY 原則の説明 (6 点)

プログラミングにおいて、DRY 原則は何の略なのかを明記の上、その意味と意義を詳しく説明しなさい。

DRY は Don't Repeat Yourself の略で、プログラムの中に同じ情報、同じ処理を
例えば単純なコピペの結果繰り返すのではなく、一回だけ記述する原理です。
DRY によってプログラムが短くなるだけでわなく、分かりやすく、そして修正しやすく、
変更しやすくなります。DRY の反対は麺棒プログラミングともいます。

下記のそれぞれの概念は DRY のためにどういう風に活用可能なのか説明しなさい。 (それぞれ 3 点)

関数: 関数ではある処理をまとめ、名前を付け、複数の場所から使えるようになる。
その結果、複数個所に同じ処理や似た処理があれば、関数でプログラムを DRY にできます。

配列: 配列は同じ型の要素が複数ある時に使う。一個一個の要素を別に処理する麺棒プログ
ラムのではなくて、繰り返しで指数を使って配列のすべての要素を同じように処理できます。

構造体: 構造体では型が異なる複数の関係のあるデータ項目をまとめます。
それによりデータ項目の関連性が見やすくなるし、関数の引数の数を減らすことが可能。

初期化: C の場合、初期化では定義と代入を同時にでき、プログラムが短くなる。
さらに、プログラムのあちこちにデータを使うよりまとまってデータ構造で初期化した方が DRY なプログラムにつながります。