基本情報技術者・午後過去問(2019春)・解答例についてソースコード付きで解説します。
【問題1】平成31年 春期 基本情報技術者 午後 問09
次のC言語プログラムの説明及びプログラムを読んで,設問1,2に答えよ。
入力ファイルを読み込んで,文字コードごとの出現回数を印字するプログラムである。
– | 〔プログラムの説明〕 |
---|---|
(1) | 入力ファイルは,バイナリファイルとして読み込む。 入力ファイル中の各バイトの内容(ビット構成)に制約はない。入力ファイル名は,#define で指定する。 |
(2) | 入力ファイル中の各バイトについて,文字コード(16 進数 00 ~ FF で表示する)ごとの出現回数を求めて印字する。印字例を,図1に示す。 |
(3) | 印字様式を次に示す(①~③は,プログラム中の記号を指している)。1 行目に,処理したバイト数を①の形式で印字する。3 行目以降に,出現回数とその文字コードを②の形式で印字する。 ただし,文字コードが 20~ 7E の場合は,文字コードの後にそれが表す文字(文字は, この冊子の末尾にあるアセンブラ言語の仕様の 1.3 で規定するもの)を③の形式で印字する。文字コードは,64 行× 4 列の範囲に,上から下, 左から右に文字コードの昇順となるように並べる。 |
(4) | プログラム中で使用している関数 fgetc(s) は,ストリーム s から1文字を読み込んで返す。 ストリームが入力ファイルの終わりに達しているときは EOF を返す。 |
(5) | 入力ファイルのサイズは,long 型(32 ビットとする)で表現できる数値の範囲を超えないものとする。 |
870 bytes processed・・・① 0 00 0 40 '@' 0 80 0 C0 0 01・・・② 0 41 'A' ・・・③ 1 81 0 C1 0 02 0 42 'B' 3 82 0 C2 0 03 1 43 'C' 4 83 0 C3 ︙ 1 3E '>' 0 7E '~' 1 BE 0 FE 0 3F '?' 0 7F 0 BF 0 FF 0 40 '@' 0 80 0 C0 1985365600 100
プログラム
#include <stdio.h> #define InName "sample.c"/* 入力ファイル名 */ int main() { FILE *infile; int chr, i; long cnt; long freq[256]; /* freq[i]: 文字コード i の出現回数 */ for (chr = 0; chr <= 255; chr++) freq[chr] = 0; infile = fopen(InName, "rb"); cnt = 0; while ((chr = fgetc(infile)) != EOF) { cnt++; freq[chr]++; } fclose(infile); printf(" %10ld bytes processed\n\n", [a]); for (i = 0; i <= 64; i++) { for (chr = i; chr <= [b] ; chr += [c] ) { if ((0x20 <= chr) && (chr <= 0x7E)) printf(" %10ld %02X '%c'", freq[chr], chr, chr); else printf(" %10ld %02X", freq[chr], chr); } printf("\n"); } return 0; }
ア cnt – 1 イ cnt ウ cnt + 1
b,c に関する解答群
ア 4 イ 64 ウ 256
エ i + 4 オ i + 64 カ i + 192
【解答1】
a=イb=カc=イ
#include <stdio.h> #define InName "C:\\github\\sample\\cpp\\fe\\2018_2\\sample.c"/* 入力ファイル名 */ int main() { FILE *infile; int chr, i; long cnt; long freq[256]; /* freq[i]: 文字コード i の出現回数 */ for (chr = 0; chr <= 255; chr++) freq[chr] = 0; infile = fopen(InName, "rb"); cnt = 0; while ((chr = fgetc(infile)) != EOF) { cnt++; freq[chr]++; } fclose(infile); printf(" %10ld bytes processed\n\n", cnt); for (i = 0; i <= 64; i++) { for (chr = i; chr <= i + 192 ; chr += 64 ) { if ((0x20 <= chr) && (chr <= 0x7E)) printf(" %10ld %02X '%c'", freq[chr], chr, chr); else printf(" %10ld %02X", freq[chr], chr); } printf("\n"); } return 0; }
870 bytes processed 0 00 0 40 '@' 0 80 0 C0 0 01 0 41 'A' 1 81 0 C1 0 02 0 42 'B' 3 82 0 C2 0 03 1 43 'C' 4 83 0 C3 0 04 0 44 'D' 0 84 0 C4 0 05 3 45 'E' 1 85 0 C5 0 06 2 46 'F' 0 86 0 C6 0 07 0 47 'G' 2 87 0 C7 0 08 0 48 'H' 0 88 0 C8 0 09 3 49 'I' 1 89 0 C9 34 0A 0 4A 'J' 1 8A 0 CA 0 0B 0 4B 'K' 0 8B 0 CB 0 0C 1 4C 'L' 0 8C 0 CC 34 0D 0 4D 'M' 1 8D 0 CD 0 0E 2 4E 'N' 0 8E 0 CE 0 0F 1 4F 'O' 1 8F 0 CF 0 10 0 50 'P' 1 90 0 D0 0 11 0 51 'Q' 0 91 0 D1 0 12 0 52 'R' 0 92 0 D2 0 13 0 53 'S' 0 93 0 D3 0 14 0 54 'T' 0 94 0 D4 0 15 0 55 'U' 2 95 0 D5 0 16 0 56 'V' 1 96 0 D6 0 17 0 57 'W' 1 97 0 D7 0 18 2 58 'X' 0 98 0 D8 0 19 0 59 'Y' 0 99 0 D9 0 1A 0 5A 'Z' 0 9A 0 DA 0 1B 6 5B '[' 2 9B 0 DB 0 1C 15 5C '\' 0 9C 0 DC 0 1D 6 5D ']' 0 9D 0 DD 0 1E 0 5E '^' 1 9E 0 DE 0 1F 1 5F '_' 0 9F 0 DF 250 20 ' ' 0 60 '`' 0 A0 0 E0 1 21 '!' 5 61 'a' 1 A1 0 E1 12 22 '"' 3 62 'b' 0 A2 0 E2 2 23 '#' 28 63 'c' 0 A3 8 E3 0 24 '$' 7 64 'd' 1 A4 0 E4 6 25 '%' 28 65 'e' 1 A5 6 E5 2 26 '&' 23 66 'f' 0 A6 2 E6 2 27 ''' 4 67 'g' 0 A7 1 E7 16 28 '(' 20 68 'h' 0 A8 0 E8 16 29 ')' 29 69 'i' 0 A9 0 E9 5 2A '*' 0 6A 'j' 0 AA 0 EA 10 2B '+' 0 6B 'k' 1 AB 0 EB 8 2C ',' 15 6C 'l' 0 AC 0 EC 0 2D '-' 5 6D 'm' 1 AD 0 ED 2 2E '.' 26 6E 'n' 1 AE 0 EE 4 2F '/' 9 6F 'o' 0 AF 0 EF 14 30 '0' 10 70 'p' 1 B0 0 F0 5 31 '1' 6 71 'q' 0 B1 0 F1 8 32 '2' 34 72 'r' 0 B2 0 F2 0 33 '3' 8 73 's' 1 B3 0 F3 2 34 '4' 15 74 't' 0 B4 0 F4 3 35 '5' 3 75 'u' 0 B5 0 F5 3 36 '6' 0 76 'v' 0 B6 0 F6 1 37 '7' 1 77 'w' 0 B7 0 F7 1 38 '8' 2 78 'x' 0 B8 0 F8 1 39 '9' 1 79 'y' 0 B9 0 F9 2 3A ':' 0 7A 'z' 1 BA 0 FA 21 3B ';' 4 7B '{' 0 BB 0 FB 6 3C '<' 0 7C '|' 1 BC 0 FC 14 3D '=' 4 7D '}' 0 BD 0 FD 1 3E '>' 0 7E '~' 1 BE 0 FE 0 3F '?' 0 7F 0 BF 0 FF 0 40 '@' 0 80 0 C0 1985365600 100
【問題2】
次の記述中の に入れる正しい答えを, 解答群の中から選べ。ここで,記述中の と には,設問1の正しい答えが入っているものとする。
文字コードを出現回数の降順に並べて印字する処理を追加する。追加した処理による印字例を, 図2に示す。印字の様式は,文字コードの並び順を除いて, 図1の3行目以降の様式と同じである。 同じ出現回数の文字コードは,それらを文字コードの昇順に並べる。
図2
追加した処理による印字例(出現回数順)
この処理のために,プログラムの行①の直後に,次の宣言を追加する。
int ih, ix, code[256];
さらに,プログラムの行②の位置に,次の整列処理部を追加する。
〔整列処理部〕
for(i = Ø; i <=255; i++) code[i] = i; ③→ ih = 256; ④→ while (ih > Ø) { ⑤→ for(i = Ø; i < ih; i++) { ⑥→ if (freq[i] < freq[i+1]) { Swap(code[i], code[i+1]); Swap(freq[i], freq[i+1]); ⑦→ } } ⑧→ ih--; } printf("\n"); for (i =Ø; i < 64; i++) { for (chr = i; chr <= ; chr += ) { if ((Øx2Ø <= code[chr]) && (code[chr] <= Øx7E)) printf(" %1Øld %Ø2X '%c'", freq[chr], code[chr], code[chr]); else printf(" %1Øld %Ø2X ", freq[chr], code[chr]); } printf("\n"); }
ここで,整列処理部で使用する Swap(x, y) は,x と y の内容を入れ替えるために用意したマクロである。
整列処理部では,整列対象のデータ数が比較的少なく,また同じ出現回数の文字コードは 元の並び順が維持されるので,バブルソートを使用している。
行④の while 文のブロックを1回実行すると,配列の走査範囲(要素番号 0 ~ ih)中の 出現回数の最小値とその文字コードが,要素番号 ih の位置に置かれ,配列の走査範囲が 1 だけ狭められる。 これを繰り返して整列を行う。この処理では while 文のブロックの実行回数は常に[d]回となる。
ここで,while 文のブロックの1回の繰返しにおいて,行⑥の if 文のブロック内の処理が 最後に実行されたときの i の値を ix とすると,行⑤の for 文のブロックの実行が終了した時点で, 配列 freq の要素番号[e]以降の要素の値は整列済みとなっている。これを利用して, 整列処理部を表1に示すように変更すれば,while 文のブロックの実行回数を減らせる可能性がある。
整列処理部の変更内容 | 処置変更内容 |
---|---|
[f]の直後に追加 | ix = Ø |
行⑦の位置に追加 | ix = i; |
行⑧を置換え | [g] |
ア 253 イ 254 ウ 255 エ 256
e に関する解答群
ア 256-ix イ ix-1 ウ ix エ ix+1
f に関する解答群
ア 行③ イ 行④ ウ 行⑤
g に関する解答群
ア ih = ix - 1 イ ih = ix ウ ih = ix + 1 エ ix = ih
【解答2】
ウエイイ
ix+1 行④ ih = ix
#include <stdio.h> #define InName "C:\\github\\sample\\cpp\\fe\\2018_2\\sample2.c"/* 入力ファイル名 */ void Swap(int *x, int *y) { int temp; temp = *x; /* xが指す変数の値を退避 */ *x = *y; /* yが指す変数の値をxが指す変数に代入 */ *y = temp; /* tempに退避しておいたxが指す変数の値をyが指す変数に代入*/ } int main() { FILE *infile; int chr, i; long cnt; long freq[256]; /* freq[i]: 文字コード i の出現回数 */ int ih, ix, code[256]; for (chr = 0; chr <= 255; chr++) freq[chr] = 0; infile = fopen(InName, "rb"); cnt = 0; while ((chr = fgetc(infile)) != EOF) { cnt++; freq[chr]++; } fclose(infile); printf(" %10ld bytes processed\n\n", cnt); for (i = 0; i <= 64; i++) { for (chr = i; chr <= i + 192 ; chr += 64 ) { if ((0x20 <= chr) && (chr <= 0x7E)) printf(" %10ld %02X '%c'", freq[chr], chr, chr); else printf(" %10ld %02X", freq[chr], chr); } printf("\n"); } // ここから機能追加 for(i = 0; i <=255; i++) code[i] = i; ih = 255; while(ih > 0) { for(i = 0; i < ih; i++) { if(freq[i] < freq[i+1]) { Swap(&code[i], &code[i+1]); Swap(&freq[i], &freq[i+1]); } } ih--; } printf("\n"); for (i = 0; i < 64; i++) { for (chr = i; chr <= i + 192 ; chr += 64 ) { if ((0x20 <= code[chr]) && (code[chr] <= 0x7E)) printf(" %10ld %02X '%c'", freq[chr], code[chr], code[chr]); else printf(" %10ld %02X ", freq[chr], code[chr]); } printf("\n"); } return 0; }
#include <stdio.h> #define InName "C:\\github\\sample\\cpp\\fe\\2018_2\\sample2.c"/* 入力ファイル名 */ void Swap(int *x, int *y) { int temp; temp = *x; /* xが指す変数の値を退避 */ *x = *y; /* yが指す変数の値をxが指す変数に代入 */ *y = temp; /* tempに退避しておいたxが指す変数の値をyが指す変数に代入*/ } int main() { FILE *infile; int chr, i; long cnt; long freq[256]; /* freq[i]: 文字コード i の出現回数 */ int ih, ix, code[256]; for (chr = 0; chr <= 255; chr++) freq[chr] = 0; infile = fopen(InName, "rb"); cnt = 0; while ((chr = fgetc(infile)) != EOF) { cnt++; freq[chr]++; } fclose(infile); printf(" %10ld bytes processed\n\n", cnt); for (i = 0; i <= 64; i++) { for (chr = i; chr <= i + 192 ; chr += 64 ) { if ((0x20 <= chr) && (chr <= 0x7E)) printf(" %10ld %02X '%c'", freq[chr], chr, chr); else printf(" %10ld %02X", freq[chr], chr); } printf("\n"); } // ここから機能追加 for(i = 0; i <=255; i++) code[i] = i; ih = 255; while(ih > 0) { ix = 0; for(i = 0; i < ih; i++) { if(freq[i] < freq[i+1]) { Swap(&code[i], &code[i+1]); Swap(&freq[i], &freq[i+1]); ix = i; } } ih = ix; } printf("\n"); for (i = 0; i < 64; i++) { for (chr = i; chr <= i + 192 ; chr += 64 ) { if ((0x20 <= code[chr]) && (code[chr] <= 0x7E)) printf(" %10ld %02X '%c'", freq[chr], code[chr], code[chr]); else printf(" %10ld %02X ", freq[chr], code[chr]); } printf("\n"); } return 0; }
- | 関連記事 |
---|---|
1 | 【基本情報】C言語の午後過去問・解答例まとめ |
2 | 【情報処理入門】テクノロジ系、マネジメント系、ストラテジ系、資格試験 |
3 | 【C言語入門】基本文法・サンプル集 |
コメント
③→ ih = 256;
は誤植ですよね?