コンテンツにスキップ

中間試験#

時間:60分,問題:25問(各4点)

総評

採点結果をCLEで公開しています.平均点は83点,100点は2人でした.90点以上の人はよく勉強していたと思います.部分点はありです.

  • 間違い数=0 → 4点
  • 間違い数=1 → 2点(1択問題の場合は部分点なし)
  • 間違い数>1 → 0点

間違っていたところはよく見直してください.良い学びの糧になります.

テスト内容は広範囲に渡りますが,プログラミング言語を理解・習得する上では基礎的な内容です.良いプログラムを書くには,まずは各種概念の理解が重要です.この理解は情報科学全体の理解にも繋がります.

1. 序論 & 特徴と分類#

プログラミング言語に関する説明のうち,適切なものを全て選択せよ#

  1. プログラミング言語の目的はプログラミング労力の軽減である ✅
  2. 高級言語で記述されたプログラムはアセンブリ言語にコンパイルされる
  3. プログラミング言語によって機械語よりも高い抽象度で記述ができる ✅
  4. C言語とPythonはプログラミング言語の一種である ✅
  5. ノイマン型コンピュータはプログラミング言語の一種である

Note

B. アセンブリではなく機械語にコンパイルされる.アセンブリもプログラミング言語の一種である.
C. 機械語のような低水準の記述を避けるためにプログラミング言語が存在する.

プログラミングパラダイムに関する説明のうち,適切なものを全て選択せよ#

  1. パラダイムとはプログラミング言語が採用する規範や哲学である ✅
  2. パラダイムの違いとはプログラミング言語が採用する構文の違いである
  3. 同一パラダイムを採用するプログラミング言語が複数存在する ✅
  4. 計算モデルとはコンピュータ上における計算を抽象化した枠組みである ✅
  5. ノイマン型コンピュータはパラダイムの一種である

Note

B. パラダイムとは構文のような表面的な性質ではなく,規範や哲学のような本質的な性質である.

ノイマン型コンピュータにおけるloadany processstoreの操作に対応するC言語の文を全て選択せよ#

  1. i = a; ✅
  2. if (i > 0);
  3. while (i > 0);
  4. return i;
  5. goto L1;
%%{init: {'flowchart': {'curve': 'linear', 'nodeSpacing': 10, 'rankSpacing': 50, 'padding': 5}}}%%
graph LR
  メモリ;
  CPU;
  メモリ -- load --> CPU;
  CPU -- store --> メモリ;

次のRAマシンプログラムを実行したときの出力として,適切なものを一つ選択せよ#

右の表はRAマシン命令の挙動である.
cはメモリ,c(0)はレジスタ,pcはプログラムカウンタ,#nは定数n

    load   #5
    store  1
    load   1
    sub    #3
    jgtz   L1
    jump   L2
L1: write  "a"
L2: write  "b"
    halt
命令 挙動
load a c(0)c(a)
store a c(0)c(a)
sub a c(0)c(0)-c(a)
jump b pcb
jgtz b pcbc(0)>0ならば
write "c" cを出力
halt 実行終了
  1. a
  2. b
  3. ab ✅
  4. aab
  5. aaaaab

Note

次のソースコードと等価である.

int i = 5;
if (i > 3)  // if (i - 3 > 0)
    printf("a");
printf("b");

2. 構文#

プログラミング言語の構文に関する説明のうち,適切なものを全て選択せよ#

  1. プログラミング言語の構文規則は文脈自由文法を用いて定義できる ✅
  2. ある文法が生成する終端記号の列を導出と呼ぶ
  3. 生成規則の書き換えによって,文法の曖昧性を排除できる場合がある ✅
  4. 曖昧さ除去のために生成規則が導入される場合がある ✅
  5. 解析木の葉(末端ノード)は常に終端記号である ✅

Note

B. 終端記号の列は言語と呼ぶ.
D. 曖昧さ除去を目的とした生成規則は多数存在する.特に四則演算は優先度と結合性という性質があり,これが曖昧さに繋がる.よって複数の生成規則を組み合わせて曖昧さが取り除かれる.

次のC言語プログラムを構成する要素のうち,文であるものを全て選択せよ#

if (b) i++;
  1. b
  2. (b)
  3. if (b)
  4. i++; ✅
  5. if (b) i++; ✅

次のC言語プログラムを構成する要素のうち,式であるものを全て選択せよ#

n = i * 2;
  1. =
  2. i ✅
  3. *
  4. 2 ✅
  5. i * 2 ✅

次の文脈自由文法\(G_1\)が生成する言語として,適切なものを全て選択せよ#

\[ \displaylines{ G_1=(&N &=& \{E\}, \\ &\mathit{\Sigma} &=& \{num,+,(,)\},\\ &P &=& \{E \ra E+E \ |\ num \ |\ (E)\},\\ &S &=& E\quad)\\ } \]
  1. num ✅
  2. num++
  3. num=num+num
  4. if(num)num++
  5. (num+num)+num ✅

