Java:Indexoutofrange发生了什么?

时间:2013-04-09 07:52:25

标签: automaton

以下是我正在处理的元胞自动机的代码:

public class Life1D {

    private Rule rule;
    private int stepCount;

    public static void main (String [ ] args) {
            Life1D simulation = new Life1D ( );
            simulation.processArgs (args);
            simulation.producePBM ( );
    }

    // Print, in Portable Bitmap format, the image corresponding to the rule and step count
    // specified on the command line.
    public void producePBM ( ) {
            int width = (stepCount*2+1);
            System.out.println("P1 " + width + " " + (stepCount+1));
            String prev_string = "";
            // constructs dummy first line of rule
            for (int i = 0; i < width; i++){
                    if (i == stepCount+1){
                            prev_string += "1";
                    } else {
                            prev_string += "0";
                    }
            }
            // contructs and prints out all lines prescribed by the rule, including the first
            for (int i = 0; i < stepCount; i++) {
                    String next_string = "";
                    for (int j = 0; j < width; j++) {
                        // prints next line, one character at a time

                            System.out.print(prev_string.charAt(j) + " ");
                            // specifies cases for the edges as well as for normal inputs to Rule
                            if (j == 0) {
                                    next_string += rule.output(0, prev_string.charAt(0), prev_string.charAt(1));
                            } else if (j == width-1) {
                                    next_string += rule.output(prev_string.charAt(width-2), prev_string.charAt(width-1), 0);
                            } else {
                                    String rule_input = prev_string.substring(j-1, j+2);
                                    int first = rule_input.charAt(0);
                                    int second = rule_input.charAt(1);
                                    int third = rule_input.charAt(2);
                                    next_string += rule.output(first, second, third);
                            }
                    }
                    // sets prev_string to next_string so that string will be the next string in line to be printed
                    prev_string = next_string;
                    System.out.println();
            }
    }


    // Retrieve the command-line arguments, and convert them to values for the rule number
    // and the timestep count.
    private void processArgs (String [ ] args) {
            if (args.length != 2) {
                    System.err.println ("Usage: java Life1D rule# rowcount");
                    System.exit (1);
            }
            try {
                    rule = new Rule (Integer.parseInt (args[0]));
            } catch (Exception ex) {
                    System.err.println ("The first argument must specify a rule number.");
                    System.exit (1);
            }
            try {
                    stepCount = Integer.parseInt (args[1]);
            } catch (Exception ex) {
                    System.err.println ("The second argument must specify the number of lines in the output.");
                    System.exit (1);
            }
            if (stepCount < 1) {
                    System.err.println ("The number of output lines must be a positive number.");
                    System.exit (1);
            }
    }
}

 class Rule {

    private int a, b, c;
    private String rulebin;

    public Rule (int ruleNum) {
            rulebin = Integer.toBinaryString(ruleNum);
    }

    // Return the output that this rule prescribes for the given input.
    // a, b, and c are each either 1 or 0; 4*a+2*b+c is the input for the rule.
    public int output (int a, int b, int c) {
        return rulebin.charAt(7 - 4*a + 2*b + c);
    }
}

运行时出现以下错误消息:

P1 7 4
0 Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index      out of range: 151
    at java.lang.String.charAt(String.java:686)
    at Rule.output(Life1D.java:90)
    at Life1D.producePBM(Life1D.java:35)
    at Life1D.main(Life1D.java:9)

到底是什么?为什么我会收到此错误,我该如何解决?我一直试图找出错误数小时,如果能得到帮助,这将是一件幸事。

2 个答案:

答案 0 :(得分:0)

在此特定部分中,您将整数转换为二进制字符串:

 rulebin = Integer.toBinaryString(ruleNum);

现在假设你的参数是:
第一个参数= 12
第二个参数=任何数字

现在,当此代码将此数字转换为二进制字符串时,您将获得:
    rulebin =“1100”(长度4)

现在在这个函数中:

 public int output (int a, int b, int c) {
    return rulebin.charAt(7 - 4*a + 2*b + c);
}

当a = b = c = 0时,此函数将尝试访问“rulebin的字符8”,但是你的规则的长度为4.这就是为什么你得到字符串索引超出约束的异常。

