Not sure why array goes out of bounds JAVA - java

I'm getting an Array Index Out of Bounds exception on the String weapon = dataz[1]; line at runtime. I'm not sure what is causing this as this is nearly the same code I've used on previous assignments. Any logic as to why this is happening would be greatly appreciated!
public Hero[] getHeroes(){
String file = getFilePath();
Hero[] heroPower = new Hero[5];
int i=0;
try{
Scanner data = new Scanner(file);
while(data.hasNextLine() && i < 5)
{
String next = data.nextLine();
if(!next.trim().isEmpty())
{
String[] derp = next.split(",");
String name = derp[0];
String weapon = derp[1];
int attackPoints = Integer.parseInt(derp[2]);
heroPower[i] = new Hero(name,weapon,attackPoints);
i++;
}
}
data.close();
} finally {
}
return heroPower;
}
}

Your next string probably doesn't split. It doesn't have a , and you're not checking for that option.

Your code processes empty lines correctly, but it fails when the input does not have at least three tokens: it assumes that derp[0], derp[1], and derp[2] are valid, but the validity depends on the input.
You can fix it by checking the number of tokens that you get back from next.split:
String next = data.nextLine();
String[] derp = next.split(",");
if(derp.length >= 3) {
...
}
This condition also covers the situation when the trimmed next is empty, so a separate check is not required.

You really need to make sure that the number of inputs you are inputting is the number of inputs you are expecting, a simple check would be to check the number of arguments in the derp array that you get from split.
public Hero[] getHeroes(){
String file = getFilePath();
Hero[] heroPower = new Hero[5];
int i=0;
try{
Scanner data = new Scanner(file);
while(data.hasNextLine() && i < 5)
{
String next = data.nextLine();
if(!next.trim().isEmpty())
{
String[] derp = next.split(",");
//This is the line to change
if(derp > 3){
String name = derp[0];
String weapon = derp[1];
int attackPoints = Integer.parseInt(derp[2]);
heroPower[i] = new Hero(name,weapon,attackPoints);
i++;
}else{
//throw an error
}
}
}
data.close();
} finally{
}
return heroPower;
}
}

The problem is most likely your input, it doesn't contain any , symbols:
String[] derp = next.split(","); // split by commas a word that has no commas so derp.length == 1
String name = derp[0]; // this is ok since length is 1
String weapon = derp[1]; // this is error
You should check derp.length before using it:
String[] derp = next.split(",");
if(!derp.length == 3) { // because name=derp[0], weapon=derp[1], attackPoints = derp[2]
// ... create name, weapon, points and assign to heroPower
} else {
System.out.println("Invalid input");
}

Related

Reading a file with Strings and floats and assigning them to arrays

