青山学院大学

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

授業
科目
計算機実習 I 学生番号 学科 学年 フリ
ガナ
  評点
                   氏名    
担当者 DÜRST, Martin J.、松原、
磯山、長谷川、盛川、吉田

英語の用語 (20 点)

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

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

side effect
副作用; 関数の戻り値以外の効果、例えば入出力やグローバル変数の変化

standard output
標準出力; プログラムで常に用意されている画面やリダイレクトによりファイルへの出力。

array
配列; 同じ型のデータがある決まった数並んでいる型、ポインタと密接な関係

call by reference
参照渡し; 値ではなく参照を関数に渡すことで変更が呼び出し元に残るやりかた

pattern
定石; プログラム内での「言い回し」みたいなもの

address operator
アドレス演算子; ある変数のアドレスを取得するための演算子

global variable
グローバル変数; プログラムのどこからでも変更できる変数、非推薦

warning
警告; エラーメッセージと違って実行可能が、残さないでプログラムを修正した方がよい

basic types
基本的なデータ型; 分解できないデータ型、例: int, char, float, double

式の評価 (16 点)

次のテーブルの式の値を計算しなさい。なお、変数 iint i; と定義されている。

番号 番号
2+3*5 17 2+3*5 17
300 / 20/5 3 --5---13 -8
3 << 4 48 9 & 17 1
0x0B * 15 165 17^13 28
3 / 5 ? 7 : 9 9 'Q' - 'W' -7
i = 23, i++ 23 i = 47, ++i, ++i 49
95 >> 3 11 22 | 35 55
13 / (double)4 3.25 0.029e5 + 135E-3 2900.135
15 * 013 165 i = 19, *&i 19

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

バイナリ入出力 (15 点)

テキスト入出力とバイナリ入出力を下記の五つの観点からできるだけ詳しく比較しなさい。

主に使う関数

テキスト入出力の場合、主に printf, scanf, fgets, putchar, getchar などを使います。 バイナリの場合は主に fread, fwrite, fseek を使います。

実行速度

例として、バイナリ出力の場合、メモリ内のデータをそのままファイルにコピーするだけなので速いが、 テキスト出力の場合、書式による変化 (二進法と十進法の変換など) に時間がかかる。

プログラムの書きやすさ・長さ

複雑なデータ構造の場合、テキスト入出力ではメンバごとに処理を書かないといけないが、 バイナリの場合ではループも含め一つの関数呼び出しで完結するので書きやすくて短い。

デバグのしやすさ

テキスト入出力ではテストデータの準備から確認まで全部テキストエディタで可能が、バイナリの場合文字化けになってデバグがしにくいことが多い。

システム間の移植性

CPU、OS、コンパイラやその設定によって、バイナリ入出力で直接つかわれるメモリ配置が変わるので移植性が悪い。 テキストの場合、改行は要注意だが、それ以外は問題ない。

演算子とその類似物 (18 点)

C のプログラムやそのコンパイル・実行において、同じ文字 (文字の組み合わせを含む) が複数の役割で使われていることがあります。下記の表で演算子・記号の名前や役割を記入しなさい。使えない場合は「なし」を記入しなさい。二項演算と単項演算両方で使える場合は両方を明記しなさい。

番号 文字 演算子としての役割 Cygwin Terminal での役割 printf の書式での役割
  * 掛け算・間接演算 なし フィールド幅に引数を使用
  > 比較演算子の大なり 標準出力のリダイレクト なし
  % 剰余演算 なし 書式指定文字列の始まり
  | ビット毎又は パイプ なし
  . 構造体とそのメンバの接続 なし 精度の前の文字
  && 論理積 論理積 なし
  - 引き算・符号 なし 左詰の指定
  < 比較演算子の小なり 標準入力のリダイレクト なし
  + 足し算・符号 なし 符号を付けて表示

青山学院大学

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

授業
科目
計算機実習 I 学生番号 学科 学年 フリ
ガナ
  評点
                   氏名    
担当者 DÜRST, Martin J.、松原、
磯山、長谷川、盛川、吉田

プログラムの作成 (合計 20 点)

中学校の先生が、インドの生徒が色々な計算結果を暗記していると聞いた。2から 10の整数乗の表を作るように頼まれた。ただし、表は四桁以下の数値に限定する。下記の出力結果のプログラムを作成しなさい。 プログラムはできるだけそのままコンパイル、実行できるようにした方がいいが、一部わからない部分があっても残りをできるだけ書きなさい。