注意:我不确定您是否对输入参数设置了任何限制,但这可能是一个潜在的问题。

答案 1 :(得分:0)

没有!问题是你将char而不是int传递给

 public int output (int a, int b, int c) {
    return rulebin.charAt(7 - 4*a + 2*b + c);
}

我试过了,当prevString.charAt(0)和prevString.charAt(1)为0时,它向输出方法发送那些参数(0,48,48)(尝试调试它,你会) 这导致指数超出范围!

并且转换为二进制字符串也不会返回7位格式..

<强>更新

public class Lif1ID {

private Rule rule;
private int stepCount;

public static void main (String [ ] args) {
        Lif1ID simulation = new Lif1ID ( );
        simulation.processArgs (args);
        simulation.producePBM ( );
}

// Print, in Portable Bitmap format, the image corresponding to the rule and step count
// specified on the command line.
public void producePBM ( ) {
        int width = (stepCount*2+1);
        System.out.println("P1 " + width + " " + (stepCount+1));
        String prev_string = "";
        // constructs dummy first line of rule
        for (int i = 0; i < width; i++){
                if (i == stepCount+1){
                        prev_string += "1";
                } else {
                        prev_string += "0";
                }
        }
        // contructs and prints out all lines prescribed by the rule, including the first
        for (int i = 0; i < stepCount; i++) {
                String next_string = "";
                for (int j = 0; j < width; j++) {
                    // prints next line, one character at a time

                        System.out.print(prev_string.charAt(j) + " ");
                        // specifies cases for the edges as well as for normal inputs to Rule
                        if (j == 0) { 
// take a look at the 'getNumericValue' Method.. in your version it didn't pass 0 or 1, now it does.. 
                                next_string += rule.output(0, Character.getNumericValue(prev_string.charAt(0)), Character.getNumericValue(prev_string.charAt(1)));
                        } else if (j == width-1) {
                                next_string += rule.output(prev_string.charAt(width-2), prev_string.charAt(width-1), 0);
                        } else {
                                String rule_input = prev_string.substring(j-1, j+2);
                                int first = Character.getNumericValue(rule_input.charAt(0));
                                int second = Character.getNumericValue(rule_input.charAt(1));
                                int third = Character.getNumericValue(rule_input.charAt(2));
                                next_string += rule.output(first, second, third);
                        }
                }
                // sets prev_string to next_string so that string will be the next string in line to be printed
                prev_string = next_string;
                System.out.println();
        }
}


// Retrieve the command-line arguments, and convert them to values for the rule number
// and the timestep count.
private void processArgs (String [ ] args) {
        if (args.length != 2) {
                System.err.println ("Usage: java Life1D rule# rowcount");
                System.exit (1);
        }
        try {
                rule = new Rule (Integer.parseInt(args[0]));
        } catch (Exception ex) {
                System.err.println ("The first argument must specify a rule number.");
                System.exit (1);
        }
        try {
                stepCount = Integer.parseInt (args[1]);
        } catch (Exception ex) {
                System.err.println ("The second argument must specify the number of lines in the output.");
                System.exit (1);
        }
        if (stepCount < 1) {
                System.err.println ("The number of output lines must be a positive number.");
                System.exit (1);
        }
   }
}

 class Rule {

private int a, b, c;
private String rulebin;

public Rule (int ruleNum) {
        rulebin = convertToBinary(ruleNum);
}

private String convertToBinary(int input) // get the binary presentation as you want
{                                         // if the input is 2 you'll get "00000010"
    String binary = "";
    for (int i = 0; i < 8; i++){
      if ((1 << i & input) != 0)
        binary += "1";
      else 
          binary+= "0";
    }
    binary = new StringBuffer(binary).reverse().toString();
    return binary;
}

// Return the output that this rule prescribes for the given input.
// a, b, and c are each either 1 or 0; 4*a+2*b+c is the input for the rule.
public char output (int a, int b, int c) {    // here you want to return a char, no?
    return rulebin.charAt(7 - 4*a + 2*b + c); // there is a problem with your formula
}

}