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.
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;
}
I'm creating a text based game, I have a class made for the main character so you can set the characters name, etc. What I'm trying to figure out is, is there any way to pass a mutator (character.setname(input)) as an argument to another method. When I try to do it I'm told that I can't use a void type as an argument to a method. When I was writing out the code for the user to enter their name, and everything else it was repetitive with the error checking so I wanted to create my own method I could call that would error check for me. A couple sentences use the setname method to reset the name if it was entered incorrectly but I can't directly use setname in the error checking method because it's going to be using the same method to check other inputs of data.
Is there any way around this?
Here is the code as requested: I indeed may be overcomplicating the problem, I'm pretty new to java so I'm still learning.
The following code is the code I use to check if the user entered something correctly, it accepts an array which contains all the possible correct answers the user can type in, I've tried to design it in a way that I can error check anything with it, not just "yes" or "no" statements, getVariable is the accessor method, and setVariable is the one I'm trying to get to work, I'm trying to pass the mutator as well so I can reset the error
public void confirmEntry(String question, String[] options, String getVariable, setVariable) throws InterruptedException
{
boolean correctEntry = false;
System.out.print("Is this correct? ");
for(int i = 0; i < options.length - 1; i++)
{
System.out.print(options[i] + ", ");
}
System.out.print("or ");
System.out.print(options[options.length - 1] + ": ");
input = in.nextLine();
for(int i = 0; i < options.length; i++)
{
if(input.equals(options[i]))
{
correctEntry = true;
System.out.println(correctEntry);
}
}
System.out.println(correctEntry);
while(correctEntry == false)
{
Thread.sleep(2000);
System.out.print("You must enter ");
for(int i = 0; i < options.length - 1; i++)
{
System.out.print("\"" + options[i] + "\", ");
}
System.out.print("or ");
System.out.print("\"" + options[options.length - 1] + "\" to continue: ");
Thread.sleep(2000);
System.out.println();
System.out.println("You chose " + getVariable);
Thread.sleep(2000);
System.out.print("Is this correct? ");
for(int i = 0; i < options.length - 1; i++)
{
System.out.print(options[i] + ", ");
}
System.out.print(" or ");
System.out.print(options[options.length - 1] + ": ");
input = in.nextLine();
for(int i = 0; i < options.length; i++)
{
if(input.equals(options[i]))
{
correctEntry = true;
}
}
}
}
The following code is what is currently in the method where you enter information about the character. I'm trying to move more of the code into the error checking method so that each time I ask the user a question, name, age, etc. I just simply need to call the method.
public void characterCreation() throws Exception
{
//create an instance of the class player (your character creation)
Player character = new Player();
//Initial Introduction to the game
System.out.println("Welcome to Stranded!");
Thread.sleep(2000);
System.out.println("Tell us a little about yourself!");
Thread.sleep(2000);
//______________________________________________________________________________________________________________
//SET YOUR CHARACTER'S NAME
String[] yesNo = {"yes", "no"}; //array to feed into confirmEntry method
System.out.print("Enter your character's name: ");
input = in.nextLine(); //asks for input of the name
character.setName(input); //sets name in the player class
System.out.println("You chose " + character.getName()
+ " for your character's name");
Thread.sleep(2000);
confirmEntry("Enter your character's name: ", yesNo, character.getName(), character.setName(input));
while(input.equals("no"))
{
Thread.sleep(2000);
System.out.print("Enter your character's name: "); //prompt to enter name again
input = in.nextLine();
character.setName(input); //sets name in player class
Thread.sleep(2000);
System.out.println("You chose " + character.getName()
+ " for your character's name"); //confirms what user entered for name
Thread.sleep(2000);
confirmEntry("Enter your character's name: ", yesNo, character.getName(), character.setName(input));
}
I'm trying to move more code after the SET CHARACTER NAME comment into the confirmEntry method, however the rest of the code involved with the character's name uses the mutator to set the name. That's the problem. I wanted to try to get as much code into confirmEntry as possible so whenever I ask the user to enter something about their character I basically just have to call the method.
If you are using java 8 you can create your method with a method reference param :
public void functionName(Consumer<String> setter){setter.
accept(string);}
and to call your method you can use : functionName(character::setname);
you can see : http://www.informit.com/articles/article.aspx?p=2171751&seqNum=3
What is an entry? It appears to be some value that the user has entered.
class Entry{
String value;
public Entry(String value){
this.value = value;
}
public boolean confirm(String input){
return value.equals(input);
}
}
How about you store all of your entries.
Map<String, Entry> entries = new HashMap<>();
String message = "Enter your character's name: ";
System.out.println(message);
String input = in.nextLine();
entries.put(message, new Entry(input));
Now when you want to confirm.
public void confirmEntries(){
for(String message: entries.keySet()){
System.out.println(message);
System.out.println(entries.get(message) + "yes/no?");
//get some input and update the value. etc.
}
}
Another way to do it would be to create a Runnables.
List<Runnable> entryRunnables = new ArrayList<>();
Then anytime you want to add an action.
Runnable r = ()->{
System.out.println("Enter your players name, yes/no");
String input = in.readLine();
//check input and do stuff.
}
entryRunnables.add(r);
Now to check entries. (stream method)
entryRunnables.forEach(Runnable::run);
Or
for(Runnable r: entryRunnables){
r.run();
}
I've been working on the same piece of java code for over a week now, t used to be a complete mess however i have got it now (through about a million iterations) to a somewhat working stage. The output i need is all three student names at the end with either a pass or fail beside their name, however my code will only output the last students name that i put in, completely ignoring the rest of the data i input.
If someone could teach me where i have gone wrong and also the quality of code i've produced and iterated, it would be much appreciated. Also to those who downvote my posts simply because it may seem easy to you, we aren't all experienced as you and don't forget that you used to be in my position once, so be thoughtful.
class Main extends BIO {
public static void main(String args[]) {
{
int i = 0;
int moduleMark = BIO.getInt();
String first_name = BIO.getString();
while (i++ < 3) {
System.out.print("Enter The Students name : ");
first_name = BIO.getString();
if (first_name.equals("END"))
break;
System.out.print("Their Module mark : ");
moduleMark = BIO.getInt();
}
if (moduleMark >= 40) {
System.out.println(first_name + " Pass");
} else {
System.out.println(first_name + " Fail");
}
}
}
}
first_name gets overwritten inside the loop constantly. When you exit the loop, first_name will be whatever the last name it received was.
If you can print them as you go, just print inside the loop. This will alternate between printing the results and asking for a new name/grade:
while (i++ < 3) {
System.out.print("Enter The Students name : ");
first_name = BIO.getString();
if (first_name.equals("END"))
break;
System.out.print("Their Module mark : ");
moduleMark = BIO.getInt();
if (moduleMark >= 40) {
System.out.println(first_name + " Pass");
} else {
System.out.println(first_name + " Fail");
}
If they must be printed at the end, you'll need to put the names and grades into lists, then iterate over the lists at the end:
// Create lists to hold grades and names
List<String> names = new ArrayList<>();
List<Integer> grades = new ArrayList<>();
while (i++ < 3) {
System.out.print("Enter The Students name : ");
first_name = BIO.getString();
if (first_name.equals("END"))
break;
// Add name to list
names.add(first_name);
System.out.print("Their Module mark : ");
moduleMark = BIO.getInt();
// Add grade to list
grades.add(moduleMark);
}
// Iterate both lists at once, printing inside the loop
for(int i = 0; i < names.size(); i++) {
String name = names.get(i);
Integer grade = grades.get(i);
if (grade >= 40) {
System.out.println(name + " Pass");
} else {
System.out.println(name + " Fail");
}
}
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)) {
...
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).