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

青山学院大学

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

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

式の値 (16 点)

次のテーブルの式の値を計算しなさい (iint の変数)。

番号 番号
2+3*5 17 2+3*5 17
2*3, 4*5 20 17 | 22 23
44 / 6/3 2 15 & 3 | 64 67
(int)8.77E6 8770000 7777 ^ ~7776 -2     
i=7, i++, i-- 8 i=9, --i, --i 7
6 > 5 > 0 1 (int)(3.5 * 2.1) 7
33 << 5 1057 88 & 39 6
1022 >> 3 127 (int)(2e12*3E-10) 600
7 > 13 ? 14:6 6 'o'-'a' 14

英語の用語 (16 点)

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

global variable
グローバル変数; プログラム全体で使える変数。使わない方がよい。

address operator
アドレス演算子; 単項の & で変数のアドレスが取れる演算子

formal argument
仮引数。関数側の引数の実際の値を受け取る変数

standard input
標準入力; キーボードやリダイレクトのファイルからの入力

regression test
退行テスト; プログラムの修正で思わぬバグが導入を防ぐためのテスト

indent
字下げ; 分かりやすさのために関数内やブロック内の行が数個のスペースで始まること

side effect
副作用; プログラムの実行による式の計算以外の結果

buffer
バッファー; データを次の処理のため一時的に読み込むなどのためのメモリ領域

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

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

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