先の文法\(G_1\)が取り得る解析木として,適切なものを全て選択せよ#

A. ✅

%%{init: {'flowchart': {'curve': 'linear', 'nodeSpacing': 5, 'rankSpacing': 20, 'padding': 5}}}%%
graph TD
  e1[E];
  e1 --- num1[num];

B.

%%{init: {'flowchart': {'curve': 'linear', 'nodeSpacing': 5, 'rankSpacing': 20, 'padding': 5}}}%%
graph TD
  e1[E];
  e1 --- paren1["("];
  e1 --- num1[num];
  e1 --- paren2[")"];

C. ✅

%%{init: {'flowchart': {'curve': 'linear', 'nodeSpacing': 5, 'rankSpacing': 20, 'padding': 5}}}%%
graph TD
  e1[E];
  e1 --- paren1["("];
  e1 --- e2[E];
  e1 --- paren2[")"];
  e2 --- num1[num];

D.

%%{init: {'flowchart': {'curve': 'linear', 'nodeSpacing': 5, 'rankSpacing': 20, 'padding': 5}}}%%
graph TD
  e1[E];
  e1 --- e3[E];
  e3 --- paren1["("];
  e1 --- e2[E];
  e1 --- e4[E];
  e4 --- paren2[")"];
  e2 --- num1[num];

E. ✅

