Check string for a character loop - java

I need to validate user input string to make sure it contains a comma. If it does not contain a comma it must print "Error" and allow for the user to re-enter input. I'm just not sure which loop to use. If else may work, but I need it to loop back to the scanner for the user input. Or a while loop that uses .contains? Thanks.

If you want to use a loop, I recommend the for-each loop:
boolean found = false;
while (found == false) {
String input = "this is a sentence, with a comma"; // read input here
for (char ch: input.toCharArray()) {
if (ch == ',') {
found = true;
}
}
if (found == false) {
System.out.println("Error");
}
}
there will probably be functions built-in in Java for this, like "string.contains(character)" returning a boolean value
input.contains(",")

Related

Creating a menu for user to make a choice and determine if it is a Palindrome

Example output
file1.txt contents
I have to do a project to determine whether user input is a Palindrome (same letters forwards as backwards). I must create a menu and the user selects whether to input through the console or through a file. I had no issue with reading from the console. I am having trouble producing the correct output through reading Files however.
For a file to be a palindrome, the whole file must be able to be read forwards and backwards and be equal. Then the file contents must be printed and labeled as a Palindrome. I am able to determine if a string is a palindrome within the file, but not the whole file itself. I tried to use .hasNextLine() and compare the lines, but the output is not exactly what is desired.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.InputMismatchException;
import java.util.Scanner;
public class PalindromeMachine { //begin class
public static void main(String[] args) { //begin main
boolean choice1 = false;
boolean choice2 = false;
boolean choice3 = false;
while (choice3 == false) {
//create a menu
System.out.println("Welcome to the Palindrome Machine!");
for (int i = 0; i < 35; i++) {
System.out.print("-");
}
System.out.printf("\n1. Read one word from the keyboard");
System.out.printf("\n2. Read one or more words from a file");
System.out.printf("\n3. Exit");
System.out.printf("\nEnter your selection: ");
//gather user input
Scanner user = new Scanner(System.in);
try {
int num = user.nextInt();
if (num > 3 || num < 1) {
System.out.println("Invalid menu option");
}
if (num == 1) {
choice1 = true;
}
if (num == 2) {
choice2 = true;
}
if (num == 3) {
choice3 = true;
}
} catch (InputMismatchException e) {
System.out.println("Invalid menu option");
}
//based on user selection, read in the word or read in lines from a file
while (choice1 == true) {
System.out.printf("Enter the word you would like to check: ");
String checkThis = user.next();
int front = 0;
int back = checkThis.length() - 1;
while (front < back) {
if (checkThis.charAt(front) != checkThis.charAt(back)) {
choice1 = false;
System.out.printf("%s: this word is not a palindrome\n\n", checkThis);
}
front++;
back--;
}
if (choice1 == true) {
System.out.printf("%s: this word is a palindrome\n\n", checkThis);
choice1 = false;
}
} //end while for choice 1
//read from file and determine if palindrome
while (choice2 == true) {
System.out.printf("Enter the file you would like to check: ");
String name;
name = user.nextLine();
try {
File pali = new File(name);
Scanner userRead = new Scanner(pali);
while (userRead.hasNextLine()) {
String checkThis = userRead.nextLine();
//palindrome info
int front = 0;
int back = checkThis.length() - 1;
while (front < back) { //palindrome
if (checkThis.charAt(front) != checkThis.charAt(back)) {
choice2 = false;
System.out.printf("\n%s: this file is not a palindrome",
checkThis);
}
front++;
back--;
} //end palindrome
if (choice2 == true && userRead.hasNextLine() != false) {
System.out.printf(checkThis
+ ": this file is a palindrome\n");
choice2 = false;
} else {
System.out.println("");
System.out.printf(checkThis);
}
} //end of while the file has text
} catch (FileNotFoundException e) {
System.out.printf("\nInvalid file");
}
} // end choice 2
//loop until the user exits + catch inputmismatch
} // end while it loop until exit
} //end main
} //end class
If your intent is to read the entire file and then check if the entire contents are a palindrome or not, then lines in general are a bit of a complicated mess.
Is:
Hello, there!
!ereht ,olleH
A palindromic file? Note that it ends in a newline, so if you attempt to compare byte-for-byte, it's not. If the intent is that it is supposed to 'count', then presumably you'd first trim (lop any whitespace off of the front and back of the entire thing) and then compare byte-for-byte?
If the file's encoding involves characters smearing out over bytes (common - UTF_8, the most common encoding, can do that for any character that isn't simple ASCII), byte-for-byte fails immediately, so I guess character-by-character? Java's 'character' is actually part of surrogate pairs, so symbols from the higher unicode planes, such as emoji, will thus immediately cause trouble (as the emoji is two characters, and therefore won't be the same backwards and forwards). Just go with 'eh, whatever, no files will contain emoji'? Or try to compare codepoints instead?
What about commas, capitals, and other symbol characters? Is this:
Hello, there!
Ereht, olleh!
supposed to 'count'? If you look at Just the actually letters and forget about casing, it is. But a char-by-char comparison will obviously fail. Before you say: That's not palindromic, the usual "A man, a plan, a canal, Panama!" requires that you disregard non-letters and disregard casing.
In any case, it all starts with reading the entire file as a string; Scanner is designed to read tokens (tokens are the things in between the separator), and it has some ugly misplaced baggage in the form of the nextLine() method that you probably shouldn't be using. In any case, it can't read the entire file in one go which makes this vastly more complicated than it needs to be, so step 1 is do not use it.
There's the new file API which is great for this:
import java.nio.file.*;
Path p = Paths.get(fileName);
String contents = Files.readString(p);
That will read the entire contents. We can then remove everything that isn't a letter from it:
contents.toLowerCase().replaceAll("[^a-z]", "");
That thing is a 'regular expression' which is a mini language for text manipulation. [^...] is 'match any character that isn't mentioned here', and a-z is naturally, everything from a to z. In other words, that says: Take the input, lowercase everything, then replace all non-letters with blank, thus giving you only the letters. I turns "A man, a plan, a canal, Panama!" into "amanaplanacanalpanama".
It even gets rid of newlines entirely.
Now you can use the principle at work in your code (start from the beginning and end, fetch the characters there, compare them. If not equal - it is not a palindrome. If equal, increment your 'front pointer', decrement your 'back pointer', and keep going with the comparisons until your pointers are identical, then it is a palindrome.
Scanner has only two uses:
Keyboard input. In which case you should never use .nextLine() (nextLine is broken. It does what the javadoc says it does, which not what anyone expects, hence, do not use it for this) - and always call .useDelimiter("\\R") immediately after making the scanner. This configures it the way you'd expect. Use .nextX() calls to fetch info. next() for strings .nextInt() for integers, etc. All next calls will read entire lines.
Tokenizing inputs. This is only useful if the input is defined in terms of tokens separated by separators. Only a few formats follow that kinda rule. Even your usual 'CSV' files don't, not really - you need custom CSV parsers for that.
"Read an entire file to see if it is palindromic" fits neither use.

How do I use boolean method correctly if I need two options?

The question is, if I need to chose only from two options in boolean method (Yes or No) how do I put it in IFs?
I try to do like this (see below), it underlines very last brace. If I use default return outside while (but I don't want to), it underlines first return (after first if).
static boolean isAnotherGamer() {
System.out.println("Play another game? Type in Y or N");
Scanner scanner = new Scanner(System.in);
String answer = scanner.nextLine();
while (true) {
if (answer.equalsIgnoreCase("Y")) {
break;
return true;
} else if (answer.equalsIgnoreCase("N")) {
break;
return false;
}
System.out.println("Input mismatch");
} //IDE underline this brace
}
Here is how I would do it. This allows any part of yes or no to be entered. I think it best to pass a Scanner instance rather than creating one each time. Using a regular expression allows for some latitude in the answer.
^$ - beginning and end of string.
(?i) - ignore case
ye?s? - says must have y but e and s are optional.
static boolean isAnotherGamer(Scanner scanner) {
System.out.println("Play another game? Type in Y(es) or N(o)");
while (true) {
String input = scanner.nextLine();
if (input.matches("(?i)^ye?s?$")) {
return true;
}
if (input.matches("(?i)^no?$")) {
return false;
}
System.out.println("Incorrect response, please enter Y(es) or N(o)");
}
}
Why can you not validate the input first, and then after the input is either a yes or no, decide on what to do. If it is not either, you can make the repetition statement continue to run until after you get what you need. The location of your return statement is the problem because if either if or else if statements are not true, the method will not return a boolean as your method signature suggests, and your method will just be an infinite loop.
Your method is declared to return a boolean. There is no return statement in the flow.
Assume you go into the endless loop. At this moment we evaluate what the user entered (why do we do that inside the endless loop? The answer does not change inbetween, does it?)
If it is 'y', we break the loop.
If it is 'n', we break the loop.
In any other case we print something and remain in the loop.
But as soon as the loop was broken -> where is the return statement?
So from my POV, the function should look like this:
static boolean isAnotherGamer() {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("Play another game? Type in Y or N");
String answer = scanner.nextLine();
if (answer.equalsIgnoreCase("Y")) {
return true;
} else if (answer.equalsIgnoreCase("N")) {
return false;
}
System.out.println("Input mismatch");
}
}
Because you've not set a default return value, if the user doesn't choose either "Y" or "N" then nothing is going to be returned so that's why you're getting an error.
Additionally, you shouldn't be putting any code after your break statements as those lines will be completely ignored (again, nothing returned as your return statements are after your breaks.)
You can just completely remove those break statements if you're just wanting to quit that method once you've got your boolean value or you can update a boolean variable for future use if you're wanting to keep running code inside your method. (I've provided an example of this)
System.out.println("Play another game? Type in Y or N");
Scanner scanner = new Scanner(System.in);
String answer = scanner.nextLine();
//To store the state of the user's answer
boolean providedAnswer = false;
//if the answer was yes, set the boolean's val to true
if(answer.equalsIgnoreCase("Yes")){
providedAnswer = true;
}
//output the boolean's value
System.out.println("User wanted to play again? " + providedAnswer);
//return the boolean value
return providedAnswer;
}```

Is there a way to write this program using another method than .hasNext?

Write a program that asks a user to input a string. Then asks a user to type in an index value(integer). You will use the charAt( ) method from the string class to find and output the character referenced by that index. Allow the user to repeat these actions by placing this in a loop until the user gives you an empty string. Now realize that If we call the charAt method with a bad value (a negative value or a integer larger than the size of the string) an exception will be thrown. Add the code to catch this exception, output a warning message and then continue with the loop
import java.util.Scanner;
class Main
{
public static void main(String[] args)
{
System.out.println("");
String s;
int ind;
Scanner sc=new Scanner(System.in);
while(sc.hasNext())
{
s=sc.next();
if(s.length()==0)
break;
ind=sc.nextInt();
try {
char ch=s.charAt(ind);
System.out.println("Character is "+ch);
}
catch(Exception e) {
System.out.println("Bad index Error!");
}
}
}
}
Yes. You could rely on assignment evaluating to the assigned value. Also, call Scanner.hasNextInt() before calling Scanner.nextInt(). Like,
System.out.println();
String s;
Scanner sc = new Scanner(System.in);
while (sc.hasNext() && !(s = sc.next()).isEmpty()) {
if (sc.hasNextInt()) {
int ind = sc.nextInt();
try {
char ch = s.charAt(ind);
System.out.println("Character is " + ch);
} catch (Exception e) {
System.out.println("Bad index Error!");
}
}
}
There is a bug; sc.next() cannot return an empty string in this code. Try editing it this way:
while(sc.hasNext()) {
s = sc.next();
if(s.length() == 0) {
System.out.println("Woah, Nelly!");
break;
}
// ...
}
See if you can get the program to print "Woah, Nelly!" by entering a blank line, or anything else. I can't, and assuming I understand the documentation correctly, it is impossible for the if condition to ever be true here (emphasis mine):
Depending upon the type of delimiting pattern, empty tokens may be returned. For example, the pattern "\\s+" will return no empty tokens since it matches multiple instances of the delimiter. The delimiting pattern "\s" could return empty tokens since it only passes one space at a time.
This pattern "\\s+" is the default one, and you haven't set a different one, so your scanner should never return an empty token. So the strict answer to "is there a way to write this program without the break statement?" is: yes, you can just delete the if(...) break; code and it doesn't change the behaviour in any way.
However, that's not really a solution to your problem because it doesn't give the user a way to exit the program. You should use nextLine() instead of next() to allow reading a blank line from the user.

How can I use something like (input == '\n') to determine when to stop accepting user input?

I have to convert an infix operation to a postfix one, however the infix operation must be inputted as one character per line. So instead of inputting something like this: 3-2, you would need to input something like this:
3
-
2
I had an idea of using =='\n' to determine whether the inputted character is a next line function so that would determine the end of the equation, but it doesn't work. I tried replacing it with a different character such as =='e', and that works perfectly. What can I do to fix this?
String string = "";
Scanner input = new Scanner(System.in);
boolean flag = true;
while (flag==true)
{
char charIn = input.next().charAt(0);
string = string + charIn;
if (charIn=='e') //inputting 'e' gives me my desired result
{
flag = false;
}
}
//code that passes string to InfixToPostfix method and prints out the answer. this part works fine
You did not specify that this was a school assignment or that you had certain restrictions, so this answer is admittedly a shot in the dark.
I would recommend using a StringBuilder within a loop and reading nextLine() instead of simply next(). This allows you to determine if the entry was empty (ie: the enter key was pressed without entering a character).
Also, we should allow the user to enter more than one character anyway (what happens when they try to enter 22 as a number). Abandoning the char type allows for this.
public static void main(String[] args) {
StringBuilder string = new StringBuilder();
Scanner input = new Scanner(System.in);
boolean flag = true;
while (flag) {
// Capture all characters entered, including numbers with multiple digits
String in = input.nextLine();
// If no characters were entered, then the [ENTER] key was pressed
if (in.isEmpty()) {
// User is done adding characters; exit the loop
flag = false;
} else {
// Otherwise, get the text entered and add it to our final string
string.append(in);
}
}
System.out.println("Final String: " + string);
}
Does this meet your needs?
This should do what you want. Reading just the first character has its limitations.
String string = "";
Scanner input = new Scanner(System.in);
boolean flag = true;
while (flag==true)
{
String nextLine = input.nextLine();
char charIn;
if(nextLine.length() > 0) {
charIn = nextLine.charAt(0); //This is bad idea as you can only operate on single digit numbers
System.out.println("charIn = " + charIn);;
string = string + charIn;
}
else
flag = false;
}

How do I avoid StringIndexOutOfBoundsException when char has no value?

Sorry if the title made no sense but I did not know how to word it.
The problem:
I'm making a multiple choice quiz game that gets either a, b, c or d from the user. This is no problem if they do as they are told, however if they don't type anything and just hit enter I get a StringIndexOutOfBoundsException. I understand why this is happening, but I'm new to Java and can't think of a way to fix it.
What I have so far:
System.out.println("Enter the Answer.");
response = input.nextLine().charAt(0);
if(response == 'a')
{
System.out.println("Correct");
}
else if(response == 'b' || response == 'c' || response == 'd')
{
System.out.println("Wrong");
}
else
{
System.out.println("Invalid");
}
Of course the program will never make it past the second line of code if the user types nothing, because you can't take the charAt(0) value of an empty String. What I'm looking for is something that will check if the response is null, and if so ask go back and ask the question to the user again.
Thanks in advance for any answers.
You can use a do-while loop. Just replace
response = input.nextLine().charAt(0);
with
String line;
do {
line = input.nextLine();
} while (line.length() < 1);
response = line.charAt(0);
This will continue to call input.nextLine() as many times as the user enters a blank line, but as soon as they enter a non-blank line it will continue and set response equal to the first character of that non-blank line. If you want to re-prompt the user for the answer, then you could add the prompt to the inside of the loop. If you want to check that the user entered a letter a–d you could also add that logic to the loop condition.
Either handle the exception(StringIndexOutOfBoundsException) or break this statement
response = input.nextLine().charAt(0);
as
String line = input.nextLine();
if(line.length()>0){
response = line.charAt(0);
}
Exception Handling:
try{
response = input.nextLine().charAt(0);
}catch(StringIndexOutOfBoundsException siobe){
System.out.println("invalid input");
}
Simple:
Get the input initially as a String, and put it into a temporary String variable.
Then check the String's length.
then if > 0 extract the first char and use it.
In addition #HovercraftFullOfEels' (perfectly valid) answer, I'd like to point out that you can "catch" these exceptions. For example:
try {
response = input.nextLine().charAt(0);
} catch (StringIndexOutOfBoundsException e) {
System.out.println("You didn't enter a valid input!");
// or do anything else to hander invalid input
}
i.e. if a StringIndexOutOfBoundsException is encountered when executing the try-block, the code in the catch-block will be executed. You can read more about catching and handling exceptions here.
StringIndexOutofBoundException will occur in the following situation also.
Searching a string which is not available
Match with the string which is not available
for ex:
List ans=new ArrayList();
temp="and";
String arr[]={"android","jellybean","kitkat","ax"};
for(int index=0;index < arr.length;index++ )
if(temp.length()<=arr[index].length())
if(temp.equlsIgnoreCase((String)arr[``index].subSequence(0,temp.length())));
ans.add(arr[index]);
the following code is required to avoid indexoutofboundexception
if(temp.length()<=arr[index].length())
because here we are cheking the length of src string is equal or greater than temp .
if the src string length is less than it will through "arrayindexoutof boundexception"

Categories