Why is my code skipping over certain elements in a txt file? - java

I'm currently working on an assignment that requires me to build a small database for an imaginary toy company. They sell four different types of toys, with all of their toy's data in a single text file. Different toys have varying attributes to them.
My job is to read every line of the text file, find out what toy it is based on it's serial number, create a new instance of that toy, and load it into an array list of Toys.
Here are some examples of a line in the .txt file for every type of toy.
Animal
2835360879;Cow;Game Assassin;19.52;3;7;Plastic;M
Puzzle
4353818087;Eight queens puzzle;Gamescape;15.69;5;6;C
Figure
1147205649;Ninja Turtles;Gamezoid;46.15;10;6;A
Board Game
7235647474;13 Dead End Drive;Game Assassin;55.18;10;9;1-8;Emeli Davis
The following method is in charge of parsing through the text file, to create new instances of Toy, and to add them into the Array List
public void loadData() {
try {
File dataFile = new File("res/toys.txt");
if (dataFile.createNewFile()) {
System.out.println("Data file created!");
}
else {
Scanner readData = new Scanner(dataFile);
readData.useDelimiter(";"); // sets semicolons as the delimiter
while(readData.hasNext()) {
sn = readData.nextDouble(); // reads the next double (serial number) on each line
category = categoryHandler(sn); // setting and returning value for category based on the serial number
nm = readData.next(); // initializes the name of the toy
brd = readData.next();
prc = readData.nextDouble();
availableCnt = readData.nextInt();
ageApp = readData.nextInt();
// creates a new object, dependant on the category
switch(category) {
case "Figures":
char classification = readData.next().charAt(0);
Figure figures = new Figure(sn, nm, brd, prc, availableCnt, ageApp, classification);
data.add(figures);
break;
case "Animals":
String material = readData.next();
char size = readData.next().charAt(0);
Animal animals = new Animal(sn, nm, brd, prc, availableCnt, ageApp, material, size);
data.add(animals);
break;
case "Puzzles":
char puzzleType = readData.next().charAt(0);
Puzzle puzzles = new Puzzle(sn, nm, brd, prc, availableCnt, ageApp, puzzleType);
data.add(puzzles);
break;
case "Board Games":
String playerCount = readData.next(); // holds the player count as a string
int minPlayers = Integer.parseInt(playerCount.substring(0, 1)); // holds the first integer
int maxPlayers = Integer.parseInt(playerCount.substring(playerCount.length() - 1, playerCount.length())); // holds the second integer
String designers = "";
BoardGame boardGames = new BoardGame(sn, nm, brd, prc, availableCnt, ageApp, minPlayers, maxPlayers, designers);
data.add(boardGames);
break;
default:
System.out.println("Invalid toy type selected!");
}
if (readData.hasNext()) {
readData.nextLine(); // skips to the next line if there's a line to skip to
}
}
readData.close();
}
}
catch (IOException e) {
System.out.println("An error occured.");
e.printStackTrace();
}
}
The following method is in charge of categorizing the toy type.
public String categoryHandler(double serialNumber) {
String serialNumCheck = Double.toString(serialNumber); // converting serial number to string to allow the first digit to be checked
double firstDigit;
// setting up the first digit, checking to see if it's zero.
if (serialNumCheck.length() == 12) {
firstDigit = 0;
}
else {
firstDigit = Double.parseDouble(Double.toString(serialNumber).substring(0, 1));
}
// conditionals
if (firstDigit == 0 || firstDigit == 1) {
category = "Figures";
}
else if (firstDigit == 2 || firstDigit == 3) {
category = "Animals";
}
else if (firstDigit == 4 || firstDigit == 5 || firstDigit == 6) {
category = "Puzzles";
}
else if (firstDigit == 7 || firstDigit == 8 || firstDigit == 9) {
category = "Board Games";
}
// this condition should not be possible to achieve, unless the first digit is negative. Still have it just in case.
else {
System.out.println("Invalid serial number created!");
category = "";
}
return category;
}
After running the loadData() method, my array list only contains 128 toys, instead of the expected 225. Almost all of them are categorized properly, but a few toys are not, at seemingly at random indices.
I suspect it has something to with readData.nextLine() at the end of the loadData() method. The problem is that when I remove the line, the program throws a NullPointerException as there nothing left to scan on the current line, so no Toy can be created.
At this point I'm fairly lost as to what is causing this bug.
Some guidance would be appreciated.

