問題の番号などが見えるようには最新のブラウザ (例えば Opera) が必要。 回答 (例) を見るにはスタイルシートを切り替える必要がある。

青山学院大学

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

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

エラーを探す (12点)

あるプログラムの想定されている出力は次のとおりである。

1 番目の学生の平均: 4.500000
2 番目の学生の平均: 4.500000
3 番目の学生の平均: 5.000000
4 番目の学生の平均: 4.500000
5 番目の学生の平均: 3.500000
全体の平均:        4.400000

このプログラムは以下のとおりであるが、現在 12 個のエラーがある (入れ代え、 ずれは一つのエラーと
数える)。 エラーを見つけて直接プログラムに書き込んで修正しなさい。

#include <stdio.h>

int grades[5][22][5] = { { 5, 6, 4, 4, 3, 4 }, { }, { 4, 3, 6, 5, 4 }};
intdouble sum1 = 0.0, sum2;
int i, j;

int main (void) {
    for (i=0; i<=5; i++) {
        sum2 = 0;
        for (j=0:; j<2; j++);
            sum2 += grades[j][i];
        pripntf ("%fd 番目の学生の平均: %f\n", i+1, sum2/2);
        sum1 += sum2;
    }
    printf ("全体の平均:         %f/\n", sum1/510);
}

式の値 (10点)

次のテーブルの式の値を計算しなさい。(優先度: + が << より優先)

番号 番号
2+3*5 17 2+3*5 17
10000 - 5000-3000 2000 (int)(0.9*1.2) 1
5 > 7 && 4 < 5 0 3 > 5 ? 3 : 5 5
4 << 3 + 1 64 (int) 3.2e3 3200
'E'-'B' 3 7777 ^ ~7777 -1
i=23, i++, i+20 44 (i=5) || (i=7), i*i 25

青山学院大学

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

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

文法の変更 (16点)

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

番号 変更前 使用禁止物 答え
i++; ++ i += 1;
for (i=0; i<10; i++) { ...; } for i=0; while (i<10) { ...; i++; }
if (a < 2 && b < 3) { ...; } && if (a < 2) { if (b < 3) { ...; } }
a[20] [] *(a+20)
t * 4 (tint 型の変数) * t << 2
puts(s); puts printf("%s", s);
if (*p != 0) != if (*p)
a[20][12] [] *(*(a+20)+12)
if (a > b) i = 7; if (a>b)|| (i=7);

プリプロセッサについて (5点)

殆ど全ての C プログラムのソースファイルの先頭に

#include <stdio.h>

の一行がある。これによってなにが起こるか、何のため必要なのか説明しなさい。

標準入出力ライブラリのヘッダーファイル stdio.h が読み込まれている。そのファイルに標準入出力に必要な方、定数、関数などの定義が入っています。それによってコンパイラが、printf などの関数が正しく使われているかどうかを (ある程度) チェックできます。<> 文字によって、システムの標準ヘッダファイルのおいてあるディレクトリから探される。

青山学院大学

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

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

関数の説明 (10点)

次の関数を簡単に説明しなさい。

番号 関数 説明
printf 複数の変数を書式などを含めて標準出力に出力
putc 一文字を標準出力に出力
scanf 一文字を標準入力から入力
fopen ファイルを名前を指定して開く
malloc 指定した大きさのメモリをヒープから用意する
free malloc で用意されたメモリを返す
rand 乱数を返す
fseek ファイルの位置を次の読み込みや書き出しの準備のためにずらす
fwrite ファイルにデータをそのまま (バイナリ) で書き出す
fgets 指定したファイルから一行を、決まった文字数まで読み込む
pow 何の何乗の計算

ビットごと演算 (12点)

次の表を穴埋めしなさい (&| より優先)

番号 a b c a | c a & b c >> a a | b & c
2 3 4 6 2 1 2
3 2 7 7 2 0 3
5 23 65 69 5 2 5
7 15 256 263 7 1 7

青山学院大学

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

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

ポインタの用途 (5点)