I want to design a code that can read a file that looks like this:
Jake 12.00 13.24 6
Sarah 11.23 24.01 8
Alex 10.65 19.45 4
I need to make separate arrays for the Strings, the first float, the second float, and the int.
How do I go about doing this?
This is what I have so far: I'm not sure how to make separate arrays for the two floats. I also keep getting an exception IndexOutOfBoundsException: 0 at EmployeePay.main..
import java.util.Scanner;
import java.io.*;
public class EmployeePay {
public static void main(String[] args) throws FileNotFoundException {
if (args.length != 1) {
final String msg = "Usage: EmployeePay name_of_input file";
System.err.println(msg);
throw new IllegalArgumentException(msg);
}
final String inputFileName = args[0];
final File input = new File (inputFileName);
final Scanner scanner = new Scanner(new BufferedReader(new FileReader(input)));
String Id = "Employee Id:";
String Hours = "Hours worked:";
String WageRate = "Wage Rate:";
String Deductions = "Deductions:";
System.out.printf("%s %-10s %-20s %-30s", Id, Hours, WageRate, Deductions);
int lineNumber = 0;
while (scanner.hasNextLine()){
lineNumber =lineNumber +1;
String [] Identification= new String [lineNumber-1];
int [] TotalDeductions = new int [lineNumber-1];
float [] WorkTime = new float[lineNumber-1];
if(scanner.hasNextInt()){
TotalDeductions[lineNumber-1] = scanner.nextInt();
System.out.println(TotalDeductions[lineNumber-1]);
}
else if (scanner.hasNextFloat()){
WorkTime[lineNumber-1]= scanner.nextFloat();
}
else {
Identification[lineNumber-1] = scanner.next();
System.out.println(Identification[lineNumber-1]);
}
}
}
}
I will assume your String value doesn't contain space. This is kind of pseudo code, Try yourself and explore each line why I did so:
String s[] = new String[size];
float f1[] = new float[size];
float f2[] = new float[size];
for(int i=0; i<numberOfLines;i++) {
String x = "Jake 12.00 13.24 6";
String[] arr = x.split(" ");
s[i] = arr[0];
f1[i] = Float.valueOf(arr[1]);
f2[i] = Float.valueOf(arr[2]);
}
This error exception IndexOutOfBoundsException: 0 at EmployeePay.main. is occuring due to this statement if (args.length != 1).
It should be if(args.length!=0)
If no arguements are passed at command prompt then args.length is 0. So, this statement will throw an exception final String inputFileName = args[0];
Thus, you need to check for args.length
If your data file is indeed as you show in your post with blank lines between the data lines then you will need to take care of those as well while reading the file and processing the information obtained. You obviously want to skip past those particular lines. If this isn't the case then it only goes to show you how important it is to provide full and accurate information when asking a question here. No one here wants to really assume anything.
When creating arrays it's always nice to know how big an array needs to be beforehand so that you can properly initialize it to its required size. This is where List or ArrayList is better, you can just add to them when needed. Never the less, to properly initialize all your different arrays (String[], float[], float[], and int[]) you need to know how many valid data line are contained within your data file. By valid data lines I mean lines that actually contain data, not blank lines. So the first natural step would be to count those lines. Once you have the count then you can initialize all your arrays to that line count.
Now all you need to do is re-read the file data line by line, split each line to acquire the data segments , then convert each numerical segment to its respective Array data type. Once you have all your arrays filled from the file you can then do whatever you like with the data contained within those arrays. The code to carry out this task might look something like this:
String inputFileName = "MyDataFile.txt";
Scanner scanner;
int linesCount = 0;
try {
// Count the total number of valid data lines
// within the file (blank line are skipped).
scanner = new Scanner(new File(inputFileName));
while (scanner.hasNextLine()) {
String strg = scanner.nextLine().trim();
if (!strg.equals("")) { linesCount++; }
}
// Declare our different Arrays and size them to
// the valid number of data lines in file.
String[] employeeID = new String[linesCount];
float[] hours = new float[linesCount];
float[] wageRate = new float[linesCount];
int[] deductions = new int[linesCount];
// Read through the file again and place the data
// into their respective arrays.
scanner = new Scanner(new File(inputFileName));
int counter = 0;
while (scanner.hasNextLine()){
// Get the next line in file...
String strg = scanner.nextLine().trim();
// If the file line is blank then skip it.
if (strg.equals("")) { continue; }
// otherwise split the line by its space
// delimiter ("\\s+" takes care of 1 OR more
// spaces just in case).
String[] values = strg.split("\\s+");
// Add to the employeeID string array.
employeeID[counter] = values[0];
// Control what is placed into the elements of each
// float or integer array. If there is no value data
// supplied in file for the employee Name then make
// sure 0.0 (for floats) or 0 (for integers) is placed
// there after all, you can't parse a null string ("").
if (values.length >= 2) { hours[counter] = Float.parseFloat(values[1]); }
else { hours[counter] = 0.0f; }
if (values.length >= 3) { wageRate[counter] = Float.parseFloat(values[2]); }
else { wageRate[counter] = 0.0f; }
if (values.length == 4) { deductions[counter] = Integer.parseInt(values[3]); }
else { deductions[counter] = 0; }
counter++;
}
scanner.close();
// Now that you have all your arrays you can
// do whatever you like with the data contained
// within them:
String Id = "Employee Id:";
String Hours = "Hours worked:";
String WageRate = "Wage Rate:";
String Deductions = "Deductions:";
System.out.printf("%-15s %-15s %-15s %-15s%n", Id, Hours, WageRate, Deductions);
for (int i = 0; i < employeeID.length; i++) {
System.out.printf("%-15s %-15s %-15s %-15s%n", employeeID[i], hours[i], wageRate[i], deductions[i]);
}
}
catch (FileNotFoundException ex) { ex.printStackTrace(); }