%%{init: {'flowchart': {'curve': 'linear', 'nodeSpacing': 5, 'rankSpacing': 20, 'padding': 5}}}%%
graph TD
  e1[E];
  e1 --- e3[E];
  e1 --- plus[#43;];
  e1 --- e2[E];
  e2 --- num2[num];
  e3 --- num1[num];

先の文法\(G_1\)において,2つ以上の解析木が得られる終端記号列を全て選択せよ#

  1. num
  2. (num)
  3. num+num
  4. num+num+num ✅
  5. ((num)+num)+num

Note

\(G_1\)は曖昧な文法であるため,言語によっては2つ以上の解析木が得られる.つまり解析手順が唯一に定まらない.選択肢Dは解析の1ステップの時点で\(E + num\)と解釈するか,\(num + E\)と解釈するかの2つのパターンに分岐できてしまう.

あるいはこう考えても良い.本来左結合であるべき+演算子に対して\(G_1\)はその結合性を一切制御していない.よって+演算子が同じ深さに複数存在する場合,2つ以上の解析木が得られる.

選択肢Eは()が存在するため複数の+が異なる深さに配置される.よって解析は唯一に定まる.

文字01の回文を生成する文法の生成規則\(P\)として,適切なものを一つ選択せよ#

回文の例: 0 1 00 11 101 110011
非回文の例:01 10 110 1110 1111001

  1. \(P = \{E \ra 0E\ |\ 1E\ |\ \varepsilon\}\)
  2. \(P = \{E \ra 0\ |\ 1\ |\ 0E0\ |\ 1E1\ |\ \varepsilon\}\) ✅
  3. \(P = \{E \ra 0E0\ |\ 1E1\ |\ \varepsilon\}\)
  4. \(P = \{E \ra 0\ |\ 1\ |\ E0E\ |\ E1E\ |\ \varepsilon\}\)
  5. \(P = \{E \ra E0E\ |\ E1E\ |\ \varepsilon\}\)

3. 命令型言語#

命令型言語の基本的な性質として,適切なものを全て選択せよ#

  1. プログラムは文で構成される ✅
  2. 代入文によりメモリの値を変化させる ✅
  3. 制御文により実行順序を制御する ✅
  4. 手続きを用いて処理を高速化させる
  5. 変数への再代入は原則禁止である

Note

A. 命令型言語プログラムの基本構成要素は文である.
D. 手続きは高速化とは無関係である.
E. 関数型言語の性質である.

命令型言語における制御文の一種である文を全て選択せよ#

  1. 代入文
  2. 条件文 ✅
  3. 複文
  4. 繰り返し文 ✅
  5. ジャンプ文 ✅

次のC言語プログラムsrc1.cにおいて,変数xの右辺値が出力されるものを全て選択せよ#

src1.c
int x = 5;
int *p = &x;
  1. printf("%d\n", x); ✅
  2. printf("%d\n", &x);
  3. printf("%d\n", p);
  4. printf("%d\n", &p);
  5. printf("%d\n", *p); ✅

先のsrc1.cにおいて,変数xのアドレスが出力されるものを全て選択せよ#

  1. printf("%d\n", x);
  2. printf("%d\n", &x); ✅
  3. printf("%d\n", p); ✅
  4. printf("%d\n", &p);
  5. printf("%d\n", *p);

手続きや関数に関する説明のうち,適切なものを全て選択せよ#

  1. 手続きを用いるとシステム全体は複雑化する傾向にある
  2. 手続き内で別の手続きを呼び出すことはできない
  3. 手続きが自分自身を呼び出す方法を再帰呼び出しと呼ぶ ✅
  4. 関数宣言int square(int n)において,仮引数nはローカル変数の一つである ✅
  5. 関数呼出しsquare(i+3)において,関数squareには式i+3が渡される

Note

E. 関数squareに渡されるのは式i+3ではなく値そのものである.もしi=5なら8が渡される.

次のC言語プログラムのの行において,有効スコープである変数名を全て選択せよ#

int v1;
void xxx(int v2) {}
void yyy(int v3) {
    if (1) { int v4; }
    
    int v5;

Note

有効スコープは「その変数の宣言から属する複文の終了まで」である.選択肢Dのv4はif文の中では有効だが,の時点では有効ではない.

  1. v1 ✅
  2. v2
  3. v3 ✅
  4. v4
  5. v5

C言語のメモリ管理に関する説明のうち,適切なものを全て選択せよ#

  1. 動的メモリ確保にはヒープ領域が利用される ✅
  2. ローカル変数はスタック領域に積み上げられる ✅
  3. スタック領域の確保と解放は開発者自身が明示的に指示する
  4. ポインタによる参照先は常にスタック領域である
  5. 再帰的関数の駆動レコードにはヒープ領域が利用される

Note

C. 開発者が明示的に確保・解放する対象はスタックではなくヒープである.
D. ポインタはスタックとヒープのどちらも参照できる.
E. 駆動レコードはヒープではなくスタックに積み上げられる.

4. オブジェクト指向言語#

オブジェクト指向言語に関する説明のうち,適切なものを全て選択せよ#

  1. 命令型とオブジェクト指向は背反するパラダイムである
  2. オブジェクトとはデータと操作を一つにまとめた概念である ✅
  3. Javaのプリミティブ型はオブジェクトとは呼べない ✅
  4. 継承とは2つのオブジェクト間に成立する関係の一つである ✅
  5. コンポジションとは2つのオブジェクト間に成立する関係の一つである ✅

Note

C. プリミティブ型int iは単なるデータでありメソッドを持たない(持てない).すなわちオブジェクトではない.

オブジェクト指向の目的や利点に関する説明のうち,適切なものを全て選択せよ#

  1. 分割統治によってプログラム全体の実行速度を改善する
  2. カプセル化によってクラスの内部実装を意識せずクラスを利用できる ✅
  3. 既存クラスの再利用によって効率的なプログラミングを実現する ✅
  4. メソッドとフィールドの可視性を広く設定することで情報隠蔽を実現する
  5. ポリモーフィズムによって複数の異なるクラスを同一の操作で扱うことができる ✅

Note

A. オブジェクト指向は高速化とは無関係である.開発を楽にするための考えである.
D. 情報隠蔽のためには可視性は狭く設定する.

インタフェースに関する説明のうち,適切なものを全て選択せよ#

  1. インタフェースには公開メソッドのシグネチャのみを定義する ✅
  2. インタフェースはインスタンス化できる
  3. インタフェースにはコンストラクタを定義できる
  4. クラスを宣言する際には常にインタフェースを継承する必要がある
  5. メソッドの処理内容はインタフェースではなくクラスに記述する ✅

Note

インタフェースは文字通り形状(シグネチャ)のみを定義する特殊なクラスである.

B. シグネチャ定義のみなので,その具体的な中身は定義できない.
C. シグネチャ定義のみなので,(具体実装が存在せず)実体化もできない.

次のJavaプログラムのうち,左辺の要素が参照型であるものを全て選択せよ#

int a           = 0;                  // A
Integer b       = 0;                  // B
int[] c         = new int[]{1, 2};    // C
String d        = new String("hi");   // D
List<Integer> e = new ArrayList<>();  // E
  1. \(~\)
  2. ✅
  3. ✅
  4. ✅
  5. ✅

Note

参照型かどうかは変数の宣言,つまり左辺のみを考えれば良い.

B. ラッパークラスは参照型である.右辺はnew Integer(0);と書いても良いが,単に0とも記述可能である.
C. 配列は参照型である.

次のJavaプログラムのStackクラスのうち,カプセル化によって隠蔽化されるべき要素を全て選択せよ#

public class Stack {
    int[] elements;               // A
    int stackpointer;             // B
    void push(int element) {...}  // C
    int pop() {...}               // D
    boolean isEmpty() {...}       // E
  1. ✅
  2. ✅
  3. \(~\)
  4. \(~\)
  5. \(~\)

次のJavaプログラムsrc2.javaのうち,クラスXと継承関係にあるクラスを全て選択せよ#

src2.java
class A           {...}             // A
class B extends X {...}             // B
class C extends B {...}             // C
class D           { X x; ...}       // D
class E           { X x; Y y; ...}  // E
  1. \(~\)
  2. ✅
  3. ✅
  4. \(~\)
  5. \(~\)

先のsrc2.javaのうち,クラスXとコンポジション関係にあるクラスを全て選択せよ#

  1. \(~\)
  2. \(~\)
  3. \(~\)
  4. ✅
  5. ✅