2009-03-27 8 views
0

Voici ce que j'essaie de faire: Je lis un fichier depuis la ligne de commande. Le fichier contient une liste de données, en dessous de ce paragraphe est à quoi il ressemble. Le problème que j'ai est avec les instructions if.Array Index hors limites

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); 
     } 
    } 
} 

Dans le code pseudo serait:

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. 
..... 

Les problèmes est que je reçois une exception arrayOutOfBounds avec le code que je utilise.

Je comprends que j ++ est ce qui ne va pas, mais comment est-ce que je suis censé parcourir le tableau de chaînes pour pouvoir lire chaque ligne et créer les objets appropriés? Je ne sais pas quoi faire. Je ai besoin d'aide.

foreign car 
aMarioy 
Mario's house 
(777) 777-7777 
[email protected] 
false 
black 
Italy 
4415.91 

truck 
aDougy 
Doug's house 
(123) 456-7890 
[email protected] 
30 
61234.56 
8/10/2003 

vehicle 
aRobby 
Rob's house 
(987) 654-3210 
[email protected] 

bicycle 
bTommy 
Tom's house 
(246) 810-1214 
[email protected] 
7 

truck 
bGeorge 
George's house 
(666) 666-6666 
[email protected] 
25 
51234.56 
12/4/2004 

vehicle 
bTim 
Tim's house 
(111) 111-1111 
[email protected] 

bicycle 
bJim 
Jim's house 
(555) 555-5555 
[email protected] 
5 

american car 
bJohn 
John's house 
(888) 888-8888 
[email protected] 
true 
green 
false 
true 

car 
cKen 
Ken's house 
(999) 999-9999 
[email protected] 
false 
orange 

foreign car 
cMario 
Mario's house 
(777) 777-7777 
[email protected] 
false 
black 
Italy 
4415.91 


american car 
gSam 
Sam's house 
(333) 333-3333 
[email protected] 
false 
blue 
true 
false 

Répondre

6

Quelques problèmes:

  • Vous incrémenter j dans les deux tests "si". Je n'ai pas vérifié pour être certain (c'est un code assez compliqué, pour être honnête) mais si vous vous assurez que vous n'augmentez que j quand vous avez trouvé une correspondance, cela vous aidera.
  • Votre test utilisant i signifie essentiellement qu'il essayera de lire autant de véhicules qu'il y a de lignes dans le fichier, plutôt que de s'arrêter lorsque vous aurez atteint la fin du fichier. Fondamentalement, vous n'avez pas besoin i ici.

En voici une version modifiée:

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); 
     } 
    } 

Il serait un peu plus propre pour extraire le type une fois que - alors vous pouvez faire les comparaisons séparément:

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); 
     } 
    } 

Il est pas encore tout à fait comment Je le ferais, mais c'est plus proche ...

Ma prochaine étape serait d'utiliser le scanner de manière plus appropriée:Ensuite, faites en sorte que le constructeur de Vehicle, Car etc. effectue l'analyse directement à partir du scanner.

L'étape suivante consisterait à séparer la construction de l'itération.Introduire une nouvelle méthode:

// 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)); 
} 
+0

il est intéressant combien de « essayer au lieu » suggestions sont affichés avant que quelqu'un explique la e réel rror. – Tomalak

+1

@Tomalak, La question dit, "Je comprends que j ++ est ce qui ne va pas, mais comment est-ce que je suis censé parcourir le tableau de chaînes afin que je puisse lire chaque ligne et créer les objets appropriés?" – strager

+0

@strager: Vrai, mais je doute que cette ligne était destinée à être une demande d'alternatives. Tout le message a "pourquoi ai-je cette exception?" écrit partout. – Tomalak

0

Mettez vos incréments et décréments dans leur propre instruction. Cela rendra le code plus facile à comprendre dans la plupart des cas.

Dans votre cas, j++ est appelée deux fois si le premier if échoue. Ce n'est probablement pas ce que vous voulez.

Je convertira le boucle while dans une boucle for, comme ceci:

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

Si i == j toujours, il suffit d'utiliser la même variable pour les deux.

1

Chaque ligne qui ne correspond pas à « véhicule » sera (à tort) incrémenter j donc environ après la ligne 50, vous obtiendrez l'exception.

Il y a plusieurs solutions à ceci:

  • Increment j qu'une seule fois par boucle.
  • Lire les lignes dans un autre ArrayList.
  • Ne pas lire les lignes dans une structure de données mais les traiter pendant qu'elles sont en cours de lecture. De cette façon, vous êtes plus indépendant de la taille de vos données.
1

N'utilisez pas j ++ dans l'indice; incrémenter une fois après la boucle entière, plutôt qu'une ou deux fois en fonction de la condition qui est la bonne.

probablement mieux faire:

  • remplacer tous vos incréments en ligne (x ++) avec des états d'incrément (x = x + 1)
  • savoir où ils doivent aller pour rendre le code faites ce que vous voulez
  • les retransformer inline incréments pré/post une fois que vous avez obtenu ce travail, si cela semble approprié