このページでは平成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言語ソースコード
#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言語ソースコード
#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