我正在尝试实现此自动机示例: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);”
Input.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");}
}
}
答案 0 :(得分:1)
Input类中似乎存在错误。当您尝试在最后一个字符之后读取字符时,它会抛出您未在main中处理的异常。我会改变输入,以便它返回一个你可以在状态机中处理的令牌。
顺便说一下,我建议你看一下上下文。 http://vanillajava.blogspot.co.uk/2011/06/java-secret-using-enum-as-state-machine.html
我认为Attila希望提供一个简单,有效的例子。我会看看他是否可以修改他的代码。
答案 1 :(得分:1)
错误在这一行
char read() { return input.charAt(current++); }
您不检查字符串input
的长度(我认为类Input
中的名称不好),并且在调用read()
三次后尝试访问第4个字符串一个3个字母的字符串,然后抛出你看到的异常。
发表评论我建议将read()
的返回值更改为新界面ReadResult
:
public interface ReadResult {
boolean isOkay();
char getReadCharacter();
}
有两个实现。一个是积极的结果...
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()) {
答案 2 :(得分: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++);
}