基本情報技術者 2018年 春期 午後 問10
次のCOBOLプログラムの説明及びプログラムを読んで、設問1,2に答えよ。
〔プログラムの説明〕
Web上でショッピングサイトを運営しているP社では、注文を受けて入金確認の処理を待っている商品の注文情報を注文ファイルに格納し、前日に入金された情報を入金ファイルに格納する。P社では毎朝10時に入金確認の処理を実行し、注文ファイルの情報と入金ファイルの情報を突き合わせて結果リストを印字する。このとき、入金が確認できなかった商品の注文情報は、出荷待ちファイルに格納する。前処理として、注文ファイルには、前日にプログラムを実行した際に出力された出荷待ちファイルの情報と、前日に受けた商品の注文情報を格納しておく。
このショッピングサイトでは、代金の支払方法として、銀行振込、コンビニ払い、クレジットカード払い(以下、カード払いという)、商品着払い(以下、着払いという)のいずれかを、注文時に選択できる。注文時に選択した支払方法と入金方法が異なることはない。銀行振込及びコンビニ払いによる入金の情報が入金ファイルに格納され、入金が確認できた注文を出荷対象とする。支払方法にカード払い又は着払いが選択された場合は、注文を受けた翌日に出荷する。
(1) 注文ファイルは、図1に示すレコード様式の順ファイルである。

① 注文番号には、注文ごとに一意に割り振られた番号が設定されている。注文番号として、99999999が割り振られることはない。
② 注文日時には、西暦の年、月、日と、24時間表記の時、分、秒が、それぞれ4桁、2桁、2桁、2桁、2桁、2桁で設定されている。
③ 請求金額には、正の整数が設定されている。
④ 支払種別には、注文時に選択された支払方法が、銀行振込、コンビニ払い、カード払い、着払いのそれぞれに対応する値、1、2、3、4で設定されている。
⑤ レコードは、注文番号の昇順に整列されている。
(2) 入金ファイルは、図2に示すレコード様式の順ファイルである。

① 注文番号には、入金が確認できた注文の注文番号が設定されている。
② 入金日時には、西暦の年、月、日と、24時間表記の時、分、秒が、それぞれ4桁、2桁、2桁、2桁、2桁、2桁で設定されている。
③ 入金金額には、正の整数が設定されている。
④ 入金種別には、入金方法が、銀行振込、コンビニ払いのそれぞれに対応する値、1、2で設定されている。
⑤ レコードは、注文番号の昇順に整列されている。同じ注文番号のレコードが複数格納されることはない。
(3) 出荷待ちファイルは、図3に示すレコード様式の順ファイルである。支払方法に銀行振込又はコンビニ払いが選択された注文のうち、入金を確認できなかった商品の注文情報が格納される。

① 各項目の内容は、注文ファイルのレコード様式と同じである。
(4) 結果リストの印字様式を図4に示す。見出しは印刷済みとする。

① 結果リストには、出荷する注文と、エラーと判定した注文の情報を印字する。結果欄に印字するコードと意味を表1に示す。

② 差額欄には、入金金額から請求金額を減算した金額を印字する。結果欄のコードが10の場合は、請求金額欄と差額欄には、0を印字する。支払方法がカード払い、着払いのいずれかであった場合は、入金金額欄と差額欄には、0を印字する。
③ 判定がエラーの場合は、出荷待ちファイルに情報は出力せず、個別に対処する。

