平成30年春期試験午後問題 問9
問9 ソフトウェア開発(C)
次のCプログラムの説明及びプログラムを読んで,設問1,2に答えよ。
簡易集計プログラムである。このプログラムを用いると,例えば,図1の入力ファイルから,品番ごとのレコード件数と金額の合計を求めて,図2の集計ファイルを得ることができる。
プログラムは,キー項目及び数値項目の,開始桁位置及び桁数を引数で受け取り,キー項目で整列済みのレコードを入力ファイルから読み込み,キー項目の値ごとに,その件数と数値項目の値の合計を求め,集計ファイルにレコードとして書き出す。ここで,数値項目には整数の値が入る。〔プログラム1の説明〕
簡易集計プログラムである。このプログラムを用いると,例えば,図1の入力ファイルから,品番ごとのレコード件数と金額の合計を求めて,図2の集計ファイルを得ることができる。
プログラムは,キー項目及び数値項目の,開始桁位置及び桁数を引数で受け取り,キー項目で整列済みのレコードを入力ファイルから読み込み,キー項目の値ごとに,その件数と数値項目の値の合計を求め,集計ファイルにレコードとして書き出す。ここで,数値項目には整数の値が入る。〔プログラム1の説明〕
- 入力ファイルは,固定長レコードの並びから成る。レコードは,1,000文字以下の1バイト文字の並びであり,最後の文字の後には改行文字が付いている。ファイル名は,引数 dataFile で指定する。
- レコード中のキー項目の開始桁位置及び桁数は,それぞれ引数 keyPos 及び keyLen で指定する。また,数値項目の開始桁位置及び桁数は,それぞれ引数 valuePos 及び valueLen で指定する。開始桁位置は,レコードの先頭文字の桁位置を 0 として数える。キー項目及び数値項目の桁数は,いずれも9桁以下とする。
- 入力レコードは,キー項目の昇順に整列されている。
- 集計ファイルにレコードとして,キー項目の値,キー項目ごとの件数及び数値項目の値の合計を各9桁分の領域に右詰めで出力し,各項目の直前に1個の空白文字を出力する。レコードの最後の文字の後には改行文字を付ける。ファイル名は,引数 listFile で指定する。
- 引数及び入力レコードの内容に誤りはないものとする。また,数値項目の値の合計は9桁以下であり,算術演算であふれは起きないものとする。
- プログラム中で使用しているライブラリ関数(一部)の概要は,次のとおりである。
- ・atol(s):
- 文字列 s が表す数値を long 型の表現に変換した値を返す。
- ・fgets(s,m,f):
- ストリーム f から文字の列(改行文字まで,最大 m-1 文字)を読み取り,配列 s に格納し,s を返す。ストリームの終わりに達した場合は NULL を返す。
- ・strcmp(s1,s2):
- 文字列 s1 と s2 を比較し,s1<s2 のとき負の値を,s1=s2 のとき 0 を,s1>s2 のとき正の値を,それぞれ返す。
- ・strcpy(s1,s2):
- 文字列 s2 を文字列 s1 に複写する。
- ・strncpy(s1,s2,n):
- 文字列 s2 の先頭から n 個の文字を文字列 s1 に複写し,文字列 s1 の値を返す。
広告
設問1
プログラム1中の に入れる適切な答えを,解答群の中から選べ。
a に関する解答群
- char
- FILE
- file
- int
b,c に関する解答群
- fprintf(outFile,format,inKey,count,inValue);
- fprintf(outFile,format,key,count,value);
- count++;
value += inValue; - count++;
value += inValue;
fprintf(outFile,format,key,count,value); - count--;
fprintf(outFile,format,inKey,count,inValue)
解答選択欄
- a:
- b:
- c:
- a=イ
- b=ウ
- c=イ
解説
以下は〔プログラム1〕の処理部分についてコメントを加えたものです。〔aについて〕
変数 inFile および outFile は、fopen 関数で開いた入力ファイル(dataFile)と集計ファイル(listFile)を格納するために使用されています。C言語では、ファイルを入出力する際にstdio.hに定義されている FILE 構造体へのポインタを使用するので、aには FILE が入ります。
∴a=イ:FILE
〔bについて〕
bは、現在読み込んでいるレコードの品番が集計中の品番と同じだったときに行われる処理です。同じ品番の場合には、集計ファイルへの出力は行わず、件数を1件増やすとともに、合計金額に現在読み込んでいるレコードの金額を加算することになります。
集計中の品番のレコード件数は count、集計中の品番の合計金額は value、現在読み込んでいるレコードの金額は inValueに、それぞれ格納されているため、count をインクリメントする処理と、value に inValue を加える処理が入ります。
∴ウ
count++
value += inValue
value += inValue
〔cについて〕
集計ファイルへの出力のタイミングは次の品番のレコードを読み込んだときなので、次の品番が存在しない最後に集計していた品番については、ファイルの終端に達しても出力が行われません。このためファイルの終端まで達したら、最後に集計していた品番の情報を出力する処理が必要になります。
直前まで集計していた品番のレコード件数は countに、合計金額は value にそれぞれ格納されているので、fprintf 関数でこれらの情報を集計ファイルに出力することになります(※key と inKey はどちらも同じ値になっているはずですので、どちらを出力しても構わないものと思われます。)
∴イ
fprintf(outFile, format, key, count, value)
広告
設問2
次の記述中の に入れる適切な答えを,解答群の中から選べ。ここで,プログラム2中のaには,設問1の正しい答えが入っているものとする。
図3に示す,時分秒のうちの時をキー項目として昇順に整列済みのレコードを入力ファイルから読み込み,時間帯(0時台,1時台,…,23時台)ごとの件数と金額の合計(合計金額)を求め,時,件数,合計金額と合計金額を表す棒グラフを印字する。この処理を,次の手順で行う。
〔プログラム2の説明〕の(2)にある前提"集計ファイル中の合計金額の値の最大値は正であり,最小値は 0 以上である"が満たされない場合も考慮に含め,コメント/* α */を付した印字処理の実行時に発生し得る事象として,①算術演算であふれが発生,②算術演算でゼロ除算が発生,③配列の定義外の要素位置を参照,がある。これらの事象が発生し得る value と valueMax の値の例を,表1にまとめた。ここで,long 型の数値の範囲は,-231~231-1(231=2,147,483,648)とする。
図3に示す,時分秒のうちの時をキー項目として昇順に整列済みのレコードを入力ファイルから読み込み,時間帯(0時台,1時台,…,23時台)ごとの件数と金額の合計(合計金額)を求め,時,件数,合計金額と合計金額を表す棒グラフを印字する。この処理を,次の手順で行う。
- プログラム1を利用して,図3の入力ファイルから,図4の集計ファイルを得る。
- プログラム2を利用して,図4の集計ファイルから,図5の印字結果を得る。
- プログラム1で書き出した集計ファイルからレコードを読み込む。ファイル名は,引数 listFile で指定する。
- 読み込んだ各レコードに,そのレコードの合計金額の値 value に応じた長さのグラフを追加して印字する。集計ファイル中の合計金額の値の最大値 valueMax を25個の"*"で表し,他の値は,25×value÷valueMax 個(小数点以下切捨て)の"*"で表す。ここで,集計ファイル中の合計金額の値の最大値は正であり,最小値は 0 以上であるものとする。
〔プログラム2の説明〕の(2)にある前提"集計ファイル中の合計金額の値の最大値は正であり,最小値は 0 以上である"が満たされない場合も考慮に含め,コメント/* α */を付した印字処理の実行時に発生し得る事象として,①算術演算であふれが発生,②算術演算でゼロ除算が発生,③配列の定義外の要素位置を参照,がある。これらの事象が発生し得る value と valueMax の値の例を,表1にまとめた。ここで,long 型の数値の範囲は,-231~231-1(231=2,147,483,648)とする。
d,e,f に関する解答群
解答選択欄
- d:
- e:
- f:
- d=カ
- e=ア
- f=イ
解説
〔dについて〕long型の整数の範囲は、およそ-21億~+21憶です。αの式中には「25 * value」がありますが、25に100,000,000を乗じると25億になるのであふれが生じます。
選択肢中で唯一「25 × value」が±21億を超える「カ」が正解です。
∴カ
〔eについて〕
ゼロ除算とは、0(ゼロ)で割る処理のことで、多くの処理系では処理が中断されたりエラーメッセージが表示されたりします。αの式中には「25 * value / valueMax」がありますが、valueMax が 0 のときにはゼロ除算になります。
選択肢中で唯一 valueMax が 0 になっている「ア」が正解です。
∴ア
〔fについて〕
各選択肢について「25 - 25 * value / valueMax」を計算することで、範囲外を指定してしまうことなる値の組合せがわかります。※C言語では整数同士の除算の結果は整数(小数点以下切り捨て)になります。
- ゼロ除算なので処理が中断されます。
- 25 - 25 * (-10,000,000) / 10,000,000
=25 - (-250,00,000) / 10,000,000
=25 - (-25)
=50
graphは、0から25(*の数+NULL文字)までのchar配列ですので、50を添え字とした場合、配列の範囲外を指定することになります。よってこれが正解です。 - 25 - 25 * 0 / 10,000,000
=25 - 0 / 10,000,000
=25 - 0
=25 - 25 - 25 * 100 / 10,000,000
=25 - 2,500 / 10,000,000
=25 - 0
=25 - 25 - 25 * 10,000,000 / 10,000,000
=25 - 250,000,000 / 10,000,000
=25 - 25
=0 - 算術演算中にあふれが発生します。
広告
広告