戦国IT - 情報処理技術者試験の過去問対策サイト
ブログお知らせお問い合わせ料金プラン

基本情報技術者 2016年 秋期 午後 問11


次のJavaプログラムの説明及びプログラムを読んで、設問1,2に答えよ。

〔プログラムの説明〕  整数値の加減乗除の演算をする電卓のプログラムである。この電卓は、数字キー、加減乗除の各演算キー、イコールキー及びクリアキーをもつ。プログラムは、キーが押されたとき、それぞれのキーに対応する処理を実行する。数値などの表示は、System.out.printlnを呼び出して行う。   (1) インタフェースKeyは、電卓のキーが押されたときの処理を実行するメソッドを定義する。  メソッドoperateOnは、引数で与えられたクラスjava.util.Stackのインスタンス(以下、スタックという)に対して、キーに対応する処理を実行する。 (2) 列挙DigitKeyは、数字キーを表す定数DIGIT0~DIGIT9を定義する。  メソッドoperateOnは、キーを10進数の入力として処理する。引数で与えられたスタックの先頭に格納されている値は0(初期値)又は入力中の数値であり、その値を更新する。 (3) 列挙OperationKeyは、加減乗除の各演算キー、イコールキー及びクリアキーを表す定数ADD, SUBTRACT, MULTIPLY, DIVIDE, EQUAL及びCLEARを定義する。  メソッドoperateOnは、加減乗除の各演算キーに対応する演算を、スタックの内容に対して実行する。 (4) クラスCalculatorは、電卓本体を表す。フィールドstackは、電卓内部の数値の状態を表すスタックを保持する。フィールドpendingKeyは、演算に必要な数値の入力が終わるまで演算キーを保持する。また、イコールキーが押されたときは、イコールキーを保持する。例えば、キーの定数DIGIT2, ADD, DIGIT4が順に処理されたとき、スタックに格納されている値は先頭から4, 2であり、pendingKeyの値はADDである。次にキーの定数EQUALが処理されたとき、演算キーADDの加算処理が実行され、スタックに格納されている値は6となり、pendingKeyの値はEQUALとなる。ここで、二つの数値に対する加減乗除の演算結果は、Javaのint型の演算結果に一致するものとする。  メソッドonKeyPressedは、電卓のキーが押されたときに呼び出される。押されたキーは、引数で与えられる。押されたキー及び電卓の内部状態に基づいて、処理を実行する。 (5) クラスCalculatorTestは、クラスCalculatorをテストするプログラムである。  メソッドmainは、まず、文字と電卓の各キーとの対応を作成し、クラスCalculatorのインスタンスを生成する。次に、引数で与えられた文字列の各文字をキーの定数に変換し、そのキーの定数を引数としてクラスCalculatorのインスタンスのメソッドonKeyPressedを呼び出す。例えば、メソッドmainの引数として文字列“2*3=”が与えられたとき、それぞれの文字を、キーの定数DIGIT2, MULTIPLY, DIGIT3, EQUALに変換し、逐次それぞれのキーの定数を引数としてメソッドonKeyPressedを呼び出す。メソッドmainを実行したときの出力を図1に示す。
基本情報技術者試験(平成28年 午後 問11 図1) ↩設問2   基本情報技術者試験(平成28年 午後 問11 プログラム1)
基本情報技術者試験(平成28年 午後 問11 プログラム2)
基本情報技術者試験(平成28年 午後 問11 プログラム3)
基本情報技術者試験(平成28年 午後 問11 プログラム4)
基本情報技術者試験(平成28年 午後 問11 プログラム5)

設問1:

問題文を見る
 プログラム中のに入れる正しい答えを、解答群の中から選べ。   aに関する解答群  ア:extends  イ:implements  ウ:imports  エ:inherits  オ:requires  カ:throws   b, cに関する解答群  ア:ordinal()  イ:stack.peek()  ウ:stack.pop()  エ:stack.push(0)  オ:stack.push(ordinal())  カ:values()   dに関する解答群  ア:DigitKey  イ:Key  ウ:stack.pop()  エ:this  オ:val1  カ:val2   eに関する解答群  ア:Calculator  イ:Character  ウ:DigitKey  エ:Integer  オ:Key  カ:OperationKey

模範解答

a:イ、b:ウ、c:ア、d:エ、e:オ

解説

解答の導き方