設問1:
問題文を見る プログラム中のに入れる正しい答えを、解答群の中から選べ。
aに関する解答群
ア:ORD-EOF
イ:ORD-EOF AND RCP-EOF
ウ:ORD-EOF OR RCP-EOF
エ:RCP-EOF
b, cに関する解答群
ア:ORD-AMNT = RCP-AMNT
イ:ORD-AMNT = ZERO
ウ:ORD-AMNT NOT = RCP-AMNT
エ:ORD-CODE = 1 OR 2
オ:ORD-CODE = 3 OR 4
カ:ORD-CODE = RCP-CODE
dに関する解答群
ア:ADD 1 TO PRT-NO
イ:MOVE SPACE TO PRT-REC
ウ:SET ORD-EOF RCP-EOF TO TRUE
エ:WRITE PRT-REC
模範解答
a:イ、b:オ、c:ア、d:エ
解説
解答の導き方
このプログラムは、注文番号順に並んだ注文ファイルと入金ファイルを、先頭から順に見比べています。注文番号を比べることで、注文と入金が対応するか、入金のない注文か、注文のない入金かを判定します。このように、順に並んだファイル同士を照合する処理を、マージ処理といいます。
まず、ファイルの終わりをどう扱うかを確認します。EOF(End Of File:ファイルの終端)は、ファイルを最後まで読み終えた状態です。プログラムでは、ORD-EOFとRCP-EOFがそれぞれのファイルの終端を表します。どちらも真になったとき、注文ファイルと入金ファイルの両方を読み終えたことになります。
注文番号には「99999999が割り振られることはない」とあります。そのため、この値を終端を表す値として使えます。片方のファイルだけを読み終えても、もう一方に処理すべきレコードが残っている可能性があります。したがって、繰返しを終える条件は、ORD-EOFとRCP-EOFの両方が真であることです。aはイです。
次に、注文番号を比べる3つの分岐を見ます。
-
ORD-NOがRCP-NOより小さい場合
注文番号順に並んでいるため、現在の注文番号に対応する入金レコードはありません。ここで確認するのは支払種別です。問題文では、銀行振込とコンビニ払いは入金ファイルに入金情報が格納されます。一方、カード払いと着払いは注文を受けた翌日に出荷します。
支払種別が3又は4なら、入金レコードがなくても出荷対象なので、結果欄に00を設定します。プログラムの選択肢では、ORD-CODE = 3 OR 4に当たるオです。
それ以外の注文は、入金が確認できていないため出荷待ちファイルに出力します。結果欄は設定されないので、後の印字処理の対象にはなりません。 -
ORD-NOとRCP-NOが等しい場合
注文と入金が対応しています。出荷対象かどうかは、請求金額と入金金額が一致するかで判定します。問題文の表1では、金額が一致した場合は結果コード00、一致しない場合は結果コード20です。
したがって、条件はORD-AMNT = RCP-AMNTであり、cはアです。一致しない場合には20を設定し、入金金額から請求金額を引いた金額を差額欄に設定します。 -
ORD-NOがRCP-NOより大きい場合
現在の入金番号に対応する注文がありません。問題文の表1に従って、結果コード10を設定します。この場合は、入金レコードだけを次に進めます。
最後に、結果を印字する条件を確認します。注文が出荷待ちファイルに出力される場合は、結果欄が空白のままです。一方、出荷対象やエラーの場合は、結果欄に00、10、20のいずれかが設定されます。したがって、結果欄が空白でないときに結果リストへ出力します。該当する処理はWRITE PRT-RECなので、dはエです。
誤りやすいポイント
- aで、どちらか一方のファイルが終わった時点で繰返しを終了すると、もう一方に残っているレコードを処理できません。両方の終端を確認します。
- 注文番号が一致しない場合でも、常にエラーになるわけではありません。注文番号が小さい側が注文ファイルなら、支払種別によって、出荷対象か出荷待ちかが変わります。
- 注文番号が一致した後に比較するのは、請求金額と入金金額です。注文番号の一致だけでは、出荷対象とは判定できません。
- 出荷待ちファイルへの出力と、結果リストへの出力は別の処理です。入金待ちの注文は出荷待ちファイルに出力されますが、結果欄が空白なので結果リストには印字されません。
FAQ
Q: 注文番号が一致しない注文は、すべて結果コード10になりますか?
A: いいえ。結果コード10は、入金ファイルにある注文番号に対応する注文がない場合です。注文ファイルにだけある注文は、支払種別に応じて出荷対象又は出荷待ちになります。
A: いいえ。結果コード10は、入金ファイルにある注文番号に対応する注文がない場合です。注文ファイルにだけある注文は、支払種別に応じて出荷対象又は出荷待ちになります。
Q: ORD-NOとRCP-NOが一致したとき、支払種別も確認しないのですか?
A: 入金ファイルには銀行振込又はコンビニ払いによる入金情報が格納されます。そのため、注文番号が一致した場合は、請求金額と入金金額が一致するかを確認しています。
A: 入金ファイルには銀行振込又はコンビニ払いによる入金情報が格納されます。そのため、注文番号が一致した場合は、請求金額と入金金額が一致するかを確認しています。
Q: 出荷待ちの注文を結果リストに印字しないのはなぜですか?
A: 問題文では、結果リストに印字するのは出荷する注文とエラーと判定した注文です。入金を確認できていない注文は出荷待ちファイルに保存し、今回の結果リストには印字しません。
A: 問題文では、結果リストに印字するのは出荷する注文とエラーと判定した注文です。入金を確認できていない注文は出荷待ちファイルに保存し、今回の結果リストには印字しません。
関連キーワード: 順ファイル、マージ処理、EOF、条件名、帳票出力
設問2:
問題文を見る 支払方法に銀行振込又はコンビニ払いが選択された注文のうち、注文日の翌日を1日目として、7日を過ぎて入金が確認できなかった注文の注文番号を表示するようにプログラムを変更する。表2中のに入れる正しい答えを、解答群の中から選べ。ここで、組込み関数INTEGER-OF-DATEは、引数に指定されたYYYYMMDD形式の日付を西暦1601年1月1日からの通算の日数に変換して返す。

