Looking up a string in a file, then copying lines after it - java

This is my first time posting to this site, so if I get any formatting wrong, please be easy on me Lol
I'm writing a Java program that needs to look up a part number from an inventory, and then print the part number along with the data following it. The code is only printing out the information at the top of the file, and then repeating my else statement 5 times.
Here is the code:
package inventory;
import java.util.Scanner;
import java.io.*;
public class inventory
{
public static void main(String[] args) throws IOException
{
Scanner keyboard = new Scanner(System.in);
// File Information
String parts;
File inventoryFile;
FileWriter inventoryFW;
PrintWriter inventoryPW;
Scanner inventorySC;
//User Information
String userChoice;
// Part Information
String partID, partFileID, partFileDesc, partFileLoc, partDesc, partLoc;
double partFilePrice, partPrice;
int partFileQuan, partQuan;
userChoice = ("A");
// Loop
if(userChoice.equalsIgnoreCase("Q"))
System.exit(0);
else
while(!userChoice.equalsIgnoreCase("Q"))
{
// Get Employee Decision
System.out.println("Please choose a letter: \n"
+ "L - Look Up Part \n"
+ "A - Add to Inventory File \n"
+ "E - Erase From Inventory File \n"
+ "G - Generate a Sales Slip \n"
+ "I - Add Quantity to Inventory File \n"
+ "D - Display Inventory \n"
+ "Q - Quit \n"
+ "Selection: ");
userChoice = keyboard.nextLine();
// Process User Choice
if(userChoice.equalsIgnoreCase("L"))
{ // Choice L
// Look Up Part
System.out.println("Enter Part I.D. Number: ");
partID = keyboard.nextLine();
// Do until partID is equal to partFileID
parts = "inventoryFile.txt";
inventoryFile = new File(parts);
inventorySC = new Scanner(inventoryFile);
partFileID = "0";
partFileDesc = "0";
partFilePrice = 0;
partFileLoc = "0";
partFileQuan = 0;
while(inventorySC.hasNextLine())
{
String lineFromFile = inventorySC.nextLine();
if(lineFromFile.contains(partID))
{
partFileDesc = inventorySC.nextLine();
partFilePrice = inventorySC.nextDouble();
inventorySC.nextLine();
partFileLoc = inventorySC.nextLine();
partFileQuan = inventorySC.nextInt();
System.out.println("Part I.D. Number: " + partFileID + "\n");
System.out.println("Part Description: " + partFileDesc + "\n"
+ "Part Price: " + partFilePrice + "\n"
+ "Part Location: " + partFileLoc + "\n"
+ "Part Quantity: " + partFileQuan);
}
else
System.out.println("Sorry, this part cannot be found");
}
}
}
}
}
And here is the datafile I am trying to pull from:
1234567
Clutch
45.68
Warehouse B
8
1234
Brake
66.78
Warehouse A
4
For example, if the user entered part number "1234" the program should search for that part number in the file, and then display:
1234
Brake
66.78
Warehouse A
4
Sorry about any poor code formatting, I have been fighting with this for a while now.
Any help would be greatly appreciated.

There are a few issues.
The contains will have multiple matches.
You will print "not found every line" you don't find.
You are not breaking out of the loop.
boolean found = false;
while(inventorySC.hasNextLine()){
String lineFromFile = inventorySC.nextLine();
if(lineFromFile.equals(partID)) {
partFileDesc = inventorySC.nextLine();
partFilePrice = inventorySC.nextLine();
partFileLoc = inventorySC.nextLine();
partFileQuan = inventorySC.nextLine();
System.out.println("Part I.D. Number: " + partFileID + "\n");
System.out.println("Part Description: " + partFileDesc + "\n"
+ "Part Price: " + partFilePrice + "\n"
+ "Part Location: " + partFileLoc + "\n"
+ "Part Quantity: " + partFileQuan);
found = true;
break;
}
}
if(!found)
System.out.println("Sorry, this part cannot be found");

