基本情報技術者 2016年 秋期 午後 問08
次のプログラムの説明及びプログラムを読んで、設問1〜3に答えよ。
事務計算においては、数値を見やすく表示(印字)するために、例えば3桁ごとに区切りの“,”を挿入するなどの編集処理がよく行われる。関数Editは、指定された編集パターンに従って、数値を編集するプログラムである。表1に、関数Editを用いた編集例を示す。例1では、3桁ごとに区切りの“,”を挿入している。例2では、例1の編集に加え、上位の空いた桁を“*”で埋めている。例3では、数値の右端から2桁目と3桁目の間に“.”を挿入している。

ここで、編集パターン中の文字“□”及び“■”は、数字と対応付けされた制御文字を表している。また、“␣”は空白文字を表している。
〔プログラムの説明〕
(1) 関数Editは、次の形式で呼び出され、二つの引数をもつ。
関数: Edit(文字型: Pattern[], 文字型: Value[])
Pattern[]には、編集パターンの文字列が格納されている。Value[]には、編集する数値を表す文字列が格納されている。各配列の添字は、0から始まる。文字列Pattern[]のi番目の文字はPattern[i-1]と表記する。文字列Value[]についても同様である。
(2) Pattern[]は、1文字以上から成る文字列であって、表示可能な図形文字及び制御文字(“□”及び“■”)から構成される。
(3) Value[]は、数値を表す文字列であって、数字“0”~“9”の並びの後に、数値が正又は0なら“+”を、負なら“-”を付加した形式である。数字の個数は、Pattern[]中の文字“□”及び“■”の個数と一致するように、必要であれば前方に“0”を付加する。例えば、Pattern[]の内容が“*□□,□■□”のとき、Value[]には、数値が123なら“00123+”、0なら“00000+”、−123なら“00123-”を指定する。
(4) 関数Editは、Value[]で与えられた数値をPattern[]に従って編集し、編集結果でPattern[]を置き換える。
〔編集方法〕
Pattern[]中の各文字について、先頭から順に1文字ずつ、次の①~③のいずれか一つの操作を実行していく。
① 関数Editが呼び出されたときのPattern[]中の先頭の文字(以下、fill文字という)で置き換える。
② Value[]中の対応する桁の数字で置き換える。
③ 置き換えないで、そのまま残す。
(5) 論理型変数signifは、on又はoffの値を取る。この変数の実行開始時の値はoffであり、Value[]中に最上位から“0”が連続した後に“0”でない数字が見つかるとonになる、などの使い方をする。
(6) 関数Editが呼び出されるとき、各引数には正しい値が設定されているものとする。


設問1:
問題文を見る 次の記述中のに入れる正しい答えを、解答群の中から選べ。
引数Pattern[]及びValue[]に幾つかのデータを与えて、関数Editを実行した結果を、表3に示す。