この問題では、空欄ごとに「どの型を使うか」「スタックの値をどう更新するか」「どの演算を選ぶか」を考えます。スタック(値を上から順に積み重ね、先頭から取り出す仕組み)の動きから順に確認しましょう。
a:列挙型がKeyを使えるようにする
プログラム1では、インタフェースKey(クラスや列挙型に共通の処理を約束する仕組み)に、operateOnというメソッドが定義されています。プログラムの説明には、DigitKeyとOperationKeyがどちらも「キーを表す定数」であり、それぞれoperateOnを実行するとあります。
列挙型(決められた選択肢を定数としてまとめる型)がインタフェースの処理を実装するときに使うキーワードはimplementsです。したがって、空欄aには両方の列挙型でimplementsが入ります。
b、c:入力中の数値を更新する
DigitKeyのoperateOnは、押された数字を入力中の数値に追加します。説明にも「スタックの先頭に格納されている値は0(初期値)又は入力中の数値」であり、その値を更新するとあります。
例えば、入力中の数値が2で、次に3を押した場合、必要な計算は次のとおりです。
つまり、まず現在の数値をスタックから取り出し、10倍してから、押された数字を足します。
  • 空欄bには、現在の数値をスタックから取り出すstack.pop()が入ります。pop()は、先頭の値をスタックから取り除き、その値を返します。
  • 空欄cには、押された数字を表すordinal()が入ります。ordinal()は、列挙型の定数が定義された順番を0から数えて返します。DIGIT0は0、DIGIT1は1という対応です。
このため、DIGIT2を押したときは、初期値0を取り出して「」を計算し、2をスタックに入れます。続けてDIGIT3を押すと、2を取り出して「」を計算し、23を入れます。元の値を取り出してから新しい値を積むので、スタックには入力中の数値が更新された状態で残ります。
d:押された演算キーに応じて計算する
OperationKeyのoperateOnでは、stack.pop()で上から取り出した値をval2、その次に取り出した値をval1にしています。したがって、val1とval2は計算に使う数値です。
一方、calculateの中で選びたいのは、加算や乗算などのどの演算かです。現在のOperationKeyの定数を表すthisをswitchの対象にすれば、ADDなら加算、MULTIPLYなら乗算というように分岐できます。よって、空欄dにはthisが入ります。
例えば、スタックの上から3、2の順に値がある場合、先に取り出すval2は3、次に取り出すval1は2です。MULTIPLYのときはval1 * val2を計算し、6をスタックに入れます。
e:文字とキーの対応を保存する型を考える
プログラム5のmapには、文字とキーの定数の対応を保存します。Map(キーと値を組にして保存する仕組み)の型は、Map<Character, Key>のように「対応を探すためのキーの型」と「対応する値の型」を指定します。
このプログラムでは、文字がCharacter型で、対応する値はDigitKeyまたはOperationKeyの定数です。どちらの列挙型もKeyを実装しているため、共通の型であるKeyとして扱えます。また、map.getで取り出した値は、CalculatorのonKeyPressedに渡されます。このメソッドの引数もKey型です。したがって、空欄eにはKeyが入ります。
文字と定数の対応も、ordinal()によって順番を合わせています。例えばOperationKeyの定数はADD、SUBTRACT、MULTIPLY、DIVIDE、EQUAL、CLEARの順で、文字列「+-*/=C」も同じ順です。そのため、同じ位置にある文字と定数が対応します。
図1の出力と処理の流れ
文字列「2*3=」を入力したときの処理を追うと、スタックの値がどう変わるかを確認できます。
押したキー処理後のスタックの先頭pendingKey
DIGIT22初期状態
MULTIPLY0(下に2が残ります)MULTIPLY
DIGIT33(下に2が残ります)MULTIPLY
EQUAL6EQUAL
MULTIPLYを押した時点では、計算に使う2を残したまま、次の数値を入力する場所として0を積みます。EQUALを押すと、保留されていたMULTIPLYの処理が実行され、2と3を掛けた6が残ります。

誤りやすいポイント

  • extendsとimplementsを混同すること
    クラスや列挙型がインタフェースの処理を実装するときに使うのはimplementsです。
  • stack.pop()とstack.peek()を混同すること
    pop()は先頭の値を取り除いて返します。peek()は先頭の値を確認するだけで、スタックから取り除きません。今回は取り出した値を計算に使い、新しい値を積むため、pop()が必要です。
  • ordinal()が列挙型の番号を返すことを見落とすこと
    ordinal()は定数の定義順を0から数えた値を返します。DigitKeyでは、各数字キーを数字として扱うために使います。
  • 演算対象と演算の種類を取り違えること
    val1とval2は数値です。どの演算をするかは、現在のOperationKeyの定数を表すthisで判断します。
  • Mapの値の型をOperationKeyだけにすること
    mapにはOperationKeyだけでなくDigitKeyも格納します。両方に共通する型はKeyです。

FAQ

Q: 数字キーを押したとき、なぜ現在の値を10倍するのですか?
A: 10進数では、右隣に数字を追加すると、これまでの数値が10倍されてから新しい数字が加わります。2の後に3を入力する場合は、です。
Q: EQUAL自体が計算をするのですか?
A: EQUALが直接計算するのではありません。Calculatorでは、EQUALを押したときに、それまでpendingKeyに保存されていた演算キーの処理を実行します。その後、pendingKeyにEQUALを保存します。
Q: CLEARはOperationKeyに含まれていますが、operateOnで計算しないのはなぜですか?
A: CLEARを押したときは、Calculator側でreset()を呼び出してスタックとpendingKeyを初期状態に戻します。そのため、OperationKeyのoperateOnでは計算せず、すぐに戻ります。

