Scanner looping headache - java

I have a homework assignment which requires input from the user and stores it in various data structures (arrays of linked-lists, stacks, etc.). However, I've been writing the main class of my previous homework assignments and this one in a very similar fashion. I have a very tiny main method. All the main method does is instantiate a new object which I don't want to be destroyed and then loop through the program forever until the user chooses otherwise. I then have a menu() method which prints a list of selections and reads the user's selection. And then from there, I pass that selection to another method which interprets the selection and performs accordingly.
The problem I have been having in the past assignments and now I've never really gotten a good answer for. The problem seems to lie with my menu() method and more specifically, the Scanner object. There always seems to be some junk left in the stream after I call the nextLine() method on a scanner object. So the next time the menu() method is called, it reads in that junk and loops though the rest of the program with that junk until menu() is called a third time. In the past, I would remedy this by calling the next() method right after I received my input and ignoring it. However, I seem to be having issues with that now as well.
In this program in particular, I have a method which request's a user enter a city name. Now, city names can be more than one word (Palm City, West Palm Beach, Satellite Beach, New York, etc.). Now, when the scanner reads in one of those multi-word cities, it does the same thing as before, reads in some junk the next time the menu() method is called and goes though the whole program with it until menu() is called again. In this case, it prints an string "Invalid Selection" and then prints the menu again. I can't for the life of me figure out what's going on. any help would be appreciated.
import java.util.Scanner;
public class CSAir
{
public static Scanner input = new Scanner(System.in);
public static void main(String[] args)
{
CityList flightLog = new CityList();
boolean loop = true;
while(loop)
{
loop = actions(menu(),flightLog);
}
}
private static String menu()
{
System.out.print("Please Make a Selection\n" +
"I) Insert a city\n" +
"A)Add a flight path (One Way)\n" +
"R) Request a flight\n" +
"L) Load from a text file\n" +
"Q) Quit\n" +
"\nSelection: ");
String in = input.next();
//input.next();
System.out.println();
return in;
}
private static boolean actions(String selection, CityList flightLog)
{
if(selection.equalsIgnoreCase("I"))
{
insert(flightLog);
return true;
}
else if(selection.equalsIgnoreCase("A"))
{
add(flightLog);
return true;
}
else if(selection.equalsIgnoreCase("R"))
{
request(flightLog);
return true;
}
else if(selection.equalsIgnoreCase("L"))
{
return true;
}
else if(selection.equalsIgnoreCase("Q")) return false;
else
{
System.out.println("Invalid Selection!\n");
return true;
}
}
private static void request(CityList flightLog)
{
System.out.print("Origin: ");
String origin = input.nextLine();
System.out.print("\nDestination: ");
try
{
flightLog.isPath(origin, input.next());
}
catch (AllDestinationsVisitedException e)
{
e.getMessage();
}
}
private static void add(CityList flightLog)
{
System.out.print("Origin: ");
String origin = input.nextLine();
System.out.print("\nDestination: ");
flightLog.addPath(origin, input.next());
}
private static void insert(CityList flightLog)
{
System.out.print("Enter a City: ");
try
{
flightLog.addCity(input.next());
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
System.out.println();
}
}

Default Deliminator for scanner is white space. So when you enter New York since it has white space now scanner treats it as two tokens if you call next().
A better option would be to use nextLine() method for reading such values.

Related

can the program be terminated early from within a methood

I am making a simple "game" where the user is asked a question and must give the correct answer to move on this is the code I currently have for one of the questions.
public static void Mascot() {
Scanner console = new Scanner(System.in);
System.out.println("what Is our school mascot?");
String Tony = console.nextLine();
String b = Tony;
Scanner scanner= new Scanner(b);
if (scanner.hasNext("tiger")){
System.out.println("Good, next riddle.");
} else{
}
scanner.close();
console.close();
}
I want the if statement to be case-insensitive and return true if tiger is input in the scanner at all. like someone could enter a full sentence into the scanner and if the word tiger is anywhere it returns as true. but if tiger (or any other incorrect answer for any other question is input in the scanner, I want the program to stop. and not continue to the next question.
Couple of things to note here.
Whether to continue the game or not should ideally be controlled by the caller of the method. The caller of the method should decide based on the return value true or false
To accommodate (1) method signature needs to change. It can't be void. It should be boolean.
You don't need the second scanner object to verify if it contains tiger
Please check if this code helps you
public static boolean Mascot() {
Scanner console = new Scanner(System.in);
try {
System.out.println("what Is our school mascot?");
String b = console.nextLine();
if (b.toLowerCase().contains("tiger")){
System.out.println("Good, next riddle.");
return true;
} else{
return false;
}
}
catch(Exception e) {
System.out.println("Exception Occurred");
}
finally {
console.close();
}
return false;
}

Arraylist User input

I would greatly appreciate some help with my java code. I am using ArrayLists to store the users favorite type of vehicles. So they will input vehicles until they type "Exit" to get out of the loop. It will then print the array list. Right now, it is only reading every other input. Depending on how many inputs there are, the user might have to type "Exit" twice before it prints the results out. Any help would be greatly appreciated, thank you!
package bacaCCh6Sec8;
import java.util.ArrayList;
import java.util.Scanner;
public class BacaCCh6Sec8 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
ArrayList<String> vehicles = new ArrayList<>();
boolean done = false;
final String EXIT = "Exit";
System.out.printf("Enter your favorite vehicles.\n");
System.out.printf("Type Exit after you have input all your vehicles.\n");
do {
String input = in.next();
if (!input.equals(EXIT)) {
vehicles.add(in.next());
} else {
done = true;
} // end If
} while (!done); // End Do While
System.out.printf("Your favorite vehicles are %s.\n" , vehicles);
} // End Main
} // End Class
the user might have to type "Exit" twice before it prints the results
out
the issue is that you're calling next() method twice hence the user must enter a value twice. the solution is to simply use the value you've got from the first next() method rather than discarding it.
String input = in.next();
if (!input.equals(EXIT)) {
vehicles.add(input); // <--- we're using the input variable
} else {
done = true;
} // end If
Each call of .next() actually reads the input. So if you call .next() twice, it'll read two lines. To rectify change vehicles.add(in.next()); to vehicles.add(input);
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
ArrayList<String> vehicles = new ArrayList<>();
boolean done = false;
final String EXIT = "Exit";
System.out.printf("Enter your favorite vehicles.\n");
System.out.printf("Type Exit after you have input all your vehicles.\n");
do {
String word = in.next();
if(word.equalsIgnoreCase("exit")) break;
vehicles.add(word);
} while (!done); // End Do While
System.out.printf("Your favorite vehicles are %s.\n" , vehicles);
}
}
Well not my best code but it helped
Enter your favorite vehicles.
Type Exit after you have input all your vehicles.
hola
mundo
exit
Your favorite vehicles are [hola, mundo].

