基本情報技術者試験 C言語問題のソースコード(平成30年 春期 )

このページでは平成30年春期 基本情報技術者試験のC言語問題のソースコードを実際に実行できるように変更したものを公開しています。さらに実行時の動きの確認が行えるように変更しています。C言語問題対策のためにも、こちらのソースコードをコピペして実際にプログラムを動作させ、どのように動作するのか、正解以外の選択肢を選んだ場合にどのような動きになって仕様を満たさないかを確認するために使用してみてください。

問題

平成30年春期のC言語問題はIPAの下記ページで公開されています。

https://www.jitec.ipa.go.jp/1_04hanni_sukiru/mondai_kaitou_2018h30_1/2018h30h_fe_pm_qs.pdf

問題の解説

問題の解き方の解説は下記ページで行なっています。自分でプログラムの動きが追うのが困難な場合などに参考にしてください。

平成30年(H30)春期 基本情報技術者試験 C言語問題 解き方解説

スポンサーリンク

設問1

C言語ソースコード

h30s_c_1.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define recSize 1002

void outList(char *dataFile, char *listFile, int keyPos, int keyLen, int valuePos, int valueLen) {
    /* 設問1の[a] */
    FILE *inFile, *outFile;
    char inBuf[recSize], inKey[10], key[10], temp[10];
    long count, inValue, value;
    char format[] = " %9s %9ld %9ld\n";

    key[keyLen] = '\0';
    inKey[keyLen] = '\0';
    temp[valueLen] = '\0';
    outFile = fopen(listFile, "w");
    inFile = fopen(dataFile, "r");

    if (fgets(inBuf, recSize, inFile) != NULL) {
      strncpy(key, inBuf + keyPos, keyLen);

      /* 動作確認用に追加 */
      printf("key = %s\n", key);

      count = 1;
      value = atol(strncpy(temp, inBuf + valuePos, valueLen));
      while (fgets(inBuf, recSize, inFile) != NULL) {
        strncpy(inKey, inBuf + keyPos, keyLen);

        /* 動作確認用に追加 */
        printf("key = %s, value = %ld, inKey = %s\n", key, value, inKey);

        inValue = atol(strncpy(temp, inBuf + valuePos, valueLen));
        if (strcmp(key, inKey) != 0) {
          fprintf(outFile, format, key, count, value);
          count = 1;
          strcpy(key, inKey);
          value = inValue;
        }
        else {
          /* 設問1の[b] */
          count++;
          value += inValue;
        }
      }
      /* 設問1の[c] */
      fprintf(outFile, format, key, count, value);
    }
    fclose(inFile);
    fclose(outFile);
}

int main(void) {
  char dataFile[256] = "input.txt"; /* 図1の入力ファイル */
  char listFile[256] = "output.txt";

  int keyPos = 14; /* 図1における品番(キー項目)の開始位置(行の先頭から何文字目の位置か) */
  int keyLen = 6; /* 図1における品番(キー項目)の桁数 */
  int valuePos = 24; /* 図1における金額(数値項目)の開始位置(行の先頭から何文字目の位置か) */
  int valueLen = 6; /* 図1における金額(数値項目)の桁数 */

  outList(dataFile, listFile, keyPos, keyLen, valuePos, valueLen);

  return 0;
}

実行方法

設問1のプログラムの実行方法について説明します。下記をコピペし、「input.txt」という名前で保存したファルをプログラム実行ファイルと同じ場所に置きます。

20180410112610FE-1110001000100
20180410154358FE-1110001000100
20180410123820FE-2220002000400
20180410153249FE-3330001000300
20180410135044FE-3330001000300
20180410152859FE-3330001000300
20180410131923FE-4440002000800
20180410123907FE-4440001000400

これは図1で示されている入力データになります。「input.txt」を置けば準備は完了で、あとはプログラムをコンパイルして実行すればオーケーです。

実行結果

実行すると下記のような中身の「output.txt」が出力されるはずです。

    FE-111         2       200
    FE-222         1       400
    FE-333         3       900
    FE-444         2      1200

これは図2の集計結果であり、このプログラムの最終出力結果となります。

また動作確認用として下記のようにkeyと、そのkeyに対するvalueの値、次に読み込んだinKeyをコンソールに出力しているようにしています。

key = FE-111
key = FE-111, value = 100, inKey = FE-111
key = FE-111, value = 200, inKey = FE-222
key = FE-222, value = 400, inKey = FE-333
key = FE-333, value = 300, inKey = FE-333
key = FE-333, value = 600, inKey = FE-333
key = FE-333, value = 900, inKey = FE-444
key = FE-444, value = 800, inKey = FE-444

動作確認用の変更箇所

main関数追加

まずmain関数の追加を行なっています。main関数では、主に問題に掲載されているoutList関数の引数に必要なデータの準備を行なっています。

設問1では入力されるデータが「品番で昇順ソート」されており、キー項目が「品番」となっていますので、これを満たすようにデータの用意をしています。

動作確認用の文字列出力追加

