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

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

問題

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

https://www.jitec.ipa.go.jp/1_04hanni_sukiru/mondai_kaitou_2017h29_1/2017h29h_fe_pm_qs.pdf

問題の解説

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

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

スポンサーリンク

設問1・設問2

C言語ソースコード

h29s_c_12.c
#include <stdio.h>
#include <string.h>

#define NUM_Q 5

void marking(int, int[], unsigned int[], unsigned int[], int[]);
int countMarkBits(unsigned int ans);

/* 動作確認用に追加 */
unsigned int bitStr2Num(char *);

void marking(int numQ, int type[], unsigned int ansC[],
  unsigned int ansE[], int mark[]){
  int i;

  for (i = 0; i < numQ; i++) {
    mark[i] = 0;
    if (type[i] == 1) {
      if (ansE[i] == ansC[i]) {
        mark[i] = 1;
      }
    }
    else if (( 2 <= type[i]) && (type[i] <= 8)) {
      /* 設問1[a]と[b] */
      if (countMarkBits(ansE[i]) <= type[i]) {
        /* 設問1[c] */
        mark[i] = countMarkBits(ansC[i] & ansE[i]);
      }
    }
  }
}

int countMarkBits(unsigned int ans) {
  int count = 0;
  unsigned int work = ans;

  while (work != 0) {
    count++;
    work = work & (work - 1);
  }
  return count;
}

/* 動作確認用に追加 */
unsigned int bitStr2Num(char *str) {
  unsigned int ans = 0;
  unsigned int num;
  int i;

  /* ビットの並びを表す文字列を十進数に変換 */
  for (i = 0; i < 16; i++) {
    num = str[i] - '0';
    ans = ans + (num << (15 - i));
  }
  return ans;

}
int main(void) {
  int numQ = NUM_Q;
  int type[NUM_Q];
  unsigned int ansC[NUM_Q];
  unsigned int ansE[NUM_Q];
  int mark[NUM_Q];

  /* ansCとansEを文字列で表現するための変数 */
  char ansCs[NUM_Q][17];
  char ansEs[NUM_Q][17];

  int i;

  /* 1問目の情報格納 */
  type[0] = 1;
  ansC[0] = bitStr2Num("0001000000000000");
  ansE[0] = bitStr2Num("0001000000000000");

  /* 2問目の情報格納 */
  type[1] = 3;
  ansC[1] = bitStr2Num("1001000000000000");
  ansE[1] = bitStr2Num("1101000000000000");

  /* 3問目の情報格納 */
  type[2] = 3;
  ansC[2] = bitStr2Num("1101000000000000");
  ansE[2] = bitStr2Num("1101000000000000");

  /* 4問目の情報格納 */
  type[3] = 2;
  ansC[3] = bitStr2Num("1101000000000000");
  ansE[3] = bitStr2Num("101000000000000");

  /* 5問目の情報格納 */
  type[4] = 8;
  ansC[4] = bitStr2Num("1111111100000000");
  ansE[4] = bitStr2Num("1010101010101010");

  marking(numQ, type, ansC, ansE, mark);

  for (i = 0; i < numQ; i++) {
    printf("%d問目は%d点\n", i + 1, mark[i]);
  }
}

実行方法

必要なデータはmain関数内で用意していますので特に準備することはないです。コンパイルしてプログラム実行するだけで良いです。

実行結果

実行すれば下記のような採点結果が表示されます。

1問目は1点
2問目は2点
3問目は3点
4問目は0点
5問目は4点

main関数内で解答情報を格納していますので、そこの値を変更することでプログラムの動きや採点結果を変化させることが可能です。

動作確認用の変更箇所

main関数追加

main関数ではmarking関数の引数となる解答情報を各変数に格納し、その後にmarking関数を実行しています。この設問1・2のソースコードでは5問分の解答情報を格納しています。

問題としてはansC[]とansE[]に選択した選択肢の情報を1 or 0で表現したものが格納されていることになりますが、実際にはansC[]とansE[]の型はunsigned intなので10進数の値を格納する必要があります。いきなりansC[]とansE[]に10進数の情報を格納すると、どの選択肢が選択されたかが分かりにくい(1 or 0をどのように設定されているのかが分かりにくい)と思ったので、bitStr2Num関数を自作し、1 or 0から構成される文字列を準備し、それを10進数に変換したものをansC[]とansE[]を格納するようにしてみました。

設問3

C言語ソースコード

h29s_c_3.c
#include <stdio.h>
#include <string.h>

#define NUM_Q 8

