Replacing a String statment that's being used by a constructor - java

So I'm working on a project to count the number of vowels and consonants of a desired string. I've got almost everything working, but I can't seem to get the option to replace the string with a new one to work properly. I think it's a problem with having the new choice be applied to the Driver construct but I can't seem to figure out a way to do that without breaking the program.
import java.util.*;
public class Driver{
private String entry;
int vowels = 0;
int cons = 0;
public Driver(String input){
entry = input;
this.count();
}
public boolean isVowel(char x){
return (x == 'A' || x == 'E' || x == 'I' || x == 'O' || x == 'U' ||
x == 'a' || x == 'e' || x == 'i' || x == 'o' || x == 'u');
}
public boolean isConsonant(char x){
return (((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z')) && !isVowel(x));}
public int getVowels(){
return vowels;
}
public int getConsonants(){
return cons;
}
public void count(){
int l = entry.length();
for(int i = 0; i < l; i++){
if(this.isVowel(entry.charAt(i))){
vowels++;
}else{
if(this.isConsonant(entry.charAt(i))){
cons++;
}
}
}
}
static Scanner kb = new Scanner(System.in);
public static void main(String[] args){
int choice; //Choice from menu
int vowels = 0; //# of vowels in entry
int cons = 0; //# of consonants in entry
String entry; //User's input
System.out.print("Enter a string:");
entry = kb.nextLine();
do{
Driver sentence = new Driver(entry);
System.out.println("Enter a number");
System.out.println("1. Count the number of vowels in the string");
System.out.println("2. Count the number of consonants in the string");
System.out.println("3. Count both the vowels and consonants in the string");
System.out.println("4. Enter another string");
System.out.println("5. Exit the program:");
choice = kb.nextInt();
switch(choice){
case 1:
System.out.println("Vowels: " + sentence.getVowels());
break;
case 2:
System.out.println("Consonants: " + sentence.getConsonants());
break;
case 3:;
System.out.println("Vowels: " + sentence.getVowels() + "\nConsonants: " + sentence.getConsonants());
break;
case 4:
System.out.print("Enter a string:");
entry = kb.nextLine();
//Driver sentence = new Driver(entry);
break;
default:
System.out.println("Please enter a value input: ");
}
}while(choice != 5);
}
}

You should have the Driver Class on its own (without the main() method).
Then create another Class that will be your startup Class which will contain the main() method). For the sake of argument let's call it VowelsAndConsonants.
The problem that's causing all the grief is your keyboard entry of 1 to 5 for the Console menu. You are using the Scanner.nextInt() method which is okay as long as you know that the whatever is entered is not all consumed and remains within the Scanner buffer and this is because the Scanner.nextInt() method doesn’t read and consume the line separator that is applied when the Enter Key is hit. So, when Scanner.nextLine() is used as the next Scanner method the first thing it gets hold of is that line separator that's held within the Scanner buffer which in turn is just like hitting the Enter key and therefore it skips what was typed. On the other hand the Scanner.nextLine() method does read in and consume the line separator. One way to get around this problem is to add (in your case) kb.nextLine(); directly after the choice = kb.nextInt(); code line. This forces the line separator to be consumed and empties the buffer. In essence the menu would then look something like this:
Driver sentence = new Driver(entry);
do {
System.out.println("Enter a Menu choice (1 to 5): ");
System.out.println("1. Count the number of vowels in the string");
System.out.println("2. Count the number of consonants in the string");
System.out.println("3. Count both the vowels and consonants in the string");
System.out.println("4. Enter another string");
System.out.println("5. Exit the program:");
choice = kb.nextInt();
kb.nextLine(); // Consume
..... the rest of your do/while code .....
}
EDIT: Based on your Question in Comment: "I'm curious as to why
there is a difference in how the line separator is dealt with tho. Is
this just something that is in Java, or is there a reason that it
isn't consumed from nextInt()?"
The Scanner Class is quite involved. It is by design that the nextInt() does this since Scanner can work based on tokens. You can use nextInt() to accept multiple numbers on a single input using (for example) a whitespace delimiter and then with the Scanner.hasNextInt() or Scanner.hasNext() methods in conjuction with the Scanner.nextInt() you can individually acquire each value, for example:
Scanner kb = new Scanner(System.in).useDelimiter(" *");
System.out.println("Enter numbers delimited with a white-space: ");
while (kb.hasNextInt()) {
int x = kb.nextInt();
System.out.println(x);
}
If you were to run this code and at the prompt enter on one line:
2 4 6 8 10
(note the whitespace between numbers) you will see a display within the Console window of:
2
4
6
8
10
Through each iteration of the while loop x would equal the next integer token from the line of numbers entered. This sort of thing however is best suited for reading numbers from a text file which Scanner can do as well. Read up on the Scanner Class.

Related

Method to check if the string contains certain elements that accepts a parameter String

I am a student and kind of new to Java. For my homework I have to:
Ask the user to input a number (at least 7) using a do while loop.
Using a for loop I am required to ask the user to input that number of words.
Then I have to check if one of the words fulfills the given conditions:
The word must:
Start with an uppercase letter
End with a number
Contain the word "cse".
I am asked to create a method inside some code homework that does a specific task, the method should check all the required conditions, the name of the method should be countTest and it accepts the String as a parameter.
I will show you my code but I don't know how to create this specific method.
Output format
System.out.println("There as a total number of words " + count + " and
the ones that fulfill the condition are: " + condition);
The problem is, I dont know how to create the method or constructor or whatever it is called that calls all of the 3 methods inside it, and then connect that particular method to the main method!
I hope you guys can understand I am new to this, thank you in advance!
public class D6_6 {
public static void main(String[]args){
Scanner sc = new Scanner(System.in);
System.out.println("Type a number that is at least 7");
int number = sc.nextInt();
int count = 0;
int condition = 0;
do{
if(number<7){
System.out.println("You should type a number that is at least 7 or higher");
number = sc.nextInt();
}
}
while(number<7);
sc.nextLine();
String str;
for(int i =0; i<number; i++){
System.out.println("Type a word");
str = sc.nextLine();
count++;
}
}
public boolean countTest(String str) {
}```
To check if the word start with an uppercase:
You can do that by first selecting the character you want to check by str.charAt(0). This will return a char that is the first letter of the input str.
To check if this char is an uppercase letter, you can easily use char.isUppercase(). This will return a boolean. You have to replace char by the name of the variable were you put the char of str.charAt(0) in.
To check if the last character is a number:
You can do that again by first selecting the last character by str.charAt(str.length()-1), were string.length-1 is the number of the last character.
To check if this character is a number, you can use the ascii table. Every character has it's own number. So if you want to check if your character is between 0 and 9, you can use char >= 48 || char <= 57 (look up in the ascii table). Again, char is the name of the variable were you put the char of str.charAt(str.length()-1) in.
To check if the word contains "cse":
There is a very easy method for that: str.contains("cse") will return a boolean that is true when "cse" is in the word and false when the word does not contain "cse".
I hope it is clear for you now!
I think I did it, thank you guys very much, I appreciate it!
public class D6_6 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Type a number that is at least 7");
int number = sc.nextInt();
int count = 0;
int condition = 0;
do {
if (number < 7) {
System.out.println("You should type a number that is at least 7 or higher");
number = sc.nextInt();
}
}
while (number < 7);
sc.nextLine();
String str;
for (int i = 0; i < number; i++) {
System.out.println("Type a word");
str = sc.nextLine();
count++;
if((countTest(str))){
condition++;
}
}
if(count == 0){
System.out.println("No words typed");
} else {
System.out.println("Total number of words typed: " + count + ", which fulfill the condition: "+ condition);
}
}
public static boolean countTest(String str) {
return Character.isUpperCase(str.charAt(0)) && str.charAt(str.length() - 1) >= 48 || str.charAt(str.length() - 1) <= 57 || str.contains("cse");
}
}```

How do I prevent an error message from repeating in Java?

I'm trying to write a program to calculate factorial but I can't figure out why the Error message displays twice if I enter a letter instead of an integer.
I feel like the issue has to do with Line 29 c = sc.next().charAt(0);, but am not sure how to fix it. Any help is appreciated.
My program:
public class Factorials {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char c = 'Y';
int num = 0;
do
{
System.out.print("Enter a number to calculate its factorial: ");
while (!sc.hasNextInt()) {
System.out.println("Invalid Entry - Enter only Integers! Try Again: ");
sc.nextLine();
}
int result = 1;
num = sc.nextInt();
for(int i = 1; i <= num; i++) {
result = result * i;
}
System.out.println("The factorial of " + num + " is: " + result);
System.out.println("Do you wish to continue? Y/N: ");
c = sc.next().charAt(0);
}while(c == 'y' || c == 'Y');
sc.close();
}
}
Simple fix: Change the sc.nextLine(); in your code to a sc.next() and you should be good to go. This error occurs because .nextLine() considers the enter/return key as a separate character, while .next() doesn't. (The enter key when you press it after entering either 'y' or 'n': if you try it, the error message doesn't print twice if you enter a letter the first time you run the program).
Side note: You probably want it to be a .print(/*invalid input sentence*/) instead of a .println() to go along with how you take in your other number values.
Otherwise, you're good!
Finds and returns the next complete token from this scanner.
A complete token is preceded and followed by input that matches
the delimiter pattern
As jdk doc shows, the 'sc.next' method will return when it reaches space, enter or return. So when you enter 'y' with enter, the enter character is still in buffer. You can assign sc.nextLine to a variable, like
String str = sc.nextLine();
System.out.println(str);
You can see the enter character and your input character.
Both #TheSj and #Lahiru Danushka answer could solve this problem.
add sc.nextLine(); after c = sc.next().charAt(0);

Printing twice, not prompted for Scanner input

Iam working on some homework and an having an issue where once the user chooses an input to enter a sentence and the program writes "Please enter a sentence" it writes this twice when it should be once. Here is my code.
import java.util.Scanner;
public class ParseSentence{
public static void main(String []args){
Scanner sc = new Scanner(System.in);
int selection = -1;
String sentence = "";
boolean flag = true;
while(flag){
while(selection == -1){
System.out.print("Menu: \n 1. Enter a new sentence\n 2. Display the sentence in uppercase \n 3. count the number of words \n 4. count the number of vowels \n 5. Display the longest word in the sentence \n 0. Exit \n");
selection = sc.nextInt();
if(selection > 1){
if(sentence.equals("")){
System.out.println("Error please first enter a sentence");
selection =-1;
}
}
}
while(selection == 1){
System.out.println("Please enter a sentence");
sentence = sc.nextLine();
if(sentence.equals("")){
selection = 1;
}else
selection = -1;
}
if(selection == 2){
System.out.println(Upper(sentence));
selection = -1;
}
if(selection == 0)
break;
selection = -1;
}
}
public static String Upper(String s){
String morph = s.toUpperCase();
return morph;
}
}
The output looks like this
Menu:
1. Enter a new sentence
2. Display the sentence in uppercase
3. count the number of words
4. count the number of vowels
5. Display the longest word in the sentence
0. Exit
1
Please enter a sentence
Please enter a sentence
I tried to replicate the bug in another program to see if I am doing something wrong with while loop but I am stumped. thanks for help.
After the last sc.nextInt(), on the line where you entered 1 the terminating newline character is not yet read.
It will be read in the first iteration of your while loop.
That is, sentence = sc.nextLine() will be empty at first,
and the loop body will be executed one more time.
One simple solution is to add a sc.nextLine() right before the loop.
// read terminating newline that remained after last int input
sc.nextLine();
while (selection == 1) {
System.out.println("Please enter a sentence");
sentence = sc.nextLine();
if (sentence.equals("")) {
selection = 1;
} else {
selection = -1;
}
}

How can I verify the int length of scanner input?

I was able to get the program to run and work with error checking to make sure that the user input is in fact an int. The issue I ran into is that I only want it to be a 3-digit int. I'm having trouble getting that into the right place:
import java.util.*;
public class listMnemonics
{
public static void main(String[] args)
{
//Defines the "keypad" similar to that of a phone
char[][] letters =
{{'0'},{'1'},{'A','B','C'},{'D','E','F'},{'G','H','I'},{'J','K','L'},
{'M','N','O'},{'P','Q','R','S'},{'T','U','V'},{'W','X','Y','Z'}};
//Creates the Scanner
Scanner scan = new Scanner(System.in);
Right here is where I need to implement that and I am running into the issue. I'm sure it's maybe only a line out of place or missing that I need, I just don't know what or where. As it sits, it will constantly ask me to enter a 3-digit number, no matter the length. Error checking for a string entered does currently work:
//Gives instructions to the user to enter 3-digit number
//Any amount of numbers will work, but instructions help
//System.out.println("Please enter a 3-digit number: ");
int j;
do
{
System.out.println("Please enter a 3-digit number: ");
while (!scan.hasNextInt()) {
System.out.println("That's not a 3-digit number! Try again!");
scan.next(); // this is important!
}
j = scan.nextInt();
}
//while (j <= 0); This works while not checking digit length
while (j != 3);
int w = (int) Math.log10(j) +1; //Found this, but not sure if it helps or not
String n = Integer.toString(w);
And here is the rest that get's it to do what I need it to:
//Determines char length based on user input
char[][] sel = new char[n.length()][];
for (int i = 0; i < n.length(); i++)
{
//Grabs the characters at their given position
int digit = Integer.parseInt("" +n.charAt(i));
sel[i] = letters[digit];
}
mnemonics(sel, 0, "");
}
public static void mnemonics(char[][] symbols, int n, String s)
{
if (n == symbols.length)
{
System.out.println(s);
return;
}
for (int i = 0; i < symbols[n].length; i ++)
{
mnemonics(symbols, n+1, s + symbols[n][i]);
}
}
}
Here's the output:
----jGRASP exec: java listMnemonics
Please enter a 3-digit number:
2345
Please enter a 3-digit number:
12
Please enter a 3-digit number:
123
Please enter a 3-digit number:
motu
That's not a 3-digit number! Try again!
With the help of MvG and pingul, this is what is currently working the way I was hoping:
import java.util.*;
import java.util.regex.Pattern;
public class listMnemonics
{
public static void main(String[] args)
{
// Defines the "keypad" similar to that of a phone
char[][] letters =
{{'0'},{'1'},{'A','B','C'},{'D','E','F'},{'G','H','I'},{'J','K','L'},
{'M','N','O'},{'P','Q','R','S'},{'T','U','V'},{'W','X','Y','Z'}};
// Creates the Scanner
Scanner scan = new Scanner(System.in);
// Gives instructions to the user to enter 3-digit number
// This 'Pattern' also guarantees that only 3 digits works.
Pattern threeDigitNumber = Pattern.compile("[0-9]{3}");
int j;
do
{
System.out.println("Please enter a 3-digit phone number: ");
// If it's not a 3-digit int, try again
while (!scan.hasNext(threeDigitNumber))
{
System.out.println("That's not a 3-digit number! Try again!");
// This is important!
scan.next();
}
j = scan.nextInt();
}
while (j <= 0);
String n = Integer.toString(j);
// Determines char length based on user input
char[][] sel = new char[n.length()][];
for (int i = 0; i < n.length(); i++)
{
// Grabs the characters at their given position
int digit = Integer.parseInt("" +n.charAt(i));
sel[i] = letters[digit];
}
mnemonics(sel, 0, "");
}
// Here is where the magic happens and creates the possible
// letter combinations based on the user input and characters
// selected in previous steps.
public static void mnemonics(char[][] symbols, int n, String s)
{
if (n == symbols.length)
{
System.out.println(s);
return;
}
for (int i = 0; i < symbols[n].length; i ++)
{
mnemonics(symbols, n+1, s + symbols[n][i]);
}
}
}
Condensed and reformatted your code reads
Scanner scan = new Scanner(System.in);
int j;
do {
System.out.println("Please enter a 3-digit number: ");
while (!scan.hasNextInt()) {
System.out.println("That's not a 3-digit number! Try again!");
scan.next(); // this is important!
}
j = scan.nextInt();
} while (j != 3);
Comparing that to the Scanner documentation we can see that the scan.next() call will read (and discard) the non-int token. Otherwise j will be the integer you read. And you continue doing so while the number you read is different from 3. Not the length of the number, but the number itself. So if you want to end the loop, enter 3. If you want to do so while following the prompt, enter 003.
If that's not what you want to check, then change the end of loop condition. Or perhaps change the way you test for three-digit numbers, by using regular expressions to match these.
Scanner scan = new Scanner(System.in);
Pattern threeDigitNumber = Pattern.compile("\\d\\d\\d");
int j;
System.out.println("Please enter a 3-digit number: ");
while (!scan.hasNext(threeDigitNumber)) {
if (scan.hasNext()) {
System.out.println(scan.next() + " is not a 3-digit number! Try again!");
} else {
System.out.println("Input terminated unepxectedly");
System.exit(1);
}
}
j = scan.nextInt();
As comments correctly indicate, the pattern "\\d\\d\\d" could just as well be written as "[0-9]{3}", or as "\\d{3}" or "[0-9][0-9][0-9]". Using {…} might be useful in situations where the number of digits is a variable.
The documentation for Scanner.hasNext(Pattern) requires the pattern to match the input. This apparently follows the Matcher.matches() semantics of matching the whole string against the pattern, as opposed to Matcher.find() which checks whether the string contains any part matching the pattern. So the input does not have to be enclosed in ^ and $, as I assumed at first, and in fact should not be using these unless the pattern is compiled with the Pattern.MULTILINE flag.
You may want to call Scanner.useDelimiter to delimit using line breaks only.
Scanner.useDelimiter("[\\r\\n]+")

Using Scanner - at java.util.Scanner.next(Unknown Source) java.util.NoSuchElementException

My full code is pasted here. Below are the 2 methods that are related to my question.
private static boolean playGameAgain()
{
char playAgain = 'y';
Scanner input = new Scanner(System.in);
while(playAgain != 'n')
{
System.out.println("Go again?(y/n)");
/// PROBLEM HERE.... Somehow, it will NOT wait for INPUT. It just throws an error
playAgain = input.next().charAt(0);
}
input.close();
return (playAgain != 'y')?false:true;
}
// [Trimmed]
public static void initialize(ArrayList<String> names, ArrayList<Integer> scores)
{
Scanner input = new Scanner(System.in);
for (int i = 1; i <= 5; i++)
{
System.out.println("Enter the name for score #" + i + ":");
names.add(input.nextLine());
System.out.println();
System.out.println("Enter the score for score #" + i + ":");
while(!input.hasNextInt())
{
//input.nextLine();
System.out.println("Please input a valid integer value for the score for #" + i + ":");
if(!input.hasNextInt())
input.nextLine();
}
scores.add(input.nextInt());
input.nextLine();
}
input.close();
}
I have tried many combinations of how to read in one character. This used to work, that I could read in one character by using:
Scanner input = new Scanner(System.in);
char temp = input.next().charAt(0);
But, somehow, in this program I wrote, it won't work.
It's a program that will read in 5 user names (strings) & 5 scores (integers) and put them in 2 arrays. It will sort the arrays in descending order and then it will print them out. So, the only problem I have is asking if they want to play again and taking some char input to see if they want to play again (y/n)?
Please help if you can. I've tried many combinations of: if (input.hasNext()), to no avail.
You are not setting playAgain to something other than 'y' in playGameAgain(). You have a bug here.

Categories

Resources