出力結果:

    2    4    8   16   32   64  128  256  512 1024 2048 4096 8192
    3    9   27   81  243  729 2187 6561
    4   16   64  256 1024 4096
    5   25  125  625 3125
    6   36  216 1296 7776
    7   49  343 2401
    8   64  512 4096
    9   81  729 6561
   10  100 1000

表作成用のプログラム:

#include <stdio.h>

int main (void)
{
    int i, j, result;

    for (i=2; i<=10; i++) {
        result = 1;
        for (j=1; j<=15; j++) {
            result *= i;
            if (result < 10000)
                printf(" %4d", result);
        }
        putchar('\n');
    }

    return 0;
}

授業へのコメント (合計 6 点)

この授業で一番分かりにくかったことを書きなさい。(具体的に書いてあれば内容にかかわらず 3 点)

@@@@

この授業で一番勉強になったことを簡単に説明しなさい。(具体的に書いてあれば内容にかかわらず 3 点)

@@@@

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

構造体 (合計 22点)

次のプログラムは、最大99人分のユーザ情報 (ID、名前、性別、年齢) を管理するプログラムである。ある条件に一致するユーザのリストを表示したい。このプログラムの空欄を埋めなさい。

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

以下のプログラムを完成させなさい

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

typedef struct {
    int  id;
    int  age;
    char name[40];
} User;

void makeList (User up[], int list[], int num)
{
    int i, j=0;

    for (i = 0; up[i].id != -1   ; i++)
        if (up[i].age > num) {
            list[j] = up[i].id;        // 条件に一致したユーザの id を list 配列に格納
            j++;
        }

    list[j] = -1;  // データの終了の印
}

void inputUsers (User *up)   // ここでは簡易的に2人分のデータを格納
{
    up->id = 0; up->age = 21;
    strcpy(up->name, "Yamada");      // 最初のユーザの名前を Yamada に設定

    (up+1)->id = 1; (up+1)->age = 19;
    strcpy((up+1)->name, "Sato");      // 次のユーザの名前を Sato に設定

    up[2  ]. id = -1;      // データの終了の印: 最後のユーザの次の id が -1
}

int main (void)
{
    User users[100];  // ユーザ情報を格納するための構造体配列
    int list[100]; // ユーザの id だけを格納するための配列
    User *up = users;
    int i;

    inputUsers(up);      // ユーザ情報の格納
    makeList(up, list, 20);  // 条件に一致するユーザの id を格納

    // 表示
    for(i = 0; list[i] != -1; i++ ) 
        printf("Id:%d, name: %s, age: %d\n",  users[ list[i] ].id,
                users[ list[i] ].name, users[ list[i] ].age);

    return 0;
}

検索条件 (2 点)

上記プログラムのユーザ検索条件を記述しなさい。

20歳を超えるユーザ = 21歳以上のユーザ

青山学院大学

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

授業
科目
計算機実習 I 学生番号 学科 学年 フリ
ガナ
  評点
                   氏名    
担当者 DÜRST, Martin J.、松原、
磯山、長谷川、盛川、吉田

関数 (合計 20 点)

友愛数 (12 点)

2つの自然数の組 n と m について、n の約数からその数自身を除いたものの総和が m、m についての同様の総和が n となる数の組を友愛数 (amicable numbers) と言う。 たとえば220、284は、220の自身を除いた約数の総和が1+2+4+5+10+11+20+22+44+55+110=284、284も同様に1+2+4+71+142=220となるため友愛数である.
次のプログラムは両方が10000を超えるまでの自然数について友愛数を表示するプログラムである。正しく動作するようにプログラム中の空欄を埋めなさい。ただし,同じ数の組み合わせは含めず,順番が異なるだけの組み合わせ(220,284と284,220)は前の数字が小さい方のみ表示する.

#include <stdio.h>
#define MAX 10000

int SumDivisor (int num  )
{   int i, sum=0;
    for (i=1; i<num; i++)
        if (num%i    == 0)
            sum += i    ;
    return sum;
}

void   SearchAmic (int num[])
{   int i, sum;
    for (i=0; i<MAX; i++) {
        sum = SumDivisor  (num[i]);
        if (i==sum && i<num[i])
            printf("(%d, %d) are amicable numbers\n", i, num[i]  );
    }
}

int main (void)
{   int i, numbers[MAX];
    for (i=0; i<MAX   ; i++)
        numbers[i] = SumDivisor(i  );
    SearchAmic(numbers   );
    return 0;
}