ポインタの五つの用途を述べなさい。

  1. 低レベルのアドレス操作 (デバイス割り当てなど)
  2. 動的メモリの管理
  3. 配列の処理の効率化
  4. 参照 (関数への渡しなど)
  5. 間接 (indirection)

入力の定石 (5点)

C のプログラム中によく次の一句が見える (cint 型の変数):

while ((c = getc()) != EOF)

この句の一つ一つの要素を説明しなさい。

番号要素説明
一番外側の () while 文の条件の区切り
getc() 一文字を読み込む関数
c = c の変数に読み込んだ文字を代入
c = getc() の外側の () 代入を != より優先させるため
EOF ファイルの終わりを表す定数
!= EOF EOF でない場合に繰り返しを続く

青山学院大学

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

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

プログラミングの心構え (5点)

効率よくプログラミングできるプログラマに必要な条件・準備・心構えを一つ取り上げて 自分の経験に基づいて説明しなさい。

この授業を通じて一番よく分かってきたのは「良く寝ること」 です。他の作業の場合には、結構眠くてもそれほど効率が落ちないが、 プログラミングの場合には少々眠くても効率が急に下がる。一日12時間頑張るより もっと寝て、6時間だけ集中した方が効率がよいことが多い。

構造体と動的メモリの使い方 (合計 15点)

教員氏名と部屋番号を登録し、一覧を表示するためのプログラムである。 (プログラムは次のページに記載されている。) 主な関数の説明は以下のとおりである:

宣言:
void addMember(char *name, char *room);
機能:
リストの先頭に新しく登録する人に関する情報を追加する。
引数:
name 新しく登録する人物の氏名
room 新しく登録する人物の部屋番号
宣言:
void printAllMember();
機能:
リストの先頭から順に走査することで、登録されている教員氏名と部屋番号の一覧を出力する。

動的メモリのメモリ不足 (5点)

α の行において動的メモリ割付けを行っているが、割付けが失敗した場合の処理が考慮されていない。α の行を書き換えなさい。

if ((p = malloc(sizeof(PERSON))) == 0) {
    printf ("Not enough memory.\n");
    exit (1);}

次ページに記載されているプログラムを実行した際の出力を記述しなさい。(4点)

Name: Taro Yabuki  RoomNo: O526b
Name: Kazunari Ito  RoomNo: O528b
Name: Martin Dürst  RoomNo: O529

青山学院大学

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

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

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

関数の仕様を満たすようにプログラム中の空欄を埋めて、プログラムを完成させよ。

プログラムそのものは次のとおりである:

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

typedef struct person {
    char *name;
    char *room;
    struct person *next;
} PERSON;

PERSON *root = NULL;

/* リストの先頭に新しく登録する人に関する情報を追加する。*/
void addMember(char *name, char *room) {
    PERSON *p;
    p = malloc(sizeof(PERSON));  /*  ←  α  */
    p->name = name;
    p->room = room;
    if (  root  ) {
        p->next =   root ;
    } else {
        p->next =   NULL ;
    }
     root =   p  ;
}

/* 登録されているすべての人の情報を表示する     */
void printAllMember() {
    PERSON *p = root;
    while (  p ) {
        printf("Name: %s  RoomNo: %s\n", p->name, p->room);
        p =   p->next ;
    }
}

void main() {
    addMember("Martin Dürst", "O529");
    addMember("Kazunari Ito", "O528b");
    addMember("Taro Yabuki", "O526b");
    printAllMember();
}

青山学院大学

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

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

用語の説明 (5点)

次の用語を簡単に説明しなさい

番号 用語 説明
配列 同じ型の要素をある一定の数納められるデータ型の種類
宣言 変数や関数の存在、名前、型を知らせる
定義 変数や関数の実際のメモリの用意、そして場合によって初期化
共同体 union で定義。構造体とにていますが、メンバーはメモリをシェアしているので、同時には使えな
列挙体 enum で定義。複数の値に名前をつけて、一つの型として使えるようにします
構造体 struct で定義します。複数の個となるデータ型のメンバーを一体に (一つの型として) 使えるようにします