Related

Why does my method overwrite positions in my array

So I have this method here
while(oMenu == 1 || oMenu == 2){
oMeny = Kbd.readInt("\nClick 1 to make an account\nClick 2 to login\nClick 3 to exit the program");
if(oMeny == 1){
for(int i = 0; Account[i] != null; i++){
if(Account[i] == null){
pos = i;
}
}
Account[pos] = new Account();
}
if(oMeny == 2){
String s = Kbd.readString("Input your accountnumber: ");
for(int i = 0; Account[i] != null; i++){
if(Account[i] != null && s.equals(Account[i].getAccountNumber())){
System.out.println("Welcome!");
// Here is rest of my code , the "inner" menu that works menyMetod(iMeny,mMeny);
}
else{
System.out.println("There are no accounts with that given accountnumber!");
}
}
}
}
}
I want to understand why if I access the oMeny == 1 and make 2 accounts Why I can't seem to access the first one I make but rather the latest one? It seems that somehow my array "overwrites" the first empty position. Basically I want to find the first empty position in my array, so in the first case it's always index 0 and then the next time I make an account again, it should be Index 1 logically.
EDIT : Heres my code for the Account class
public class Account{
private int money, transactions;
private String AccountNumber;
public Account(){
money = Kbd.readInt("\nHow much money do you want to put in?");
AccountNumber = Kbd.readString("\nWhat account number do you want?");
}
The error is here:
for (int i = 0; accounts[i] != null; i++) {
if (accounts[i] == null)
The for loop repeats as long i points to a non-null entry. Therefore the if-condition is never true.
This becomes quickly obvious when you run the program line by line in a debugger.
Next time please provide a complete code example that can be compiled. Your code is full of error, It took me a lot of time to fix it before I was able to execute it.
Corrected code:
import java.util.Scanner;
class Main
{
static Scanner kbd = new Scanner(System.in);
static Account[] accounts = new Account[100];
static class Account
{
//public int money;
public String accountNumber;
public Account()
{
//System.out.println("\nHow much money do you want to put in?");
//money = Kbd.nextInt();
System.out.println("\nWhat account number do you want?");
accountNumber = kbd.next();
}
}
public static void main(String[] args)
{
int oMenu = 1;
int pos = 0;
while (oMenu == 1 || oMenu == 2)
{
System.out.println("\nClick 1 to make an account\nClick 2 to login\nClick 3 to exit the program");
oMenu = kbd.nextInt();
if (oMenu == 1)
{
for (int i = 0; i<accounts.length; i++)
{
if (accounts[i] == null)
{
accounts[i] = new Account();
break;
}
}
}
if (oMenu == 2)
{
System.out.println("Input your accountnumber: ");
String s = kbd.next();
Account found=null;
for (int i = 0; i<accounts.length; i++)
{
if (accounts[i] != null && s.equals(accounts[i].accountNumber))
{
found=accounts[i];
}
}
if (found!=null)
{
System.out.println("Welcome! nr. "+found.accountNumber);
}
else
{
System.out.println("There are no accounts with that given accountnumber!");
}
}
}
}
}
Notice how I also fixed the second for-loop.
You did not show the declaration or initialization of pos, so I think it is not working how you expect because you do not go into the for loop where Account[i] is null to set pos. Try this
if(oMenu == 1){
int pos = 0;
while (Account[pos] != null && pos < Account.length)
pos++;
if (pos < Account.length)
Account[pos] = new Account();
else{
//expand array and add account or throw error
}
}

File Becomes Empty After Overwriting It

so I have written a code in my project where I have stored some votes in rows in a separate file. I then read that file and extract the votes in rows into a 1D array, then I have to increment them like if the user enters 1, 1 vote is added to the first row, if the user enters 2, one vote is incremented to the 2 row and so on. After that, I have to store that incremented array with added votes to the same file (overwrite) from where they were originally extracted.
I am facing two issues, first, when the user enters 1, there are actually 7 increments done because the loop runs for 7 times as the array length is 7. The second issue is, after the file is overwritten, it shows results with incremented votes in the output but the file becomes empty and when it is run again, it shows 0,0,0,0 .... even after using output.close() at the end.
Please suggest, I have to submit the project tomorrow and there is still a lot to write, if someone could please lend 2,3 hours to help too would be great.
public static int[] voteCasting(String resultFile) {
String[] votesArray = new String[7];
int[] votesConverted = new int[votesArray.length];
try {
String partyVotes = "";
int castedVotes;
int i = 0;
Scanner uI = new Scanner(System.in);
Scanner rF = new Scanner (new File(resultFile));
int userInput = uI.nextInt();
while (rF.hasNext()) {
partyVotes = rF.next();
votesArray[i]= partyVotes;
votesConverted[i] = Integer.parseInt(votesArray[i]);
i++;
if (userInput == 1) {
votesConverted[0] = ++votesConverted[0];
}
else if (userInput == 2) {
votesConverted[1] = votesConverted[1]++;
}
else if (userInput == 3) {
votesConverted[2] = votesConverted[2]++;
}
else if (userInput == 4) {
votesConverted[3] = votesConverted[3]++;
}
else if (userInput == 5) {
votesConverted[4] = votesConverted[5]++;
}
else if (userInput == 6) {
votesConverted[6] = votesConverted[6]++;
}
else if (userInput == 7) {
votesConverted[7] = votesConverted[7]++;
}
}
PrintWriter wF = new PrintWriter(resultFile);
while ( rF.hasNext()) {
wF.write(votesConverted[i]);
i++;
}
wF.flush();
wF.close();
} catch (IOException ex) {
Logger.getLogger(ProjectTesting.class.getName()).log(Level.SEVERE, null, ex);
}
return votesConverted;
}
Overwriting like this does not work - when the file is opened for writing, it is actually emptied. This does not happen when the file is opened for appending, but this does not seem like you want it. You need to write to a different file, then at the end remove the original file and move the new file to its location.
your problem lies with this loop:
while ( rF.hasNext()) {
wF.write(votesConverted[i]);
i++;
}
in previous loop rF.hasNext() already false.
...
while (rF.hasNext()) {
partyVotes = rF.next();
votesArray[i]= partyVotes;
....
so there was nothing to write. instead you could try:
i=0;
while ( i<7) {
wF.write(votesConverted[i]);
i++;
}

how do i complete an if statement to see if a valid direction was entered

This is a program I'm writing for school, its a 2D array adventure game. I need help with the blank if statement. It needed to know if a valid direction was entered. I'm just not sure where to go from here. I also want to make it so there is an amount of keys to access the locked rooms. I'm not very talented at coding so this may seem messy, but I'ts the best I have. How can i do this?
package hauntedhouse;
import java.util.Scanner;
public class HauntedHouse {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Scanner c = new Scanner(System.in);
String room[][] = new String[2][2]; // allocate 2 dimensional array of strings
//This section of code fills the 2D array with room names
room[0][0] = "Entry Hall";
//code to fill the rest of the rooms here
room[1][0] = "Dining Room";
room[2][0] = "Master Bedroom";
room[0][1] = "Storage [locked]";
room[1][1] = "Grand Hall";
room[2][1] = "Bedroom";
room[0][2] = "Garage [locked]";
room[1][2] = "Back Door";
room[2][2] = "";
int x = 0; // the coordinates of the room to start
int y = 0;
String di = ""; // variable used to hold the direction they entered
System.out.println("Theres a secret in this house,");
System.out.println("go into the locked rooms to find");
System.out.println("out what it is, have these two keys!");
do {
System.out.println("You are now in the " + room[x][y]);
//this next loop will repeat until a valid direction is entered
while (true) //this loop continues until the "break" statement is executed
{
System.out.println("Enter your direction");
if () //figure this out!!
{
break; //exits while loop
}
} // end while (true)
if (di.equals("W"))
{
y = y+1;
} else if (di.equals("A")) {
x = x-1;
} else if (di.equals("S")) {
y = y-1;
} else if (di.equals("D")) {
x = x+1;
} else {
//an illegal direction has been entered
}
}
while (x>=2); }// end when you make it to the locked room SOMEHOW
} // TODO code application logic here
To validate a 2D array you can simply use .equals() function
String room [][] = new String [2][2];
room[0][0] = "Entry Hall";
if(room[0][0].equals("Entry Hall")){
System.out.println("Inside Entry Hall");
}

Finding duplicates in an array of objects

The purpose of this project is to make a pokedex that adds and holds all the pokemon passed in by user input. When the user inputs a pokemon that is already stored in the pokedex the word "duplicate" is supposed to be printed to the console. The word duplicate is printed even though there are no actual duplicates within the object array. Here is my output from the console :
Welcome to your new PokeDex!
How many Pokemon are in your region?: 3
Your new Pokedex can hold 3 Pokemon. Let's start using it!
List Pokemon
Add Pokemon
Check a Pokemon's Stats
Sort Pokemon
Exit
What would you like to do? 2
Please enter the Pokemon's Species: red
Duplicate
Now here is all the code used that could possibly be making this error
import java.util.Scanner;
public class Project4 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Welcome to your new PokeDex!");
System.out.print("How many Pokemon are in your region?: ");
int size = input.nextInt();
Pokedex pokedex = new Pokedex(size);
System.out.println("\nYour new Pokedex can hold " + size + " Pokemon. Let's start using it!");
int choice = 0;
boolean done = false;
while (!done) {
System.out.println("\n1. List Pokemon\n2. Add Pokemon\n3. Check a Pokemon's Stats" + "\n4. Sort Pokemon\n5. Exit");
System.out.print("\nWhat would you like to do? ");
choice = input.nextInt();
switch (choice) {
case 1:
String[] pokemonList = pokedex.listPokemon();
if (pokemonList == null)
System.out.println("Empty");
else
for (int i = 0; i < pokemonList.length; i++) {
System.out.println((i + 1) + ". " + pokemonList[i]);
}
break;
case 2:
System.out.print("\nPlease enter the Pokemon's Species: ");
String species = input.next();
pokedex.addPokemon(species);
break;
}
}
}
}
In the following class I have the actual method that adds the pokemon and the constructor for Pokedex
public class Pokedex {
Pokemon[] pokedex;
String pokeArray[];
public Pokedex(int size) {
pokedex = new Pokemon[size];
pokeArray = new String[size];
}
public boolean addPokemon(String species) {
Pokemon stuff = new Pokemon(species);
for (int i = 0; i < pokedex.length; i++) {
if (pokedex[i] == null) {
pokedex[i] = stuff;
}
else if (i < pokedex.length && pokedex[i] != null) {
System.out.println("Max");
}
if (pokedex[i].getSpecies().equalsIgnoreCase(species)) {
System.out.print("Duplicate");
break;
}
}
return false;
}
}
Sorry for the mass amounts of code I just need help tracing where this unexpected result is coming from.
The reason it's doing that is because of this bit of code here:
public boolean addPokemon(String species)
{
Pokemon stuff = new Pokemon(species);
for (int i = 0; i < pokedex.length; i++)
{
if (pokedex[i] == null)
pokedex[i] = stuff;
else if (i < pokedex.length && pokedex[i] !=null)
System.out.println("Max");
if(pokedex[i].getSpecies().equalsIgnoreCase(species))
{
System.out.print("Duplicate");
break;
}
}
return false;
}
The problem is just a little bit of syntax missing. In your for loop, you check to see if
A) there are any empty spots in the array
B) if every element in the array up to the user inputted size is full
and C) if any element in the array matches the one we're trying to add.
The problem you're encountering is because your C is an if instead of an else if. Because A sees the index is null, it assigns the new Pokemon to the Pokedex. Then because C is an if instead of an else if, it runs after you assign the new Pokemon and sees the Pokemon we just added and says it's a duplicate. Changing it to an else if would fix this.
Also, since there was no break; in A, it would assign every element of the array to the first one entered, causing any further additions to call Max. I edited the code and this is what I had that worked for me:
public boolean addPokemon(String species)
{
Pokemon stuff = new Pokemon(species);
for (int i = 0; i < pokedex.length; i++)
{
if(pokedex[i] !=null && pokedex[i].getSpecies().equalsIgnoreCase(species))
{
System.out.println("Duplicate");
break;
}
else if (pokedex[i] == null)
{
pokedex[i] = stuff;
break;
}
else if(i + 1 == pokedex.length)
{
System.out.println("Max");
break;
}
}
return false;
}
Also, out of curiosity, why is the addPokemon() function a boolean? You return a value (albeit arbitrarily) and then never do anything with that value. You could just make it a void, have it return nothing, and it would work just as fine.

