I have code for a Binary Search Tree that will accept user input such as
insert 3 and it will call the insert function on 3. When I try to call a function that requires no arguments like my traverse function it will give an out of bounds error unless the user input is traverse 0 I want to call it by using just traverse, here is my code:
public static void main(String[] args)
{
int quit = 0;
BinarySearchTree bst = new BinarySearchTree();
Scanner in = new Scanner(System.in);
//Accept user input and call funtions
while(quit != 1)
{
System.out.print("\nEnter the instructions to perform (type quit when done):");
String input = in.nextLine();
String[] instruction = input.split(" ");
String function = instruction[0].toLowerCase();
String parameter = instruction[1];
//What to do with user input
if(function.equals("insert"))// for insert
{
int key = Integer.parseInt(parameter);
bst.insert(key);
System.out.println(parameter + " was inserted successfully!");
}
else if(function.equals("delete"))// for delete
{
int key = Integer.parseInt(parameter);
if(bst.delete(key) == true)
System.out.println(parameter + " was deleted successfully!");
else
System.out.println(parameter + " does not exist.");
bst.delete(key);
}
else if(function.equals("search"))// for search
{
int key = Integer.parseInt(parameter);
if(bst.search(key) == true)
System.out.println(parameter + " was found!");
else
System.out.println(parameter + " not found.");
bst.search(key);
}
else if(function.equals("traverse"))// for traverse
{
bst.traverse(BinarySearchTree.root);
}
}
}//end main
Your problem occurs when you try to assign instruction[1] to parameter. If there is no space character in your input string then the split method will return an array of length 1 and you will get an out of range exception when you try to access the second element.
The solution is:
if (input.equals("traverse")) {
...
} else {
String[] instructions = input.split(" ");
assert instruction.length == 2;
String function = instruction[0].toLowerCase();
int key = Integer.parseInt(instruction[1]);
...
}
There are better ways to model commands. Ideally you'd use a command pattern rather than if statements. But if you don't want to go to that trouble you should at least consider using patterns to make the parsing more robust.
Pattern commandPattern = Pattern.compile("(traverse|search|delete|insert) *(\\d*)");
Matcher matcher = commandPattern.match(in.nextLine());
if (!matcher.matches()) {
System.out.println("Illegal command. Try again.");
matcher = commandPattern.match(in.nextLine());
}
switch (matcher.group(1).toLowerCase()) {
case "traverse":
bst.traverse(root);
break;
case "delete":
int deleteKey = Integer.parseInt(matcher.group(2));
if (bst.delete(deleteKey)) {
...
Related
I refactored a working project to practice creating callable methods when I broke the app. This app includes a simple String array with a method that matches user input with the array and prints the element name and index.
If I don't include a break at the end of the if else statements the app can match valid input but runs both if and else statements. It actually prints the if statement in the order of the index and prints the else output the number of times as the length of the array. In the attached pic, the input was index 0. if statement output In the pic index 0 was matched and printed with the number of else outputs as in the array. It seems the else statement is reading the array length.
If I add the break, the app only recognizes index 0 and will run the if statement as expected, but also runs the else statement. But only prints out if else output once. I hope this is clear. Trainers have simply said it is impossible to for a for loop to print of which I understand, yet I'm having a different experience.
Here is the code:
import java.util.Scanner;
public class Main {
static Scanner scan = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("What are you looking for? ");
//String product = scan.nextLine();
String[] aisles = {"apples", "bananas", "candy", "chocolate", "coffee", "tea"};
searchProduct(aisles);
}
public static void searchProduct(String[] aisles) {
String product = scan.nextLine();
for (int i = 0; i < aisles.length; i++) {
if (product.equals(aisles[i])) {
System.out.println("We have " + aisles[i] + " in aisle " + i);
} else {
System.out.println("Sorry we do not have that product");
}
}
}
}
I expect to match valid user input and run the if statement or run the else statement.
Here is a suggestion.
Change your method to return an int (aisle if the product exists or -1 if not).
Don't do any I/O in the method. Just pass the target of the search as an argument.
String[] aisles = {
"apples","bananas","candy","chocolate","coffee","tea"
};
System.out.println("What are you looking for? ");
String product = scan.nextLine();
int aisle = searchProduct(product, aisles);
if (aisle >= 0) {
System.out.println("We have " + product + " in aisle " + aisle);
} else {
System.out.println("Sorry we do not have that product");
}
public static int searchProduct(String product, String[] aisles) {
for (int aisle = 0; aisle < aisles.length; aisle++) {
if (product.equals(aisles[aisle])) {
return aisle;
}
}
return -1;
}
So I am completely new to java, and I want to create a code to accept string inputs from a user, and store it into an array. After this in the next statement, I will type a value into the terminal, and I want the code to compare my string input to one of the strings in the array and print available on the terminal when the string is available and vice versa. The first part of my code was right (hopefully) but I had a problem in comparing the strings. I feel it doesn't check the strings with my input in the code. Here is my code, Could anyone please help me with this? Thank you so much.
import java.util.Scanner;
class Course {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String a[] = new String[20] //assuming max 20 strings
System.out.println("Enter no. of courses");
int no_of_courses = sc.nextInt(); // number of strings
if (no_of_courses <= 0)
System.out.println("Invalid Range");
else {
System.out.println("Enter course names:");
for (int i = 0; i < no_of_courses; i++) {
a[i] = sc.next(); //accepting string inputs
}
System.out.println("Enter the course to be searched:");
String search = sc.next() //entering a string to search
for (int i = 0; i < no_of_courses; i++) {
if (a[i].equals(search)) //I feel the problem is here
System.out.println(search + "course is available");
break;
else
System.out.println(search + "course is not available");
}
}
}
}
I expect the output to be
<string> course is available
when my string matches a string in the array and
<string> course is not available
when my entered string doesn't match a string in the array
But there is no output :(
I have modified your code and commented on line where it need to be explained. check it carefully.
import java.util.Scanner;
class Course {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter no. of courses");
int no_of_courses = sc.nextInt(); // number of strings
String a[] = new String[no_of_courses]; // do not assume when you have proper data.
if (no_of_courses <= 0)
System.out.println("Invalid Range");
else {
System.out.println("Enter course names:");
for (int i = 0; i < no_of_courses; i++) {
a[i] = sc.next(); // accepting string inputs
}
System.out.println("Enter the course to be searched:");
String search = sc.next(); // entering a string to search
boolean flag = false;
for (int i = 0; i < no_of_courses; i++) {
if (a[i].equals(search)) // I feel the problem is here
{
flag = true;//do not print here. just decide whether course is available or not
break;
}
}
//at the end of for loop check your flag and print accordingly.
if(flag) {
System.out.println(search + "course is available");
}else {
System.out.println(search + "course is not available");
}
}
}
}
class Course {
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String a[] = new String[20] ; //assuming max 20 strings
System.out.println("Enter no. of courses");
int no_of_courses = sc.nextInt(); // number of strings
if(no_of_courses <= 0)
System.out.println("Invalid Range");
else
{
System.out.println("Enter course names:");
for(int i=0 ; i < no_of_courses ; i++)
{
a[i] = sc.next(); //accepting string inputs
}
System.out.println("Enter the course to be searched:");
String search = sc.next() ; //entering a string to search
boolean found = false;
for(int i = 0 ; i < no_of_courses ; i++)
{
if(a[i].equalsIgnoreCase(search)) //I feel the problem is here
{
**found = true;**
break;
}
}
if(found) {
System.out.println(search+ "course is available");
}else {
System.out.println(search+ "course is not available");
}
}
}
}
This is really a good effort and you almost got it. So just a couple of things
Since you are inputting the number of courses, just use that value to initialise your array (it's just a good practice to get into to try not initialise things before you actually need them).
If you are doing String comparisons and case sensitivity does not matter, rather use .equalsIgnoreCase(String)
To solve your problem, you just needed a boolean variable to indicate whether or not you had found a match. Initially this would be FALSE (no match found) and you would run through your array until a match is found. Once found this would be flagged TRUE and you'd breakout your loop (which you correctly did).
Only once out your loop, you'd print out whether you found a match.
Have a look:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter no. of courses");
int no_of_courses = sc.nextInt(); // number of strings
if (no_of_courses <= 0) {
System.out.println("Invalid Range");
} else {
String a[] = new String[no_of_courses];
System.out.println("Enter course names:");
for (int i = 0; i < a.length; i++) {
a[i] = sc.next(); //accepting string inputs
}
System.out.println("Enter the course to be searched:");
String search = sc.next(); //entering a string to search
boolean courseFound = Boolean.FALSE;
for(int i = 0; i < a.length; i++) {
if (a[i].equalsIgnoreCase(search)) {
courseFound = Boolean.TRUE;
break;
}
}
if(courseFound) {
System.out.println(search + "course is available");
} else {
System.out.println(search + " course is not available");
}
}
}
Oh, just for interest (and when you start working with some more advanced constructs), you could always just use stream, which was introduced in Java 8. It'll trim down 12 lines to 5...
if(Arrays.stream(a).anyMatch(i -> i.equalsIgnoreCase(search))) {
System.out.println(search + " course is available");
} else {
System.out.println(search + " course is not available");
}
I noticed a few things - Does your program run to the end? When i copy/pasted into my ide i noticed a few missing semi-colons, and like Yhlas said, your last if/else statement syntax is incorrect.
And this doesn't have anything to do with whether or not your program will give you the right answer, but your last loop will print over and over again because it will check each element in a, and each time it loops and finds a mismatch it will print something out
System.out.println("How many items will be supplied by this supplier?");
SPItemAmount = SupplierEntry.nextInt();
System.out.println("Ok, your item ID with this supplier is:");
for(int i = 1;i <= SPItemAmount; i++) {
System.out.println("I" + i);
}
public String getSupplierDetails() {
return "SP" + AddSupplier.getSupplierID() + SPName+
}
My ItemID will be generated based on the user input. When comes to the getSupplierDetails, how am i going to print all the ItemID with one variable? Or there is another way? Appreciate for help.
Although your question is rather straightforward with the problem at hand, when you ask a question you should supply as much pertinent code as possible. This will remove a lot of guessing and assumptions. At least provide code that will compile.
One way you can do is to fill (append to) a string variable for every iteration of your for loop (see the getSupplierID() method below). Although not mandatory, allow your methods to accept parameters so that variables don't need to be class global.
public static void main(String args[]) {
Scanner supplierEntry = new Scanner(System.in);
// Get supplier name...
String sPName = "";
// Continue to ask for Supplier Name if validation fails.
while(sPName.equals("")) {
System.out.println("What is the Supplier's Name (c to cancel):");
sPName = supplierEntry.nextLine().trim();
// Privide a Quit option.
if (sPName.toLowerCase().equals("c")) {
System.out.println("User Quit!");
System.exit(0); // Close the application.
}
// Supplier Name validation...
if (sPName.equals("")) {
System.err.println("Invalid Supplier Name Provided! Try again.\n");
}
}
// Get number of items supplied by supplier...
int sPItemAmount = 0;
// Continue to ask for Items Count if validation fails.
while (sPItemAmount == 0) {
System.out.println("How many items will be supplied by " + sPName + "?");
// Trap exception for Numerical validation...
try {
sPItemAmount = supplierEntry.nextInt();
} catch(InputMismatchException ex) {
System.err.println("Invalid Items Amount Provided! " +
"Whole Numbers Only! Try again.\n");
}
supplierEntry.nextLine(); // Clear scanner buffer
}
// Generate the Supplier ID
String supplierID = getSupplierID(sPItemAmount);
// Get Supplier Details.
String supplierDetails = getSupplierDetails(sPName, supplierID);
// Display information...
System.out.println("Ok, your item ID with " + sPName + " is: " + supplierID);
System.out.println("Supplier Details Are: " + supplierDetails);
// Close the Scanner object.
supplierEntry.close();
}
public static String getSupplierID(int itemAmount) {
String itemID = "";
for(int i = 1; i <= itemAmount; i++) {
itemID+= "I" + i;
// which is the same as:
// itemID = itemID + "I" + i;
}
return itemID;
}
public static String getSupplierDetails(String supplName, String itemID) {
// Replace any whitespaces in Supplier Name with
// the underscore character ( _ ). You can remove
// the .replace() method if you don't want this.
return "SP" + itemID + supplName.replace(" ", "_");
}
I am writing a program that takes a document created by one program by PrinterWriter and then hashes the lines in that document to an array in the new program. The hash is done by using the ASCII code for the letter and adding them up. I am able to get the correct hash for each line and save it in the hash table. By the way, it is a list of countries that is hashed. My problem is that it does not seem to be able to compare the countries entered by the user, even though it is copy and paste, to the ones in the hash table to display them. It is not only supposed to display the country in the hash table, but all the ones leading up to the hash table. So if one was supposed to go to spot 23 but went to spot 26, display 23-26 to show clustering. I have tired everything to get it to work, but nothing seems to work, please help. I have included some of the code:
import java.io.PrintWriter;
import java.io.File;
import java.util.*;
import java.text.*;
public class Hashing
{
String[] line = new String[238];
String[] HashTable = new String[300];
public Hash() {
for (int i = 0; i< HashTable.length; i++) {
HashTable[i]=null;
}
}
public void readIn()throws Exception {
Scanner ln = new Scanner(new File(System.getProperty("user.home"), "user.home.CountryUnSortedFormat.txt"));
int i = 0;
while (ln.hasNextLine()) {
line[i] = ln.nextLine();
i++;
}
}
public int toASCII(String input) {
int total = 0;
char character;
String str = input.replaceAll(",","").trim();
if (str.length() > 50) {
for (int i = 0; i<50; i++) {
int ascii = str.charAt(i);
if (ascii > 32) {
total = total + ascii;
}
}
} else if (str.length()<50) {
for (int i = 0; i<str.length(); i++) {
int ascii = str.charAt(i);
if (ascii > 32) {
total = total + ascii;
}
}
}
return total % 300;
}
public void hashIt(String input, int where){
int counter = where;
if (where==299 && HashTable[where]!=null){
counter = 0;
}
while (HashTable[counter]!=null){
counter++;
}
System.out.println("Country = " + input + " HashValue = " + where + " actual HashSpot = " + counter);
HashTable[counter]=input;
}
public boolean showCountries(String paramCountry, int where){
int location = where;
int length = paramCountry.length();
while (!(HashTable[location].substring(0,length).contains(paramCountry))){
System.out.println("Input = " + paramCountry + " and HashTableCOunty = " + HashTable[location].substring(0,length));
System.out.println("The Hash Table Index is " + location + " " + HashTable[location]);
if (!(HashTable[location].substring(0,length).contains(paramCountry))){
location++;
}
else if (HashTable[location].substring(0,length).contains(paramCountry)){
System.out.println("The Hash Table Index is " + location + " " + HashTable[location]);
System.out.println("Eguals");
return true;
}
if (location==300||HashTable[location]==null){
System.out.println("End");
return false;
}
}
return false;
}
public void displayHashTable() {
for (int i = 0; i<HashTable.length; i++) {
System.out.println("i = " + i + " " + HashTable[i]);
}
}
public static void main(String[]args)throws Exception {
Scanner kb = new Scanner(System.in);
Hash H = new Hash();
H.readIn();
for (int i = 0; i< 238; i++) {
int where = H.toASCII(H.line[i]);
H.hashIt(H.line[i], where);
}
H.displayHashTable();
String UserChoice;
System.out.println("Enter the Name of the Country you wish to locate in the Hash Table or Enter -1 to quit: ");
UserChoice = kb.nextLine();
while (!(UserChoice.equalsIgnoreCase("-1"))) {
int index = H.toASCII(UserChoice);
boolean error = H.showCountries(UserChoice, index);
while (error == false) {
System.out.println("The country you searched for is not in the hash table. Try again.");
UserChoice = kb.nextLine();
index = H.toASCII(UserChoice);
error = H.showCountries(UserChoice, index);
}
System.out.println("Enter the Name of the Country you wish to locate in the Hash Table or Enter -1 to quit: ");
UserChoice = kb.nextLine();
}
}
}
Let us look at showCountries method:
public boolean showCountries(String paramCountry, int where) {
//....
return false;
}
I removed every line, that does not contain a return statement. As you can see, you always return false no matter if the searched element was found or not.
Therefore this loop:
while (error == false) {
//...
}
is like an infinite loop.
Change the code in your showCountries method to return true, it the country was found.
And consider changing the variable name error to something else. error == false sounds like "everything was ok", but this is not the case here.
If I understand your code correctly, you can change this:
else if (paramCountry.equals(HashTable[location].substring(0,length))) {
System.out.println("The Hash Table Index is " + location + " " + HashTable[location]);
break;
}
to:
else if (paramCountry.equals(HashTable[location].substring(0,length))) {
System.out.println("The Hash Table Index is " + location + " " + HashTable[location]);
return true;
}
Edit:
Another error-prone point is right here:
int length = paramCountry.length()-1;
while (!(paramCountry.equals(HashTable[location].substring(0,length)))) {
//...
You're cutting off the last character due to the usage of -1.
A small example:
paramCountry = "Eng";
HashTable[0] = "England";
int length = paramCountry.length()-1; // 2 (paramCountry.length() is 3)
And this are the results with the above values:
HashTable[0].substring(0,length)) // "En"
paramCountry.equals(HashTable[0].substring(0, length)) // "Eng".equals("En") -> false
So, you can remove that -1 or get rid of that substring and use contains instead.
Edit 2:
So, after your edit use contains instead of substring you only have one error left (the last one I cuurently see ):
while (!(HashTable[location].substring(0, length).contains(paramCountry))) {
// ...
}
return false;
Before you're calling the method showCountries you're calculating the possible position by calling H.toASCII(UserChoice);. This position is given to the method as location there it is used in the above while loop. This loop will be skipped, because the search country is already found. The bad thing is: you will return false in this case.
Now I suggest to change this return to return true; because this line will only be reached if the searched country was already found (and the while loop was skipped). If the country could not be found, you will return false in this if body: if (location==300||HashTable[location]==null).
I'm trying to write a method that will delete a CD (CD include artist name, album title, and track titles).. there are 5 CDs and I want to delete on of them... this is what the method should do :
void delete() will 1) ask the user for an artist and title, then attempt to find a CD with
matching artist and title, 2) display the CD if found, or tell the user it was not found, and 3)
if found, ask the user to confirm deletion (this needs keyboard input), deleting the CD
entry if the user confirms.
and this is my code:
public void delete() {
Scanner deleteInput = new Scanner(System.in);
System.out.println("Which artist you would like to delete? ");
System.out.println("Enter artist name and title to be deleted:");
String artist = deleteInput.nextLine();
String title = deleteInput.nextLine();
for (int i = 0; i <= CDlist.length - 1; i++) {
if ((CDlist[i].getArtist().equals(artist))
&& (CDlist[i].getTitle().equals(title))) {
System.out.println("Found: " + CDlist[i].getArtist() + " "
+ CDlist[i].getTitle());
if (CDlist[i] == null) {
continue;
}
System.out.println("Would you like to delete it? Yes 0 No 1");
if (deleteInput.nextInt() == 1) {
CDlist[i] = null;
cdnum--;
}
} else {
System.out.println("CD not found in the list.");
}
}
my problem is that when I type the correct Artist and Title to be removed I'm getting output as CD not found ( but it should say found and then removes it) how do I fix this please?
This is what I meant. Also you have an extra { in your first if right after the for loop starts. I hope that isn't causing an issue.
I have added the ignore case part based on some comments.
public void delete() {
Scanner deleteInput = new Scanner(System.in);
System.out.println("Which artist you would like to delete? ");
System.out.println("Enter artist name and title to be deleted:");
String artist = deleteInput.nextLine();
String title = deleteInput.nextLine();
boolean found = false;
int idx = -1;
System.err.println("DEBUG: Input Data");
System.err.println("Artist Name: "+artist+" Length of String: "+artist.length());
System.err.println("Title: "+artist+" Length of String: "+title.length());
System.err.println();
for (int i = 0; i <= CDlist.length - 1; i++) {
if (CDlist[i]!=null) {
System.err.println("DEBUG: Checking Index "+i);
System.err.println("Artist Name: "+CDlist[i].getArtist()+" Length of String: "+CDlist[i].getArtist().length() + " Matches: "+CDlist[i].getArtist().equalsIgnoreCase(artist));
System.err.println("Title: "+CDlist[i].getTitle()+" Length of String: "+CDlist[i].getTitle().length() + " Matches: "+CDlist[i].getTitle().equalsIgnoreCase(title));
System.err.println();
}
if (CDlist[i]!=null && CDlist[i].getArtist().equalsIgnoreCase(artist) && CDlist[i].getTitle().equalsIgnoreCase(title)) {
System.out.println("Found: " + CDlist[i].getArtist() + " " + CDlist[i].getTitle());
found = true;
idx = i;
break;
}
}
if (found) {
System.out.println("Would you like to delete it? Yes 0 No 1");
if (Integer.parseInt(deleteInput.nextLine()) == 1) {
CDlist[idx] = null;
//I am assuming cdnum is a variable of the class that can be accessed.
cdnum--;
}
} else {
System.out.println("CD not found in the list.");
}
}
Note: You need not put CDlist[i] in an if statement on its own you can just merge into the other statement. This can be done because java looks at things left-> right and so it'll check for null before trying to do anything. You can put it on its own but you'll need to put it BEFORE your first if statement.