この警告はどうしたらよいか: incompatible implicit declaration of built-in function 'pow'
必要なヘッダーファイル (この場合 <math.h>) をインクルードしなさい。
printf%lf を使ったらものすごい桁数の数が出力されましたが。
初期化されてない可能性があります。あとは、%lf を %lg に変えたら有効桁だけを E を使って出力できる。
cannot open output file a.exe: Device or resource busy がでました。助けてください。
a.exe はまだ実行中なのでコンパイラは上書きできない。タスクマネージャで a.exe を終了します。
普通に出力したのに English average is nan となってしまった。nan って何ですか。
nan は「not a number」 (数ではない)。浮動小数点数で 0.0 で割るなどの時に出る。
Uploaded file starts with a BOM (Signature), please fix. はどうしたらいいだろうか。
BOM は一部の UTF-8 の最初にある「印」です。コンパイラによっては処理できない。Notepad2 等で BOM 無しに変換する。
プログラムは if (islower(*a)==1) では動かなかったが、if (islower(*a)) では動いた。なぜ?
C の場合、0 以外は全部真。islower みたいな関数が真の時に 1 を返す保証はない。
教科書にいつも main の最後に return (0); とあるが、なぜ?
コマンドラインシェルでは C と違って、0 が真で、それ以外が偽。0 をシェルに返すのはプログラムが無事に終わったという印。
warning: the `gets' function is dangerous and should not be used. とありました。なぜ?
gets はいくら長くても一行を読む。場所が足りなくて、他のデータが上書きされるおそれがある。fgets を使おう。
error: stray '\357' in program 見たいのが 3 回でました。どうやったら直るだろうか。
半角スペースの変わりに全角スペースがないか確認しなさい。
ビット毎演算の問題ですが、どうやって変数を2進数に直せるでしょうか。
直す必要はない。コンピュータ内部では整数は常に2進数で扱われていて、入力と出力で人間が見やすい10進数と変換される。

青山学院大学

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

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

プログラム概念の使い方 (15 点)

次の概念は C プログラム言語においてどう使われるか、どう使うべきか論じなさい。

ポインタ C のポインタにはいつつの用途がある。1) 低レベルのアドレス操作、2) 動的メモリ
の管理、3) 配列の処理の効率化、4) 参照、5) 間接。3 は最近のコンパイラ技術で重要度が
小さくなりましたが、1 と 2 は OS 等の実装に必要な機能である。4) と 5) は情テク一般で
よく使われる。ポインタで少ない機能で多くの用途をカバーするのはまさに C の特長である。

関数 関数ではプログラムの中で一つのまとまりとして考えられる仕事 (計算や処理など)
をまとめて、名前を付けて、出入り口 (引数や戻り値) をはっきりさせておくことでプログラムを
部品化、抽象化できる。同じ関数はプログラムの複数の場所から呼べますし、再帰で直接や
間接的に関数が自分も呼べますが、複数回呼ばなくてもプログラムが見やすくなる。

構造体 構造体では複数の異なる型のデータを新しいデータ型にまとめることができる。
それによって型やデータそのもの抽象化、部品化につながる。関係あるデータをまとまって
代入し、引数や戻り値に使える。新しい構造体を作る時には
typedef を使って既存の型と同じように使えるようにするのがいい。

日本語の文字コード (8 点)

日本語によく使われる二つの文字コードを選び、明記の上にその特長や使われかたを説明しなさい。

UTF-8: 日本語も含め世界中の 文字が扱えるユニコードベースの文字符号化。(半角) 英数字は1バイト、平仮名、カタカナ (半角も含め)、漢字、 全角英数字は3バイトのを取る。最近使われる場所や頻度が増えている。

Shift_JIS: 昔から PC や MacIntosh で使われて、半角かなを含め日本語に必要な文字を扱っている。(半角) 英数字と半角カナは1バイト、 平仮名、(全角) カタカナ、全角英数字と漢字が2バイトを取る。

データ型 (16 点)

以下に定義された変数のメモリ使用量 (バイト) を記入し、変数の型を説明しなさい。ただし、int もポインタも 4 バイトのマシンを前提にしなさい。

番号 宣言 メモリ使用量 説明
int x; 4 整数
int *x; 4 整数へのポインタ
int **x; 4 整数へのポインタのポインタ
int x[10]; 40 整数の配列
int x[3][3]; 36 整数の二次元配列
char *x[12]; 48 文字 (列) へのポインタの配列
int x[][4]; 4 長さ4の整数の配列へのポインタ (引数の型のみ)
int (*x)[10]; 4 十個の整数の配列へのポインタ
struct { int a; int b; } x; 8 二つの整数の構造体

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

標準関数の引数と戻り値 (15 点)

以下の標準関数の引数や戻り値を説明しなさい。

番号関数名引数・戻り値説明
printf 第一引数 直接出力する文字と第二引数以降の型と書式の指定
scanf 戻り値 読み込みに成功した引数の数
fgets 戻り値 バッファのポインタ、又は EOF の場合 NULL
fgets 第二引数 バッファの長さ (改行と \0 を入れて読み込める最大文字数)
getc 第一引数 FILE * の型のファイル情報へのポインタ
pow 第二引数 a の b 乗の計算のための b (指数)
qsort 第四引数 並び換えの時に二つの要素のどちが小さいかを比べる関数
fseek 第三引数 ファイル内の位置の移動をどこ (頭、最後、現在地) から量の可の指示
fread 第二引数 バイナリ入力での一個の要素の大きさ
fread 第三引数 バイナリ入力での読み込む要素の数
realloc 戻り値 メモリの「引っ越し」の後の場所 (へのポインタ)。失敗の時に NULL。

関数の値の受け渡し (合計 12 点)

実行結果の穴埋め (8 点)

下記のプログラムを実行したときの出力結果の空欄を埋めなさい。

#include <stdio.h>

int value_test(int x, int *y, int *z)
{
    x = 2;
    *y = x + 1;
    z = y;

    return (*z + 1);
}

int main (void)
{
    int a = 1, b = 1, c = 1, d = 1;

    d = value_test(a, &b, &c);
    printf("a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);

    return 0;
}

実行結果

a = 1, b = 3, c = 1, d = 4

変数の個数 (4 点)

上記のプログラムにおいて、int 型の変数、及び int のポインタ型の変数はいくつメモリ上に用意されるか答えなさい。

int 型変数5

int のポインタ型変数2

青山学院大学

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

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

再帰によるユークリッドの互除法 (合計 16 点)

二つの正の整数 AB の最大公約数を以下の方法 (ユークリッドの互除法) で求めることが出来る。

  1. AB で割った余りを C とする。
  2. C が 0 ならば、B が最大公約数となる。
  3. そうでなければ、BA に代入、CB に代入して 1. に戻る。

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

以下は再帰を用いてユークリッドの互除法を実行するプログラムである。空白を埋めて完成させなさい。

#include <stdio.h>

int euclid(int A, int B)
{
    int C;

    printf("A = %d, B = %d\n", A, B);
    C = A % B;
    if (C == 0) {
      return (B);
    }
    else {
      return (euclid(B,C));
    }
}

int main (void)
{
    int A = 10, B = 7;

    printf("最大公約数 = %d\n", euclid(A, B));

    return 0;
}

実行結果の穴埋め (6 点)

上記プログラムを実行したときの結果を完成させなさい。

A = 10, B = 7
A = 7, B = 3
A = 3, B = 1
最大公約数 = 1

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

文字列処理と動的メモリ (合計 18 点)

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

以下のプログラムは、キーボードにより入力された文字列を、 必要なだけのメモリを確保して保存し、そのまま出力する。 空欄を埋めてプログラムを完成させなさい。ただし、入力文字列は'\0'を含めて 100文字以内、保存可能な入力行数は100行以内とする。

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

int main (void)
{
    char buffer[100];
    char *str[100];
    int n = 0, i;

    while(fgets(buffer,100,stdin)!=NULL){
        str[n] = (char *)malloc((strlen(buffer)+1)*sizeof(char));
        strcpy(str[n], buffer);
        n++;
    }
    for(i=0; i<n; i++){
        printf("%s", str[i]);
    }

    return(0);
}

入力の終了 (3 点)

上記プログラムの実行中、キーボードからの文字列の入力を終了したい場合の操作を説明しなさい。

Controlキーを押しながら'd'のキーを押す。

改行文字 (3 点)

上記プログラムにおいて、printf("%s", str[i]); になぜ改行文字が不要なのか説明しなさい。

fgetsが改行文字も含めて読み込むため。

警告 (8 点)

コンパイラが警告を出してもプログラムが動く。しかし授業では警告の出るプログラムを不正解としました。その理由を説明しなさい。

警告は「もしかして間違っているのではないか」という意味です。 間違ってない可能性もあるが、間違った可能性もあるので、確認した方がいい。 しかし警告を残すと後日で (又は他人が) 確認されたかどうか分からなくて、再度確認の作業が発生する。 その様な無駄を防ぐにはできるだけ早い段階で警告を無くした方がいいのは IT 業界の常識である。

青山学院大学

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

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

Fizz-Buzz 問題 (20 点)

1から100までの数をプリントするプログラムを書きなさい。 ただし3の倍数のときは数の代わりに「Fizz」と、 5の倍数のときは「Buzz」とプリントし、 3と5両方の倍数の場合には「FizzBuzz」とだけプリントする。 読みやすさを考慮し、各行最大30文字程度で20行以内のプログラムで記述すること。

実行結果例

1 2 Fizz 4 Buzz (中略) 97 98 Fizz Buzz

#include <stdio.h>

int main (void)
{
    int i;
    for (i=1; i<=100; i++) {
        if (i%15==0)
            printf("FizzBuzz ");
        else if (i%3==0)
            printf("Fizz ");
        else if (i%5==0)
            printf("Buzz ");
        else
            printf("%d ",i);
    }

    return (0);
}

授業へのコメント (何か書いたら 6 点)

授業でよったこと、勉強になったこと、そして問題点などについて教えてください。

[@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
[@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
[@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
[@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
[@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]
[@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@]