Как мне избавиться от StringIndexOutOfBoundsException в моем коде?
Это мой первый вопрос по stackru. Я хотел проверить себя и создать мини-язык программирования. Но с тех пор, как я решил расширить свой код, я продолжаю получать StringIndexOutOfBoundsExceptions. Я провел некоторое исследование здесь на stackru и на YouTube, и кажется, что у меня возникла конкретная проблема. Можете ли вы проверить это, пожалуйста? Заранее спасибо... PS: Извините за путаницу имен переменных, я назвал их на своем родном языке:P code:
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)
2 ответа
В execute
метод, у вас есть внутренний цикл, как показано
for (int k = 0; k < code.size(); i++)
здесь вы увеличиваете i
не k
, А ты звонишь substring
с помощью i
, Я думаю, что проблема здесь. Потому что цикл for никогда не закончится и в конечном итоге будет i
значение, за которое вы получаете indexOutOfBound
Из вашего вопроса:
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")) {
// ...
}