-4

这是我关于stackoverflow的第一个问题。我想测试自己并制作一种迷你编程语言。但是自从我决定扩展我的代码后,我不断收到 StringIndexOutOfBoundsExceptions。我在这里对 stackoverflow 和 youtube 进行了一些研究,似乎我遇到了一个特定的问题。你能检查一下吗?提前谢谢你... PS:抱歉混淆变量名,我用我的母语命名它:P代码:

import java.util.Scanner;
import java.util.Vector;

public class Komanda {
private String tip;
private String naziv;
private String parametar;
public Komanda() {
    super();
}
public Komanda(String tip, String parametar) {
    super();
    this.tip = tip;
    this.parametar = parametar;
}
public Komanda(String tip, String naziv, String parametar) {
    super();
    this.tip = tip;
    this.naziv = naziv;
    this.parametar = parametar;
}
public String getTip() {
    return tip;
}
public void setTip(String tip) {
    this.tip = tip;
}
public String getNaziv() {
    return naziv;
}
public void setNaziv(String naziv) {
    this.naziv = naziv;
}
public String getParametar() {
    return parametar;
}
public void setParametar(String parametar) {
    this.parametar = parametar;
}
}


public class Main {

public static void execute(Vector<Komanda> code) {
    for (int i = 0; i < code.size(); i++) {
        if (code.elementAt(i).getTip().equals("print:")) {
            if (!code.elementAt(i).getParametar().contains(":")) {
                System.out.println(code.elementAt(i).getParametar());
            } else {
                System.out.println("");
                System.out.print(code.elementAt(i).getParametar().substring(0,
                        code.elementAt(i).getParametar().indexOf(':') + 1));
                for (int k = 0; k < code.size(); i++) {
                    if (code.elementAt(k).getNaziv().equals(code.elementAt(i).getParametar()
                            .substring(code.elementAt(i).getParametar().indexOf(':') + 1))) {
                        System.out.print(" " + code.elementAt(k).getParametar());
                    }
                }
            }
        }
        if (code.elementAt(i).getTip().equals("var")) {

        }
    }
}

public static void main(String[] args){
    Vector<Komanda> code = new Vector<Komanda>();
    Scanner console = new Scanner(System.in);
    System.out.println("NNS 0.1 (v0.1.0:1, Oct  7 2017, 18:40:49) [MSC v.1900 64 bit]");
    for (int i = 0; i < 1;) {

        String line = console.nextLine();
        Scanner lineRreader = new Scanner(line);
        if (lineRreader.next().equalsIgnoreCase("SLC;")) {
            code.removeAllElements();
            line = line.substring(line.indexOf(';') + 2);
            if (line.equals("terminate")) {
                break;
            }
            if (lineRreader.next().equals("print:")) {
                System.out.println(line.substring(line.indexOf(':') + 2));
            }
            if (line.substring(0, line.indexOf(' ')).equals("print")) {
                line = line.substring(line.indexOf(' ') + 1);
                int firstNumber = lineRreader.nextInt();
                char operation = lineRreader.next().charAt(0);
                int secondNumber = lineRreader.nextInt();
                System.out.print(firstNumber + " " + operation + " " + secondNumber);
                switch (operation) {
                case '+':
                    int a = firstNumber + secondNumber;
                    System.out.print(" = " + (int) a);
                    break;
                case '-':
                    int b = firstNumber - secondNumber;
                    System.out.print(" = " + (int) b);
                    break;
                case '*':
                    int c = firstNumber * secondNumber;
                    System.out.print(" = " + (int) c);
                    break;
                case '/':
                    double d = firstNumber / secondNumber;
                    System.out.print(" = " + (double) d);
                    break;
                }
                System.out.println("");
            }

        } else {
            if (line.substring(0, line.indexOf(' ')).equalsIgnoreCase("print: ")) { // THIS IS THE 72ND LINE
                code.add(new Komanda("print:", line.substring(line.indexOf(' ')+1)));
            }
            else if (line.substring(0, line.indexOf(' ')).equalsIgnoreCase("var")) {
                code.add(new Komanda("var", lineRreader.next(),
                        line.substring(line.lastIndexOf(' ') + 1, line.length())));
            }
            else if (line.equalsIgnoreCase("exec")) {
                execute(code);
            }

        }
        lineRreader.close();
    }
    console.close();
}

}

我的控制台输出:

NNS 0.1 (v0.1.0:1, Oct  7 2017, 18:40:49) [MSC v.1900 64 bit] <--STATUS STRING
print: helloworld <---- ME TYPING PRINT: COMMAND
exec <---- THIS IS THE COMMAND THAT TRIGGERS THE EXCEPTION
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String 
index out of range: -1
    at java.lang.String.substring(Unknown Source)
    at Main.main(Main.java:72)
4

2 回答 2

0

从你的问题:

exec <---- THIS IS THE COMMAND THAT TRIGGERS THE EXCEPTION

你得到了例外,因为你有这样的条件:

if (line.substring(0, line.indexOf(' ')).equalsIgnoreCase("print: ")) {
  // ...
} else if (line.substring(0, line.indexOf(' ')).equalsIgnoreCase("var")) {
  // ...
} else if (line.equalsIgnoreCase("exec")) {
  // ...
}

因为exec不包含空格,所以line.indexOf(' ')返回-1,line.substring(0, -1)因为第二个参数是负数而失败。您没有进行检查,exec因为它是在引发异常的检查之后。

if (line.equalsIgnoreCase("exec"))在需要空格的条件之前移动要检查的,例如

if (line.equalsIgnoreCase("exec")) {
  // ...
} else if (line.substring(0, line.indexOf(' ')).equalsIgnoreCase("print: ")) {
  // ...
} else if (line.substring(0, line.indexOf(' ')).equalsIgnoreCase("var")) {
  // ...
}

尽管您可能希望将 的值提取line.indexOf(' ')到变量中,并明确检查它是否为非负数,但您可以避免在该行不是exec且不包含空格的情况下检查条件:

if (line.equalsIgnoreCase("exec")) {
  // ...
} else {
  int spacePos = line.indexOf(' ');
  if (spacePos >= 0) {
    if (line.substring(0, spacePos).equalsIgnoreCase("print: ")) {
      // ...
    } else if (line.substring(0, spacePos).equalsIgnoreCase("var")) {
      // ...
    }
  }
}

String.regionMatches请注意,您可以通过使用: 这避免了显式创建子字符串来检查是否line以给定字符串开头的需要,从而减少出错并提高效率。该方法本身有点麻烦,但是您可以将其包装成一个方法:

static boolean startsWithIgnoreCase(String line, String cmd) {
  return line.regionMatches(
      true         /* ignore case */,
      0            /* from start of line */,
      cmd          /* the thing you're searching for */,
      0            /* from start of cmd */,
      cmd.length() /* all of cmd */);
}

现在您可以保留条件的原始顺序:

// Extra space appended because you were searching for the space after the command.
if (startsWithIgnoreCase(line, "print: " + " ")) {
  // ...
} else if (startsWithIgnoreCase(line, "var" + " ")) {
  // ...
} else if (line.equalsIgnoreCase("exec")) {
  // ...
}
于 2017-10-07T22:20:20.687 回答
0

在该execute方法中,您有内部 for 循环,如下所示

for (int k = 0; k < code.size(); i++)

在这里你不i增加k。而您正在substring使用i. 我认为问题就在这里。因为 for 循环永远不会结束,最终会有一个i你得到的值indexOutOfBound

于 2017-10-07T21:36:24.680 回答