Debugging do-while loop appear more than one statements - java

I write a code for o-while loop where I take an input from user and check if it is equal to 'c' or 'C' the exit from the loop. If input other than c or C entered the internal statement of do block is appearing 3 times and if i just enter press without pressing any character then do block's inner statement appears 2 times why?? Can anyone explain
int ch = 0;
do {
System.out.println("Press C or c to continue.");
ch = System.in.read();
}
while(ch !='C' && ch !='c');

(Judging from the output you described, you are probably on a Windows machine, right?)
read returns the next character in the input stream. When you enter C or c, and then press enter, you have actually entered three characters:
c
\r
\n
The last two characters together is the Windows way of representing a new line. Since there are three characters to read, read gets called three times before you are prompted to enter anything again, so println gets called three times as well.
If you just press enter, then you have only entered two characters:
\r
\n
so two lines are printed.
To fix this, you can use a java.util.Scanner. Scanner has a nice method called nextLine, which returns everything the user enters until it reaches a new line character.
Scanner sc = new Scanner(System.in);
String line = "";
do {
System.out.println("Press C or c to continue.");
line = sc.nextLine();
}
while(!ch.equals("C") && !ch.equals("c"));

Related

Why does this While loop cycle twice?

I made this while loop that is supposed to fulfill functions for different shapes and after it fulfills the function for that shape, it will keep asking for shapes until the user types "Exit". I have only done Triangles so far so I just have some filler functions to fulfill to make sure that it loops correctly. The problem is, after I'm done with triangles, it will print the menu twice before asking for an input instead of just printing once. Can anyone explain this to me?
while(password){
System.out.println();
System.out.println("---Welcome to the Shape Machine---");
System.out.println("Available Options:");
System.out.println("Circles");
System.out.println("Rectangles");
System.out.println("Triangles");
System.out.println("Exit");
String option = keyboard.nextLine();
if(option.equals("Exit")){
System.out.println("Terminating the program. Have a nice day!");
return;
} else if(option.equals("Triangles")){
System.out.println("Triangles selected. Please enter the 3 sides:");
int sideA = 0;
int sideB = 0;
int sideC = 0;
do{
sideA = keyboard.nextInt();
sideB = keyboard.nextInt();
sideC = keyboard.nextInt();
if(sideA<0 || sideB<0 || sideC<0)
System.out.println("#ERROR Negative input. Please input the 3 sides again.");
} while(sideA<0 || sideB<0 || sideC<0);
if((sideA+sideB)<=sideC || (sideB+sideC)<=sideA || (sideA+sideC)<=sideB){
System.out.println("#ERROR Triangle is not valid. Returning to menu.");
continue;
} else {
System.out.println("good job!");
}
}
}
It might be that you are using keyboard.nextLine();. In your code outside the while loop make sure that you are always using .nextLine() and nothing else.
Reasoning: If you use .next(), it'll only consume one word so the next time you call .nextLine(), it'll consume the end of that line.
After you say sideC = keyboard.nextInt() the carriage return that you typed (after typing the number) is still in the input buffer. Then you print the menu and execute String option = keyboard.nextLine(); That command reads up to and including the first newline it finds, which is the newline that is still in the buffer.
So option is now a bare newline character, which does not match "Exit" or "Triangle", so it loops again and prints th menu again.
This problem is caused by left-over characters like space, carriage-return, newline, form-feed in the input buffer.
Since the next keyboard.nextLine() doesn't match any of given options (and since there is no "else" at the bottom of while loop to deal with this case), the control goes into next iteration, prints the options again. Based on surrounding context of processing of input, there are several good answers to address this problem on SO.
Since your intention is to skip over all blanks, carriage-returns, newlines, form-feeds till you get a valid string (option) again, the following code works best in a case like yours.
System.out.println();
System.out.println("---Welcome to the Shape Machine---");
//...
System.out.println("Exit");
String option = keyboard.nextLine();
keyboard.skip("[\\s]*");