aに関する解答群
ア:"*******#"
イ:"********"
ウ:"******0#"
エ:"******0*"
b, cに関する解答群
ア:"*****12#"
イ:"*****12*"
ウ:"****.12#"
エ:"****.12*"
オ:"***0.12#"
カ:"***0.12*"
模範解答
a:イ、b:ア、c:エ
解説
解答の導き方
関数Editでは、Pattern[]の先頭の文字をfill文字として使います。Pattern[]の中にある「□」や「■」は、Value[]の数字に置き換えるための制御文字です。それ以外の文字は、signifがoffならfill文字に置き換え、onならそのまま残します。
また、Value[]の数字を使うたびに、次の数字へ進みます。Pattern[]の記号や文字ではValue[]の位置は進みません。末尾の「+」や「-」は、数字を置き換える文字ではなく、表2の処理でsignifを更新するために使われます。
aの行
Pattern[]は「□□,□□□#」、Value[]は「00000+」です。fill文字は先頭の「」です。
Pattern[]の文字は全部で8文字あり、どの文字もfill文字の「」になります。したがって、結果は「********」です。解答群では、アの7個でもウの「0」を含む文字列でもなく、8個の「」から成るイが一致します。
bの行
Pattern[]は「□□□.□□#」、Value[]は「00012-」です。fill文字は「」です。
先頭の「*」と、最初の3個の「□」は、signifがoffの間に処理されます。3個の「□」に対応する数字は「0」なので、表2のケース1でfill文字になります。「.」もsignifがoffの間にあるため、ケース8でfill文字に置き換わります。
ここまでで「*」は、先頭、3個の「□」、「.」の分を合わせて5個です。
残りの「□」には「1」と「2」が対応します。「1」の次のValue[]の文字は「2」で「+」ではないため、表2のケース4で「1」に置き換え、signifをonにします。「2」の次は「-」です。これも「+」ではないため、ケース6で「2」に置き換え、signifはonのままです。
最後の「#」は、signifがonなのでケース9でそのまま残ります。結果は「*****12#」です。先頭に「*」が5個あり、末尾が「#」のアと一致します。
cの行
Pattern[]は「□□■.□□#」、Value[]は「00012+」です。fill文字は「」です。
先頭の「」と最初の2個の「□」は、signifがoffの間に処理されます。対応する数字は「0」なので、どちらの「□」もケース1で「」になります。
次の「■」にも「0」が対応します。ただし、「■」では次のValue[]の文字も確認します。このとき次の文字は「1」で、「+」ではありません。そのため表2のケース2となり、「■」はfill文字の「*」に置き換わり、signifがonになります。
ここまでの結果は「***」です。「.」はsignifがonのため、そのまま残ります。その後の「□」には「1」と「2」が対応し、どちらも数字に置き換わります。最後の「2」の次は「+」なので、表2のケース7によりsignifはoffになります。したがって、末尾の「#」はケース8でfill文字の「」に置き換わります。
結果は「**.12」です。4個の「」、「.12」、末尾の「*」から成るエが一致します。
誤りやすいポイント
- 「□」と「■」は、どちらも数字に対応しますが、先頭のゼロの扱いが異なります。特に「■」に「0」が対応した場合は、Value[]の次の文字によってsignifがonになることがあります。
- 「.」や「,」、「#」は数字を使わない文字です。これらの文字を処理しても、Value[]の位置は進みません。
- signifは、一度onになったら最後までonのまま、という変数ではありません。最後の数字の次が「+」なら、表2のケース7でoffになることがあります。
- 「#」が常にそのまま残るわけではありません。処理時のsignifがoffならfill文字に置き換わり、onならそのまま残ります。
- 選択肢を比べるときは、「*」の個数だけでなく、「.」や「#」が残るかどうかも確認します。
FAQ
Q: Value[]の末尾にある「+」や「-」は、編集結果に出ますか?
A: 出ません。数字の末尾に付いている符号は、表2のケースを判断するために使われます。Pattern[]の文字に置き換えられるのは、数字の部分です。
A: 出ません。数字の末尾に付いている符号は、表2のケースを判断するために使われます。Pattern[]の文字に置き換えられるのは、数字の部分です。
Q: なぜcでは「■」に対応する「0」が表示されず、後ろの「.」は残るのですか?
A: 「■」に「0」が対応したときは、表2のケース2によりfill文字に置き換わります。一方、その処理でsignifがonになるため、後ろの「.」はケース9でそのまま残ります。
A: 「■」に「0」が対応したときは、表2のケース2によりfill文字に置き換わります。一方、その処理でsignifがonになるため、後ろの「.」はケース9でそのまま残ります。
Q: bでは「#」が残り、cではfill文字に変わるのはなぜですか?
A: bでは最後の数字の次が「-」なので、signifはonのまま「#」に進みます。cでは最後の数字の次が「+」なので、signifがoffになってから「#」に進みます。この違いによって、「#」の処理が変わります。
A: bでは最後の数字の次が「-」なので、signifはonのまま「#」に進みます。cでは最後の数字の次が「+」なので、signifがoffになってから「#」に進みます。この違いによって、「#」の処理が変わります。
関連キーワード: 文字列編集、制御文字、配列、繰返し処理、条件分岐、状態管理
設問2:
問題文を見る 次の記述中のに入れる正しい答えを、解答群の中から選べ。
プログラム中の破線で囲んだ部分の処理(表2のケース1〜7の処理)を、詳細なプログラムとして記述すると、次のようになる。

