How to make Java detect keypress in my scenario? - java

I am writing a program for a project for school. The project requires me to create a record of pets for a pet hospital. I am supposed to create a list of pet owners (maximum of 30 owners) with their first name, last name, e-mail, and phone, and an array pets for each owner (maximum of pets per owner is 5). However, the user can create a list of less than 30 owners. The issue I have is I want to make code where the user can press the escape key to stop the outside while loop that asks them for the owner info when they don't need to add anymore owners. Also, where it says, "System.out.println("Press enter to add another owner or Esc to finish list.");" it is in another loop, so if the user hits an incorrect key it will loop asking them if they want to stop adding tot he list or not (until they hit esc or enter). (Note: the code below is not my whole program, I just needed help with one specific part. I left the if statements blank, because that is where my keypress code will be.).
public class Runner
{
public static void main(String[]args)
{
while(i <= 30)
{
System.out.println(i + ". " + "Enter the owner's first name.");
String first = scan.nextLine();
System.out.println(i + ". " + "Enter the owner's last name.");
String last = scan.nextLine();
System.out.println(i + ". " + "Enter the owner's email address.");
String emailAdd = scan.nextLine();
System.out.println(i + ". " + "Enter the owner's phone number.");
String phone = scan.nextLine();
Owner owner = new Owner(first, last, emailAdd, phone);
int j = 1;
while(j > 0)
{
System.out.println("Press enter to add another owner or Esc to
finish list.");
if ()
{
}
if ()
{
}
j++;
}
list.add(owner.toString());
i+=1;
}
System.out.println(list);
}
}

Since Java is merely using the console, there's no native way to detect a single keypress... any input must end with an "enter" to actually be taken by the program.
As such, to emulate detecting an enter keypress you could do something like:
if (scan.nextLine().isEmpty())
// do stuff
Since we know that a line always means that the enter key was pressed, if the String is empty, it means that only the enter key remains.
For the ESC key, you should use a 3rd party library if is imperative to have it work like that, otherwise, you could have the user actually write "ESC" or some other key word defined by you as input.

Related

User string input validation and exception error

I'm new in Java programming and I'm trying to create a user input validation to make sure that the user only input one of the three possible strings: Mammals, Reptiles, Birds. But I'm stock on trying to validate and create a loop. So far I have this:
public void validName() {
Scanner typeInput = new Scanner(System.in);
String [] type = {"Mammals", "Reptiles", "Birds"};
System.out.println("Enter Animal Type: ");
String atype = typeInput.next();
try {
if
(!Arrays.asList(type).contains(atype)){
System.out.println("Not a correct animal");
}
}
catch(Exception e){
System.out.println(e+"Plase add the correct Animal Type: (Mammals, Reptile, or Bird");
atype= typeInput.nextLine();}
while (atype.equalsIgnoreCase("Mammals") || atype.equalsIgnoreCase("Reptile") || atype.equalsIgnoreCase("Birds"));
{ System.out.println("Continue to next step");}
}
}
When I run the previous code I get this output:
Please enter First Name
Cris
Please enter Last Name
Cruz
User logged In: Criz Cruz
Welcome to ZooOrganizer!
Enter Animal Type:
Cow
Not a correct animal
Continue to next step
------------------------------------------------------------------------
BUILD SUCCESS
-----------------------------------------------------------------------
I can't get to execute the Catch Exception neither the loop to make the user to input the animal type again.
public void validName() {
Scanner typeInput = new Scanner(System.in);
String [] type = {"Mammals", "Reptiles", "Birds"};
System.out.println("Enter Animal Type: ");
String atype = typeInput.next();
try {
if
(!Arrays.asList(type).contains(atype)){
System.out.println("Not a correct animal");
}
}
catch(Exception e){
System.out.println(e+"Plase add the correct Animal Type: (Mammals, Reptile, or Bird");
atype= typeInput.nextLine();}
while (atype.equalsIgnoreCase("Mammals") || atype.equalsIgnoreCase("Reptile") || atype.equalsIgnoreCase("Birds"));
{ System.out.println("Continue to next step");}
}
}
If you want to think about it, the prompt you have coded is actually rather cruel. It doesn't inform the User of what is expected as input. You may as well display a prompt like:
Hey, enter an Animal Type and if you guess it right
you get two free OH-Henry Bars (yum yum): -->
Be up-front with what is required from the User and if you can, make the entry as simple as possible. If you do then the errors that can be possibly produced by that User is almost completely eliminated, for example:
Enter an Animal Type (Mammals, Reptiles, Birds): -->
Now the User can see what input you're expecting. This however still has issues which your code would need to deal with and take care of such as spelling mistakes, improper letter case, no word entered, etc. In my opinion it's sort of actually a pain in the butt to have to write the word Reptile into something like a Console Application which is why I would avoid those applications, you know :
Enter the full path and file name to your Database located within
the Windows Documents folder: -->
Ya, I don't think so....next app.
When you have multiple items that can be entered then use a Menu System. This way the User can see the choices available and only needs to enter a single letter or number for the desired menu item, for example:
Select an Animal Type (1-3):
1) Mammal
2) Reptiles
3) Birds
4) Quit
Menu Choice: -->
Doing it this way also reduces the amount of code required to carry out validity. Is the entered menu choice an Integer Number, is the entry greater than or equal to 1 and is it less than or equal to 4. If not then tell the User of non-validity and loop again. Here is how you might do this with your current scheme:
String ls = System.lineSeparator();
Scanner typeInput = new Scanner(System.in);
String[] type = {"Mammals", "Reptiles", "Birds"};
String selectedAnimalType = "";
String atype = "";
// Start a prompt WHILE loop...
while (atype.equals("")) {
/* Display a Menu. Doing things this way doesn't leave
the User in the dark as to what is required for input. */
System.out.print("Select an Animal Type (1-3): " + ls
+ "1) Mammal" + ls + "2) Reptiles" + ls
+ "3) Birds" + ls + "4) Quit" + ls
+ "Menu Choice: --> ");
// Get User input...
atype = typeInput.nextLine();
// Is the Input a Valid menu choice?
if (!atype.matches("\\d") || Integer.valueOf(atype) < 1 || Integer.valueOf(atype) > 4) {
/* If it's not a string representation of a Integer numerical value OR
if it's a numerical value less than 1 OR if it's a numerical value
greater than 4 */
System.out.println("Invalid entry! Please try again..." + ls);
atype = ""; // Make atype equal null string ("") to continue WHILE loop
}
// Otherwise, was the menu choice the numerical value 4 to quit?
else if (Integer.valueOf(atype) == 4) {
// Yes, it was...
System.out.println("Quiting... Bye-Bye");
System.exit(0); // Quit (end) Application.
}
}
// Prompt loop successful...continue on with code.
/* Get the proper name for the Animal Type from the 'type' Array
based on the menu choice (numerical value minus 1) so as to get
the desired array index value. */
selectedAnimalType = type[Integer.valueOf(atype) - 1];
/* The condition for the below WHILE loop is redundant since we
would NEVER get this far unless a menu choice for either Mammal,
Reptiles, or Birds, was made, so don't bother using it. Do something
similar as to what was done in the first prompt loop above. */
while (atype.equalsIgnoreCase("Mammals") || atype.equalsIgnoreCase("Reptile") || atype.equalsIgnoreCase("Birds")) {
System.out.println("Continue to next step");
// ........................................
}
You should use a Do...While loop in this case:
public void validName() {
Scanner typeInput = new Scanner(System.in);
String [] type = {"Mammals", "Reptiles", "Birds"};
do {
System.out.println("Enter Animal Type: ");
String atype = typeInput.next();
try {
if
(!Arrays.asList(type).contains(atype)){
System.out.println("Not a correct animal");
System.out.println("Continue to next step");}
}
}
catch(Exception e){
System.out.println(e+"Plase add the correct Animal Type: (Mammals, Reptile, or Bird");
atype= typeInput.nextLine();}
} while (atype.equalsIgnoreCase("Mammals") || atype.equalsIgnoreCase("Reptile") || atype.equalsIgnoreCase("Birds"));
}

