3

このオートマトンの例を実装しようとしています: http://www.javacodegeeks.com/2012/03/automaton-implementation-in-java.html

ただし、プログラムの実行中にエラーが表示され続けます。

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: 
           String index out of range: 3
at java.lang.String.charAt(String.java:686)
at mealy.Input.read(Input.java:7)
at mealy.States$4.next(Input.java:46)
at mealy.Test.main(Test.java:9)

エラーの原因となっている行を変更しようとしましたが、何も変わりませんでした。誰かがこのプログラムを見て、解決策を見つけるのを手伝ってくれませんか?

私は次の .java を持っています:

State.java :

interface State {
    public State next(Input in);
}

注意: 元の「public Stat next()」を「public State next(Input in);」に変更する必要がありました。

入力.java:

class Input {
    private String input;
    private int current;
    public Input(String input) {this.input = input;}
    char read() { return input.charAt(current++); }
}

enum States implements State {
    Init {
        @Override
        public State next(Input word) {
            switch(word.read()) {
                case 'a': return A;
                default: return Fail;
            }
        }
    },
    A {
        @Override
        public State next(Input word) {
            switch(word.read()) {
                case 'a': return A;
                case 'b': return B;
                case 'c': return C;
                case 'd': return null;
                default: return Fail;
            }
        }
    },
    B {
        @Override
        public State next(Input word) {
            switch(word.read()) {
                case 'b': return B;
                case 'c': return C;
                case 'd': return null;
                default: return Fail;
            }
        }
    },
    C {
        @Override
        public State next(Input word) {
            switch(word.read()) {
                case 'c': return C;
                case 'd': return null;
                default: return Fail;
            }
        }
    },
    Fail {
        @Override
        public State next(Input word) {
               return Fail;
        }
    };

    public abstract State next(Input word);
}

Test.java :

public class Test {
    public static void main(String args[]){
        State s;
        Input in = new Input("abc");

        for(s = States.Init; s != null || s != States.Fail; s = s.next(in)) {}
        if(s == States.Init) {System.out.println("Valid!");}
        else {System.out.println("Failed");}
    }
}
4

3 に答える 3

1

Input クラスにバグがあるようです。最後の文字の後に文字を読み取ろうとすると、メインで処理していない例外がスローされます。入力を変更して、ステート マシンで処理できるトークンを返すようにします。

ところで、コンテキストについてはこれをご覧になることをお勧めします。http://vanillajava.blogspot.co.uk/2011/06/java-secret-using-enum-as-state-machine.html

Attila は、単純で実用的な例を提供しようとしていたと思います。彼がコードを修正できるかどうかを確認します。

于 2013-11-04T08:43:05.587 に答える
1

エラーはこの行にあります

char read() { return input.charAt(current++); }

String の長さをチェックせずinput(class 内の悪い名前と見なしますInput)、3 回呼び出した後read()、3 文字の String の 4 番目の文字にアクセスしようとすると、表示される例外がスローされます。

アップデート:

あなたのコメントに対処するには、戻り値をread()新しいインターフェイスに変更することをお勧めしますReadResult:

public interface ReadResult {
    boolean isOkay();
    char getReadCharacter();  
}

2 つの実装で。肯定的な結果のための 1 つ...

public class ReadOkay implements ReadResult{
    private char readCharacter;

    public ReadOkay(char readCharacter) {
        this.readCharacter = readCharacter;
    }

    @Override
    public boolean isOkay() {
        return true;
    }

    @Override
    public char getReadCharacter() {
        return readCharacter;
    }
}

否定的な結果の場合

public class ReadFailed implements ReadResult {

    @Override
    public boolean isOkay() {
        return false;
    }

    @Override
    public char getReadCharacter() {
        throw new IllegalStateException("Read failed! no character data there to return!");
    }
}

これを変更read()して、新しいインターフェイスに戻すことができます

public ReadResult read() {
        if (input != null && current >= 0 && current < input.length()) {
            return new ReadOkay(input.charAt(current++));
        } else {
            return new ReadFailed();
        }
    }

それに応じて州を更新します。

交換:

switch(word.read()) {

と:

ReadResult result = word.read();
if (!result.isOkay()) {
    return Fail;
}
switch (result.getReadCharacter()) {
于 2013-11-04T08:43:29.053 に答える
1

read() method以下のように変更する必要があります

char read() { 
    if(current>=input.length())      // this if condition should be checked
          return 'z';                // you need to change your character according to your need
    return input.charAt(current++); 
}
于 2013-11-04T08:47:06.990 に答える