d, eに関する解答群
ア:"1" ≦ Value[v] and Value[v] ≦ "9"
イ:Value[v] = "0"
ウ:Value[v + 1] = "-"
エ:Value[v + 1] = "+"
オ:Value[v + 1] ≠ "-"
カ:Value[v + 1] ≠ "+"
模範解答
d:イ、e:エ
解説
解答の導き方
この設問では、表2のケース1〜7を表す条件が、詳細なプログラムのどこに当たるかを考えます。特に、現在の状態がsignif = offの場合とsignif = onの場合を分けて見ると、dとeを判断できます。
まず、Pattern[p] が「□」または「■」のときは、Value[v] の数字を使う処理に入ります。vは、Value[]の中で現在見ている文字の位置を表します。Value[]には数字の並びの後に「+」または「-」が付くため、Value[v+1]は現在の数字の次の文字です。
signif = offの場合
表2のケース1〜5に当たります。signifは、表2の更新処理で切り替わる状態を表します。offの間に、「■」の位置か「1」〜「9」の数字を処理するとonになります。ただし、次の文字Value[v+1]が「+」のときは、offのままです(ケース3・5)。こうした状態を記録する変数を、フラグといいます。
この分岐では、最後に次の処理をします。
- Value[v] が「0」なら、Pattern[p] をfill文字に置き換える。
- Value[v] が「0」以外なら、Pattern[p] をValue[v] に置き換える。
そのため、dに入る条件はValue[v] = 「0」です。解答群では イ です。
表2のケース1〜3では、Value[v] が「0」のときにfill文字へ置き換えています。ケース4〜5では、Value[v] が「1」~「9」のときに数字をそのまま表示しています。この違いを分ける条件がdです。
signif = onの場合
signif = offの分岐に入らなかった場合、つまりsignif = onの場合は、表2のケース6・7に当たります。この分岐では、Pattern[p] をValue[v] に置き換える処理を行い、条件に合えばsignifをoffに戻します。
表2のケース6では、Value[v+1] が「+」以外なのでsignifはonのままです。一方、ケース7では、Value[v+1] が「+」なのでsignifをoffにします。したがって、eに入る条件はValue[v+1] = 「+」です。解答群では エ です。
Value[]は数字の並びの後に「+」または「-」が付く形式です。現在の数字が最後の桁なら、その次の文字Value[v+1] は符号になります。正又は0のときは「+」なので、この条件によってケース7を判定できます。
誤りやすいポイント
-
dとeが別々の分岐にあることを見落とす
dはsignif = offの分岐で、Value[v] が「0」かどうかを判定します。eはsignif = onの分岐で、Value[v+1] が「+」かどうかを判定します。 -
Value[v] とValue[v+1] を混同する
Value[v] は現在処理している数字です。Value[v+1] はその次の文字で、最後の数字の次に来る「+」または「-」を判定するときに使います。 -
「0」の扱いと「+」の扱いを混同する
「0」かどうかは、Pattern[p] をfill文字にするか数字にするかを決めます。「+」かどうかは、signifをoffに戻すかどうかを決めます。
FAQ
Q: Value[v] が「0」のときは、いつもsignif = offになりますか?
A: いいえ。Value[v] が「0」のとき、signif = offの分岐ではPattern[p] をfill文字にします。signifをonにするかどうかは、Pattern[p]やValue[v+1]など、表2の条件によって決まります。
A: いいえ。Value[v] が「0」のとき、signif = offの分岐ではPattern[p] をfill文字にします。signifをonにするかどうかは、Pattern[p]やValue[v+1]など、表2の条件によって決まります。
Q: eがValue[v+1] = 「+」なのはなぜですか?
A: eはsignif = onの分岐にあり、表2のケース6・7を分けています。ケース7ではValue[v+1] が「+」でsignifをoffにし、ケース6では「+」以外なのでsignifをonのままにします。
A: eはsignif = onの分岐にあり、表2のケース6・7を分けています。ケース7ではValue[v+1] が「+」でsignifをoffにし、ケース6では「+」以外なのでsignifをonのままにします。
Q: Pattern[p] が「□」や「■」以外の場合も、Value[v]を使いますか?
A: いいえ。その場合は表2のケース8・9の処理に進みます。数字に対応する制御文字ではないため、Value[v]を使う処理やvを進める処理は行いません。
A: いいえ。その場合は表2のケース8・9の処理に進みます。数字に対応する制御文字ではないため、Value[v]を使う処理やvを進める処理は行いません。
関連キーワード: 条件分岐、フラグ、配列、文字列処理、ループ制御
設問3:
問題文を見る 次の記述中のに入れる正しい答えを、解答群の中から選べ。
関数Editでは、例えば、fill文字を“␣”とする編集パターンを指定することによって、数値が正なら“␣␣1,234␣”、負なら“␣␣1,234-”と編集することができる。表2のケース1〜7のうち、数値が正なら数値の後に続く文字をfill文字で置き換えるために用意されたケースはfである。
fに関する解答群
ア:2, 4及び7
イ:3, 5及び7
ウ:4及び7
エ:5及び7
模範解答
f:エ
解説
解答の導き方
数値の後に続く文字をfill文字で置き換えるには、数字を処理し終えたときに、変数signifをoffにしておく必要があります。
プログラムでは、数字に対応する制御文字を処理した後、数字以外の文字を次のように扱います。
- signifがoffなら、その文字をfill文字に置き換えます。
- signifがonなら、その文字をそのまま残します。
したがって、数値の後に続く文字をfill文字にするケースは、数字の最後を処理するときにsignifをoffにするケースです。
Value[]は、数字の並びの後に、数値が正又は0なら「+」、負なら「-」が付く形式です。そのため、Value[v+1]が「+」なら、Value[v]は正又は0の数値の最後の桁です。
表2で、この条件に当てはまるケースを確認します。
ケース5は、signifがまだoffの状態で、最後の桁が「1」~「9」の場合です。たとえば、先頭の0をfill文字にした後、最後の桁に到達したときに該当します。
ケース7は、それより前の桁ですでにsignifがonになっていて、最後の桁に到達した場合です。最後の桁が「0」でも、前の桁に0以外の数字があれば数値は正なので、このケースに含まれます。
どちらも、数値の最後の桁を数字で置き換えた後、signifをoffにします。その後に続く数字以外の文字はfill文字に置き換えられます。よって、該当するのはケース5及び7で、解答群ではエです。
ケース3もValue[v+1]が「+」ですが、Value[v]が「0」の場合です。数値が0のときの処理であり、正の数の最後の桁を処理するケースではありません。
誤りやすいポイント
- Value[v+1]が「+」であることだけを見て、ケース3も選ばないようにします。ケース3はValue[v]が「0」で、数値が0の場合の処理です。
- ケース5とケース7は、どちらも最後の桁を数字で置き換えます。違いは、その桁を処理する前のsignifがoffかonかです。
- signifがoffなら常にPattern[p]がfill文字になる、と考えないようにします。数字に対応する制御文字の処理では、表2のケースに従って数字を設定する場合があります。fill文字への置換は、数字以外の文字を処理するときの話です。
FAQ
Q: Value[v+1]が「+」なら、なぜValue[v]が最後の桁だと分かるのですか?
A: Value[]は、数字の並びの直後に「+」又は「-」を付けた形式だからです。「+」が次の位置にあるなら、Value[v]の数字の後に数字はなく、Value[v]が最後の桁です。
A: Value[]は、数字の並びの直後に「+」又は「-」を付けた形式だからです。「+」が次の位置にあるなら、Value[v]の数字の後に数字はなく、Value[v]が最後の桁です。
Q: ケース5とケース7は、どのように使い分けますか?
A: 最後の桁を処理する前のsignifで分かれます。まだ0以外の数字が現れておらずsignifがoffならケース5、すでに0以外の数字が現れてsignifがonならケース7です。
A: 最後の桁を処理する前のsignifで分かれます。まだ0以外の数字が現れておらずsignifがoffならケース5、すでに0以外の数字が現れてsignifがonならケース7です。
Q: signifがoffになると、後ろに続く数字もfill文字になりますか?
A: 数字に対応する制御文字は、表2のケースに従って処理されます。signifがoffのときにfill文字へ置き換えるのは、数字以外の文字です。
A: 数字に対応する制御文字は、表2のケースに従って処理されます。signifがoffのときにfill文字へ置き換えるのは、数字以外の文字です。
関連キーワード: 編集処理、制御文字、配列、論理型変数、条件分岐