String input of more than one word causes exception error

I am inputting the following things:
book
12.46
music cd
For some reason, the prompt for cost comes up and the next output line comes on the same line. Could someone help me to spot my mistake?
public class SalesTax {
public static void main(String[] args) {
// Input items for shopping cart
HashMap<String, String> cart = new HashMap<String, String>();
// Create a Scanner
Scanner input = new Scanner(System.in);
// variables
char done;
boolean goods;
double tax;
// Pick items for list.
do {
System.out.print("Please enter an item.");
String item = input.next();
System.out.print("Please enter the price for "+ item + ": ");
String price = input.next();
if (item.contains("book")) {
goods = false;
} else if(item.contains("chocolate")) {
goods = false;
} else if(item.contains("pill")) {
goods = false;
}
cart.put(item, price);
System.out.print("Would you like to continue to add items? (Type Y) for Yes and (Type N) for No.");
done = input.next().charAt(0);
} while(Character.toUpperCase(done) == 'Y');
}
}
problem:
String item = input.next();
By the time you input music cd it will consume music by item and price will consume the cd thus skipping it.
solution:
you need to call input.nextLine(); to consume the whole line of string
By default, next() just gets input upto a whitespace so you'd have to use nextLine() instead, which will read in the whole line of input upto a carriage return.
use input.nextLine() to read an entire line from the keyboard. Means what ever the user typed till the user presses the enter key.
One thing that I did not understand is, what is the use of having this in your code
if(item.contains("book"))
{
goods = false;
}
else if(item.contains("chocolate"))
{
goods = false;
}
else if(item.contains("pill"))
{
goods = false;
}
???
Can you please explain?
Thanks,
you are using System.out.print() instead use System.out.println();
print() will just print the word and stays on the same line.
println() will print the whole line and cursor goes to second line .
And don't use the spaces while reading as you are writing it as
input.next();
The next() and hasNext() methods and their primitive-type companion methods (such as nextInt() and hasNextInt()) first skip any input that matches the delimiter pattern, and then attempt to return the next token. Both hasNext and next methods may block waiting for further input. Whether a hasNext method blocks has no connection to whether or not its associated next method will block.
edit:
just change the declaration to this.
Scanner s = new Scanner(input).useDelimiter("\n");
It will change the delimiter to new line and read the complete line.

Scanning Basics Java

So the loop works but I have to press enter twice for it to print out the next input, I know it's with my loop and I know it's because the new input is set after the method scanz but I can't put it before/ eliminate it outside the loop because then the creation of the object Scanning doesn't work. Help is appreciated!
public class NumberScanned {
public static void main(String[] args) {
System.out.println("Please enter '.' when you want to terminate");
Scanner keyboard = new Scanner(System.in);
String scannedString=keyboard.nextLine();
Scanning scanz= new Scanning(scannedString);
do
{
System.out.println("Numbers: "+scannedString);
scanz.set(scannedString);
scanz.printState();
scannedString=keyboard.nextLine();
}
while(!keyboard.nextLine().equals("."));
keyboard.close();
}
}
Change your loop to the following pattern:
String scannedString = keyboard.nextLine();
do {
System.out.println("Numbers: "+scannedString);
scanz.set(scannedString);
scanz.printState();
} while (!(scannedString = keyboard.nextLine()).equals("."));
This way condition check is done together with reading a new line. There is even more readable approach available:
String scannedString = null;
while (!(scannedString = keyboard.nextLine()).equals(".")) {
System.out.println("Numbers: "+scannedString);
scanz.set(scannedString);
scanz.printState();
}

