Java Menu Loop Problems; Program loops too soon? - java

I am working on an assignment where I have to write a program to encrypt and decrypt Caeser ciphers. The part I am having trouble with though is not encrypting or decrypting, but another one of the requirements, which was that I have to provide a menu so that the user can choose to encrypt, decrypt, or quit. Furthermore, the program should keep prompting the use until the use selects quit. My code so far is:
import java.util.*;
public class CaeserShiftTester
{
public static void main (String[] args)
{
Scanner in = new Scanner(System.in);
String choice = "";
while (!choice.equalsIgnoreCase("C"))
{
System.out.println("\nPlease select an option");
System.out.println("[A] Encrypt Code");
System.out.println("[B] Decrypt Code");
System.out.println("[C] Quit");
choice = in.next();
if(choice.equalsIgnoreCase("A"))
{
System.out.println("Please enter your key:");
final int KEY = in.nextInt();
System.out.println(CaeserShiftEncryption.shiftAlphabet(KEY));
System.out.println("\nPlease enter your message:");
String message = in.nextLine();
System.out.println(CaeserShiftEncryption.encryptCode(message,KEY));
}
if(choice.equalsIgnoreCase("C"))
{
System.out.println();
}
}
}
}
My problem is, after the "New Alphabet" is printed out to the screen, the program loops back to the very beginning, asking the user to choose a, b, or c. The use never gets a chance to enter a message to be encrypted. Unfortunately, I am required to print out the New Alphabet that is generated, and I can't think of what might be wrong here. I hope you guys can help me out.
Also, the shiftAlphabet and encryptCode methods are both fully functional.

Take a look on this website: http://www.java-made-easy.com/java-scanner.html
particularly
don't try to scan text with nextLine(); AFTER using nextInt() with the same scanner! It doesn't work well with Java Scanner, and many Java developers opt to just use another Scanner for integers

Problems occur with the Scanner class when mixing different type of scans and then using the same Scanner instance with nextLine.
When you get such a problem try to create a new Scanner instance. A simple cure would be to have 1 Scanner for using nextLine and another for everything else.
In the past I've had problems with using the Scanner when it came to next and nextLine, the cure for me was to simply stick to only using nextLine.

Related

If statement skips to else

I'm pretty new to Java coming from Python so please pardon my retardedness. I'm trying to make a simple if statement and it won't work :(. It ignores the if statement and goes straight else.
I've tried to use .contains and .equalsIgnoreCase in the if statement.
package me.johnminton;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner user_input = new Scanner(System.in);
String species_animal;
System.out.println("Please enter your species: ");
species_animal = user_input.next();
if (species_animal.contains("Erectus")) {
System.out.println("random input statement");
}
else
{
System.out.println("okay");
}
}
}
I'm hoping for it output "random input statement" if I input Erectus in the first input. But instead, it goes straight to the else and outputs "okay".
The next() method just fetches a single word from the scanner, although you can change that behaviour by specifying a delimiter for the scanner.
In your case, if you type Eructussian or something similar, you'll get the result you want, but if you type Home Erectus, you won't.
I suspect you meant to use nextLine() instead of next(), which fetches an entire line of text.
The problem is that your scanner isn’t finishing without getting a return key. Try ‘user_input.nextLine()’ instead of ‘user_input.next()’

while (sc.hasNext) loop java

public class Test1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
System.out.println("First name: ");
String fname =sc.next();
System.out.print("Last name: ");
Lname = sc.next();
}
}
I'm just a beginner at java, hope someone can help me out please. Ignore the last print line i used it so i could understand what exactly i can ouptut.
without the while loop i get the correct output i expect of the code, but once i add the while(sc.hasnext)
a scanner comes before the first name and ignores the scanner that used to input the first name. Does the hasNext() skip scanner?
From the documentation of Scanner.hasNext():
Returns true if this scanner has another token in its input. This method may block while waiting for input to scan. The scanner does not advance past any input.
This means that the while loop which you add will wait until you write something. After you write something, it will be read for first name and it will continue on. When you fill all the data it will wait again to write something and basically loop for ever.
You need other condition for the loop. For example you can use do while and after last data is written, you can ask the user additional question whether he wants to add something else. E.g:
do {
// gather data
System.out.println("Continue ?");
String c = scanner.next();
} while("yes".equals(c))
It's not actually ignoring or skipping the scanner for first name (variable fname), but in your case, when the hasNext() function runs, it puts the input in the buffer and transfers it to the immediate sc.next() or sc.nextLine() (if any of them exists).

Java: how to reject incorrect input and wait for proper input using Scanner