婚約数 (8 点)

2つの自然数の組nとmについて、n の約数からその数自身と1を除いたものの総和が m、m についての同様の総和が n となる数の組を婚約数 (betrothed numbers) と言う。たとえば48、75は、48の自身と1を除いた約数の総和が2+3+4+6+8+12+16+24=75、75も同様に3+5+15+25=48となるため婚約数である。
上記の SearchAmic 関数を修正して、婚約数を表示する SearchBetro 関数を作成したい。main 関数の SearchAmic の呼び出しを SearchBetro の呼び出しに変更するだけで正しく動作するように、下記の空欄を埋めなさい。

void   SearchBetro (int num[])
{   int i, sum;
    for (i=0; i<MAX; i++) {
        sum = SumDivisor(num[i]-1)-1     ;
        if (i==sum && i<num[i]-1   )
            printf("(%d, %d) are betrothed numbers\n", i, num[i]-1  );
    }
}

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

ポインタと動的メモリ (合計 18 点)

動的メモリの使用 (12 点)

次のプログラムは何日分か分からない気温データが保存されたテキストファイル (temperature.txt) を読み込み、その平均気温を表示する。正しく動作するようにプログラム中の空欄を埋めなさい。テキストファイルには1行ずつ気温データが記載されているものとする。

#include <stdio.h>
#include <stdlib.h>   

int main(void)
{
    FILE *fp;
    int c, count = 0, size = 0;
    double   *temperatures, *position;
    double mean_temperature = 0;

    if (fp = fopen  ("temperature.txt", "r")) {
	while ((c = getc(fp)) != EOF)
      	    if (c == '\n')
                size++;
    }
    else
      	fprintf(stderr, "Cannot open file.\n"), exit(1);

    if (!(temperatures = (double *)    malloc(size   * sizeof(double)   )))
	fprintf(stderr, "Not enough memory, sorry.\n"), exit(1);

    fseek(fp, 0, SEEK_SET);
    while (count<size && fscanf(fp, "%lf", temperatures+count) == 1) // (*)
	count++;

    for (position=temperatures; position < temperatures+size  ; position  ++)
	mean_temperature += *position   ;
    mean_temperature /= size;
    printf("Mean temperature: %.1f\n", mean_temperature);

    fclose(fp  );
    free  (temperatures);

    return 0;
}

ポインタ方式から配列方式への変換 (2 点)

上記のプログラムの (*) の行内の「temperatures+count」をポインタ方式から配列方式へ変換しなさい。

&temperatures[count]

malloc 関数の応用例 (4 点)

malloc 関数を用いるのが効果的な応用例を2つ挙げなさい。

例) データ数が分からない温度データを読み込み、平均値を出す。

  1. 編集ソフトで同時に複数のファイルを開くことが可能で、数などが予想できないとき。
  2. 様々な店舗において、顧客データを記録するが、店舗ごとに記録する項目数が異なる。

青山学院大学

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

授業
科目
計算機実習 I 学生番号 学科 学年 フリ
ガナ
  評点
                   氏名    
担当者 DÜRST, Martin J.、松原、
磯山、長谷川、盛川、吉田

C++ (合計 18 点)

クラスの定義 (6 点)

次のクラスの定義において、それぞれの行で何を宣言しているかの名称を記入しなさい。

class Point {
    double x, y; // メンバ変数      
  public:
    Point (double new_x, double new_y); // コンストラクタ      
    void set_x (double new_x); // メンバ関数      
};

クラスの利用 (12 点)

下記のプログラムで、車の色を取得し、表示するコードは既に書かれている。空欄を埋めることで車の排気量 (displacement) を取得し、表示するコードを完成しなさい。ただし空欄を埋める必要がない場合は「なし」と記入しなさい。

#include <stdio.h>

typedef enum { Red, Black, Blue, White, Silver } carColor;

class Car {
  public:
    Car(carColor inputColor, double inputDisplacement);
    carColor color;
    double getDisplacement(void);                 (3 点)
  private:
    double displacement;
    なし                                          (2 点)
};

Car::Car(int inputColor, double inputDisplacement) {
    color = inputColor;
    displacement = inputDisplacement;
}

double Car::getDisplacement(void) { return displacement; } (4 点)
int main (void) { Car myCar(Red, 1300); double myCarDisplacement; int myCarColor = myCar.color; printf("%d\n", myCarColor); myCarDisplacement = myCar.getDisplacement(); (3 点) printf("%lf\n", myCarDisplacement); return 0; }