バグ検出ドリル(17)「よくある単純なバグ」だからこそ見つけにくい山浦恒央の“くみこみ”な話(117)(2/3 ページ)

» 2019年04月25日 10時00分 公開

4.今回の問題

 本プログラムは、音楽プレーヤーのモード遷移を模擬するソフトウェアである。以下に、仕様を示す。プログラムを(リスト1-1、1-2)に、実行結果をリスト2に示す。

 リスト2に示す通り、本来は、再生モードで再生指令を出すと、一時停止モードとなるはずだが、再生モードのままとなっている。なぜ遷移しないか、推察せよ。

音楽プレーヤーシミュレーターの仕様

1.概要

 本プログラムは、ユーザーのコンソール入力に従って、音楽プレーヤーのモードを表示するものである。

2.詳細

2.1 モードの定義

 各モードの定義を以下の表1に示す。

モード 名称
MODE_POWER_OFF 電源OFFモード
MODE_IDLE アイドルモード
MODE_PLAY 再生モード
MODE_PAUSE 一時停止モード
表1 モード定義表

2.2 モード遷移指令

 モード遷移指令の定義とキーボード入力値を以下の表2に示す。

モード(変数名) 名称 キーボード入力値
ACT_POWER_ONOFF 電源ON/OFF指令 0
ACT_PLAY 再生指令 1
ACT_STOP 停止指令 2
表2 モード遷移指令表

3.モード入力

 ユーザーは、コンソールから変更したいモードを入力する。なお、入力値は、表2の通り。

4.モード遷移

4.1 初期モード

 プログラム実行時は、電源OFFモードから始まる。

4.2 電源OFFモード

 電源OFFモードでのモード遷移を以下に示す。

  • ①電源ON指令を入力すると、アイドルモードに遷移する

4.3 アイドルモード

 アイドルモードでのモード遷移を以下に示す。

  • ①電源OFF指令を入力した場合は、電源OFFモードに遷移する
  • ②停止指令を入力した場合は、アイドルモードのままで、遷移しない
  • ③再生指令を入力した場合は、再生モードへ遷移する

4.4 再生モード

 再生モードでのモード遷移を以下に示す。

  • ①電源OFF指令を入力した場合は、電源OFFモードへ遷移する
  • ②停止指令を入力した場合は、アイドルモードへ遷移する
  • ③再生指令を入力した場合は、一時停止モードへ遷移する

4.5 一時停止モード

 一時停止モードでのモード遷移を以下に示す。

  • ①電源OFF指令を入力した場合は、電源OFFモードへ遷移する
  • ②停止指令を入力した場合は、アイドルモードへ遷移する
  • ③再生指令を入力した場合は、再生モードへ遷移する

5.表示機能

 コンソールからの入力後、モードに従って以下の文字列をコンソールへ表示する。

  • ①電源OFFモード:「電源OFFモード:」
  • ②アイドルモード:「アイドルモード:」
  • ③一時停止モード:「一時停止モード:」
  • ④再生モード:「再生モード:」

6.プログラムの終了

 プログラムは、コンソールから「Ctrl+c」を入力すると終了すること。

7.制限事項

 入力ミスなどのバグは考慮せず、リスト2の結果が正しくなることを目的とする。なお、環境は、GCC7.3.0を想定する。

/*
	音楽プレーヤーシミュレーターヘッダ
	MusicSim.h
*/
//モード定義
typedef enum{
	MODE_POWER_OFF,		//電源OFF
	MODE_IDLE,		//アイドル
	MODE_PLAY,		//再生
	MODE_PAUSE		//一時停止
}MODE;
//モード遷移指令
typedef enum{
	ACT_POWER_ONOFF,	//電源ON/OFF指令
	ACT_PLAY,		//再生指令	
	ACT_STOP		//停止指令
}ACT;
void output();			//モード出力関数
int gMode;			//モード変数(グローバル)
リスト1-1 音楽プレーヤーシミュレーター(MusicSim.h)
/*
	音楽プレーヤーシミュレーター
	MusicSim.c
*/
#include <stdio.h>
#include "MusicSim.h"
int main()
{
	int in;	//指令入力用変数
	
	// 初期モードは電源OFFモード
	gMode = MODE_POWER_OFF;
	
	// 初期モードを表示
	output();
	while(1) {
		// 指令をコンソールから入力
		scanf("%d",&in);
		switch(gMode){
		// 電源OFFモードの場合
		case MODE_POWER_OFF:
			if (in == ACT_POWER_ONOFF)
				gMode = MODE_IDLE;
			break;
		// 再生モードの場合
		case MODE_PLAY:
			if (in == ACT_STOP){
				gMode = MODE_IDLE;
			} else if (in == ACT_PLAY){
				gMode = MODE_PAUSE;
			} else if (in == ACT_POWER_ONOFF){
				gMode = MODE_POWER_OFF;
			}
		// アイドルモードの場合
		case MODE_IDLE:
			if (in == ACT_PLAY){
				gMode = MODE_PLAY;
			} else if (in == ACT_POWER_ONOFF){
				gMode = MODE_POWER_OFF;
			}
			break;
		// 一時停止モードの場合
		case MODE_PAUSE:
			if (in == ACT_STOP){
				gMode = MODE_IDLE;
			} else if (in == ACT_PLAY){
				gMode = MODE_PLAY;
			} else if (in == ACT_POWER_ONOFF){
				gMode = MODE_POWER_OFF;
			}
			break;
		default:
			break;
		}
		// モードを表示
		output();
	}
	return 0;
}
// コンソールにモードを表示する
void output(){
	if (gMode == MODE_POWER_OFF){
		printf("電源OFFモード: ");
	} else if (gMode == MODE_IDLE){
		printf("アイドルモード: ");
	} else if (gMode == MODE_PAUSE){
		printf("一時停止モード: ");
	} else if (gMode == MODE_PLAY) { 
		printf("再生モード: ");
	}
}
リスト1-2 音楽プレーヤーシミュレーター(MusicSim.c)

 リスト2は、下記の手順で実行した結果を示す(先頭の数字は、説明用に追加したもの)。

  • ①電源OFFモードで、「0(電源ON/OFF指令)」を入力、Enterを押し、アイドルモードに遷移する
  • ②アイドルモードで、「1(再生指令)」を入力、Enterを押し、再生モードに遷移する
  • ③再生モードで、「2(停止指令)」を入力、Enterを押し、アイドルモードに遷移する
  • ④アイドルモードで、「1(再生指令)」を入力、Enterを押し、再生モードに遷移する
  • ⑤再生モードで、「1(再生指令)」を入力、Enterを押し、一時停止モードに遷移するはずが、再生モードのままとなっている
  • ⑥コンソールから入力をせず、Ctrl+cでプログラムを終了する
① 電源OFFモード  : 0
② アイドルモード : 1
③ 再生モード     : 2
④ アイドルモード : 1
⑤ 再生モード     : 1
⑥ 再生モード     :
リスト2 実行結果

Copyright © ITmedia, Inc. All Rights Reserved.