eに関する解答群
ア:行番号51と52の間
イ:行番号53と54の間
ウ:行番号65と66の間
エ:行番号71と72の間
fに関する解答群
ア:W-CNT < 7
イ:W-CNT = 7
ウ:W-CNT > 7
エ:W-CNT NOT = 7
模範解答
e:イ、f:ウ
解説
解答の導き方
この変更では、「注文日の翌日を1日目として、7日を過ぎても入金されていない注文」を見つけ、その注文番号を表示します。ポイントは、入金が確認できない注文を処理する場所と、注文日から何日たったかを計算する方法です。
まず、注文ファイルと入金ファイルは、どちらも注文番号の昇順に並んでいます。順ファイル(決められた順番に並べて記録したファイル)をこのように突き合わせると、注文番号の大小から、対応する入金情報があるかどうかを判断できます。
プログラムの行番号49では、注文番号を比べています。行番号49の「ORD-NO < RCP-NO」は、現在処理している注文の注文番号が、現在の入金情報の注文番号より小さいという意味です。入金情報が注文番号の昇順に並び、同じ注文番号のレコードが複数ないため、この場合、現在の注文番号に対応する入金情報はありません。
その後、行番号50から54では、支払方法に応じて処理を分けています。入金が確認できていない銀行振込又はコンビニ払いの注文は、行番号53で出荷待ちファイルに書き出されます。したがって、期限を過ぎたかどうかを調べる処理は、この注文を扱っている箇所に追加する必要があります。
追加位置の候補を比べると、行番号51と52の間は行番号50の条件が成立した側です。入金未確認の注文を出荷待ちファイルに書き出す側ではありません。行番号65と66の間は注文番号が一致し、入金情報が見つかった場合です。行番号71と72の間は入金情報に対応する注文がない場合で、期限を確認する対象の注文を処理している場所ではありません。
これに対して、行番号53と54の間なら、出荷待ちファイルに書き出した注文の情報を使って、注文日からの日数を計算できます。次の注文を読み込む処理は行番号56にあるので、その前に判定する必要があります。よって、追加位置は行番号53と54の間です。
次に、経過日数を考えます。変更内容では、CURRENT-DATEから現在の日付を取り出し、ORD-DATEに入っている注文日と比べます。INTEGER-OF-DATEは日付を通算日数に変換する関数です。通算日数とは、基準日から数えた日数のことです。日付をこの形に変換してから引き算すれば、月や年をまたぐ場合も、実際に何日経過したかを求められます。
計算する値は、次のとおりです。
W-CNT = 現在の日付の通算日数 - 注文日の通算日数
注文日の翌日は差が1、その翌日は差が2です。したがって、注文日からちょうど7日後ならW-CNTは7です。「7日を過ぎて」いるのは、差が7より大きい場合なので、条件はW-CNT > 7になります。
誤りやすいポイント
- 注文番号が一致する場合と、入金が確認できない場合を混同しないようにします。行番号57の「ORD-NO = RCP-NO」は、注文と入金情報の注文番号が一致する場合です。
- 行番号53の出荷待ちファイルへの書き出しより後に注文番号を表示する処理を追加します。次の注文を読み込んだ後では、ORD-DATEやORD-NOが次の注文の値に変わってしまいます。
- 「7日を過ぎて」は、経過日数が7日ちょうどではなく、7日より大きいことを表します。そのため、W-CNT = 7ではなくW-CNT > 7です。
- YYYYMMDDの数字をそのまま引き算すると、月末や年末をまたぐときに正しい日数になりません。INTEGER-OF-DATEで通算日数に変換してから差を求めます。
FAQ
Q: 注文日の翌日を1日目とするのに、なぜ注文日からの日数の差を使えるのですか?
A: 注文日当日の差は0です。翌日は差が1、その翌日は差が2となるため、「翌日を1日目」と数える方法と一致します。
A: 注文日当日の差は0です。翌日は差が1、その翌日は差が2となるため、「翌日を1日目」と数える方法と一致します。
Q: W-CNTが7のときは、なぜ注文番号を表示しないのですか?
A: W-CNTが7なら、注文日からちょうど7日経過した状態です。「7日を過ぎて」とは、7日経過した状態をさらに超えた場合なので、表示する条件はW-CNT > 7です。
A: W-CNTが7なら、注文日からちょうど7日経過した状態です。「7日を過ぎて」とは、7日経過した状態をさらに超えた場合なので、表示する条件はW-CNT > 7です。
Q: 日付の数字を直接引き算しないのはなぜですか?
A: たとえば月末から翌月初めに進む場合、日付の数字の差と、実際に経過した日数は一致しません。通算日数に変換すれば、月や年をまたいでも日数を正しく計算できます。
A: たとえば月末から翌月初めに進む場合、日付の数字の差と、実際に経過した日数は一致しません。通算日数に変換すれば、月や年をまたいでも日数を正しく計算できます。
関連キーワード: 順ファイル、整列処理、通算日数、日付関数、条件分岐