総合問題 (合計20点)

文字配列照合関数 isMatch (3点)

関数 isMatch は文字列 pattern が文字列 text に含まれる場合は 1 を、 含まれない場合は 0 を返す文字列照合関数である。 仕様を満たすように空欄を埋め関数を完成しなさい。

int isMatch(char *text, char *pattern){
    char *pi, *pj;

    pi = text;
    pj = pattern;
    while (  *pi != 0 && *pj != 0  ) {
        if (  *pi != *pj  ) {
	    pi++;
	    pj++;
	} else {
	    pi -= (int)( pj – pattern ) - 1;
	    pj = pattern;
	}
    }
    if (  *pj == 0  ) {
        return 0;
    }
    return 1;
}

青山学院大学

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

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

パターン検索プログラム

標準入力ファイルから、コマンド行で指定されたパターン(文字列)を含むすべての行を出力するプログラム find.exe のプログラムソース find.c である。

  1. プログラムの仕様は以下のとおりである。

    1. –n オプション機能が指定された場合には、行番号付きで出力するものである。
    2. -r オプション機能が指定された場合には、パターン(文字列)を含まないすべての行が表示される。
    3. –n オプションと -r オプションが同時に指定されてもよい。
  2. プロンプトから find.exe -n int < find.cと入力した場合の出力は、次のとおりである。

     7: int isMatch(char *text, char *pattern);
     9: int main(int argc, char *argv[]){
    11:     int lineno= 0; /* 行番号 */
    12:     int nflag = UNSET; /* -n オプション指定有無 */
    13:     int rflag = UNSET; /* -r オプション指定有無 */
    26:                     printf("find: illegal option\n");
    36:         printf("Usage: find -n -r pattern\n"); /* 使い方を表示 */
    44:                 printf("%5d: ", lineno);
    
  3. プログラム中で使用されている関数 isMatch は前に定義されているものである。

出力の予想 (2点)

プロンプトより find.exe –r -n int < find.c と入力した場合の出力の最初の 2行を書きなさい。

一行目#include <stdio.h>
二行目#include <string.h>

argc の値 (2点)

プロンプトより find.exe –r -n int < find.c と入力した場合を考える。main 関数実行開始時における argc の値を書きなさい:    3   

gets の問題点 (5点)

プログラム中の α において標準ライブラリ関数 gets が用いられているがこれは好ましくない。理由を日本語で述べよ。

gets は書き込める文字列の場所を指定するが、その長さを指定しない ので、入力する一行はそれより長いと別のものを上書きし、ビーラスの入り口になる可能性まである

青山学院大学

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

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

プログラムの中の空欄を埋め仕様どおりにプログラム (ファイル名: find.c) を完成しなさい (8点)

#include <stdio.h>
#include <string.h>
#define MAXLINE 100+1
#define UNSET 0 /* オプション指定なし */
#define SET 1   /* オプション指定有り */

int isMatch(char *text, char *pattern);

int main(int argc, char *argv[]) {
    char line[MAXLINE]; /* 入力行 */
    int lineno= 0; /* 行番号 */
    int nflag = UNSET; /* -n オプション指定有無 */
    int rflag = UNSET; /* -r オプション指定有無 */

    while (--argc > 0) {
        if ((*++argv)[0] ==  '-'  ) {
            switch(  (*argv)[1]  ) {
                case 'n':
                    nflag = SET;
                    break;
                case 'r':
                     rflag = SET;  ;
                    break;
                default:
                    printf("find: illegal option\n");
                    argc = 0;
                    break;
            }
        } else {
            break;
        }
    }

    if (  argc != 1  ) {
        printf("Usage: find -n -r pattern\n"); /* 使い方を表示 */
        return 1;
    }

    while (gets (line) != NULL) {          /* ←α */
        lineno++;
        if (isMatch(  line  ,  *argv  ) ^  rflag  ) {
            if (  nflag  ) {
                printf("%5d: ", lineno);
            }
            puts(line);
        }
    }

    return 0;
}