Your issue is that you are only skipping to the next line if the part list doesn't contain your part value. You actually want to skip down 5 lines if the part is not on the 'next line'.
In your "else" statement, you'll just want to call the inventorySC.nextLine(); 4 more times to get to the next place in the file you actually want to check for a part number.
If you want the 'not found' condition to reflect more effectively that the part number actually wasn't found at all, you'll want to move that message to after it could have scanned the whole file. Set a boolean with a name like 'found' to false before the file scan. If you enter your 'contains' condition because there is a part number in the file that contains your input, set the 'found' equal to true.
At the end if the 'found' is still 'false', you can output the 'not found' message.

As MadProgrammer commented above, you'll need to use 'equals' instead of 'contains'- this is why you match on the first entry. When you find a match and output it, you need to exit the while loop using a 'break' - otherwise you output the else value for each line left over (as is happening to you). But there is one other problem in that you may need to read an entire record - not just the first line of the record - when there is no match so you don't get screwed up when an inventory item has a quantity of 1234 when searching for part number 1234.

Related

What is causing this StringIndexOutOfBoundsException?

I am writing a program that takes names from a text file and prints the initials of the names.
The names are in "Last, First M." format, with each name being on a separate line.
Because the text file contains the names of everybody in my class I am not including it in this post.
The error I am receiving is:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 1
at java.lang.String.substring(String.java:1963)
at AS01a.main(AS01a.java:28)
/* My Name
** February 6, 2019
** Class Name
** Assignment Name
** Collaborations: None
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class AS01a{
public static void main(String args[]) throws FileNotFoundException{
String DEFAULT_FILE_NAME = "AS01.txt";
String fileName;
if (args.length != 0)
{ fileName = args[0]; }
else
{ fileName = DEFAULT_FILE_NAME; }
Scanner input = new Scanner(new File(fileName));
String fullName, first, middle, last, initials;
while(input.hasNextLine()){
fullName = input.nextLine();
//Dividing the full name into individual initials
first = fullName.substring(fullName.indexOf(" ")+1, fullName.indexOf(" ")+2);
middle = fullName.substring(fullName.lastIndexOf(" ")+1, fullName.lastIndexOf(" ")+2);
last = fullName.substring(0,1);
//Testing to see if the full name contains a middle name
if(fullName.indexOf(" ") == fullName.lastIndexOf(" ")){
initials = first + ". " + last + ".";
}
else{
initials = first + ". " + middle + ". " + last + ".";
}
if(input.hasNextLine()){
System.out.println(fullName + " yields " + initials);
}
}
}
}
My results come out as expected, the only problem is the errors previously mentioned.
Your StringIndexOutOfBoundsException may be due to the data your receiving as we do not know the "Full Name". If someone doesn't have a first/middle/last name you will get the exception because you are not checking for this before the first middle and last are initialized. Move your initializers into your if statements and see if that helps.
Try this.
while(input.hasNextLine()){
fullName = input.nextLine();
if(fullName.isEmpty())
fullName = input.nextLine();
//Testing to see if the full name contains a middle name
if(fullName.indexOf(" ") == fullName.lastIndexOf(" ")){
first = fullName.substring(fullName.indexOf(" ")+1, fullName.indexOf(" ")+2);
last = fullName.substring(0,1);
initials = first + ". " + last + ".";
}
else{
first = fullName.substring(fullName.indexOf(" ")+1, fullName.indexOf(" ")+2);
middle = fullName.substring(fullName.lastIndexOf(" ")+1, fullName.lastIndexOf(" ")+2);
last = fullName.substring(0,1);
initials = first + ". " + middle + ". " + last + ".";
}
if(input.hasNextLine()){
System.out.println(fullName + " yields " + initials);
}
}
fullName seems to be an empty string, you can easily check this with debugger. And the reason why it's empty is that you probably have a blank line in your file. If it so, you should add empty check like if (fullName.isEmpty()) continue; to iterate over the remaining lines.

Negation not working with .equalsIgnoreCase()

I am trying to run a do...while while a condition is not met but for some reason my code keeps looping every time regardless of the value of the condition. I've checked my debugger and the value of the variable is correct and the conditions within the loop are met according to similar logic. For some reason the ! doesn't work. Here is my code
do
{
if(isRaceHorse.equalsIgnoreCase("Y"))
{
System.out.print("Please enter the number of races your horse has been in >> ");
numRaces = input.nextInt();
input.nextLine();
System.out.println("Your horse is named " + name + " it is a " + color + " horse born in " + birthYear + " and it has been in " + numRaces + " races.");
}
else if(isRaceHorse.equalsIgnoreCase("N"))
{
System.out.println("Your horse is named " + name + " it is a " + color + " horse born in " + birthYear + ".");
}
else
{
System.out.println("Please use Y for yes and N for no.");
System.out.print("Is your horse a race horse? Enter Y for yes and N for no >> ");
isRaceHorse = input.nextLine();
}
}while(!(isRaceHorse.equalsIgnoreCase("y")) || !(isRaceHorse.equalsIgnoreCase("n")));
Anybody have any ideas as to why this is not giving me what I want?
!(isRaceHorse.equalsIgnoreCase("y")) || !(isRaceHorse.equalsIgnoreCase("n"))
In English, this means the loop will continue as long as isRaceHorse is not equal to "y" or isRaceHorse is not equal to "n". Since it cannot be equal to both "y" and "n" at the same time, I'm pretty certain you want to use && instead:
!isRaceHorse.equalsIgnoreCase("y") && !isRaceHorse.equalsIgnoreCase("n")

Adding result for each attempt in Java

I'm completely new to Java and need some help. I'm trying to add results for each attempt in a competition but I got stuck. So far I have the first part that works but without any results added and then I tried to find a way to add results while counting allowed attempts (which are different for each discipline) but without success. What would be the best way both to count attempts and to add results for each attempt?`
private void addResult() {
System.out.print("Enter the number of the participant you would like to add results for: ");
int number = scan.nextInt();
scan.nextLine();
while (number < 0) {
System.out.println("Error: must be greater than or equal to zero!");
number = scan.nextInt();
scan.nextLine();
}
System.out.print("Enter the name of the event you would like to see results for: ");
String event = scan.nextLine();
Participant p = findParticipantByNumber(number);
Event e = findEventByName(event);
if (p == null) {
System.out.println("No participant with number " + number + " found!");
} else if (e == null) {
System.out.println("No event called " + event + " found!");
} else {
System.out.print("Results for " + p.getFirstName() + " " + p.getLastName() +
" from " + p.getTeam() +
" in " + e.getEventName() + ":" + " " + p.getResult() );
scan.nextLine();
Result r = new Result(e, p);
p.addResult(r);
}
}
I would store a HashMap of attempts as an instance variable in the Participant class, where the keys are Strings representing the events and the value corresponding to each key is the number of attempts so far for that event. You could call this map attemptsByEvent and have getter and setter methods for it in Participant. If you need, you can take a look at this page from TutorialsPoint about how to create and populate maps, and what they are.
You should also make a map that is accessible from within addResult() which has Strings representing the events as keys and the maximum allowed attempt for that event as the values. You could call this map attemptMaximums.
Then, you can modify your final block of code to check the number of attempts so far before adding the result. You should also increment the value in the Participant's map if you do add results for an attempt.
else {
System.out.print("Results for " + p.getFirstName() + " " + p.getLastName() +
" from " + p.getTeam() +
" in " + e.getEventName() + ":" + " " + p.getResult() );
scan.nextLine();
Result r = new Result(e, p);
int attempts = p.getAttemptsByEvent().get(e);
if(attempts < attemptMaximums.get(e)){
p.addResult(r);
p.getAttemptsByEvent().put(e, attempts+1);
}
}

Searching a string arrays with an array

I am attempting to search a user input array of text with another user input array of search terms using nested loops and then output the search terms with the number of times they appear in the text along with the percentage of total text. I think I am on the right track and my issue is that the counter is not resetting each time the if statement is true. I am very new to programming -- so I could be completely wrong. Below is the entire program. If anyone could take a look and give me a hand at figuring out what my issue is I would be eternally grateful.
public class termFrequency {
public static void main(String[] args) {
String searchTextPeriod, searchTextComma, searchTextApostrophe, searchTextColon, searchTextExclamation,
searchTextQuestion, searchText, searchTerm;
int counter=0, total, searchIndex=0, termIndex=0;
double percentage=0.0;
String [] searchArray, termArray;
searchText = JOptionPane.showInputDialog("Enter a sentence that is at least 20 words long");
//removes some common punctuation from the searchable text
searchTextPeriod = searchText.replace(".", "");
searchTextComma = searchTextPeriod.replace(",", "");
searchTextApostrophe = searchTextComma.replace("'", " ");
searchTextColon = searchTextApostrophe.replace(":", " ");
searchTextExclamation = searchTextColon.replace("!", "");
searchTextQuestion = searchTextExclamation.replace("?", "");
searchArray = searchTextQuestion.split(" "); //splits the sentence and and puts it into an array
total=searchArray.length;
System.out.println("There are " +total +" words in your sentence");
searchTerm = JOptionPane.showInputDialog("Enter your search terms here seperated by a space");
termArray = searchTerm.split(" ");
DecimalFormat two = new DecimalFormat("#0.00");
boolean found = false;
for (termIndex=0; termIndex<termArray.length; termIndex++)
{
for (searchIndex=0; searchIndex<searchArray.length; searchIndex++)
if (termArray[termIndex].equalsIgnoreCase(searchArray[searchIndex]))
{
counter++;
found = true;
percentage= ((double) counter/(double)total) * 100;
}
if (found)
System.out.println("Search word " + "\'" + termArray[termIndex] + "\' is found " +counter +" times. That is "+ two.format(percentage)+"% of the statement." );
else
System.out.println("Search word " + "\'" + termArray[termIndex] + "\' is not found in the statement.");
}
}
}
}
You have to move the if/else on "found" from the inner loop to the end of the first loop.
You also need to reset the boolean and the counter in the first loop, like that you start the analysis of each new word in termArray with initial values.
for (termIndex=0; termIndex<termArray.length; termIndex++)
{
counter=0; //Reset the counter for each word in termArray
found=false; //Reset the "found" flag for each word in termArray
for (searchIndex=0; searchIndex<searchArray.length; searchIndex++)
if (termArray[termIndex].equalsIgnoreCase(searchArray[searchIndex]))
{
counter++;
percentage= ((double) counter/(double)total) * 100;
found=true
System.out.println("Search word " + "\'" + termArray[termIndex] + "\' is found " +counter +" times. That is "+ two.format(percentage)+"% of the statement." );
}
}
if (found)
System.out.println("Search word " + "\'" + termArray[termIndex] + "\' is found " +counter +" times. That is "+ two.format(percentage)+"% of the statement." );
else
System.out.println("Search word " + "\'" + termArray[termIndex] + "\' is not found in the statement.");
}
By the way you don't really need the "found" var, now if counter == 0 you know that the word has not been found in searchArray.
Move found = false inside of the first loop. that way it will be reset to false with each iteration. Right now if it is ever changed to true it stays true for the rest of the process.

Null Pointer exception with array of objects

The following program I'm creating will allow the user will input values to create an array of videos. Each video contains several data fields (number, title, publisher, duration & date). The program is primarily controlled through a switch menu. However after creating the array, choosing another option, such as Show videos will throw a Null Pointer Exception. These exceptions usually occur when you haven't assigned values to the array, but that should have been already done in the first option, createLibrary(). Other functions in Search videos and Change videos have the same issue and it occurs every time a get method is used.
Anyone with a reasonable practical answer will greatly help.
Here is a segment of my code:
import java.util.*;
public class EnterLibrary
{
public final int MAX_ITEMS = 5;
public Library[] videos;
public int size = 0;
public EnterLibrary()
{
videos = new Library[MAX_ITEMS];
java.util.Scanner scannerObject =new java.util.Scanner(System.in);
LibraryMenu Menu = new LibraryMenu();
Menu.displayMenu();
switch (scannerObject.nextInt())
{
case 1:
System.out.println ("1 - Add Videos");
if (size < MAX_ITEMS) {
Library video = createLibrary();
videos[size++] = video;
}
new EnterLibrary();
break;
case 2:
System.out.println ("2 - Show Videos");
printVidLibrary(videos);
new EnterLibrary();
break;
case 3:
System.out.println ("3 - Search Videos");
searchLibrary(videos);
new EnterLibrary();
break;
case 4:
System.out.println ("4 - Change Videos");
changeLibrary(videos);
break;
case 5:
System.out.println ("5 - Delete Videos");
deleteVideo(videos);
new EnterLibrary();
break;
default:
System.out.println ("Unrecognized option - please select options 1-5 ");
break;
}
}
public Library createLibrary()
{
Library video = new Library();
java.util.Scanner scannerObject =new java.util.Scanner(System.in);
for (int i = 0; i < videos.length; i++)
{
//User enters values into set methods within the Library class
System.out.print("Enter video number: " + (i+1) + "\n");
String number = scannerObject.nextLine();
System.out.print("Enter video title: " + (i+1) + "\n");
String title = scannerObject.nextLine();
System.out.print("Enter video publisher: " + (i+1) + "\n");
String publisher = scannerObject.nextLine();
System.out.print("Enter video duration: " + (i+1) + "\n");
String duration = scannerObject.nextLine();
System.out.print("Enter video date: " + (i+1) + "\n");
String date= scannerObject.nextLine();
System.out.print("VIDEO " + (i+1) + " ENTRY ADDED " + "\n \n");
//Initialize arrays
videos[i] = new Library ();
videos[i].setVideo( number, title, publisher, duration, date );
}
return video;
}
public void printVidLibrary( Library[] videos)
{
//Get methods to print results
System.out.print("\n***VIDEO CATALOGUE*** \n");
for (int i = 0; i < videos.length; i++)
{
System.out.print("Video number " + (i+1) + ": \n" + videos[i].getNumber() + "\n ");
System.out.print("Video title " + (i+1) + ": \n" + videos[i].getTitle() + "\n ");
System.out.print("Video publisher " + (i+1) + ": \n" + videos[i].getPublisher() + "\n ");
System.out.print("Video duration " + (i+1) + ": \n" + videos[i].getDuration() + "\n ");
System.out.print("Video date " + (i+1) + ": \n" + videos[i].getDate() + "\n ");
}
}
//Code for other functions not displayed here
public static void main(String[] args)
{
new EnterLibrary();
}
}
The exception error:
Exception in thread "main" java.lang.NullPointerException
at EnterLibrary.printVidLibrary(EnterLibrary.java:80)
at EnterLibrary.<init>(EnterLibrary.java:26)
at EnterLibrary.<init>(EnterLibrary.java:22)
at EnterLibrary.<init>(EnterLibrary.java:22)
at EnterLibrary.<init>(EnterLibrary.java:22)
at EnterLibrary.<init>(EnterLibrary.java:22)
at EnterLibrary.main(EnterLibrary.java:202)
There are at least two serious errors in your code:
There's a stack overflow waiting to happen: you're calling EnterLibrary() inside EnterLibrary(), that will produce an infinite recursion
Although you have instantiated the videos array, you haven't initialized it yet ant it's full of null objects; make sure to call createLibrary() at the beginning of EnterLibrary's constructor, before calling printVidLibrary(), which iterates over all the contents of videos and assumes that it's entirely initialized
videos = new Library[MAX_ITEMS]; doesn't initialize the Library items, so each of them is null. Try this
videos = new Library[MAX_ITEMS];
for(int x = 0; x < MAX_ITEMS; x++)
videos[x] = new Library();
You can also check in printVidLibrary if the videos argument is null to avoid the exception.
You got it wrong, you have a twisted mind !
If I understand you want to go over your switch again (after adding a video for example) : you should use a loop around your switch, not create a new, hence video-virgin "EnterLibrary" object.
Some code :
while (i = scannerObject.nextInt()) {
switch(i) {
case 1:
System.out.println ("1 - Add Videos");
if (size < MAX_ITEMS) {
Library video = createLibrary();
videos[size++] = video;
}
break;
case 2:
System.out.println ("2 - Show Videos");
printVidLibrary(videos);
break;
case 3:
System.out.println ("3 - Search Videos");
searchLibrary(videos);
break;
case 4:
System.out.println ("4 - Change Videos");
changeLibrary(videos);
break;
case 5:
System.out.println ("5 - Delete Videos");
deleteVideo(videos);
break;
default:
System.out.println ("Unrecognized option - please select options 1-5 ");
break;
}
}
On a side note, I haven't given it much thought and I'm kind of tired right now, but this doesn't feel like an overall good use of OOP, I might be wrong but I can't get a catch of what an "EnterLibrary" object would be, for starters.
And yep, get familiar with the debugger as suggested by bmargulies, he's your best friend I guess
edit: I edited the code, forgot to remove your recursive call

Categories

Resources