基本情報技術者試験の過去問と解説
[TOP] [午前分野別] [午後分野別] [キーワード索引] [令和元年秋午前] [令和元年秋午後]

平成30年 春期 基本情報技術者 午後 問09
問09   C言語

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

 

 簡易集計プログラムである。このプログラムを用いると,例えば,図1の入力ファイルから, 品番ごとのレコード件数と金額の合計を求めて,図2の集計ファイルを得ることができる。

 プログラムは,キー項目及び数値項目の,開始桁位置及び桁数を引数で受け取り, キー項目で整列済みのレコードを入力ファイルから読み込み,キー項目の値ごとに, その作数と数値項目の値の合計を求め,集計ファイルにレコードとして書き出す。 ここで,数値項目には整数の値が入る。

 

図1 入力ファイルのレコード例       図2 集計ファイルのレコード例

 

〔プログラム1の説明〕

(1) 入力ファイルは,固定長レコードの並びから成る。レコードは, 1,000 文字以下の 1 バイト文字の並びであり,最後の文字の後には改行文字が付いている。 ファイル名は,引数 dataFile で指定する。

(2) レコード中のキー項目の開始桁位置及び桁数は,それぞれ引数 keyPos 及び keyLen で指定する。 また,数値項目の開始桁位置及び桁数は,それぞれ引数 valuePos 及び valueLen で指定する。 開始桁位置は,レコードの先頭文字の桁位置を 0 として数える。キー項目及び数値項目の桁数は, いずれも 9 桁以下とする。

(3) 入力レコードは,キー項目の昇順に整列されている。

(4) 集計ファイルにレコードとして,キー項目の値,キー項目ごとの件数及び数値項目の値の 合計を各 9 桁分の領域に右詰めで出力し,各項目の直前に1個の空白文字を出力する。 レコードの最後の文字の後には改行文字を付ける。ファイル名は, 引数 listFile で指定する。

(5) 引数及び入力レコードの内容に誤りはないものとする。また,数値項目の値の 合計は 9 桁以下であり,算術演算であふれは起きないものとする。

(6)プログラム中で使用しているライブラリ関数(一部)の概要は,次のとおりである。

・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〕
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define recSize 1ØØ2   /* 入力レコードの最大文字数 + 2('\n', '\Ø') */

void outList(char *dataFile, char *listFile,
             int keyPos, int keyLen, inl valuePos, int valueLen) {
  a  *inFile, *outFile;
  char inBuf[recSize], inKey[1Ø], key[1Ø], temp[1Ø];
  long count, inValue, value;
  char format[] = " %9s %9ld %9ld\n";
  key[keyLen] = '\Ø';
  inKey[keyLen] = '\Ø';
  temp[valueLen] = '\Ø' ;
  outFile = fopen(listFite, "w");
  inFile = fopen(dataFile, "r");

  if (fgets(inBuf, recSize, inFite) != NULL) {
     strncpy(key, inBuf + keyPos, keyLen);
     count = 1;
     value = atol(strncpy(temp, inBuf + valuePos, valueLen));
     while (fgets(inBuf, recSize, inFile) != NULL) {
        strncpy(inKey, inBuf + keyPos, keyLen);
        inValue = atol(strncpy(temp, inBuf + valuePos, valueLen));
        if (strcmp(key, inKey) != Ø) {
           fprintf(outFile, format, key, count, value);
           count = 1;
           strcpy(key, inKey);
           value = inValue;
        }
        else {
          b
        }
     }
     c
  }
  fclose(inFile);
  fclose(outFile);
}

 

設問1  プログラム中の   に入れる適切な答えを,解答群の中から選べ。

 

a に関する解答群 ア char       イ FILE       ウ file       エ int

 

b,c に関する解答群 ア fprintf(outFile, format, inKey, count, inValue);

イ fprintf(outFite, format, key, count, value);

ウ count++:
  value += inValue;