Using boolean to exit loops and then redo the loops

I'm fairly new to Java, so I don't know too many fancy stuff and I'm kind of stuck.
What I need to do is, take a text file; import the content into an ArrayList; check each line for a specific Char that is between two "#"; then check each line in the ArrayList again to see if one of the lines already has that Char; if it does, then I need to re-enter the whole String line and re-check it; and if it doesn't, then I need to put it at the bottom of the ArrayList and into the text file.
So far, I've gotten to the part where I need to check if the entered line's Char is repeating, but I can only do it once. If, for example, I enter it again I would get an IndexOutOfBoundsException because of one of the loops. So, I figured I'd use a boolean to exit the loops and re-enter them, but unfortunately, after entering the whole String once, it asks me to do it again in order to repeat the process because I'm exiting and entering the wrong loop, but I can't seem to figure out which.
ArrayList<String> Prices = new ArrayList<String>();
try (BufferedReader br = new BufferedReader (new FileReader("file.txt"))){
String CurrentLine;
while ((CurrentLine = br.readLine()) != null){
Prices.add(CurrentLine);
}
}catch (IOException e) {
e.printStackTrace();
}
boolean CheckSequence = true;
boolean Redo = false;
String StringArrayPrices[] = new String[Prices.size()];
Scanner sc = new Scanner (System.in);
while (CheckSequence == true){
System.out.println("Insert product in the following format, 'Product#Letter#Number': ");
String ProductString = sc.nextLine();
char ProductArray[] = ProductString.toCharArray();
for (int i = 0; i < Prices.size(); i++){
StringArrayPrices[i] = Prices.get(i);
char CharArrayPrice[] = StringArrayPrices[i].toCharArray();
for (int j = 0; j < CharArrayPrice.length && Redo == false; j++){
if (CharArrayPrice[j] == '#' && CharArrayPrice[j+2] == '#'){
char TemporaryLetter = CharArrayPrice[j];
for (int k = 0; k < ProductArray.length && Redo == false; k++){
if (ProductArray[k] == '#' && ProductArray[k+2] == '#'){
char TemporaryLetter2 = ProductArray[k];
if (TemporaryLetter == TemporaryLetter2){
System.out.println("The letter is repeating. Enter product again or exit by writing '-1': ");
ProductString = sc.nextLine();
if (ProductString == "-1"){
CheckSequence = false;
}
Redo = true;
}
if (TemporaryLetter != TemporaryLetter2){
Prices.add(ProductString);
}
}
}
}
}
}
}
Right now, when I re-enter the String, I'm greeted with the first message ""Insert product in the following format, 'Product#Letter#Number': "", instead of the ""The letter is repeating. Enter product again or exit by writing '-1': "".
The first line should only show up when I'm entering a completely new String instead of when the previous one's repeating.
I hope I didn't make this too confusing.
All of the loops is not the way to go.
I'm not entirely sure of the requirement, but I think this meets it.
Note that you should probably define a Product class to encapsulate much of this.
List<String> prices;
Set<String> letters;
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
prices = reader.lines.collect(Collectors.toList());
}
letters = prices.stream.map(p -> getLetter(p)).collect(Collectors.toSet());
Scanner scanner = new Scanner(System.in);
boolean shouldContinue = true;
while (shouldContinue) {
System.out.println("Enter Product");
String product = scanner.nextLine();
if (product.equals("-1")) {
shouldContinue = false;
} else {
String letter = getLetter(product);
if (letters.contains(letter) {
System.out.println("Repeat. Re-enter");
} else {
prices.add(product);
letters.add(letter);
}
}
}
with the helper
private String getLetter(String s) {
return s.split("#")[1]; //Or use the appropriate regex to extract the letter.
}
which could use some error handling.
To avoid java 8's streams, You can use the same code you used in the question to build prices and
Set<String> letters = new HashSet<>();
for (String price : prices) {
letters.add(getLetter(price));
}

how do i check the data in an array with indexOf in java

i'm fairly new to java and i'm trying to use indexOf to check if a persons name ends with the letters in the array and output a word it rhymes with. Where am i going wrong? e.g. Dean ends in "ean" so it rhymes with green. Thanks guys
String [] first = new String [3];
first [0] = "eem";
first [1] = "een";
first [2] = "ean";
for (int i = 0; i < first.length; i++) {
if (first[i].indexOf(first.length) != -1){
System.out.println("That rhymes with green");
}
}
To check with weather the input contains any array given element's, you should receive input and then iterate over your array to look at. For ex
String personname = "Dean";
String [] first = new String [3];
first [0] = "eem";
first [1] = "een";
first [2] = "ean";
for (int i = 0; i < personname.length; i++) {
if (input.indexOf(first[i]) != -1){ // check my input matched
System.out.println("That rhymes with green");
}
}
You should use endsWith instead of indexOf. indexOf will return the index where the passed string exactly matches the current string and, as the name suggests, endsWith will check if the current string ends with the passed string.
Take a look at the following code:
String personName = "Dean";
String[] suffix = {"eem", "een", "ean"};
String[] names = {"greem", "green", "grean"};
for(int i = 0; i < suffix.length; i++) {
if (personName.endsWith(suffix[i])){
System.out.println("That rhymes with " + names[i]);
}
}
Also, ideally, you would want to keep a map of suffix -> name for maintainability, but for simplicity/exploring this should be fine.
I have tested and ran it on the compiler. This is working fine. Please comment for any quesions. Thanks
import java.util.*;
public class HelloWorld
{
public static void main(String []args)
{
String [] first = new String [3];
first [0] = "eem";
first [1] = "een";
first [2] = "ean";
/* I am trying to get the input from user here */
String s;
Scanner in = new Scanner(System.in);
System.out.println("Enter the string:");
s = in.nextLine();
/* Now, String.indexOf(substring) will check the condition if the match happens it will print the output, if it doesn't it returns -1 */
for (int i = 0; i <s.length(); i++)
{
if (s.indexOf(first[i]) != -1)
{
System.out.println("That rhymes with green");
}
}
}
}

Reading from an array list and comparing to an input string

Basically I have been asked to create a small letters game in which the user picks some vowels and consonants and these are added to an array list, once that has happened, we have to print out the contents of the array list e.g. it could look like this, [T,S,I,L,Y,A,R,R,A] and then we prompt the player to input what words they think they can make from the given list of characters. What I am looking for some pointers on is how to make sure the user can only use they characters and also how to compare their answer to a dictionary file. The only code I have so far is reading in my dictionary file. Any help would be greatly appreciated.
try {
BufferedReader reader = new BufferedReader(new FileReader("dictionary.txt"));
String line = reader.readLine();
List<String> words = new ArrayList<String>();
while (line != null) {
String[] wordsLine = line.split(" ");
for (String word : wordsLine) {
words.add(word);
}
line = reader.readLine();
}
System.out.println("Here is your board again: " + genString + "\n");
System.out.println("Please enter your answer!\n");
} catch (Exception e) {
System.out.println(e);
}
genString is my, what would be the list of characters and I have still to place the scanner in for user input.
The basic idea is putting the characters from user input into some collection, then iterating over the characters of the word and checking against that collection.
Finally, if everything is kosher, look up the word in the dictionary.
List<Character> charsFromUser = new LinkedList<Character>();
Set<String> dictionary = new HashSet<String>();
boolean illegalCharUsed = false;
boolean done = false;
String wordFromUser = null;
// dictionary = // fill dictionary
// charsFromUser = // get chars from user
// wordFromUser = // get word from user
for (int i = 0, l = wordFromUser.length(); i < l && !illegalCharUsed; ++i) {
char c = wordFromUser.charAt(i);
if (!charsFromUser.contains(c)) {
illegalCharUsed = true;
} else {
charsFromUser.remove(Character.valueOf(c)); // remove this line if
// users may reuse letters
}
}
if (!dictionary.contains(wordFromUser)) {
if (!illegalCharUsed && charsFromUser.isEmpty()) { // isEmpty check if users
// must use all letters
System.out.println("well done");
} else {
System.out.println("you didn't use the correct characters");
}
} else {
System.out.println("not a legal word");
}

java scanner - how to split a mac address?

The mac address string may be in format:
00:aa:bb:cc:dd:ee
or
00aabbccddee
I need a good way to retrieve the 6 parts.
Here my code:
public class Mac
{
public static void main(String[] args)
{
String mac = "00:aa:bb:cc:dd:ee"; /* 00aabbccddee */
Scanner s = new Scanner(mac);
s.useDelimiter(":?"); /* zero or one occurrence */
String t = null;
while ((t = s.next("[0-9a-f][0-9a-f]")) != null)
System.out.println(t);
}
}
It throws a exception:
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:840)
at java.util.Scanner.next(Scanner.java:1461)
at java.util.Scanner.next(Scanner.java:1394)
at Mac.main(Mac.java:11)
What's wrong with it?
public static String[] getMacAddressParts(String macAddress) {
String[] parts = macAddress.split(":");
if (parts.length == 0) {
parts = new String[6];
for (int i = 0; i < 6; i++) {
parts[i] = macAddress.substring(i * 2, i * 2 + 1);
}
}
return parts;
}
String[] splitMac(String mac) {
String[] parts = null;
if (mac.length() == 6*3) {
parts = mac.split(":");
} else if (mac.length() == 6*2) {
parts = new String[6];
parts[0] = mac.substring(0,1);
parts[1] = mac.substring(2,3);
parts[2] = mac.substring(4,5);
parts[3] = mac.substring(6,7);
parts[4] = mac.substring(8,9);
parts[5] = mac.substring(10,11);
} else {
throw new RuntimeException("Invalid arg for mac addr: " + mac);
}
return parts;
}
Setting a delimiter for zero or more occurrences will split the string as every single char in the next() findings like this:
a
a
b
b
c
c
d
d
e
e
because you are saying if it does or doesn't find it, split it.
So looking for the next token that matches your regex "[0-9a-f][0-9a-f]" throws that exception because its trying to match one character with a 2 character regex every time, and it throws it then the token you are trying to get doesnt match the regex you are giving, thus doing the hasNext("Pattern") before prevents that.
Also you're code will throw a NoSuchElementException when the string stops reading the characters through the next() method, verify if it does have a next token with the hasNext("Pattern") in the while conditional.
So just remove the ? on the delimiter and it will work.
Example:
String mac = "00:aa:bb:cc:dd:ee"; /* 00aabbccddee */
Scanner s = new Scanner(mac);
s.useDelimiter(":"); /* zero or one occurrence */
String t = null;
while (s.hasNext("[0-9a-f][0-9a-f]"))
{
t = s.next("[0-9a-f][0-9a-f]");
System.out.println(t);
}
Regards
String mac = "00:aa:bb:cc:dd:ee";
String[] partsArray = mac.split(":");
for(int i = 0; partsArray.length < i ;i++){
String part = partsArray[i];
System.out.println ("Splitted mac address part "+i+" is - "+part);
}

Categories

Resources