連載
» 2019年03月25日 10時00分 公開

山浦恒央の“くみこみ”な話(116):バグ検出ドリル(16)音楽プレーヤーに潜むバグを見つけ出せ (2/3)

[山浦恒央 東海大学 大学院 組込み技術研究科 非常勤講師(工学博士),MONOist]

3.今回の問題

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

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

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

1.概要

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

2.詳細

2.1 モードの定義

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

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

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モード:「POWER OFF:」
  • ②アイドルモード:「IDLE MODE:」
  • ③一時停止モード:「PAUSE MODE:」
  • ④再生モード:「PLAY MODE:」

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_IDLE:
			if (in == ACT_PLAY){
				gMode = MODE_PLAY;
			} else if (in == ACT_POWER_ONOFF){
				gMode = MODE_POWER_OFF;
			}
			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;
			}
			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("POWER OFF: ");
	} else if (gMode == MODE_IDLE){
		printf("IDLE MODE: ");
	} else if (gMode == MODE_PAUSE){
		printf("PAUSE MODE: ");
	} else if (gMode == MODE_PLAY) { 
		printf("PLAY MODE: ");
	}
}
リスト1-2 音楽プレーヤーシミュレーター(MusicSim.c)

 リスト2は、下記の手順で実行した結果を示す。

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

Copyright © ITmedia, Inc. All Rights Reserved.