ループの中で、キー項目とそのキー項目に対しての数値項目の合計がどのように変化していくかを追えるように、キー項目取得後(strncpy後)にこれらを出力するように変更しています。

設問2

C言語ソースコード

h30s_c_2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define recSize 1002

#define listLen 32

void outList(char *dataFile, char *listFile, int keyPos, int keyLen, int valuePos, int valueLen) {
    /* 設問1の[a] */
    FILE *inFile, *outFile;
    char inBuf[recSize], inKey[10], key[10], temp[10];
    long count, inValue, value;
    char format[] = " %9s %9ld %9ld\n";

    key[keyLen] = '\0';
    inKey[keyLen] = '\0';
    temp[valueLen] = '\0';
    outFile = fopen(listFile, "w");
    inFile = fopen(dataFile, "r");

    if (fgets(inBuf, recSize, inFile) != NULL) {
      strncpy(key, inBuf + keyPos, keyLen);

      /* 動作確認用に追加 */
      printf("key = %s\n", key);

      count = 1;
      value = atol(strncpy(temp, inBuf + valuePos, valueLen));
      while (fgets(inBuf, recSize, inFile) != NULL) {
        strncpy(inKey, inBuf + keyPos, keyLen);

        /* 動作確認用に追加 */
        printf("key = %s, value = %ld, inKey = %s\n", key, value, inKey);

        inValue = atol(strncpy(temp, inBuf + valuePos, valueLen));
        if (strcmp(key, inKey) != 0) {
          fprintf(outFile, format, key, count, value);
          count = 1;
          strcpy(key, inKey);
          value = inValue;
        }
        else {
          /* 設問1の[b] */
          count++;
          value += inValue;
        }
      }
      /* 設問1の[c] */
      fprintf(outFile, format, key, count, value);
    }
    fclose(inFile);
    fclose(outFile);
}

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

  inFile = fopen(listFile, "r");
  valueMax = 0;
  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("%.30s |%s\n",
      inBuf, &graph[25 - 25 * value / valueMax]);
  }
  fclose(inFile);
}

int main(void) {
  char dataFile[256] = "input_2.txt"; /* 図1の入力ファイル */
  char listFile[256] = "output_2.txt";

  int keyPos = 8; /* 図1における時(キー項目)の開始位置(行の先頭から何文字目の位置か) */
  int keyLen = 2; /* 図1における時(キー項目)の桁数 */
  int valuePos = 24; /* 図1における金額(数値項目)の開始位置(行の先頭から何文字目の位置か) */
  int valueLen = 6; /* 図1における金額(数値項目)の桁数 */

  outList(dataFile, listFile, keyPos, keyLen, valuePos, valueLen);

  outListG(listFile);

  return 0;
}

実行方法

プログラムの実行方法について説明します。下記をコピペし、「input_2.txt」という名前で保存したファルをプログラム実行ファイルと同じ場所に置きます。

20180410112610FE-1110001000100
20180410123820FE-2220002000400
20180410123907FE-4440001000400
20180410131923FE-4440002000800
20180410135044FE-3330001000300
20180410152859FE-3330001000300
20180410153249FE-3330001000300
20180410154358FE-1110001000100

これは図3で示されている入力データになります。設問1の「input.txt」とは行データの並び順が異なるので注意してください。「input_2.txt」を置けば準備は完了で、あとはプログラムをコンパイルして実行するだけです。

実行結果

実行すると下記のような中身の「output_2.txt」が出力されるはずです。

        11         1       100
        12         2       800
        13         2      1100
        15         3       700

これは図4の集計結果となります。

さらに設問2では図4をグラフ化した印字結果(図5)を出力する必要がありますので、下記のような印字結果がコンソールに出力されます。

        11         1       100 |**
        12         2       800 |******************
        13         2      1100 |*************************
        15         3       700 |***************

動作確認用の変更箇所

main関数追加

設問1と同様に、main関数でoutList関数の引数に必要なデータの準備を行なっています。

設問2では入力データが「時間で昇順ソート」されており、キー項目が「時」であると言う前提がありますので、これを満たすように入力データを準備しています。

さらに、設問2ではoutList関数を実行した結果に対して図5のようなグラフを出力する必要がありますので、そのためにoutList関数実行直後にoutListG関数を実行するようになっています。

動作確認用の文字列出力追加

設問1同様にループの中で、キー項目とそのキー項目に対しての数値項目の合計がどのように変化していくかを追えるように、キー項目取得後(strncpy後)にこれらを出力するように変更しています。

 

他の回のソースコード

他の回のソースコードについても下記ページで公開していますので、是非ソースコードを使用してプログラムの動きを見てみてください。

基本情報技術者試験C言語問題のプログラムを動かしてみよう(まとめ)

本ページのプログラムについて

プログラムはIPA公開の過去問題から引用し、さらに動作確認できるように必要な部分に関してのみ加工して使用させていただいております。

出典:平成30年度 春期 基本情報技術者試験(FE)試験区分 午後 問9

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です