void marking(int, int[], unsigned int[], unsigned int[], int[]);
int countMarkBits(unsigned int ans);

/* 動作確認用に追加 */
unsigned int bitStr2Num(char *);

void marking(int numQ, int type[], unsigned int ansC[],
  unsigned int ansE[], int mark[]){
  int i;
  unsigned int sumC, sumE;

  for (i = 0; i < numQ; i++) {
    mark[i] = 0;
    if (type[i] == 1) {
      if (ansE[i] == ansC[i]) {
        mark[i] = 1;
      }
    }
    else if (( 2 <= type[i]) && (type[i] <= 8)) {
      /* 設問1[a]と[b] */
      if (countMarkBits(ansE[i]) <= type[i]) {
        /* 設問1[c] */
        mark[i] = countMarkBits(ansC[i] & ansE[i]);
      }
    }
    else if ((11 <= type[i]) && (type[i] <= 13)) {
      if (type[i] == 11) {
        sumC = 0;
        sumE = 0;
      }
      sumC = sumC | ansC[i];
      if (countMarkBits(ansE[i]) == 1) {
        sumE = sumE | ansE[i];
      }
      if (type[i] == 13) {
        mark[i] = countMarkBits(sumC & sumE);
      }
    }
    printf("sumE = %d\n", sumE);
  }
}

int countMarkBits(unsigned int ans) {
  int count = 0;
  unsigned int work = ans;

  while (work != 0) {
    count++;
    work = work & (work - 1);
  }
  return count;
}

/* 動作確認用に追加 */
unsigned int bitStr2Num(char *str) {
  unsigned int ans = 0;
  unsigned int num;
  int i;

  /* ビットの並びを表す文字列を十進数に変換 */
  for (i = 0; i < 16; i++) {
    num = str[i] - '0';
    ans = ans + (num << (15 - i));
  }
  return ans;

}
int main(void) {
  int numQ = NUM_Q;
  int type[NUM_Q];
  unsigned int ansC[NUM_Q];
  unsigned int ansE[NUM_Q];
  int mark[NUM_Q];

  /* ansCとansEを文字列で表現するための変数 */
  char ansCs[NUM_Q][17];
  char ansEs[NUM_Q][17];

  int i;

  /* 1問目の情報格納 */
  type[0] = 1;
  ansC[0] = bitStr2Num("0001000000000000");
  ansE[0] = bitStr2Num("0001000000000000");

  /* 2問目の情報格納 */
  type[1] = 3;
  ansC[1] = bitStr2Num("1001000000000000");
  ansE[1] = bitStr2Num("1101000000000000");

  /* 3問目の情報格納 */
  type[2] = 3;
  ansC[2] = bitStr2Num("1101000000000000");
  ansE[2] = bitStr2Num("1101000000000000");

  /* 4問目の情報格納 */
  type[3] = 2;
  ansC[3] = bitStr2Num("1101000000000000");
  ansE[3] = bitStr2Num("101000000000000");

  /* 5問目の情報格納 */
  type[4] = 8;
  ansC[4] = bitStr2Num("1111111100000000");
  ansE[4] = bitStr2Num("1010101010101010");

  /* 6問目の情報格納 */
  type[5] =11;
  ansC[5] = bitStr2Num("0100000000000000");
  ansE[5] = bitStr2Num("0000100000000000");

  /* 7問目の情報格納 */
  type[6] = 12;
  ansC[6] = bitStr2Num("0001000000000000");
  ansE[6] = bitStr2Num("0000100000000000");

  /* 8問目の情報格納 */
  type[7] = 13;
  ansC[7] = bitStr2Num("0000100000000000");
  ansE[7] = bitStr2Num("0101000000000000");


  marking(numQ, type, ansC, ansE, mark);

  for (i = 0; i < numQ; i++) {
    printf("%d問目は%d点\n", i + 1, mark[i]);
  }
}

実行方法

設問1・設問2同様にコンパイルしてプログラム実行するだけで良いです。

実行結果

実行すれば下記のような採点結果が表示されます。

1問目は1点
2問目は2点
3問目は3点
4問目は0点
5問目は4点
6問目は0点
7問目は0点
8問目は1点

1問目から5問目は設問1・設問2と同じ採点結果になっており、6問目から8問目は設問3用の順不同形式の問題の採点結果になっています。

動作確認用の変更箇所

main関数追加

追加したmain関数は、基本的に設問1・設問2と同様の作りになっています。6問目から8問目の解答情報には設問3のプログラムで採点可能となる順不同形式の問題を対象としたものを格納しています。

 

他の回のソースコード

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

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

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

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

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

コメントを残す

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