Why do I keep on getting an ArrayIndexOutofBoundsException? - java

I am trying to program a program that mimics the actions of a vending machine for my CS class. I have a double array stock that represents the the number of items at a particular "slot" [my vending machine is weird and is kinda like one long vending machine with 1 column of different items]. Here is my code so far:
public class VendingMachine
{
// define fields here
public static double itemPrice[];
public static String[] itemName;
public static int stock[][];
public static int maxPerSlot;
public static double cashAmmount;
public VendingMachine(int numslots, int maxperslot, double cash)
{
final int numSlots = numslots;
maxPerSlot = maxperslot;
cashAmmount = cash;
stock = new int[numSlots][0];
itemPrice = new double[numSlots];
itemName = new String[numSlots];
// complete this method
}
public void setProduct(int slot, String product, double price)
{ int Slot = slot;
itemPrice[slot] = price;
itemName[slot] = product;
stock[Slot][0] = 0;
//
}
public void restockProduct(String product, int quantity)
{
String Product = product;
int currentCapacity = quantity - maxPerSlot;
for(int i = 0; i < stock.length; i++){
if (itemName[i]==Product){
for(;quantity <= maxPerSlot && currentCapacity != 0; quantity--)
stock[i][0] += 1;
}
}
//Put # of products in slot that holds it and if that slot is full put the rest in the next
//availble slot that holds that product, if all full return error.
}
public double getCashOnHand()
{
return cashAmmount; // replace this line with your code
}
public int getQuantity(int slot)
{
return stock[slot][1]; // replace this line with your code
}
public int getQuantity(String product)
{ int total = 0;
for (int i = 0; i<itemName.length;i++){
if (product == itemName[i]){
total += stock[i][1];
}
}
return total;
}
public boolean buyItem(int slot)
{ int snum = slot;
if (stock[snum][1] != 0){
stock[snum][1]--;
return true;
} else {
return false;} // replace this line with your code
}
}
Every time I runException in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at VendingMachine.setProduct(VendingMachine.java:27)
at vmd.main(vmd.java:9) this code though I get this error message:
Can someone here please explain to me why I continue to get this error? I mean the logic seems quite correct .

Your problem's here:
stock = new int[numSlots][0];
This defines an array of numSlot arrays with a length of 0 each.

when you initialize stock in the constructor do this instead:
stock = new int[numSlots][1];
using 0 instead of 1 initializes an array of length 0!

You allocate zero elements in the second dimension of stock,
stock = new int[numSlots][0];
so you get that exception when you try to access the element at index zero.
stock[Slot][0] = 0;

This line
stock = new int[numSlots][0]; // <-- A length of zero? You want a one there.
Should be
stock = new int[numSlots][1]; // <-- like so. Or, if you really don't
// want to change your other code make it a 2.
// But you'll leave memory unused, and you really should change it.
Everywhere else (where you have code like this) -
stock[slot][1] // <-- stock[INDEX][1] <--- should be 0.
Like this
stock[slot][0] // <-- all of the other accesses.

Because this line:
stock = new int[numSlots][0];
allocates stock to be an array of arrays, and each of those arrays has length 0. So you can't assign anything into those arrays (they don't have any elements to assign). So when you do this:
stock[Slot][0] = 0;
you will get an ArrayIndexOutOfBounds. Remember that in Java, indexes start at 0, so if you want an array where the indexes go from 0 to N, you have to allocate the array with size N+1.

Related

Index out of bounds for an array (java)