Sentinel number in if statement

For data structures and algorithms in java class I've been assigned to create a program that takes user input for an item's name and price and then averages the price. I have successfully done that, however, I am having a great deal of trouble on a certain specification for the program: a sentinel number (-1) that terminates the project. Here is my code, I will explain what the issue is after.
while(true){
System.out.print("Enter item " + (count + 1) + " name: "); // enter name
names[count] = in.next(); // next string becomes count index
System.out.print("Enter item " + (count + 1) + " price: "); // enter price
prices[count] = in.nextDouble(); // stores price entered as array index
if(prices[count] == -1) break; // if next price == -1 // the code i want to change.
if(names[count].equalsIgnoreCase("peas")) flag = true;
average += prices[count];
count++;
}
So, my issue is: I want to terminate the program when I enter -1 for the item name, not have to enter a "dummy" item name and then have to enter the sentinel number (-1).
Sorry for the long explanation, just trying to be thorough.
Thanks for taking the time to read this and help a programmer hopeful out.
You need to use a String for your comparison (but "-1" will do). Also, do it immediately after you get the input. Something like,
names[count] = in.next();
if (names[count].equals("-1")) {
break;
} // ...

Labels in Java for exception handling

I'm doing the Java Associate level certification and while we are expressly told we won't be tested on labels, we have been shown them. Looking on here though the advice seems to be never use labels?
I'd like to use them in a catch block/user input console as a means of validating input.
do {//Keep calculator going as long as user wants
numInputCheck:
do {
try {//Force user to input a whole number
System.out.print("\nPlease enter the Mark you want to Calculate\n(Enter marks between " + GradeCalculator.getMIN_MARK() + " and " + GradeCalculator.getMAX_MARK() + " only): ");
mark = Integer.parseInt(scn.nextLine());
}catch(NumberFormatException nfe) {
System.out.println("\nInvalid entry - Please ensure entry is a number only.");
continue numInputCheck;
}
gradeCalc.isValidMark(mark);//Ensure input is within valid range
}while(!gradeCalc.getIsValidMark());
*etc*......
Is this bad coding?
EDIT: The code above wasn't doing what I thought it was/wanted it to do - it wasn't actually jumping back to the label at all.
I ended up changing the code to
do {//Keep calculator going as long as user wants
do {//Force user to enter number within valid range
do {//Force user to enter a whole number
try {
System.out.print("\nPlease enter the Mark you want to Calculate\n(Enter marks between " + GradeCalculator.getMIN_MARK() + " and " + GradeCalculator.getMAX_MARK() + " only): ");
mark = Integer.parseInt(scn.nextLine());
isValidInput = true;
}catch(NumberFormatException nfe) {
System.out.println("\nInvalid entry - Please ensure entry is a number only.");
isValidInput = false;
}
}while(!isValidInput);
}while(!gradeCalc.isValidMark(mark));
which I'm fairly sure is working correctly.
Anyway, I think I answered my own question - labels are discouraged because people like me try to use them.
No this is not actual example because continue can do all the job by itself without the help of the label .
A good example is when you have 2 nested loops and you want to break the outer loop from a condition in the inner loop
outerloop:while(condition1) {
while(condition2) {
if(condition3)
break outerloop;
}
{
Continue statement skips all sentences above, you have to use break sentence for stopping the loop. Labels are useful for more than one loop, for example:
label1:
for (int i = 0 ; i<10; i++){
for (int j = 0 ; j<10; j++){
if (i+j = 3)
break label1;
}
}

Repeating error message inside a while loop [duplicate]

This question already has answers here:
Loop user input until conditions met
(3 answers)
Closed 7 years ago.
I'm currently working my way through a Udemy Java course and am practicing what i have learnt thus far.
I have the following simple program which i am planning on using to get the user to input his name.
import java.util.Scanner;
public class Adventure {
public static final int menuStars = 65;
private static Scanner input = new Scanner(System.in);
public static void main(String[] args) {
String firstName = "";
String lastName = "";
boolean validName = false;
while(!validName){
//Entering first name
System.out.println("Please enter your first name.");
try {
firstName = input.nextLine();
if(firstName.length() == 0){
throw new Exception("Please enter a first name of at least 1 character.");
}else{
//Entering last name
System.out.println("Please enter your last name.");
lastName = input.nextLine();
if(lastName.length() == 0){
throw new Exception("Please enter a last name of at least 1 character");
}else{
System.out.println("You have entered " + firstName +" " + lastName);
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
continue;
}
//Used to terminate loop when both first & last names are valid
validName = true;
}
}
}
I want to make the program repeat the error message when the user inputs a blank name instead of restarting the entire program from the beginning.
E.g When the user enters a blank first name, i want the program to keep repeating "Please enter a first name of at least 1 character" and when the user enters a blank last name, for it to keep repeating "Please enter a last name of at least 1 character" until the user enters a valid name.
However, currently when the user enters a blank first name or last name, my program will repeat itself from the very beginning instead of repeating just the error message.
How would i go about making the program repeat just the error message?
Use a boolean variable that stores true when "Please enter your first name." is printed. Check before printing this string each time if this variable is false or not. Also, initialize it to false before the loop. Same idea goes for last name.
if(!printed)
{
System.out.println("Please enter your first name.");
printed=true;
}
havent tested that but i am guessing it can be like that, with out try/catch though, it just makes no sense to me using it in the way you have it on your code
String firstName = "";
String lastName = "";
System.out.println("Please enter your first name.");
firstName = input.nextLine();
while(firstName.length<1){
System.out.println("Please enter a first name of at least 1 character.");
firstName = input.nextLine();
}
lastName=input.nextLine();
while(firstName.length<1){
System.out.println("Please enter a last name of at least 1 character.");
lastName = input.nextLine();
}
System.out.println("You have entered " + firstName +" " + lastName);
Edit, some basic info about exceptions
try catch is used when something unexpected happens and you try to find a way round it. for example if an array of 10 positions is expected at some point and a smaller array (lets say 4 positions) is being used. Then this would cause an exception causing the program to terminate with no further information.
With try catch you can check what the problem is, and try to either inform the user to do something(if they can) or close the program in a better way, using System.exit() for example and saving all the work that was done till that point
An other example is that if you ask for 2 numbers to do an addition. if the user enters letters instead of number the int sum=numbA+numbB; would throw and exception. This of course could be handled using an if. but even better would be something like this
A whitespace is actually considered a character, so the check of (length == 0) doesn't work for your purposes.
Although the following code below is incomplete (ex: handles the potentially undesirable case of firstname=" foo", (see function .contains()), it does what the original post asks - when the user enters a blank first/last name, it keeps repeating "Please enter a first/last name of at least 1 character" until the user enters a valid first/last name.
import java.util.Scanner;
public class Adventure {
public static final int menuStars = 65;
private static Scanner input = new Scanner(System.in);
public static void main(String[] args) {
String firstName = "";
String lastName = "";
boolean firstNameLegal = false;
boolean lastNameLegal = false;
// Entering first name
while (!firstNameLegal) {
System.out.println("Please enter your first name.");
firstName = input.nextLine();
if (!firstName.equals(" "))
firstNameLegal = true;
else
System.out.println("Please enter a first name of at least 1 character.");
}
// Entering last name
while(!lastNameLegal){
System.out.println("Please enter your last name.");
lastName = input.nextLine();
if(!lastName.equals(" "))
lastNameLegal = true;
else
System.out.println("Please enter a last name of at least 1 character.");
}
System.out.println("You have entered " + firstName +" " + lastName);
}
}

basic java database organization

I'm working on this database type program for school. so far I've been able to make this part of the code fully functional:
import jpb.*;
//jpb is a package that lets me use SimpleIO as you'll see below
public class PhoneDirectory {
public static void main(String[] args) {
PhoneRecord[] records = new PhoneRecord[100];
int numRecords = 0;
// Display list of commands
System.out.println("Phone directory commands:\n" +
" a - Add a new phone number\n" +
" f - Find a phone number\n" +
" q - Quit\n");
// Read and execute commands
while (true) {
// Prompt user to enter a command
SimpleIO.prompt("Enter command (a, f, or q): ");
String command = SimpleIO.readLine().trim();
// Determine whether command is "a", "f", "q", or
// illegal; execute command if legal.
if (command.equalsIgnoreCase("a")) {
// Command is "a". Prompt user for name and number,
// then create a phone record and store it in the
// database.
if (numRecords < records.length) {
SimpleIO.prompt("Enter new name: ");
String name = SimpleIO.readLine().trim();
SimpleIO.prompt("Enter new phone number: ");
String number = SimpleIO.readLine().trim();
records[numRecords] =
new PhoneRecord(name, number);
numRecords++;
} else
System.out.println("Database is full");
} else if (command.equalsIgnoreCase("f")) {
// Command is "f". Prompt user for search key.
// Search the database for records whose names begin
// with the search key. Print these names and the
// corresponding phone numbers.
SimpleIO.prompt("Enter name to look up: ");
String key = SimpleIO.readLine().trim().toLowerCase();
for (int i = 0; i < numRecords; i++) {
String name = records[i].getName().toLowerCase();
if (name.startsWith(key))
System.out.println(records[i].getName() + " " +
records[i].getNumber());
}
} else if (command.equalsIgnoreCase("q")) {
// Command is "q". Terminate program.
return;
} else {
// Command is illegal. Display error message.
System.out.println("Command was not recognized; " +
"please enter only a, f, or q.");
}
System.out.println();
}
}
}
// Represents a record containing a name and a phone number
class PhoneRecord {
private String name;
private String number;
// Constructor
public PhoneRecord(String personName, String phoneNumber) {
name = personName;
number = phoneNumber;
}
// Returns the name stored in the record
public String getName() {
return name;
}
// Returns the phone number stored in the record
public String getNumber() {
return number;
}
}
I'm trying to do a few things, and they're probably simple solutions I'm just looking over. I need to make a command "d" for delete that will prompt for a name and delete all records that match. I tried using the same approach as the "f" command where partial matches are allowed, but again I couldn't get it to work.
Next I need to modify the f command so that it lines up names and numbers in columns. I tried to force the string to be a certain length by making it = to the array length to no avail, it just returns looking blank. essentially it needs to look like this:
Smith, John 555-5556
Shmoe, Joe 565-5656
and I need to set records to 1 instead of 100 and have in double in size every time it gets full. I haven't messed with this yet, but I'm not sure where to start.
Because the requirement is to be able to remove records i would recommend using an ArrayList which grows dynamically and you are able to easily remove records.
It is declarer like this:
ArrayList<PhoneRecord> records = new ArrayList<PhoneRecord>();
and you add like this:
records.add(PhoneRecord(name, number)));
you can remove a record like this:
records.remove(i);
to remove the ith record of the list.
the current size of the list is given by records.size() function.
As for your second question you can use string formatting to tell it to format the name for a specified number of characters for example you could use this:
System.out.println(String.format("%s%15s", records[i].getName(), records[i].getNumber());
In this example will be added space characters before the telephone in order the total number of characters will be 15.
So if your number is 555-5556 then 7 space blank characters will be added before the number.

Categories