I'm making a program for school which inserts contacts into an array lists using JOptionPane/Dialog boxes for input/output.
The problem I'm having is with the Cancel and "X" buttons : when pressed by the user they crash the program.
I figured out using "return" I could stop the method, and that worked for the first dialog box but if information is entered and the user proceeds to the next Dialog box it crashes even though i'm using return again.
So basically what I want to do is if the user presses cancel or "X" to escape the current method it will do so without crashing and return to the main method to carry out other processes.
This code works for the first entry and exits the program successfully:
while(nameError)
{
surname = JOptionPane.showInputDialog(null, "Enter a Surname");
if(surname == null)
{
return;
}
else
{
if(!(surname.matches(NamesTest)))
{
JOptionPane.showMessageDialog(null,errorMsg);
}
else nameError = false;
temp[0] = surname;
}
}
but the next line of code in the method for the second Dialog box doesnt:
while(nameError1)
{
if(forename == null)
{
return;
}
else
{
forename = JOptionPane.showInputDialog(null, "Enter a Forename");
if(!(forename.matches(NamesTest)))
{
JOptionPane.showMessageDialog(null,errorMsg);
}
else nameError1 = false;
temp[1] = forename;
}
}
Something like this should do it:
import javax.swing.JOptionPane;
public class DialogExample {
public static void main(String[] args) {
new DialogExample().getNames();
}
private void getNames() {
String firstName = null;
String lastName = null;
while (firstName == null || firstName.length() == 0) {
firstName = getFirstName();
}
while (lastName == null || lastName.length() == 0) {
lastName = getLastName();
}
JOptionPane.showMessageDialog(null, "Hello " + firstName + " " + lastName);
}
private String getFirstName() {
String rtn = JOptionPane.showInputDialog(null, "Enter First Name");
if(rtn == null || rtn.length() == 0) {
JOptionPane.showMessageDialog(null, "Name cannot be empty");
}
return rtn;
}
private String getLastName() {
String rtn = JOptionPane.showInputDialog(null, "Enter Last Name");
if(rtn == null || rtn.length() == 0) {
JOptionPane.showMessageDialog(null, "Name cannot be empty");
}
return rtn;
}
}
Related
When I run the code I do not get my desired result for the setDepartment method. I'm trying to trap the user if they entered a wrong selection. When I execute the code and put in a value (string) that should without a doubt execute, it does not execute. I have tested to see where the problem could lay. The only thing that worked is when I tried hardcoding the correct value into the method. If I put in an incorrect value and trap the user, and put in the correct value, the user is still trapped in the loop. I checked to see if there are any logical errors in my loop, but I could not find a problem. I am at a complete loss, I can't wait to find what I messed up on.
Please ignore the courseCost instance variable I haven't worked on that yet, and please disregard the system.out.println(department) after the department = department.toUpperCase in the setDepartment method. I was using the system.out.println(department) in the setDepartment method to rule out any possible errors that may have been on the department = department.toUpperCase line of code. Also, you can ignore everything else, everything else works just fine. Thank you for taking the time to take a look.
import java.util.Scanner;
public class Course {
static Scanner keyboard = new Scanner(System.in);
private String department;
private int courseNumber;
private int courseCredits;
private double courseCost;
public Course () {
department = "unknown";
courseNumber = 0;
courseCost = 0;
courseCredits = 0;
}
public Course(String department, int courseNumber, int courseCredits) {
setDepartment(department);
setCourseNumber(courseNumber);
setCourseCredits(courseCredits);
//courseCost = no value will be passed to the constructor, courseCost will be calculated as courseCredits/2 * $500, see setter below (if the course is a Lab Course add $100 to the cost)
}
public String getDepartment() {
return department;
}
public int getCourseNumber() {
return courseNumber;
}
public int getCourseCredits() {
return courseCredits;
}
public double getCourseCost() {
return courseCost;
}
public void setDepartment(String department) {
boolean enteredCorrectly = false;
//department = department.toUpperCase();
do{
department = department.toUpperCase();
System.out.println(department);
//ENGL, MATH, COMP, HIST, HUMN, SCIE, LANG, PHYS
if( (department == "ENGL") || (department == "MATH") || (department == "COMP") ||
(department == "HIST") || (department == "HUMN") || (department == "SCIE") ||
(department == "LANG") || (department == "PHYS") ) {
this.department = department;
enteredCorrectly = true;
} else {
System.out.println("Please re-enter a valid department.");
department = keyboard.nextLine();
}
} while(!(enteredCorrectly));
}
public void setCourseNumber(int courseNumber) {
boolean enterCorrectly = false;
do{
if(1 <= courseNumber && courseNumber <= 399) {
this.courseNumber = courseNumber;
enterCorrectly = true;
} else {
System.out.println("Please re-enter a valid course number.");
courseNumber = keyboard.nextInt();
keyboard.nextLine();
}
} while(!(enterCorrectly));
}
public void setCourseCredits(int courseCredits) {
boolean enterCorrectly = false;
do{
if(courseCredits == 3 || courseCredits == 4 || courseCredits == 6) {
this.courseCredits = courseCredits;
enterCorrectly = true;
} else {
System.out.println("Please re-enter a valid course credits.");
courseCredits = keyboard.nextInt();
keyboard.nextLine();
}
} while(!(enterCorrectly));
}
public void setCourseCost(double courseCost) {
this.courseCost = courseCost;
}
public static void main(String[] args) {
Course c = new Course ("engl", 991, 1);
}
}
I think the reason it is not giving you the expected results is because in the comparison block you are using the operator ==, which means you are comparing the reference of the strings:
if( (department == "ENGL") || (department == "MATH") || (department == "COMP") ||
(department == "HIST") || (department == "HUMN") || (department == "SCIE") ||
(department == "LANG") || (department == "PHYS") ) {
this.department = department;
enteredCorrectly = true;
}
In Java, to compare the value of strings, you should use the .equals() method:
if( (department.equals("ENGL") || (department.equals("MATH") || (department.equals("COMP") ||
(department.equals("HIST") || (department.equals("HUMN") || (department.equals("SCIE") ||
(department.equals("LANG") || (department.equals("PHYS") ) {
this.department = department;
enteredCorrectly = true;
}
the probable reason is in two thing - declaring a private global variable:
private String department;
and these lines:
department = department.toUpperCase();
System.out.println(department);
To my mind, the problem is in same names between global private var and method param.
Just try to rename the method parameter to departmentParam (for example) and then try to print it.
Full Disclosure: This was an assignment, it has been marked already, but I want to understand why I'm getting this error.
I'm having some issues understanding why junit.framework.AssertionFailedError is being thrown. Normally when errors occur I could at least look at the stack trace and see what is happening. In this case, the output console shows this:
Testcase: testIsCorrectMCQ(mr_3.myTester): FAILED
null
junit.framework.AssertionFailedError
at mr_3.MyTester.testIsCorrectMCQ(Assign03Tester.java:207)
testIsCorrectMCQ(mr_3.MyTester): FAILED
In the test result tab in NetBeans, copying the stack trace gives me:
junit.framework.AssertionFailedError
at mr_3.myTester.testIsCorrectMCQ(myTester.java:207)
In the tester file, I have this:
#Test
public void testIsCorrectMCQ() {
System.out.println("isCorrect of MCQ");
MCQuestion instance = new MCQuestion(1,"Capital city of Canada is", 'A',
"Ottawa", "Vancouver", "New York", "Toronto");
assertFalse(instance.isCorrect("B"));
assertTrue(instance.isCorrect("A")); // line 207
}
My isCorrect method is this:
#Override
public boolean isCorrect(Object guess) {
if (guess == null)
return false;
if (guess instanceof String) {
String userGuess = (String)guess;
return (userGuess.charAt(0) == this.getAnswer());
}
if (guess instanceof Character) {
Character userGuess = (Character)guess;
return (userGuess == this.getAnswer());
}
else return false;
}
Any help in understanding what is happening is greatly appreciated.
Edit 1 : My MCQuestion source code
public class MCQuestion extends Question {
private char answer;
private String[] options;
public MCQuestion() {
super();
questionType = QuestionType.MULTIPLE_CHOICE;
}
public MCQuestion(int id, String text, char answer, String... options) {
super(id, text);
setOptions(options);
setAnswer(answer);
questionType = QuestionType.MULTIPLE_CHOICE;
}
public String[] getOptions() {
String[] getOptions = new String[this.options.length];
System.arraycopy(this.options, 0, getOptions, 0, this.options.length);
return getOptions;
}
public void setOptions(String... options) {
if (options.length > 0) {
this.options = new String[options.length];
for (int i = 0; i < options.length; i++) {
if (options[i].isEmpty())
throw new IllegalArgumentException("You have nothing in this option");
else
this.options[i] = options[i];
}
}
else throw new IllegalArgumentException("You have no options set");
}
public char getAnswer() {
return this.answer;
}
public void setAnswer(char ans) {
ans = Character.toLowerCase(ans);
int index = ans - 97;
if (Character.isLetter(ans) && index >= 0 && index < this.options.length)
this.answer = ans;
else throw new IllegalArgumentException(ans + " is not a valid answer option");
}
#Override
public boolean isCorrect(Object guess) {
if (guess == null)
return false;
if (guess instanceof String) {
String userGuess = (String)guess;
return (userGuess.charAt(0) == this.getAnswer());
}
if (guess instanceof Character) {
Character userGuess = (Character)guess;
return (userGuess == this.getAnswer());
}
else return false;
}
#Override
public String toString() {
String option = "";
if (this.options.length == 0)
option = "No options added, yet!";
else {
char index = 'a';
for (String e: options)
option += index + ") " + e + "\n";
}
return (super.toString() + "\n" + option);
}
}
You execute ans = Character.toLowerCase(ans); for whatever reason in your setAnswer() method before saving it in this.answer. This means that (userGuess.charAt(0) == this.getAnswer()) will return false when you provide the answer in upper case, but compare it with the stored lower case character.
Depending on if you want case insensitive answers or not, you should add or remove the Character.toLowerCase() call to your isCorrect() method as well.
I've found this ugly piece of code from some time ago:
#FXML
private void buttSellAction(ActionEvent event){
InfoTip infoTip = new InfoTip();
if(comboPizza.getValue() != null){
if(comboPizzaSize.getValue() != null){
PizzaData selectedPizza = getPizzaData(comboPizza.getValue());
PizzaSizeData selectedPizzaSize = getPizzaSizeData(comboPizzaSize.getValue());
Date date = new Date();
Timestamp timestamp = new Timestamp(date.getTime());
if( selectedPizza != null ){
if(groupDelivery.getSelectedToggle().equals(radioNo)){ // sale without delivery
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirm");
alert.setHeaderText("Total cost: " + String.format("%.2f", selectedPizza.getPrice() + selectedPizzaSize.getPrice()));
alert.setContentText("Proceed with sale?");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
insertSale(timestamp, currentUser.getLogin(), selectedPizza.getID(),
selectedPizzaSize.getSize(), false, selectedPizza.getPrice() + selectedPizzaSize.getPrice());
infoTip.getInfoTip().setId("greenInfoTip");
infoTip.showTip((Button)event.getSource(), " Saved ");
}
}else{ //Sale with delivery
String adress = textFAdress.getText();
String clientName = textFClientName.getText();
String telephone = textFTelephone.getText();
String deliveryCost = textFCost.getText();
boolean isAdressOK = ((adress.length() < 51) && (adress.isEmpty() == false))? true: false;
boolean isClientNameOK = (clientName.length() < 36)? true: false;
boolean isTelephoneOK = ((telephone.length() < 21) && (telephone.isEmpty() == false))? true: false;
boolean isCostOK;
try{ Double.valueOf(deliveryCost); isCostOK = true; }
catch(NumberFormatException exception){ isCostOK = false; }
if(isAdressOK == true){
if(isClientNameOK == true){
if(isTelephoneOK == true){
if(isCostOK == true){
double totalCost = selectedPizza.getPrice() + selectedPizzaSize.getPrice() + Double.valueOf(deliveryCost);
//everything is okey
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirm");
alert.setHeaderText("Total cost: " + totalCost);
alert.setContentText("Proceed with sale?");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
int id = insertSale(timestamp, currentUser.getLogin(), selectedPizza.getID(),
selectedPizzaSize.getSize(), true, selectedPizza.getPrice() + selectedPizzaSize.getPrice());
insertDelivery(id, adress, clientName, telephone, Double.valueOf(deliveryCost));
infoTip.getInfoTip().setId("greenInfoTip");
infoTip.showTip((Button)event.getSource(), " Saved ");
} else {
// ... user chose CANCEL or closed the dialog
}
}else{ //cost not ok
infoTip.showTip(textFCost, "keep right format e.g. 4.35");
}
}else{ //telephone not ok
infoTip.showTip(textFTelephone, "max 20 characters, not empty");
}
}else{ //client name not ok
infoTip.showTip(textFClientName, "max 35 characters");
}
}else{ //adress not ok
infoTip.showTip(textFAdress, "max 50 characters, not empty");
}
}
}else{ //couldnt found selected pizza in pizzaList(which should not be possible)
ExceptionDialog exceptionDialog = new ExceptionDialog("Error when searching for selected pizza", new Exception());
exceptionDialog.showAndWait();
}
}else{ //pizza size not choosen
infoTip.showTip(comboPizzaSize, "select pizza size");
}
}else{ //pizza not choosen
infoTip.showTip(comboPizza, "select pizza");
}
}
I know now it has few major flaws:
method is doing too much and its too long,
it has too many conditional statements so it is easy to get lost,
unnecessary comments making code less readable.
repeated code,
possibly mixed levels of complexity.
testing it would be horrible.
something else??
How can I refactor it to make it clean and simple?
I'd take a slightly different approach to the other answer. I'd separate the validation from the other logic in the method. This means that you don't have to read lots of if statements to see the core logic of the method and if you want to change the validation you only need to update one statement in one place. eg for the first section, add a private method:
private PizzaSizeData getAndVerifySelectedPizza() {
if (comboPizza.getValue() == null) {
infoTip.showTip(comboPizza, "select pizza");
return null;
}
if (comboPizzaSize.getValue() == null) {
infoTip.showTip(comboPizzaSize, "select pizza size");
return null;
}
PizzaData selectedPizza = getPizzaData(comboPizza.getValue());
if (selectedPizza == null) {
ExceptionDialog exceptionDialog = new ExceptionDialog("Error when searching for selected pizza", new Exception());
exceptionDialog.showAndWait();
return null;
}
return getPizzaSizeData(comboPizzaSize.getValue());
}
You could return optionals instead of null but this illustrates the mechanism.
And then call the new method:
private void buttSellAction(ActionEvent event){
InfoTip infoTip = new InfoTip();
PizzaSizeData selectedPizzaSize = getAndVerifySelectedPizza();
if (selectedPizzaSize == null) {
return;
}
// Carry on with the method....
Putting validation at the start of a method with an early return statement is a common pattern so the multiple returns aren't going to confuse anyone and they allow each validation rule to be written separately.
you can use ladder if else in your code. like this
if(isAdressOK == true && isClientNameOK == true && isTelephoneOK == true && isCostOK == true){
double totalCost = selectedPizza.getPrice() + selectedPizzaSize.getPrice() + Double.valueOf(deliveryCost);
//everything is okey
Alert alert = new Alert(AlertType.CONFIRMATION);
alert.setTitle("Confirm");
alert.setHeaderText("Total cost: " + totalCost);
alert.setContentText("Proceed with sale?");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK){
int id = insertSale(timestamp, currentUser.getLogin(), selectedPizza.getID(),
selectedPizzaSize.getSize(), true, selectedPizza.getPrice() + selectedPizzaSize.getPrice());
insertDelivery(id, adress, clientName, telephone, Double.valueOf(deliveryCost));
infoTip.getInfoTip().setId("greenInfoTip");
infoTip.showTip((Button)event.getSource(), " Saved ");
} else {
// ... user chose CANCEL or closed the dialog
}
}else if(!isAdressOK == true){
infoTip.showTip(textFAdress, "max 50 characters, not empty");
}else if(!isClientNameOK == true){
infoTip.showTip(textFClientName, "max 35 characters");
}else if(!isTelephoneOK == true){
infoTip.showTip(textFTelephone, "max 20 characters, not empty");
}else{
infoTip.showTip(textFCost, "keep right format e.g. 4.35");
}
same for other if else condition.
I'm having a problem calling a method and then trapping its return.
I need it to update the result so the next time round the loop it will see it and return a different message.
public class Patient {
private char patientStatus;
public boolean admit() {
if (patientStatus != 'S')
return false;
else
patientStatus = 'A';
return true;
}
This section is in the main() method
do {
Patient temp = null;
System.out.print("Enter selection: ");
menuSelect = sc.nextLine();
// validation
if (menuSelect.length() != 1) {
System.out.println("You must enter a single character");
} else {
menuAnswer = menuSelect.charAt(0);
switch (menuAnswer) {
case 'A':
case 'a':
// patient number
System.out.print("Enter patient number: ");
patNumber = sc.nextLine();
// search for patient number
for (int i = 0; i < pat.length && temp == null; i++) {
if (pat[i].getPatientNo().equals(patNumber)) {
temp = pat[i];
}
}
if (temp == null) {
System.out.println("Patient not found");
} else {
System.out.println("Patient " + patNumber + " Found");
boolean patStatus = temp.admit();
if (patStatus == false) {
System.out.println("Admitted");
} else if (patStatus == true) {
System.out.println("Already admitted");
}
}
}
}
} while (menuAnswer != 'x' && menuAnswer != 'X');
System.out.println("Exiting menu");
I don't know how to update the patStatus so the next time in the menu if you select 'A' and the same patient number it returns "Already admitted".
Let me know if there's enough code to understand what's happening.
Your Patient has the atribute for patientStatus but its value is never saved. Your admit() method needs to set the value for it.
Currently, your code only returns the value but does not save it.
Try this:
public class Patient {
private char patientStatus;
/** "Getter" method for patientStatus
*/
public char getPatientStatus(){
return patientStatus;
}
/** "Admits" the new patient, changing its patientStatus
* #return "true" if patient is admitted; "false" if patient was already admitted.
*/
public boolean admit() {
if (patientStatus != 'A')
patientStatus = 'A'; //set the value to Admitted
return true;
else
return false;
}
}
Then, in your loop, test the value for the admit() call:
if (temp == null) {
System.out.println("Patient not found");
} else {
System.out.println("Patient " + patNumber + " Found");
boolean admitted = temp.admit(); // try to admit the patient
if (admitted) {
System.out.println("Admitted");
} else { //You don't need another if here
System.out.println("Already admitted");
}
}
Since admitted is of type boolean, you don't need to use the == operator, as the if statement uses a boolean value as argument.
You don't need a second if statement after the else either, since boolean can only have two values, if it is not true, then it can only be false
/* You have to re-factor the code on these lines.
Maintain Patients class which holds admitted patients.*/
public class Patients{
private ConcurrentHashMap<Integer, Patient> allPatients = new ConcurrentHashMap();
private HashSet<Integer) admittedPatients = new HashSet();
public Patients(){
}
public void add(Patient p){
allPatients.put(p.getPatientId(),p);
}
public Patient removePatient(int patientId){
dischargePatients.remove(patientId);
return allPatients.remove(patientId);
}
public Patient getPatient(int patientId){
return allPatients.get(patientId);
}
public void admitPatient(int patientId){
admittedPatients.add(patientId);
}
public boolean dischargePatient(int patientId){
return admittedPatients.remove(patientId);
}
public boolean isAdmittedPatient(int patientId){
return admittedPatients.contains(patentId);
}
}
From `Patient.java` class, you can admit & discharge patient.
If getPatient() is null implies patient is not present in list.
Once he is present, isAdmittedPatient returns whether
he is admitted or not.
First off, the code is long, but I am only concerned about the toString method. I pasted everything in case its relevant.
The code is supposed to check whether or not the element entered is less than the element at the top of the stack. I have that part figured out. When I call my toString method to print the saved input, it doesn't print the first node added to the stack. However, it prints all remaining inputs. A example would be if a user enters the following:
testing
test
te
t
What its currently outputing:
t te test
What it needs to output:
t te test testing
Main:
import java.util.*;
public class Stack {
public static void main(String args[]) {
int loopInt = 1;
PyramidStack<String> stringStack = new PyramidStack<String>();
PyramidStack<Integer> intStack = new PyramidStack<Integer>();
System.out
.println("This program will save some of the strings you enter. ");
System.out
.println("Can you predict which ones will be saved? (Enter nothing to quit.)");
Scanner sc = new Scanner(System.in); // Opens Scanner for keyboard input
try {
do {
System.out.print("Enter a String: ");
String input = sc.nextLine();
if (input.length() > 0) {
if (stringStack.size() == 0) {
intStack.push(input.length());
stringStack.push(input);
System.out.println("String Saved");
}
else if (input.length() < intStack.peek()) {
stringStack.push(input);
intStack.push(input.length());
System.out.println("String Saved");
}
else {
System.out.println("String NOT saved. Already saved "
+ intStack.countBefore(input.length())
+ " strings that should come before this one.");
}
} else {
System.out.println();
System.out.println(stringStack.toString());
System.out.println(intStack.toString());
loopInt--;
sc.close();
}
} while (loopInt > 0);
} catch (NullPointerException e) {
System.out.println("No strings have been entered. Ending the program.");
}
}
}
PyramidStack Method:
import java.util.*;
import java.lang.Comparable;
public class PyramidStack<E extends Comparable<E>> extends Stack<E> {
#Override
public void push(E item) throws IllegalArgumentException {
if (super.size == 0) {
super.push(item);
}
else if(item.compareTo(super.peek()) <= 0) {
super.push(item);
}
else {
System.out.println("String NOT saved. " + countBefore(item) + " strings that should come before this one.");
}
}
#Override
public String toString() {
Node<E> node;
node = this.top;
String s = "";
while(node.getNext() != null){
s += node.getData() + " ";
node = node.getNext();
}
return s;
}
public int countBefore(E item) {
Node<E> node;
node = this.top;
int i = 0;
while(node.getNext() != null){
if(item.compareTo(super.peek()) <= 0) {
node = node.getNext();
}
else{
i++;
node = node.getNext();
}
}
return i;
}
}
Stack method and Node Method below in comments.
while(node.getNext() != null){
s += node.getData() + " ";
node = node.getNext();
}
This is where you are missing to print the last data.. you are checking node.getnext() is null.. so it skips the last object and doesn't print that.. your condition should be
node != null
OR
After the loop end have this
s += node.getData() -- this will not give null pointer exception as node is not null.. as it did check node.getnext()
Hope it helps