関連キーワード: インタフェース、列挙型、スタック、ジェネリクス、メソッドオーバーライド

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

 表1は、文字列を引数としてメソッドmainを実行したときの出力の最後の行(図1の場合は6)を表している。表中のに入れる正しい答えを、解答群の中から選べ。ここで、プログラム中のには、全て正しい答えが入っているものとする。
基本情報技術者試験(平成28年 午後 問11 表1)
f, gに関する解答群  ア:0  イ:2  ウ:4  エ:8  オ:16  カ:32  キ:64  ク:ArithmeticException  ケ:Error

模範解答

f:イ、g:ケ

解説

解答の導き方

表1のfとgは、それぞれの文字列を左から順に処理したとき、最後に何が出力されるかを求めます。
ここで、スタックは値を積み重ねておき、最後に積んだ値から取り出す入れ物です。以下の表では、スタックの値を「先頭から」の順に示します。pendingKeyには、次の数値が入力された後に実行する演算キーが入ります。
f:2*4C2= の場合
「演算に必要な数値の入力が終わるまで演算キーを保持する」とあります。したがって、2の後に押された*は、すぐには実行せず、pendingKeyに保持します。その後、Cが押されると、CLEARの処理でスタックとpendingKeyが初期状態に戻ります。
押されたキー処理後のスタック(先頭から)pendingKey出力
22なしDIGIT2、2
*0, 2MULTIPLYMULTIPLY、2
44, 2MULTIPLYDIGIT4、4
C0なしCLEAR、0
22なしDIGIT2、2
=2EQUALEQUAL、2
Cが押された後は、それ以前の2や4、MULTIPLYの状態は残りません。そのため、最後の=を処理しても演算は行われず、最後に出力されるのは2です。よって、fにはイの0ではなく、イ:2が入ります。
g:8/2/= の場合
最初の/は、次の数値が入力されるまでpendingKeyに保持されます。2の後にもう一度/が押されると、保持していた最初の/が実行されます。
押されたキー処理後のスタック(先頭から)pendingKey出力
88なしDIGIT8、8
/0, 8DIVIDEDIVIDE、8
22, 8DIVIDEDIGIT2、2
/0, 4DIVIDEDIVIDE、4
=0にしようとする処理で例外が発生—EQUAL、Error
2回目の/を処理する時点では、スタックの先頭から2, 8です。プログラムは先頭の値をval2、その次の値をval1に取り出すので、となります。その後、次の数値を入力するための0がスタックに追加され、再びDIVIDEがpendingKeyに入ります。
続いて=が押されると、保持されているDIVIDEを実行します。このときスタックの先頭は0、その次は4なので、計算はになります。整数の0除算ではArithmeticExceptionが発生しますが、プログラムはその例外を受け取り、「Error」を出力します。したがって、最後の行はケ:Errorです。

誤りやすいポイント

  • 演算キーを押した時点で、演算がすぐ実行されるとは限りません。pendingKeyに演算キーを保持し、次の演算キーや=が押されたときに処理します。
  • Cは直前の数値だけを消すのではなく、resetによってスタックを0にし、pendingKeyも初期状態に戻します。
  • gでは、最初のは正しく計算できます。しかし、末尾の/によって次の数値として0が用意され、=でを実行しようとして例外になります。
  • 例外が発生しても、その例外名がそのまま出力されるわけではありません。このプログラムはArithmeticExceptionを捕捉し、「Error」を出力します。

FAQ

Q: なぜ2回目の/を押したときに、最初のが実行されるのですか?
A: 2を入力した後も、最初の/がpendingKeyに保持されています。次の演算キーが押されると、プログラムはまず保持中の演算を実行し、その後、新しく押された/をpendingKeyに設定します。
Q: fでCを押した後、最初の2や4が計算に使われないのはなぜですか?
A: CLEARの処理でスタックを空にしてから0を積み、pendingKeyもnullに戻すためです。それ以前に入力した数値や演算キーの状態は引き継がれません。
Q: gの最後に「ArithmeticException」ではなく「Error」と出るのはなぜですか?
A: ArithmeticExceptionが発生したときの処理として、プログラムが「Error」を出力するように書かれているためです。

関連キーワード: スタック、列挙型、状態遷移、例外処理、整数除算

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

戦国ITクイズ機能

\ せっかくなら /

基本情報技術者を
クイズ形式で学習しませんか?

クイズ画面へ遷移する→

すぐに利用可能!

©︎2026 情報処理技術者試験対策アプリ

このサイトについてブログプライバシーポリシー利用規約特商法表記開発者について