Counting number of times a character is inputted--Do-While Loops Java

I'm a bit confused as to why I need the do-while loop in this piece. What I am trying to do is count the number of times a user inputs a character. The count should stop when the user types a ".". When I try to run the program without the do-while, the count of x is multiplied by 3. I've read online that the console input is line buffered. The way I understand it, is a an entire line is created by one character and as such there are actually more characters? Is my understanding correct? And if possible, could I have an explanation of the do-while loop?
public class readCharLengths {
public static void main(String args[])
throws java.io.IOException {
char typed, ignore;
int x=0;
for ( ; ; ) { //infinite loop to keep reading in values
typed = (char) System.in.read(); //get typed character
do { //confused here
ignore = (char) System.in.read(); //confused here
} while (ignore != '\n'); //confused here
if (typed =='.') break; //break loop when . is typed
x++; //increment x
}
System.out.println("The number of characters is: " + x); //print x
}
}
It depends on the circumstances around how a user is giving input into the console. If they insert one character at a time, each on a separate line. Or if they input a string of characters, basically like a sentence, and then you count the number of characters until a period is reached.
If it is one character per line, I would suggest:
int x = 0;
Scanner in = new Scanner(System.in);
while (true) {
String input = in.nextChar();
if (input.equals('.') {
break;
} else {
x++;
}
}
If it is a string of characters, I would suggest:
int x = 0;
Scanner in = new Scanner(System.in);
String input = in.nextLine();
for (int i=0; i<input.length(); i++) {
if (input.charAt(i).equals('.') {
break;
} else {
x++;
}
}
To answer what a do...while loop is, I'm going to go into some very basic programming concepts. I don't mean to be condescending if I come across that way: I just don't know your skill level with programming, so I'm assuming you are very new to it.
First, let me explain the concept of a loop condition. A loop condition is code that, when it is evaluated while your program runs, will either come out to true or false. So, in the case of a regular while loop, the format is:
while (loop condition) {
run some code, maybe multiple times
}
When your code reaches the while line of code it evaluates the condition and decides whether to run the code inside the loop's braces.
Let's say your condition is "x must be less than 5". You might have a while loop like this:
int x = 0;
while(x < 5) {
System.out.println("A");
x++;
}
This code will print A on 5 lines because x = 0 when it reaches the while statement the first time, and since 0 < 5 evaluates to true, the loop's code is going to execute. When the end of the loop is reached, it jumps up to the loop condition and evaluates it again. This time, x = 1 because we added 1 to x. Since 1 < 5, the loop happens again. This happens a total of 5 times and then when it evaluates the loop condition, you have it try 5 < 5, which is false. It skips the loop code and continues the program at this point.
A do...while loop is based on the same idea. Instead of checking the loop condition at the start of the loop, it is checked at the end. So...
int x = 0;
do {
System.out.println("A");
} while(x < 0);
This code will output A once. Even though the loop condition is not met (since x starts at 0), when you use a do...while, the loop code is always executed at least once. At the end of the loop, the condition is checked and since 0 < 0 is false, the loop does not repeat.
So, on to how System.in.read() works. You have it right that it buffers the input until a linebreak is reached. But do you actually know what that means?
Here's how it works. You start typing stuff into the console. Say you type aabbcc and then press enter. Your program waits when it calls System.in.read() until user input is sent back to the program. It does not continue running when the first a is typed though! Your program only gets to continue running once you press enter (that is, a linebreak is sent).
The idea of buffering input is that all the letters you typed are stored and available once your program starts running again. So when your program runs after you have entered aabbcc, all of those letters are available (and also the linebreak for the enter key you pressed).
With your code, that means that the first time you call System.in.read(), you get back the character a, but there is still abbcc and newline waiting. It enters the loop and reads each character. So it reads a, then b, then b, then c, then c, then newline. At this point the loop condition is false and the loop ends.
Well, there are a couple of things about this.
First, this might not do what you want because the do/while loop will consume every character after the first one without incrementing the counter until it hits the LF. So, your count will always be 1 with the do/while loop in place assuming you type at least one character and then hit Enter. However, if your intention is that the user is allowed to enter only one character at a time (followed by Enter), then see the second item.
Second, console input defaults to buffered until you press Enter. So, if you take the do/while loop out, enter a single character and press Enter, you'll actually get three characters on Windows--the character you typed, CR and LF. Assuming you're testing with single characters, that would explain the multiplication by 3.

Scanner nextLine() issues

I've been working on a programming assignment that acts as a Scrabble dictionary for a while now. The program takes input from the user and outputs a file with a list of words, depending on what the user requests from a menu. The problem I've been having has to do with Scanner.nextLine().
I'm not aexactly sure why, but for some reason I have to press enter once sometimes before my code will take my input and store it as the variable. Essentially, I end up entering the input twice. I tried inserting Scanner.nextLine() around the code to "take up" the empty enter/spaces but it doesnt work, and I have to press enter multiple times to get it to process what I want.
Does anybody have any suggestions? I'd appreciate any and all help.
Here is a bit of the code:
System.out.println("Enter the length of the word you are" + " searching for.");
int n = -1;
while(!(n >=0)) {
if(in.hasNextInt())
n = in.nextInt();
else {
System.out.println("You have not entered a valid number.
Please enter a real number this time.");
in.nextLine();
}
}
in.nextLine();
System.out.println("Enter the first letter of the words" + " you are searching for.");
String firstLetter = "";
while(!(firstLetter.length() == 1)) {
if(in.nextLine().length() > 1) {
System.out.println("You have not entered a valid letter.
Please press enter and enter only one real letter.");
}
else if(in.hasNextInt()) {
System.out.println("Do not enter a number. Please enter one real letter.");
}
else {
in.nextLine();
firstLetter = in.nextLine();
break;
}
}
At the end of this, I have to press enter once and then input to get it to store anything in the variable firstLetter. I assume it has something to do with the nature of nextLine(), as the conditions using nextInt() give no issues.
It's because you're using both nextLine() and nextInt(), what's going on is that nextLine() is searching for a new line (enter) and nextInt will automatically stop the search if any integer is typed through System.in.
Rule of thumb: Just use Scanner.nextLine() for your input, then convert your string from Scanner.nextLine() accordingly through Integer.parseInt(string), etc.
I think you're overcompensating with too many nextLines. You may want to do that once to clear the line after the int is inputted, for example, to clear the newline, but the second time here just absorbs an extra line of input:
System.out.println("You have not entered a valid number. Please enter a real number this time.");
in.nextLine();//first time
}
}
in.nextLine();//this second time is unnecessary.
The same thing happens with your duplicate uses here:
in.nextLine();
firstLetter = in.nextLine();
break;
You should only add an extra in.nextLine() immediately between inputting nextSOMETHINGELSE() and another nextLine().
EDIT:
Additionally, note that whenever you call in.nextLine(), you are absorbing a line of input. For example, this line should be fixed:
if(in.nextLine().length() > 1){
because it reads in a line, using it up, and then checks whether that (now used-up) line is long enough.

Java, do while loop runs twice before asking for input again

I am just polishing my java skills and I wrote out this code to play around with keyboard input and do while loops.
package Chapter3;
import java.io.IOException;
public class convertCase {
public static void main(String args[]) throws IOException {
char ch = 'a';
do {
System.out.println("please type in a value: ");
ch = (char) System.in.read();
if((int) ch < 96) {
ch += 32;
int newCh = (int) ch;
System.out.println("The lowercase version is: " + (char)newCh);
}
else if((int) ch >96) {
System.out.println("You have typed in" + ch);
ch -= 32;
int newCh = (int) ch;
System.out.println("the uppercase version is: " + (char)newCh);
}
} while(ch!='.');
}
}
Problem is that when I test it the 'while loop' runs twice before asking for input instead of just the once:
please type in a value:
a
You have typed ina
the uppercase version is: A
please type in a value:
The lowercase version is: *
please type in a value:
L
The lowercase version is: l
please type in a value:
The lowercase version is: *
please type in a value:
Can someone bring clarity to this situation??
That's because
System.in.read();
takes in every key pressed. that is, in your case, the 'a' key, and the 'return' key.
If you want your functionality then use the following:
Scanner scanner = new Scanner(System.in);
And then use:
String line =(char)scanner.nextLine();
and then parse the value.
It is looping twice because it is processing the newline that follows each character.
You are processing the newline character as if it is legitimate input. You should either read the entire line (including the newline, perhaps using a Scanner) and then process the first character of the line or simply add a test to skip newlines in your loop logic.
P.S. Converting case by adding or subtracting 32 is a really awful approach. It won't work with anything but a-z and A-Z (in the English alphabet). It won't work for most characters outside the Basic Latin block and shouldn't be used at all for characters that have no alternate case (such as newline). You should be using Character.toUpperCase() and Character.toLowerCase() instead.
Answer taken from Book "Java: A Beginner's Guide"
The answers mentioned above are right as well. Just for more clarification, I will post this.
do {
System.out.print("Pres a key followed by Enter: ");
//get a char
ch = (char) System.in.read();
//REFERRING TO THIS PART
do{
ignoreNewLineENTER = (char) System.in.read();
}
while (ignoreNewLineENTER != '\n');
} while (ch != 'q');
console input is line buffered—you have to press ENTER before characters are sent. Pressing ENTER causes a carriage return and a line feed (newline) sequence to be generated. These characters are left pending in the input buffer. Also, if you typed more than one key before pressing ENTER, they too would still be in the input buffer. This loop discards those characters by continuing to read input until the end of the line is reached. If they were not discarded, then those characters would also be sent to the program as guesses, which is not what is wanted. (To see the effect of this, you might try removing the inner do-while loop.) In Chapter 10, after you have learned more about Java, some other, higher-level ways of handling console input are described. However, the use of read( ) here gives you insight into how the foundation of Java's I/O system operates. It also shows another example of Java's loops in action.

findWithinHorizon(".",0).charAt(0) Clarification

I'm having trouble understanding the source below:
myChar1 = myScanner.findWithinHorizon(".",0).charAt(0);
System.out.println(myChar1);
myChar2 = myScanner.findWithinHorizon(".",0).charAt(0);
System.out.print(myChar2);
I understand what it does, but I'm just having a bit of a trouble understanding how it works.
The actual prompting of the user for input is done at the first line right? but the real meaning of the first line is: "put the first char of input in myChar1". Then what happens? It seems the input still stays inside myScanner because when I use it in myChar2 I get the second char, but why? why not the first char? Does findWithinHorizon(".",0).charAt(0) deletes the char that is assigned to the variable?
And last question: if in the first line the program prompts the user for input why doesn't it do it again in the second line?
Also, a quick recap of the (".",0) would be helpful as well.
Perhaps the piece you are missing is that findWithinHorizon actually takes a regular expression as the String argument. In a regular expression, . matches any character (except a new line).
A call to findWithinHorizon(".", 0) simply finds the next character in the input and advances the Scanner past whatever was found.
So for example,
Scanner in = new Scanner("abc123");
for(;;) {
String found = in.findWithinHorizon(".", 0);
if(found == null) break;
System.out.println(found);
}
the output is:
a
b
c
1
2
3
The reason it does not prompt for input at the second line is that is the way Scanner and System.in work together. They will only block and prompt for input if there is no more existing input to consume. As a short example, try this out:
Scanner in = new Scanner(System.in);
while(true) {
System.out.println(in.findWithinHorizon(".", 0));
}
That will loop infinitely, repeating back whatever you input, character by character. It will only prompt for more when it's done with the prior input. On the first iteration, Scanner will call read on System.in which will block and wait for input. When the input runs out, read will block again.

Categories