My code is supposed to print out the student with the highest range. There is a method in my Student class which calculates the range, while in my Classroom class there is another method that determines which student had the highest growth. My problem comes in the class Student, I get an Out of Bounds Exception in the addExamScore method.
Main class:
public class ClassroomTester
{
public static void main (String[] args)
{
Classroom c = new Classroom(2);
Student ada = new Student("Ada", "Lovelace", 12);
ada.addExamScore(44);
ada.addExamScore(65);
ada.addExamScore(77);
Student alan = new Student("Alan", "Turing", 11);
alan.addExamScore(38);
alan.addExamScore(24);
alan.addExamScore(31);
c.addStudent(ada);
c.addStudent(alan);
c.printStudents();
Student mostImproved = c.getMostImprovedStudent();
System.out.println("The most improved student is " + mostImproved.getName());
}
}
Student class:
public class Student
{
private static final int NUM_EXAMS = 4;
private String firstName;
private String lastName;
private int gradeLevel;
private double gpa;
private int[] exams;
private int numExamsTaken;
public Student(String fName, String lName, int grade)
{
firstName = fName;
lastName = lName;
gradeLevel = grade;
exams = new int[numExamsTaken];
numExamsTaken = 0;
}
public int getExamRange()
{
int maximum = 0;
int minimum = 0;
for(int i = 0; i < exams.length; i++){
if(exams[i]<exams[minimum]){
minimum = i;
}
else if(exams[i]>exams[maximum]){
maximum = i;
}
}
return exams[maximum]-exams[minimum];
}
public String getName()
{
return firstName + " " + lastName;
}
public void addExamScore(int score)
{
exams[numExamsTaken] = score;
numExamsTaken++;
}
public void setGPA(double theGPA)
{
gpa = theGPA;
}
public String toString()
{
return firstName + " " + lastName + " is in grade: " + gradeLevel;
}
}
First, you're initializing exams in the constructor the line before you initialize numExamsTaken, the order should be reversed because you need to know what numExamsTaken is before using it. I'd recommend storing the maximum and minimum as scores instead of indexes but that's just personal preference I think it makes the code more readable, so up to you. The index out of bounds problem probably has to do with your addExamScore method. If you've taken 4 exams it might look like [90, 85, 74, 82] where the indexes are 0, 1, 2, 3 and numExamsTaken = 4. Indexes starting at 0 is called zero-indexing and is used in most if not all programming languages.
exams[3] = 82 and exams[4] is going to give you an out of bounds error. Since you're not using an arrayList every time you want to add an element you're going to need to create an empty array of one size bigger than your current array, copy the previous scores over, and slide the new score into the last slot (in the case above would be index 4, which isn't out of bounds in the new array). Store your new array where your old array was in exams[].
Index out of bounds exception shows when array crosses it limits to store the value.
You have declared array of size '0' inside the constructor
in the line exams = new int[numExamsTaken];
initialize the size of the array with your expected range or use ArrayList to add values without specifying the size in prior
The problem with your code here is that you are trying to access a value in an array, which has not been allocated there. This is why the output is giving a ArrayIndexOutOfBoundsException, since you are trying to access an index in an array that is out of bounds of the array. In Java, arrays are fixed in size, meaning once you call new on an array, you cannot change the size of it without calling new on another array with a different size. In this case, it will be easiest to use a List, like an ArrayList, which does all of the resizing, copying, etc. for you, so you can use it as if it were a dynamically sized array. Your code would change to look something like this:
public class Student
{
// ...
private List<Integer> exams;
// ...
public Student(String fName, String lName, int grade)
{
// ...
exams = new ArrayList<>();
// ...
}
public int getExamRange()
{
int maximum = 0;
int minimum = 100;
for(int i = 0; i < exams.length; i++){
if (exams.get(i) > maximum) {
maximum = exams.get(i);
}
if (exams.get(i) < minimum) {
minimum = exams.get(i);
}
}
return maximum - minimum;
}
public void addExamScore(int score)
{
exams.add(score);
numExamsTaken++;
}
}
You can look more into List and ArrayList documentation at the java API website. Also, your logic for getting the minimum element is not correct, since if you have no scores that are less than 0, it will always assume that the minimum score is 0. You can fix this by setting the initial value to 100(the maximum possible value of a test score), or using another method that you prefer.

Converts array to LinkedList

I would like to convert the following code from array to any other way (the most important is effective) which means that there is infinite space and I will not have to set the length of the array.
How can this be done? How can I set up an unlimited cities? using LinkedList
The idea is that it is possible to define a certain country in which certain cities are stored (the name of the city, the city center, the central bus station,... - as in the picture below) - In my code MAX_NUM_CITIES = 1000;
My Code:
public class Country {
//instance variables
private String _countryName; // name of the country
private City[] _cities; // Array of the cities
private int _noOfCities; //number of cities in a country
public void CityArray() {
_cities = new City[MAX_NUM_CITIES];
_noOfCities = 0;
}
//constants:
public final int MAX_NUM_CITIES = 1000;
/**
* Constructer for object in Country class construct Country with info accordingly
* #param countryName represents the name of country
* #param cities represents the cities array
* #param noOfCities represents the number of cities
*/
public Country(String countryName) {
this._countryName = _countryName;
this._noOfCities = _noOfCities;
City[] cities = new City[MAX_NUM_CITIES];
}
boolean addCity(java.lang.String cityName, double XcityCenter, double YcityCenter, double XStationPoint, double YStationPoint, long numOfResidents, int numOfNeighborhoods) {
if (_noOfCities <= MAX_NUM_CITIES) return false;
_cities[_noOfCities++] = new City(cityName, XcityCenter, YcityCenter, XStationPoint, YStationPoint, numOfResidents, numOfNeighborhoods);
return true;
}
public long getNumOfResidents() {
long SumOfCities = 0;
if (_noOfCities > 0) //empty Array
{
SumOfCities = _cities[0].getNumOfResidents();
for (int i = 1; i < _noOfCities; i++)
SumOfCities += _cities[i].getNumOfResidents();
} else
SumOfCities = 0;
return SumOfCities;
}
public String getCountryName() {
return this._countryName;
}
public int getNumOfCities() {
return this._noOfCities;
}
public City[] getCities() {
int noOfCities = this._noOfCities;
City[] cities = new City[noOfCities];
for (int i = 0; i < _noOfCities; i++) cities[i] = new City(this._cities[i]);
return cities;
}
public String toString() {
if (_noOfCities == 0) //empty Array
System.out.println("There are no cities in this country ");
else
for (int i = 0; i < _noOfCities; i++) _cities[i].toString();
return toString();
}
}
I would step away from arrays if the length is:
unknown
can change
I suggest using one of the different List implementations from the JDK, specifically ArrayList and LinkedList.
The first uses an internal array which may be expanded if an element is added and would lead to the array being too small (it does this all by itself, so no need to worry).
The second is a node list, which means that for every element you add, a new (internal) node object is appended to the last node.
You'd of course have to change your code for this.
Define your _cities to be a List<City>: private List<City> _cities
Initialize that with the wanted implementation in the constructor: _cities = new ArrayList<>(); or _cities = new LinkedList<>();
In your add method you can just call: _cities.add(new City(cityName, XcityCenter, YcityCenter, XStationPoint, YStationPoint, numOfResidents, numOfNeighborhoods));
In your getNumOfResidents you can use the following snippet (which uses Java streaming api introduced in java 8):
return _cities.stream()
.mapToLong(City::getNumOfResidents)
.sum();
for getCities() you'd have to change the return type to List<City> and use the following: return new ArrayList<>(_cities) or return new LinkedList<>(_cities) depending on the implementation you want to use.

java for loop does not update variable

public CarDealerShip() {
cars = new Car[80];
listSize=0;
}
public void addNewCar (String model, int year, int price, String color) {
m = model;
y = year;
p = price;
c = color;
cars [listSize] = new NewCar (m,y,p,c);
listSize++;
}
public void addUsedCar (String model, int year, int price, boolean rusty) {
m = model;
y = year;
p = price;
r = rusty;
cars [listSize] = new UsedCar(m,y,p,r);
listSize++;
}
public String printReport() {
String list="";
if (cars.length==listSize)
for (int i =0; i <= listSize; i++)
list+=cars[i].toString()+"\n";
return list;
}
In the method printReport, the for loop is suppose to update the variable list but does nothing at all. It been a while since i use Java again so any help is appreciated.
Since 0 <= 0, the for loop will iterate once even if listSize==0 (even if cars[0] is not defined).
So if printReport "does nothing at all" (including throwing an exception), the most likely cause is that the expression in the if statement evaluates to false.
This might happen if you haven't added 80 cars to cars when you try calling printReport.
When you create an object of the class CarDealerShip, the variable listSize gets a value of 0 while the 'cars' array is 80 elements long.
So basically this IF fails:
if (cars.length==listSize).
Hence, the for loop is never entered.
This is all that can be said from the code you provided.
Remove this line :
if (cars.length==listSize)
Because cars is a array whose length is 80 and the variable listSize gets a value of 0 at the time of creating this class . So for loop is not executed .

Using a data structure to solve this in O(n)

we have sequence of 4 characters (A,B,C and D)that map to numbers form 1 to n.
we define components to be:
Component(k) :
A {cell[k]}
if Color(left_k) = Color(k)
then
A <-- A U Component(left_k)
if Color(right_k) = Color(k)
then
A <-- A U Component(left_k)
return A
there is 3 types of operations(the numbers in list indicate the input):
by giving index it should remove the component in that index(the numbers mapping to characters are fixed)
example : AABBBDA is the string. if index is 3 it should return AADA
by giving index it should rotate the string based on the component on that index(the numbers mapping to characters are fixed)
example : AABBBDA is the string. if index is 3 it should return DABBBAA
it should print the string.
inputs are like:
1 2 --> first operation with index=2
2 3 --> second operation with index=3
3 --> third operation
It's an assignment, happy to get help.
this is what i've tried so far:
public static void main(String[] args)
{
int numberOfOps;
String[] print = new String[30];
List list = new List();
Scanner input = new Scanner(System.in);
int count = input.nextInt();
String colors = new String();
colors = input.next();
for(int i = 0; i < count; i++)
{
list.add(colors.charAt(i));
}
numberOfOps = input.nextInt();
list.printElement();
for (int i = 0; i < numberOfOps; i++)
{
int op = input.nextInt();
if(op == 1)
{
int index = input.nextInt();
char c = list.item[index];
int temp = index;
int prevIndex = index;
int nexIndex = index;
if(index != 0)
{
while (list.item[--index] == c)
{
prevIndex--;
}
while (list.item[++temp] == c)
{
nexIndex++;
}
list.setNext(prevIndex-1, nexIndex+1);
}
else
{
while (list.item[++temp] == c)
{
nexIndex++;
}
list.setNext(prevIndex, nexIndex+1);
}
}
if(op == 2)
{
int index = input.nextInt();
}
if(op == 3)
{
print[i] = list.printElement();
}
}
}
here is my List class:
public class List {
// reference to linked list of items
public static final int MAX_LIST = 20;
public static final int NULL = -1;
public char item[] = new char[MAX_LIST]; // data
public int avail;
public int next[] = new int[MAX_LIST]; // pointer to next item
private int numItems; // number of items in list
public List()
{
int index;
for (index = 0; index < MAX_LIST-1; index++)
next[index] = index + 1;
next[MAX_LIST-1] = NULL;
numItems = 0;
avail = 0;
} // end default constructor
public void add(char e)
{
item[avail] = e;
avail = next[avail];
numItems++;
}
public String printElement()
{
String temp = null;
int index = 0;
while(index<avail)
{
temp += item[index];
System.out.println(item[index]);
index = next[index];
}
return temp;
}
public int size()
{
return numItems;
}
public void setNext(int i, int value)
{
next[i] = value;
}
}
if you test it you'll get, it has lots of problems, such as, I have no idea to do the rotate operation, and it has problem with connecting two components when the middle component has been removed.
This is a difficult question to answer, because the requirements are not properly stated.
For example the first bunch of pseudo-code does not make it clear whether A is a set, a multi-set or a list. The notation (use of curly brackets, and U (union?)) seems to say set ... but the output seems to be a list. Or maybe it is supposed to be a schema for a data structure??
And even the inputs are not clearly described.
But putting that on one side, there is still room for some (hopefully) helpful advice.
Make sure that >>you<< understand the requirements. (I imagine that the real requirements for the assignment are better stated than this, and the details have been "lost in translation".)
I would actually use an array list (or a StringBuilder) rather than a linked list for this. (But a properly implemented linked list ... implementing the List API ... would work.)
But whatever data structure you chose, there is no point in implementing it from scratch ... unless you are specifically required to do that. There are perfectly good list classes in the Java standard libraries. You should reuse them ... rather than attempting to reinvent the wheel (and doing a bad job).
If you are required to implement your own data structure type, then your current attempt is a mess. It looks like a hybrid between an array list and a linked list ... and doesn't succeed in being either. (For example, a decent array list implementation does not need a MAX_LIST, and doesn't have next pointers / indexes. And a linked list does not have any arrays inside it.)