Loop Keyword Program Homework

It will ask the user for a keyword to search for. Then, it will ask the user to enter sentences over and over. The user can stop the process by typing “stop” instead of a sentence (which means, of course, that we can’t analyze the one word sentence ‘stop’, but that is OK). Once the user has finished entering the sentences, the program should display the following statistics:
The total number of sentences entered
The total number of sentences that contain the keyword
The average starting position of the keyword in the sentences that contain the keyword.
Can somebody help me put this program together? For #3 we only do average position of the sentences that contain the keyword.
I have the loop part, and for #3 I'm guessing we would use indexOf. #2 inputString.contains(keyword) I'm guessing? Can somebody help me with 1-3 and putting them into a Java program? Thanks.
import java.util.Scanner;
public class Lab6Loops {
public static void main(String[] args) {
String keywordString;
String inputString;
Scanner keyboard = new Scanner (System.in);
int numofSentences = 0;
int numofKeyword = 0;
System.out.println ("Enter a keyword. We will search each sentence for this word.");
keywordString = keyboard.nextLine ();
System.out.println ("Please enter a sentence or type 'stop' to finish");
inputString = keyboard.nextLine ();
while( !inputString.equals ("stop"))
{
if(inputString.contains (inputString));
numofSentences = numofSentences + 1;
if(inputString.contains (keywordString));
numofKeyword = numofKeyword + 1;
System.out.println ("Enter a line of text or 'stop' to finish");
inputString = keyboard.nextLine();
}
System.out.println ("You entered " + numofSentences + " sentences");
System.out.println ("You have " + numofKeyword + "sentences that contain the keyword");
}
}
I like having self-documenting code, so here are a couple suggestions for how you can have a nice tight main loop:
functional-ish semantics
public void loop() {
// TODO: ask for the keyword and store it somewhere
while(true) {
try {
updateStatistics(checkOutput(getSentence()));
} catch (EndOfInput) {
printStatistics();
}
}
}
Object-Oriented
public void loop() {
String keyword = myPrompter.getNextSentence();
myAnalyzer.setKeyword(keyword);
while (true) {
String sentence = myPrompter.getNextSentence();
AnalysisResult result = myAnalyzer.analyze(sentence);
if (result.isEndOfInput()) {
myAnalyzer.printStatistics();
return;
}
}
}
What both of these approaches gives you is a simple framework to plug in the specific logic. You could do all of it inside the main loop, but that can get confusing. Instead, it's preferable to have one function doing one task. One function runs the loop, another gets the input, another counts the # of sentences, etc.
Sometimes I'll start with those little functions, and build the app from the bottom-up, so I'd write a method that takes a string and returns true/false depending on if it's the string "stop". You can even write unit tests for that method, so that when you're building the rest of the app, you know that method does what you intended it to. It's nice to have lots of modular components that you can test along the way, rather than writing a huge long loop and wondering why it's not doing what you want.
sounds like you need to prompt the user for an initial input then enter in to a loop that will last until the user presses stop (or whatever), in each iteration you need to prompt the user for a sentence, if the user inputs data increment one counter that stores the number of sentences, test the sentence against the keyword entered and increment a second counter as applicable, you will also need to push the position that the word occured in to a stack to later get the average which should be the sum of the stack divided by the size. you should be able to use indexOf() to get the position.
package console;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Console {
static float averagePositionInSentence = 0;
static String searchTerm = "";
static int noOfSentencesEntered = 0;
static int noOfMatches = 0;
public static void main(String[] args) {
searchTerm = writeToConsoleAndReturnInput("Add phrase to search for.");
writeToConsole("Now type some sentences. To exit type the word 'stop' on its own");
mainInputLoop();
outputResults();
}
public static void mainInputLoop() {
boolean ended = false;
while (!ended) {
try {
String input = readLineFromConsole();
if (!input.equalsIgnoreCase("stop")) {
maintainStatisticalData(input);
} else {
ended = true;
}
} catch (Exception e) {
writeToConsole("There was an error with your last input");
}
}
}
public static void outputResults() {
writeToConsole("You entered " + noOfSentencesEntered + " sentences of which " + noOfMatches + " conatined the search term '" + searchTerm + "'");
writeToConsole("");
writeToConsole("On average the search term was found at starting position " + (averagePositionInSentence / noOfSentencesEntered) + " in the sentence");
}
public static void maintainStatisticalData(String input) {
noOfSentencesEntered++;
if (input.contains(searchTerm)) {
noOfMatches++;
int position = input.indexOf(searchTerm)+1;
averagePositionInSentence += position;
}
}
//terminal helper methods
public static void writeToConsole(String message) {
System.out.println(message);
}
public static String writeToConsoleAndReturnInput(String message) {
System.out.println(message);
try {
return readLineFromConsole();
} catch (IOException e) {
//should do something here
return "Exception while reading line";
}
}
public static String readLineFromConsole() throws IOException {
InputStreamReader converter = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(converter);
return in.readLine();
}
}

Categories