Индекс массива вне границ - PullRequest
0 голосов
/ 27 марта 2009

Вот что я пытаюсь сделать: я читаю файл из командной строки. Файл содержит список данных, ниже этого абзаца выглядит так. У меня проблема с операторами if.

import java.util.*;
import java.io.*;

public class VehicleTest {
    public static void main(String[] args) throws FileNotFoundException {
        String vehicle = "vehicle";
        String car = "car";
        String americanCar = "american car";
        String foreignCar = "foreign car";
        String truck = "truck";
        String bicycle = "bicycle";

        File file = new File(args[0]);
        Scanner input = new Scanner(file);

        String[] autos = new String[100];
        ArrayList allVehicles = new ArrayList();


        for (int i = 0; i < autos.length; i++) {
            autos[i] = input.nextLine();
        }

        int j = 0;
        int i = 0;

        while (i++ < autos.length) {
            if (vehicle.equalsIgnoreCase(autos[j++])) {
                Vehicle v = new Vehicle();
                v.setOwnerName(autos[j]);
                allVehicles.add(v);
            }else if(car.equalsIgnoreCase(autos[j++])){
                Car c = new Car();
                c.setOwnerName(autos[j]);
                allVehicles.add(c);
            }
        }

        for(Object a: allVehicles){
            System.out.println(a);
        }
    }
}

В псевдокоде это будет:

while i is less than the length of the string  array  
 if you see the word vehicle create a new vehicle object and add it to the arrayList.  
 if you see the word car create a new car object and add it to the arrayList.  
.....

Проблема в том, что я получаю исключение arrayOutOfBounds с кодом, который я использую.

Я понимаю, что j ++ - это то, что не так, но как иначе я должен перебирать массив строк, чтобы я мог читать каждую строку и создавать соответствующие объекты? Я в растерянности относительно того, что делать. Мне нужна помощь.

foreign car  
aMarioy  
Mario's house  
(777) 777-7777  
gmario@mario.com  
false  
black  
Italy  
4415.91  

truck  
aDougy  
Doug's house  
(123) 456-7890  
hdoug@doug.com  
30  
61234.56  
8/10/2003  

vehicle  
aRobby  
Rob's house  
(987) 654-3210  
irob@rob.com  

bicycle  
bTommy  
Tom's house  
(246) 810-1214  
jtom@tom.com  
7  

truck  
bGeorge  
George's house  
(666) 666-6666  
kgeorge@george.com  
25  
51234.56  
12/4/2004  

vehicle  
bTim  
Tim's house  
(111) 111-1111  
tim@tim.com  

bicycle  
bJim  
Jim's house  
(555) 555-5555  
Ajim@jim.com  
5  

american car  
bJohn  
John's house  
(888) 888-8888  
Bjohn@john.com  
true  
green  
false  
true  

car  
cKen  
Ken's house  
(999) 999-9999  
Cken@ken.com  
false  
orange  

foreign car  
cMario  
Mario's house  
(777) 777-7777  
Dmario@mario.com  
false  
black  
Italy  
4415.91  


american car  
gSam  
Sam's house  
(333) 333-3333  
Hsam@sam.com  
false  
blue  
true  
false  

Ответы [ 4 ]

6 голосов
/ 27 марта 2009

Пара проблем:

  • Вы увеличиваете j в обоих тестах "если". Я не проверял, чтобы быть уверенным (это довольно запутанный код, если честно), но если вы убедитесь, что увеличиваете j, только когда нашли совпадение, это поможет.
  • Ваш тест с использованием i в основном означает, что он будет пытаться прочитать столько файлов, сколько строк в файле, чем останавливаться, когда вы достигнете конца файла. В основном вам не нужно i здесь.

Вот одна измененная версия:

    while (j < autos.length) {
        if (vehicle.equalsIgnoreCase(autos[j])) {
            j++;
            Vehicle v = new Vehicle();
            v.setOwnerName(autos[j++]);
            allVehicles.add(v);
        } else if(car.equalsIgnoreCase(autos[j])){
            j++;
            Car c = new Car();
            c.setOwnerName(autos[j++]);
            allVehicles.add(c);
        }
    }

Было бы немного чище извлечь тип, хотя - тогда вы можете сделать сравнения отдельно:

    while (j < autos.length) {
        String type = autos[j++];
        if (vehicle.equalsIgnoreCase(type)) {
            Vehicle v = new Vehicle();
            v.setOwnerName(autos[j++]);
            allVehicles.add(v);
        } else if(car.equalsIgnoreCase(type)){
            Car c = new Car();
            c.setOwnerName(autos[j++]);
            allVehicles.add(c);
        }
    }

Это все еще не совсем то, как я это сделаю, но это ближе ...

Следующим моим шагом будет более правильное использование сканера:

while (scanner.hasNext()) {
    String type = scanner.nextLine();
    if (type.equalsIgnoreCase("vehicle")) {
        allVehicles.add(new Vehicle(scanner));
    } else if (type.equalsIgnoreCase("car")) {
        allVehicles.add(new Car(scanner));
    }
    // ...
}

Затем заставьте конструктор для Vehicle, Car и т. Д. Выполнять синтаксический анализ непосредственно из сканера.

Следующим шагом будет отделение конструкции от итерации. Введите новый метод:

// Use a base type in real code
private static Object parseNextVehicle(Scanner scanner) {
    String type = scanner.nextLine();
    if (type.equalsIgnoreCase("vehicle")) {
        return new Vehicle(scanner);
    } else if (type.equalsIgnoreCase("car")) {
        return new Car(scanner);
    }
    // ... throw an exception indicating an unknown vehicle type
}

// ... and then in the main method, use it like this:
while (scanner.hasNextLine()) {
    allVehicles.add(parseNextVehicle(scanner));
}
1 голос
/ 27 марта 2009

Не используйте j ++ в нижнем индексе; увеличивайте его один раз после всего цикла, а не один или два раза в зависимости от того, какое условие выполняется.

Вероятно, лучше сделать это:

  • замените все ваши встроенные приращения (x ++) на операторы приращения (x = x + 1)
  • выясните, куда им нужно идти, чтобы код делал то, что вы хотите
  • превратите их обратно во встроенные приращения до / после того, как все заработало, если это кажется подходящим
1 голос
/ 27 марта 2009

Каждая строка, которая не равна «транспортное средство», будет (неправильно) увеличиваться j, поэтому примерно после строки 50 вы получите исключение.

Существует несколько решений для этого:

  • Увеличение j только один раз за цикл.
  • Читайте строки в другой ArrayList.
  • Не считывайте строки в структуру данных, а обрабатывайте их во время чтения. Таким образом, вы более независимы от размера ваших данных.
0 голосов
/ 27 марта 2009

Положите ваши приращения и убавления в собственном утверждении. Это облегчит понимание кода в большинстве случаев.

В вашем случае, j++ вызывается дважды, если первый if терпит неудачу. Это, вероятно, не то, что вы хотите.

Я бы преобразовал ваш while цикл в for цикл, вот так:

for (int i = 0, j = 0; i < autos.length; ++i, ++j) {
    if (vehicle.equalsIgnoreCase(autos[j])) {
        // ...

Если i == j всегда, просто используйте одну и ту же переменную для обоих.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...