This is the basic setup for a little console-based quiz game. The answers are numbered. I want the player to give the answer number. If the input is not a number, then my program should give a warning, and wait for proper input.
Instead, what I get (after inserting something that is not a number) is an infinite loop of asking the question and presenting the answers again.
public static void main(String[] args) {
boolean quizActive = true;
while(quizActive) {
presentQuestion();
presentAnswers();
Scanner s = new Scanner(System.in);
if (s.hasNext()) {
String choice = s.next();
if (!NumberUtils.isNumber(choice)) {
presentText("Please insert the answer number.");
} else {
System.out.println("You made a choice!");
checkAnswer(choice);
quizActive = false;
}
s.close();
}
}
}
What am I doing wrong here?
If you do not want to question and answers be presented each time move presentQuestion() and presentAnswers() outside the loop.
But main problem is that you closing Scanner.
Remove s.close(); and move Scanner s = new Scanner(System.in); outside of the loop.
I really don't get the point in using scanner for acquiring user input.
The scanner class is perfect to process structured input from a flat file with known structure like an CSV.
But user input need to deal with all the human imperfection. After all the only advantage you get is not needing to call Integer.parseInt() your yourself at the cost to deal with the not cleared input when scanne.nextInt() fails...
So why not using InputStreamReader aside with a loop suggested by others?
Here an Example :
public class Application {
public static void main(String [] args) {
System.out.println("Please insert the answer number. ");
while (true) {
try {
Scanner in = new Scanner(System.in);
int choice = in.nextInt();
System.out.println("You made a choice!");
checkAnswer(choice);
break;
} catch (Exception e) {
System.out.println("Invalid Number, Please insert the answer number ");
}
}
}
}
You started your Quiz in a loop which is regulated by your quizActive boolean. That means that your methods presentQuestion() and presentAnswers() get called every time the loop starts again.
If you don't input a number but a character for example, your program will run the presentText("Please insert the answer number.") and start the loop again. As it starts the loop again, it will call the methods presentQuestion() and presentAnswers().
To stop that, you can do another loop around the input-sequence. Also your Scanner s = new Scanner(System.in) should be outside the loop. And you shouldn't close your Scanner right after the first input and then open it again!
if you want a code example, please tell me :)

I need to make Scanner check to see if input is "quit", and then if it's not, accept an integer

I'm trying to write a program that gets an integer from the user, but also ends the program if the user enters "quit". When I run the program, it works when I enter "quit", but when I start entering an integer, I get a blank line. If I enter the integer the second time, it works. I have tried several suggestions that I have found for similar problems - including try/catch, parsing the input to Integer, and firing a blank Scanner#nextLine or Scanner#nextInt (and going back and forth between all of these options). Here is an example of my latest attempt. Any insight would be appreciated.
int colInput;
System.out.println(", please pick a column in which to place your token (1-8).");
System.out.println("(Type 'quit' to exit the game or 'restart' to start over.)");
System.out.print("Column Choice: ");
Scanner selectCol = new Scanner (System.in);
try {
if (selectCol.next().equals("quit"))
Connect4.close();
}
finally {
colInput = selectCol.nextInt();
}
String input = selectCol.next();
int colInput;
if (input.equals("quit"))
Connect4.close();
else
colInput = Integer.parseInt(input);
//Use colInput here or return colInput or whatever you wish to do with it
In the code you mention you are consuming the "next token" found by your scanner in the line
if (selectCol.next().equals("quit"))
the token is received and compared against "quit". No matter what the value of the token originally was it is lost afterwards. Then later in the finally block you ask your scanner for a new token. He is then waiting for a new value from System.in.
To receive the token from the scanner only if it matches "quit" you should change the line to
if (selectCol.next("quit"))
This way you are making use of a method offered by the Scanner class javadoc for next(String).

Why is System.in not responding properly to synchronization attempts?

I can't seem to force my calls to System.out to go in order if one of them takes input from a Scanner on System.in.
I'm sure that there's a simple answer (I can feel the down votes coming already), but it's eluding me.
public class RegexApp{
static Scanner s = new Scanner(System.in);
static String read = "";
public static void main(String[] args) {
while (true) {
System.out.println("Please enter text.");
RegexApp.GetLine mg = new RegexApp().new GetLine();
mg.start();
mg.join();
}
}
public class GetLine extends Thread{
public void run()
{
read=s.nextLine();
System.out.println(read);
}
}
}
Even though I've tried using thread.join() to force the app to complete the System.out.println(read); before the next iteration of the while loop and printout of another System.out.println("Please enter text.");, I can't seem to get these two things to happen in the right order.
I'll often get another System.out.println("Please enter text.");, immediately followed by the result of System.out.println(read); from the last line of input (vs. the reverse order as expected.)
It seems that the System.out call waiting for the input from System.in is just allowed to return whenever, and the app goes on with other System.out calls in the meantime. I'd like to ensure that the app actually waits for the result of one System.out call before looping to the next.
(I have tried synchronized(System.out),(this) and (System.in), with wait() and notify(), all to no avail.)
I get
Please enter text.
(I type HELLO and hit enter)
Please enter text.
HELLO
(I type GOODBYE and hit enter)
Please enter text.
GOODBYE
where I'd have expected
Please enter text.
(I type HELLO and hit enter)
HELLO
Please enter text.
(I type GOODBYE and hit enter)
GOODBYE
Please enter text.
Basically, the order is inverted, and I can't figure out why.
I've seen a related question on the site in which the order of flushing of streams is mentioned, and the fix involving synchronized(System.out){} is given, but that did not solve this problem.

Categories

Resources