Java: EmptyQueueException being thrown before processing method

I'm working on a stock exchange program as a project and so far I've gotten about 98% of it done, the only issue I am having is when I am trying to sell more shares than a current day holds. So for example, I buy 20 shares for $30 each on day 1 and 40 shares for $20 each on day 2. I then input saying I want to sell 30 shares for $20 each. What the code is supposed to do is sell all the shares from day one, and then sell 10 shares from day 2. However, what I'm getting is an EmptyQueueException being thrown. I feel that my sellShares method might be having the error when it goes into the final else statement with the while loop. However I cannot wrap my mind around what might be the error. I've been staring the code down for quite some time and I can't seem to figure out a solution to this. Some assistance on this would greatly be appreciated. The following code is from my main class and the CircleArrayQueue class:
import java.util.Scanner;
import java.lang.Integer;
public class StockTran {
String command = "";
int gain = 0;
int totalPrice = 0; // totalPrice variable will keep of gain or loss of shares being sold
int shareTracker = 0; // shareTracker variable will keep track of shares being bought and sold
String[] stockParts = null;
CircleArrayQueue Q;
boolean quit = false;
public StockTran(String inputCommand) {
try {
Q = new CircleArrayQueue(32);
Scanner conReader = new Scanner(System.in);
this.command = inputCommand.toLowerCase();
this.stockParts = command.split("\\s"); // splits the input into three parts
while (quit == false) { // will loop until user says "q" to quit program
if (this.stockParts[0].equals("q")) { // ends transaction and terminates program
System.out.println("Share trading successfully terminated.");
quit = true;
System.exit(0); // exits the program
}
if (this.stockParts == null || this.stockParts.length > 3) {
System.out.println("That is an invalid input. Please try again.");
}
if (stockParts[0].equals("b")) { // checks to see if it is a buying of shares
int shares = Integer.parseInt(stockParts[1]); // stores share amount
int value = Integer.parseInt(stockParts[2]); // stores selling value
buyShares(shares, value); // calls buyShares method and adds share to queue
}
else if (stockParts[0].equals("s")) { // checks to see if it is a selling of shares
int shares = Integer.parseInt(stockParts[1]);
int value = Integer.parseInt(stockParts[2]);
sellShares(shares, value); // calls sellShares method
}
else if (stockParts[0].equals("c")) { // checks to see if it is capital gain
gain = capitalGain(); // calls capitalGain and calculates net gain
System.out.println("Capital gain is " + gain);
}
else {
System.out.println("That is an invalid input. Please try again."); // any other input is invalid
}
System.out.println("Enter your next command, or press 'q' to quit: ");
command = conReader.nextLine().toLowerCase();
stockParts = command.split("\\s");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void buyShares(int shareAmount, int sharePrice) { // takes in share total and values for each share
shareTracker = shareTracker + shareAmount; // adds to amount of shares bought
Node temp = new Node(shareAmount, sharePrice); // stores values into node
try {
Q.enqueue(temp); // enqueues the node into the CircularQueue
} catch (FullQueueException e) {
e.printStackTrace();
}
}
public void sellShares(int shareAmount, int sharePrice) throws Exception {
Node temp = new Node(); // stores values into node
int tempShare = 0;
try {
temp = Q.front(); // gets the first node from CircleArrayQueue and stores it in temporary node
int share = temp.getShare();
int price = temp.getPrice();
System.out.println(Q.size());
if (shareAmount > shareTracker) { // throws exception if trying to sell more shares than purchased
throw new Exception ("You don't have that many shares to sell.");
}
else if (share > shareAmount) { // checks to see if first node has a larger share amount or less
temp.setShare(share - shareAmount); // will decrease amount sold from the first days share
shareTracker = shareTracker - shareAmount;
totalPrice = shareAmount * (sharePrice - price) + totalPrice; // calculates total profit or loss
}
else if (share == shareAmount) {
Q.dequeue();
shareTracker = shareTracker - shareAmount; // updates shareTracker to show how many shares are remaining
totalPrice = shareAmount * (sharePrice - price) + totalPrice;
}
else {
while (shareAmount != tempShare) { // will loop until it sells total share amount user wanted
Node temp2 = Q.dequeue(); // removes another node from CircleArrayQueue
int newShare = temp2.getShare();
int newPrice = temp2.getPrice();
tempShare = tempShare + newShare; // adds the shares together to check if while loop condition still holds
totalPrice = shareAmount * (sharePrice - newPrice) + totalPrice;
sellShares(shareAmount - tempShare, sharePrice); // recursively calls sellShares on new amount of shares
}
}
} catch (EmptyQueueException e) {
e.printStackTrace();
}
}
public int capitalGain() { // returns the total net gain or loss in share trading
return totalPrice;
}
public static void main(String[] args) {
String inputCommand = "";
Scanner mainReader = new Scanner(System.in);
System.out.println("Enter 'b' to purchase share, 's' to sell share, 'c' for capital gain, or 'q' to quit: ");
inputCommand = mainReader.nextLine();
StockTran tran = new StockTran(inputCommand);
}
}
public class CircleArrayQueue implements Queue {
protected Node Q[]; // initializes an empty array for any element type
private int MAX_CAP = 0; // initializes the value for the maximum array capacity
private int f, r;
public CircleArrayQueue(int maxCap) {
MAX_CAP = maxCap;
Q = new Node[MAX_CAP]; // sets Q to be a specific maximum size specified
f = 0; // sets front value to be 0
r = 0; // sets rear value to be 0;
}
public int size() {
return (MAX_CAP - f + r) % MAX_CAP; // returns the size of the CircularArrayQueue
}
public boolean isEmpty() { // if front and rear are of equal value, Queue is empty
return f == r;
}
public Node front() throws EmptyQueueException { // method to get the front value of the CircularArrayQueue
if (isEmpty()) throw new EmptyQueueException("Queue is empty.");
return Q[f]; // returns object at front of CircularArrayQueue
}
public Node dequeue() throws EmptyQueueException { // method to remove from the front of the CircularArrayQueue
if (isEmpty()) throw new EmptyQueueException("Queue is empty.");
Node temp = Q[f]; // stores front object in local variable
Q[f] = null; // sets the value to be null in the array
f = (f + 1) % MAX_CAP; // sets the new front value to be this
return temp; // returns the object that was originally in the front
}
public void enqueue(Node element) throws FullQueueException { // method to add to the end of the CircualarArrayQueue
if (size() == MAX_CAP - 1) throw new FullQueueException("Queue has reached maximum capacity.");
Q[r] = element; // stores the new element at the rear of array
r = (r + 1) % MAX_CAP; // sets the new rear value to be the location after element insertion
}
}
Your sellShares routine calls front() without checking to see if there is anything in the queue. If the queue is empty(), you get your exception.

Categories

Resources