Check duplicates of numbers input by user

I'm doing a program where user input five numbers and in the end the numbers are printed out which is working fine. What I can't get to work is a boolean function to check for duplicates. It should check for duplicates as the user write them in, so e.g. if number one is 5 and the second numbers is also 5, you should get an error until you write in a different number. Meaning if the user input a duplicate it should NOT be saved in the array. This is obviously an assignment, so I'm just asking for a hint or two.
This program is written based on pseudo-code given to me, and therefore I have to use a boolean to check for duplicates with the public boolean duplicate( int number ) class.
I've tried getting my head around it and tried something by myself, but obviously I'm doing a stupid mistake. E.g.:
if(int i != myNumbers[i])
checkDuplicates = false
else
checkDuplicates = true;
return checkDuplicates;
DuplicatesTest class:
public class DuplicatesTest {
public final static int AMOUNT = 5;
public static void main(String[] args) {
Duplicates d = new Duplicates(AMOUNT);
d.inputNumber();
d.duplicate(AMOUNT);
d.printInputNumbers();
}
}
Duplicates class:
public class Duplicates {
private int amount;
private int[] myNumbers;
private boolean checkDuplicates;
public Duplicates(int a) {
amount = a;
myNumbers = new int[amount];
}
public void inputNumber() {
for(int i = 0; i < amount; i++ ) {
int input = Integer.parseInt(JOptionPane.showInputDialog("Input 5 numbers"));
myNumbers[i] = input;
}
}
public boolean duplicate( int number ) {
<BOOLEAN TO CHECK FOR DUPLICATES, RETURN FALSE OR TRUE>
}
public void printInputNumbers() {
JTextArea output = new JTextArea();
output.setText("Your numbers are:" + "\n");
for(int i = 0; i < myNumbers.length; i++) {
if (i % 5 == 0) {
output.append("\n");
}
output.append(myNumbers[i] + "\t");
}
JOptionPane.showMessageDialog(null, output, "Numbers", JOptionPane.PLAIN_MESSAGE);
}
}
Sorry if the code tag is messy, I had some trouble with white fields in between and such. I'm new here.
Don't store the numbers in an array. Use a Set<Integer> instead. And then do a Set#contains() operation. It's O(1) operation which is actually far better than iterating over the array to search for duplicates.
Ok, if it's a compulsion to use an array, then you should modify your current approach, to return true as soon as you find a duplicate, instead of iterating over the array again. In your current approach, since you are setting the boolean variable to false in the else block, your method will return false if the last element of the array is not the same as what you are checking. So, just modify your approach to:
// loop over the array
if (number == myNumbers[i])
return true;
// outside the loop, if you reach, return false
return false;
Note that your current if statement will not compile. You are declaring an int variable there, which you can't do.
if (int i == myNumbers[i]) // this is not a valid Java code.
int nums[] = new int[5];
int count = 0;
public boolean duplicate(int number)
{
boolean isDup = false;
for (int i = 0; i <= count; i++)
{
if (number == nums[i])
{
isDup = true;
break;
}
}
if (!isDup)
{
count++;
nums[count] = number;
}
return isDup;
}

Categories

Resources