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

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

問題

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

https://www.jitec.ipa.go.jp/1_04hanni_sukiru/mondai_kaitou_2018h30_2/2018h30a_fe_pm_qs.pdf

問題の解説

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

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

スポンサーリンク

設問1・設問2・設問3

C言語ソースコード

h30f_c.c
#include <stddef.h>

/* 動作確認用に追加 */
#include <stdlib.h>
#include <stdio.h>

#define RED (0)
#define GREEN (1)

struct block_info {
    struct train_info *train;
    struct block_info *next[2];
    int signal;
};

struct train_info {
    int number;
    struct block_info* dest;
};

void set_signals(struct block_info[], int);
void proceed(struct block_info[], int);
int find_block(struct block_info*, struct block_info*);
void start(struct block_info[], int);
void printBlocks(struct block_info[], int);

void set_signals(struct block_info blocks[], int nblocks) {
    int i;
    struct block_info* block;
    for (i = 0; i < nblocks; i++) {
        block = &blocks[i];
        if (block->train == NULL) {  /* 設問1の(a) */
            block->signal = GREEN;
        }
        else {
            block->signal = RED;
        }
    }
}

void proceed(struct block_info blocks[], int nblocks) {
    int i, j;
    struct block_info* block;
    for (i = nblocks - 1; i >= 0; i--) {
        block = &blocks[i];
        if (block->train == NULL) {
            continue;
        }
        if (block == block->train->dest) {
            block->train = NULL;
            continue;
        }
        for (j = 0; j < 2; j++) {
            if (block->next[j] == NULL) {
                continue;
            }
            if (block->next[j]->signal == RED) {
                continue;
            }
            if (find_block(block->next[j], block->train->dest) == 1) {
                block->next[j]->train = block->train;
                block->next[j]->signal = RED;
                block->train = NULL;
                break; /* 設問2の(c) */
            }
        }
    }
}

int find_block(struct block_info* block, struct block_info* dest) {
    int i ;
    if (block == dest) {
        return 1;
    }
    for (i = 0; i < 2; i++) {
        if (block->next[i] == NULL) {
            continue;
        }
        if (find_block(block->next[i], dest) == 1) {
            return 1;
        }
    }
    return 0;
}

void start(struct block_info blocks[], int nblocks) {
    int i;
    set_signals(blocks, nblocks);
    for (i = 0; i < 4; i++) {
        proceed(blocks, nblocks);

        /* 動作確認用に追加 */
        printf("i = %dの時のproceed()実行後の各区間の状態\n", i);
        printBlocks(blocks, nblocks);

        set_signals(blocks, nblocks);

        /* 動作確認用に追加 */
        printf("i = %dの時のset_signals()実行後の各区間の状態\n", i);
        printBlocks(blocks, nblocks);
    }
}

/* 動作確認用に追加 */
void printBlocks(struct block_info blocks[], int nblocks) {
  int i;
  for (i = 0; i < nblocks; i++) {
    printf(" ・区間[%d]の情報\n", i);
    if (blocks[i].train != NULL) {
        printf("  列車[%d]が停車\n", blocks[i].train->number);
    }
    if (blocks[i].signal == RED) {
      printf("  信号の色は[赤]\n");
    }
    else {
      printf("  信号の色は[緑]\n");
    }
  }
}

/* 動作確認用に追加 */
int main(void) {
    struct block_info blocks[9];
    struct train_info train[5];

    /* 表1記載の区間情報をblocks[]に格納 */
    blocks[0].train = &train[4];
    blocks[0].train->dest = &blocks[8];
    blocks[0].train->number = 4;
    blocks[0].next[0] = &blocks[2];
    blocks[0].next[1] = NULL;
    blocks[0].signal = RED;

    blocks[1].train = &train[3];
    blocks[1].train->dest = &blocks[5];
    blocks[1].train->number = 3;
    blocks[1].next[0] = &blocks[2];
    blocks[1].next[1] = NULL;
    blocks[1].signal = RED;

    blocks[2].train = NULL;
    blocks[2].next[0] = &blocks[3];
    blocks[2].next[1] = NULL;
    blocks[2].signal = GREEN;

    blocks[3].train = &train[2];
    blocks[3].train->dest = &blocks[6];
    blocks[3].train->number = 2;
    blocks[3].next[0] = &blocks[4];
    blocks[3].next[1] = &blocks[7];
    blocks[3].signal = RED;

    blocks[4].train = &train[1];
    blocks[4].train->dest = &blocks[5];
    blocks[4].train->number = 1;
    blocks[4].next[0] = &blocks[5];
    blocks[4].next[1] = &blocks[6];
    blocks[4].signal = RED;

    blocks[5].train = NULL;
    blocks[5].next[0] = NULL;
    blocks[5].next[1] = NULL;
    blocks[5].signal = GREEN;

    blocks[6].train = NULL;
    blocks[6].next[0] = NULL;
    blocks[6].next[1] = NULL;
    blocks[6].signal = GREEN;

    blocks[7].train = NULL;
    blocks[7].next[0] = &blocks[8];
    blocks[7].next[1] = NULL;
    blocks[7].signal = GREEN;

    blocks[8].train = &train[0];
    blocks[8].train->dest = &blocks[8];
    blocks[8].train->number = 0;
    blocks[8].next[0] = NULL;
    blocks[8].next[1] = NULL;
    blocks[8].signal = RED;

    start(blocks, 9);

    return 0;
}

実行方法

特に準備などはする必要はありません。プログラムをただ実行してやれば動作します。

実行結果

下記のようにproceed関数とset_signals関数実行後に、そのタイミングでの各区間の状態が表示されます。

i = 3の時のset_signals()実行後の各区間の状態

 ・区間[0]の情報

  信号の色は[緑]

 ・区間[1]の情報

  信号の色は[緑]

 ・区間[2]の情報

  列車[4]が停車

  信号の色は[赤]

 ・区間[3]の情報

  信号の色は[緑]

 ・区間[4]の情報

  列車[3]が停車

  信号の色は[赤]

 ・区間[5]の情報

  信号の色は[緑]

 ・区間[6]の情報

  信号の色は[緑]

 ・区間[7]の情報

  信号の色は[緑]

 ・区間[8]の情報

  信号の色は[緑]

動作確認用の変更箇所

main関数追加

C言語プログラムを動作させるにはmain関数が必要ですので、main関数を追加しています。main関数では各区間の情報をblock_info構造体に格納しています。各区間に列車が停車している場合はその列車の情報をtrain_info構造体に格納しています。そして格納後に、元からあるstart関数を実行しています。

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

各区間の状態がどうなっているかを追跡するためにprintBlocks関数を追加し、これをproceed関数とset_signals関数呼び出し直後に実行するようにしています。proceed関数・set_signals関数実行によりどのように区間の状態が変わるかが分かるようにしたつもりです。なぜこのように出力されるのかがわからない場合は、他のところにもprintfを追加してさらに細かく状態の変化が分かるようにしてプログラムを実行すると良いと思います。

 

他の回のソースコード

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

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

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

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

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

コメントを残す

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