エ count++;
  value += inValue;
  fprintf(outFite, format, key, count, value);

オ count--;
  fprintf(outFite, format, inKey, count, inValue);

 

解答 a ←クリックすると正解が表示されます

解答 b ←クリックすると正解が表示されます

解答 c ←クリックすると正解が表示されます

基本情報技術者試験


設問2  次の記述中の   に入れる適切な答えを,解答群の中から選べ。 ここで,プログラム2中の a には,設問1の正しい答えが入っているものとする。

 

 図3に示す,時分秒のうちの時をキー項目として昇順に整列済みのレコードを 入力ファイルから読み込み,時間帯( 0 時台,1 時台,…,23 時台)ごとの件数と 金額の合計(合計金額)を求め,時,件数,合計金額と合計金額を表す棒グラフを印字する。 この処理を,次の手順で行う。

(1) プログラム1を利用して,図3の入力ファイルから,図4の集計ファイルを得る。

(2) プログラム2を利用して,図4の集計ファイルから,図5の印字結果を得る。

 

図3 入力ファイルのレコード例       図4 集計ファイルのレコード例

 

図5 印字結果の例

 

〔プログラム2の説明〕

(1) プログラム1で書き出した集計ファイルからレコードを読み込む。ファイル名は, 引数 listFile で指定する。

(2) 読み込んだ各レコードに,そのレコードの合計金額の値 value に応じた長さのグラフを 追加して印字する。集計ファイル中の合計金額の値の最大値 valueMax を 25 個の “*”で表し,他の値は,25 × value ÷ valueMax 個(小数点以下切捨て)の“*”で表す。 ここで,集計ファイル中の合計金額の値の最大値は正であり,最小値は 0 以上であるものとする。

 

〔プログラム2〕
#include <stdio.h>
#include <stdlib.h>

#define  listLen  32        /* 入力レコードの最大文字数 + 2 ('\n', '\Ø') */

void outListG(char *listFile) {
   a *inFile;
   char inBuf[listLen];
   long value, valueMax;
   char graph[] = "*************************";

   inFile = fopen(listFile, "r");
   valueMax = Ø;
   while (fgets(inBuf, listLen, inFile) != NULL) {
      value = atol(inBuf + 21);
      if (value > valueMax) {
         valueMax = value;
      }
   }
   fclose(inFile);
   inFile = fopen(listFile, "r");
   while (fgets(inBuf, listLen, inFile) != NULL) {
      value = atol(inBuf + 21) ;
      printf("%.3Øs l%s\n",
             inBuf, &graph[25 - 25 * value / valueMax]);  /* α */
      /* %.3Øs はレコードの先頭からの 3Ø 桁(\n の直前まで) を出力する */
   }
   fclose(inFile);
}

 

 プログラム2は,作成途中である。図4の集計ファイルを用いると図5の印字結果が 得られるが,集計ファイル中の合計金額の値によっては,コメント /* α */ を 付した印字処理の実行時に問題が発生する場合がある。

 〔プログラム2の説明〕の (2) にある前提“集計ファイル中の合計金額の値の 最大値は正であり,最小値は 0 以上である”が満たされない場合も考慮に含め, コメント /* α */ を付した印字処理の実行時に発生し得る事象として, @算術演算であふれが発生,A算術演算でゼロ除算が発生,B配列の定義外の要素位置を参照,がある。 これらの事象が発生し得る value と valueMax の値の例を,表1にまとめた。 ここで,long 型の数値の範囲は,−231〜231 − 1 (231=2,147,483,648)とする。

 

表1 事象@〜Bが発生し得る value とvalueMax の値の例

 

d 〜 f に関する解答群

 

解答 d ←クリックすると正解が表示されます

解答 e ←クリックすると正解が表示されます

解答 f ←クリックすると正解が表示されます


[←前の問題] [次の問題→] [問題一覧表] [分野別] [基本情報技術者試験TOP ]