■状態遷移マシンの例■

ここで,for文とswitch文を組み合わせて状態遷移マシンを作成する.

演習問題1

キーボードから金額を入力し,130円のジュースを販売する自動販売機のプログラムを作成せよ.動作例は次のようになる.

お金をいれてください.100 ←100とキーボードから入力
ただいま100円が入っています.
お金をいれてください.50 
ジュースを出します.
お釣りは20円です.
お金をいれてください.

このような自動販売機を作成するためには,現在お金がいくら入っているのかという内部状態を記憶し,その状態によって動作を変化させる状態遷移マシンを作成する必要がある.

  • お金は50円,100円,500円の3種類とする.それ以外はエラーとしてよい
  • 50円をいれた後,100円を入れれば150円になる.さて,内部状態としてとりうる全ての金額は何種類か
  • すべての種類を,状態遷移図として表現せよ.
  • それを,プログラムとして記述するにはどうしたらいいだろうか

ヒント

自動販売機は,処理を無限に繰り返す必要があるため,無限ループしておく.そしてその内側では現在投入されている合計金額の状態別に処理を行う.それぞれの状態で,さらにコインが投入されるわけで,その合計金額が次の状態を表す.つまり,外側のswitch文の内側では,投入されたコインの種類別に動作させるためにもうひとつswitch文が必要になる.

  for(;;)
  {

   int a = コインの入力

    入力がコイン以外だったらエラー
 
    switch(state) //stateは,現在自販機に投入されている合計金額
    {
    case 0: //0円投入されている状態 各金額ごとに処理を決める
        switch(a) //
        {
        case 50: //そこへ,さらに50円投入されたら
           state = 50; //次の状態は50円状態へ遷移
           break;
        case 100://そこへ,さらに100円投入されたら
           state = 100; //次の状態は100円状態へ遷移
        case 500:
           state = ....
        }
        break;
    case 50: //50円投入されている状態 


    case 100: //100円投入されている状態

  }

変数stateは,この状態遷移マシンにおける状態を表すため,状態変数と呼ぶ.状態変数を使ってswitchし,各状態(各case文)の中で次の状態に遷移できるように「state=次の状態;」を実行してstateの値を変化させる.これが状態遷移マシンの基本形である.

キーボード入力

キーボードからの整数の入力はJavaの標準ライブラリを用いて次のように行う.これで変数aに格納される.標準ライブラリの機能でBufferdReaderなどいろいろな記述があるが,それらは後で説明する.ここでは呪文だと思ってもらって構わない.

BufferedReader r = new BufferedReader(new InputStreamReader(System.in), 1);
                                        // データ入力の準備
System.out.print("お金をいれてください");
System.out.flush();             // 強制出力
String s="";
try
{
  s = r.readLine();        // 文字列の入力
}
catch(IOException e)
{
  e.printStackTrace();
  System.exit(0);
}
int a = Integer.parseInt(s);    // 整数に変換

BufferdReaderなどの標準ライブラリ利用するためには次のようにインポートする必要がある.

import java.io.*;

インポートはclass宣言の外側(上側),プログラムの最初でしておく必要がある.

また,readLineは例外をthrowすることになっているため,それをcatchする必要がある.このためやや複雑に見える.

演習問題2

キーボードから入力されたアルファベット文字列の中に"abc"という部分があればその先頭文字の位置を表示するプログラムを書け.(新規プロジェクトとして)プログラムを作成せよ.

文字を入力してください.jfdskfjhiewrujjjjkabcjfkdjfskdjfk
19
文字を入力してください. jfklsjflksdahfoisaheoirfhywiuetry
0(見つからない)

これも,状態遷移マシンとして考えられる.

     a       b       c
初期状態 → a入力状態 → ab入力状態 → カウントした文字数を表示

aが入力され,次にbが入力され,最後にcが入力されれば成功となるような状態遷移を書けばよい.それ以外の入力はすべて初期状態へ遷移させること.各状態で行末まで達した段階で,「失敗」となる.

この動作例を示す.自分のプログラムが下記のように動作するか必ず確認すること.

abc 1 
aabc 2 
ababc 3
abcd 1
xyz 0
fjdskjfksjadk 0
jfskdabcfjdsk 6
fdjksabcfjdeksabc 6
fdjsabbbbc 0
aabbbccabbbcabc 13
aaaacbc 0
ab 0

文字列操作

この例題のような機能は,実はjavaの標準ライブラリに存在するためわずか一行で書くこともできるが,ここではあえて,自分で状態遷移マシンを書いてほしい.このために必要な文字列操作のためのライブラリとしては次の2つだけ使用すること.

  • n番めの文字を取り出す
  • char c = s.charAt(n);
  • 文字列の長さを求める
  • int l = s.length();