So I'm fairly new to programming, and I'm working on a simple practice program that finds a letters order in the alphabet. This should have been pretty easy...but for some reason I get a StringIndexOutOfBoundsException when I add a while loop. So the program does do what it should the first time...but will not allow me to test again with out re-running the program. I tested the while loop with nothing but a simple print statement inside and it worked, so I'm confused as to why the while loop isn't working with my alphabet program.
Any help would be greatly appreciated
thanks!
import java.io.*;
public class test {
public static void main(String[] args) throws IOException
{
BufferedReader in;
in = new BufferedReader (new InputStreamReader (System.in));
boolean again=true;
String response;
while (again)
{
System.out.println("Enter a letter to find it's order in the alphabet");
char theLetter = (char) in.read();
System.out.println(theLetter + " is the " + convertLetter(theLetter) + "th letter of the alphabet");
System.out.println("want to play again?");
response = in.readLine();
if (response.charAt(0)=='n')
{
again=false;
}
}
System.out.println("end program");
}
public static int convertLetter(char TheLetter)
{
//number value 'a'=97
//number value 'b'=98
//number value 'c'=99
//subtracting 'a' from any other number will reveal how many places away that number is from the start
//thus finding it's chronological place in the alphabet
int NumberValue= (int)TheLetter;
int a = 'a';
int CalulateOrder = (NumberValue - a) + 1;
return CalulateOrder;
}
}
When you hit enter for the original char, that newline is still in the buffer since you only call read() and only get 1 character, leaving the newline in the buffer from hitting enter. So when you call readLine it simply hits that newline and returns an empty string.
You can test this by typing something with more than one character when it first asks you for a character, and it will go for a second loop since the readLine will return a non-empty string.
To fix this change your original read() to readLine() so that it gets the newline caused from you hitting enter, then just grab the first character from the string.
This should fix it:
import java.io.*;
public class test {
public static void main(String[] args) throws IOException {
BufferedReader in;
in = new BufferedReader (new InputStreamReader (System.in));
boolean again=true;
String response;
while (again) {
System.out.println("Enter a letter to find it's order in the alphabet");
response = in.readLine();
if (response.length() > 0) {
char theLetter = response.charAt(0);
System.out.println(theLetter + " is the " + convertLetter(theLetter) + "th letter of the alphabet");
System.out.println("want to play again?");
response = in.readLine();
if (response.length() > 0 && response.charAt(0)=='n') {
again=false;
}
}
}
System.out.println("end program");
}
public static int convertLetter(char TheLetter) {
return (TheLetter - 'a') + 1;
}
}
if (response.charAt(0)=='n')
If the String is empty "", there will be no character at position 0. Check for it before doing charAt()
is the length of response null or ""? if it is you will not be able to get the char at index 0
I bet the culprit is that you're hitting "enter" at the want to play again? prompt. The in.readLine(); returns the line without the trailing newline (see the javadocs), which means that if you only press "enter" it will return an empty string, thus the StringOutOfBoundException while checking the first char.
Check for the empty string before checking for the char:
if(response.length() > 0 && response.charAt(0) == 'n')
The only place you access a string index is at if (response.charAt(0) == 'n') so that is most likely your problem area.
if(response.length() > 0 && response.charAt(0) == 'n')
Should do the trick.
Edit:
As #TreySchroeder points out, there is another problem with your program, in that you don't read the full line at first. Put in.readLine(); after your initial theLetter = (char) in.read();, and use this fix for the other issue.
if (response.isEmpty() && response.charAt(0)=='n')
will avoid the exception.
Related
Hi I'm finishing an assignment, however I'm getting the wrong output.
The goal of the project is to reverse a string.
So it's supposed to take in a line of text as input, and outputs that line of text in reverse. The program repeats, ending when the user enters "Done", "done", or "d" for the line of text.
Ex: If the input is:
Hello there
Hey
done
the output is:
ereht olleH
yeH
My code:
import java.util.Scanner;
public class LabProgram {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
String str;
while (true) {
str = scnr.nextLine();
if (str.equals("quit") || str.equals("Quit") || str.equals("q")) break;
for (int i = 0; i < str.length(); i++) {
System.out.print(str.charAt(str.length() - i - 1));
}
System.out.println();
}
}
}
My current code is that however output is coming back as:
Input
Hello there
Hey
done
Output
ereht olleH
yeH
enod
Expected output
ereht olleH
Cannot figure out what I'm doing wrong.
/*
I don't know what you know, so I am not sure how your professor
wants you to complete this, but I will do what comes to mind for myself.
*/
//Instead of while(true) I like to use do while, which runs once automatically, and continues running until a condition is met
do {
str = scnr.nextLine();
int i = 0;
//This isn't the cleanest way to solve this, especially because it doesn't remove the space before done.
//You could add more if statements for that, but the cleanest way would be to split the words into a String array
// and check if any of the values of the array equal done, and remove it before flipping it around
if(str.toLowerCase().contains("done"))
i = 4;
else if(str.toLowerCase().contains("d"))
i = 1;
while (i < str.length()) {
System.out.print(str.charAt(str.length() - i - 1));
i++;
}
System.out.println();
}
while (!str.toLowerCase().contains("done") || !str.toLowerCase().contains("d")); //This replaces that if statement from before
you are using .equals() to check if the line is equal to one of your break words, but you are giving it the input Hello there Hey done, so it will not detect the the break word (ignoring the fact that you gave it done, not quit, I'm assuming that was a typo), so to detect that, you would either have to check if the line contains that word and if so, toggle a boolean and remove the word and any text after it from the line, e.g:
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
String str;
boolean end = false;
while (!end) {
str = scnr.nextLine();
if (str.contains("quit") || str.contains("Quit") || str.contains("q")) { // checks if str contains the word, so if you write "hello quit" it will still detect it.
str = str.substring(0,str.toLowerCase().indexOf("q")); // cuts off the string from the q.
end = true;
}
for (int i = 0; i < str.length(); i++) {
System.out.print(str.charAt(str.length() - i - 1));
}
System.out.println();
}
}
otherwise, you would just need to add the quit to the line after, and then it would work, so you would put in Hello there Hey then press enter, and then quit, and that will work.
When I run the program and the user input field comes up, when I just hit enter without entering anything in the blank space another input field comes up. This happens over and over if I keep hitting enter. If there is a way to solve this please let me know. I couldn't find anything to fix it in the documentation.
import java.util.Scanner;
import java.util.Random;
class Game {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//generate a random number
//take user input
//check the input act appropriately
boolean running = true;
boolean guessed = true;
boolean realInt = true;
int number = 0;
int input = 0;
String firstName=" ";
System.out.print("want to play the game? Yes/No: ");
firstName = sc.next();
while (running) {
if (guessed && (("yes".equals(firstName)) | ("cheater".equals(firstName)))){
System.out.println("I have chosen a random value");
System.out.println("Have a go at guessing it");
Random rand = new Random();
number = rand.nextInt(10) + 1;
guessed = false;
}
if(("yes".equals(firstName)) | ("cheater".equals(firstName)))
{
if(sc.hasNextInt()) {
realInt=true;
input = sc.nextInt();
}
else{
System.out.println("That is not an integer.");
running = false;
}
}
else
running = false;
if((((input != number) && realInt)&&(input != -1))){
System.out.println("Plsease try again");
}
//below line sets up when to stop the program, when -1 is entered
if (input == -1){
running = false;
}
else{
guessed = input == number;
}
//below lines are cheat codes
if (input == -5){
System.out.println("Answer: " + number);
}
if ("cheater".equals(firstName) && (input != number)){
System.out.println("Answer: " + number);
}
}
}
}
This is due to the way how Scanner's next() method reads input.
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.
So even if you hit number of enters, there will not be any token and hence Scanner is just waiting from user to have one valid token so that in can read and continue reading the next token.
public String next()
Finds and returns the next complete token from this scanner. A complete token is preceded and followed by input that matches the delimiter pattern. This method may block while waiting for input to scan, even if a previous invocation of hasNext() returned true.
Solution:
Use Scanner's hasNextLine() and nextLine() methods.It will allow you to capture empty or white-space lines. Refer to the API on java site for other methods.
I'm learning Java with the book: Java. A begginer's guide.
The book shows the following example:
// Guess the letter game, 4th version.
class Guess4 {
public static void main (String args[])
throws java.io.IOException {
char ch, ignore, answer = 'K';
do {
System.out.println ("I'm thinking of a letter between A and Z.");
System.out.print ("Can you guess it: ");
// read a character
ch = (char) System.in.read();
// discard any characters in the input buffer
do {
ignore = (char) System.in.read();
} while (ignore != '\n');
if ( ch == answer) System.out.println ("** Right **");
else {
System.out.print ("...Sorry, you're ");
if (ch < answer) System.out.println ("too low");
else System.out.println ("too high");
System.out.println ("Try again!\n");
}
} while (answer != ch);
}
}
Here is a sample run:
I'm thinking of a letter between A and Z.
Can you guess it: a
...Sorry, you're too high
Try again!
I'm thinking of a letter between A and Z.
Can you guess it: europa
...Sorry, you're too high
Try again!
I'm thinking of a letter between A and Z.
Can you guess it: J
...Sorry, you're too low
Try again!
I'm thinking of a letter between A and Z.
Can you guess it:
I think the output of the program should be:
I'm thinking of a letter between A and Z.
Can you guess it: a...Sorry, you're too high
Try again!
Without a \n between 'a' and '...Sorry, you are too high'. I don't know why apears a new line. The do-while erases it.
Thank you.
ch = (char) System.in.read();
actually reads a single character.
if the input is - a\n only the first character is read and stored in ch. which is a in this case.
do {
ignore = (char) System.in.read();
} while (ignore != '\n');
This is used to remove any unwanted characters.
Why did they use this?
We just need a single letter.
So if the user had given an input which is not a single character, like "example" and if your code didn't have the loop check.
First the ch becomes e, then x ....so on.
Even without the user entering a alphabet the previous input is considered to be entered.
what if only Enter(\n) was pressed
As even \n is considered a character it is also read. In the comparison the ASCII value of it is considered.
Have a look at this question. In which a user didn't check for the unnecessary characters and got an unexpected output.
Instead doing stuff char-by-char, you could easily utilize a Scanner:
replace
// read a character
ch = (char) System.in.read();
// discard any characters in the input buffer
do {
ignore = (char) System.in.read();
} while (ignore != '\n');
with
Scanner in = new Scanner(System.in); //outside your loop
while(true) {
String input = in.nextLine();
if(!input.isEmpty()) {
ch = input.charAt(0);
break;
}
}
import java.util.*;
public class VowelCounter
{
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
System.out.println("Input a series of characters: ");
String letters = keyboard.next();
int count = 0;
for (int i = 0; i < letters.length(); i++)
{
char characters = letters.charAt(i);
if (isVowel(characters) == true)
{
count++;
}
}
System.out.println("The number of vowels is: " + count);
}
public static boolean isVowel(char characters)
{
boolean result;
if(characters=='a' || characters=='e' || characters=='i' || characters=='o' || characters=='u')
result = true;
else
result = false;
return result;
}
}
The code works but im suppose to input "Spring break only comes once a year." which if i do with the spaces my program will only find the vowels of Spring. how do i make it so it will skip the spaces and read the whole sentence.
This is your problem:
String letters = keyboard.next();
It has nothing to do with the vowel-counting part - but everything to do with reading the value. The Scanner.next() method will only read to the end of the token - which means it stops on whitespace, by default.
Change that to
String letters = keyboard.nextLine();
and you should be fine.
You should verify this is the problem by printing out the string you're working with, e.g.
System.out.println("Counting vowels in: " + letters);
When you do:
String letters = keyboard.next();
The Scanner stops reading at the first whitespace.
To read the complete phrase until you press enter, you should use nextLine() instead:
String letters = keyboard.nextLine();
Just use
String letters = keyboard.nextLine();
instead of
String letters = keyboard.next();
This is because .nextLine() will read line by line so that you can have your complete statement in latters. Hope this will help you
This is a simple question selection, and then answer program:
import java.util.Scanner;
public class Mains {
static Scanner console = new Scanner(System.in);
static Tof tof = new Tof();
static int Ievel = 0;
static int Input = 0;
static boolean GAME = true;
static boolean AT_START = true;
static boolean IN_QUESTION = false;
public static void main (String[] args) {
while (GAME) {
String InputS = "";
if (AT_START) {
System.out.println("Welcome to the game! Please select a number from 1 to 10.");
AT_START = false;
}
if (!IN_QUESTION)
Input = console.nextInt();
if (Input == -1) {
GAME = false;
console.close();
} else {
String question = tof.getQuestion(Input);
String answer = tof.getAnswer(Input);
System.out.println(question);
IN_QUESTION = true;
while (IN_QUESTION) {
InputS = console.nextLine();
if (InputS != console.nextLine()) {
if (InputS.equals(answer)) {
System.out.println("Correct!");
} else {
System.out.println("Incorrect. " + InputS + " " + answer);
}
}
}
}
}
}
}
Problem:
When entering the IN_QUESTION loop, and writing a answer, it will always be incorrect.
That's because the InputS variable is ALWAYS empty, no matter what, while it has console.nextLine() set on it.
Why is it empty? How do I fix this?
In-case you need the other class Tof: http://pastebin.com/Fn5HEpL2
nextInt doesn't get the line terminator after the integer and you're reading from the console twice (the second time being in the if-statement).
So if you enter:
123
apple
The following happens:
Input gets assigned a value of 123
InputS gets assigned an empty string
InputS gets compared against apple and it is not equal (from InputS != console.nextLine() - I'm not sure why it's there)
You can fix it by:
Putting a console.nextLine(); after console.nextInt();
OR
Use Input = Integer.parseInt(console.nextLine()) instead of nextInt
Removing this - if (InputS != console.nextLine())
You're reading from the console twice. This should work:
while (IN_QUESTION) {
InputS = console.nextLine();
if (InputS.equals(answer)) {
System.out.println("Correct!");
} else {
System.out.println("Incorrect. " + InputS + " " + answer);
}
}
The problem is that the new line character was not read by the nextInt() method so it remain in the scanner buffer and when the next time you called nextLine() that character was printed first.
This is how to fix the issue:
//empty the newline character from the scanner
console.nextLine();
while (IN_QUESTION) {
InputS= console.nextLine();
if (InputS.equals(answer)) {
System.out.println("Correct!");
} else {
System.out.println("Incorrect. " + InputS + " " + answer);
}
}
You call console.nextLine twice. This means that you read a line that you'll check, and another you won't. This is probably not what you are after. Also note that your initial call of nextInt will not consume the newline you pressed after entering the number. You need a nextLine right after that, but before the main loop.
Some general remarks:
uppercase names are only for constants, so your variables should be lowercase;
you should really be using local variables instead of static ones. Right now this isn't hurting you, but it soon could.