//TestEmployeesProgram driver with menu & object array.
import java.util.*;
public class TestEmployeesProgram {
public static Scanner console = new Scanner(System.in);
public static void main(String[] args) {
final int MAX = 7;
Employee employee[] = new Employee[MAX];
int choice,k;
String name;
boolean notFound;
employee[0] = new Manager("Jerry Bloggs","gfr",5,38.5);
employee[1] = new Manager("Joe Bloggs","gdr",4,32.5);
employee[2] = new Admin("Mary Jennings","nnv",35.3,88.5,34.3);
employee[3] = new Clerk("Brian Jones","bbl",42.4,78.5,23.5,45.3);
employee[4] = new Manager("John Bloggs","gvr",5,33.5);
employee[5] = new Admin("Bridget Jennings","nvv",45.3,98.5,36.3);
employee[6] = new Clerk("Jack Jones","bbb",43.4,78.5,23.5,47.3);
//Initial Read
choice = showMenu();
//Continue Until 4/Exit
while (choice != MAX) {
switch (choice) {
case 1://Manager
System.out.println();
System.out.printf("%s %-16s %-10s %6s","Name","Id","Hours Worked","Pay");
System.out.println("\n==================================================");
for (k = 0; k < MAX; ++k)
{
if (employee[k] instanceof Manager){ //use of string method instance of.
System.out.println(employee[k].toString());
}
}
break;
case 2://Administration
System.out.println();
System.out.printf("%s %-16s %-10s %6s %-19s","Name","Id","Hours Worked","Pay","Admin Quota");
System.out.println("\n==================================================");
for (k = 0; k < MAX; ++k)
{
if (employee[k] instanceof Admin){
System.out.println(employee[k].toString());
}
}
break;
case 3://Clerk
System.out.println();
System.out.printf("%s %-16s %-10s %6s %-19s","Name","Id","Hours Worked","Pay","Admin Quota","Units Sold");
System.out.println("\n==================================================");
for (k = 0; k < MAX; ++k)
{
if (employee[k] instanceof Clerk){
System.out.println(employee[k].toString());
}
}
break;
I was running the program and the name search in case 4 goes directly to default "employee name not found" and doesnt allow user input.I looked through the code but cant find the error,any tips or help?
case 4://Name search
System.out.print("Enter employee name: ");
name = console.nextLine();
k = -1;
notFound = true;
while ((k < MAX-1) && (notFound))
{
++k;
if (name == employee[k].getName()){
System.out.println();
System.out.printf("%s %-16s %-10s %6s %-19s","Name","Id","Hours Worked","Pay","Admin Quota","Units Sold");
System.out.println("\n==================================================");
System.out.println(employee[k].toString());
System.out.println();
notFound = false;
}
}//end of case 4 while.
if (notFound){
System.out.println("Employee name not found\n");
}
break;
case 7://exit
System.out.println("Program exiting...");
System.exit(0);
default:
System.out.println("Invalid menu choice 1..3 of 7 to Exit");
}//end of switch
//sub read
choice = showMenu();
}//end of while
}//end of main
//Menu method for employee selection.
public static int showMenu()
{
int choice;
System.out.println();
System.out.println("Employee Program Menu");
System.out.println("1.Show Manager pay details ");
System.out.println("2.Show Admin pay details ");
System.out.println("3.Show Clerk pay details ");
System.out.println("4.Search by employee name ");
System.out.println("7.Exit");
System.out.print("Enter option: ");
choice = console.nextInt();
return choice;
}
}
There are two errors. The first is here:
System.out.print("Enter option: ");
choice = console.nextInt();
The nextInt method doesn't consume the end-of-line character. Try this instead:
System.out.print("Enter option: ");
String line = console.nextLine();
choice = Integer.parseInt(line);
The second error is that here you should use equals instead of == to compare strings:
if (name == employee[k].getName())
Try this instead:
if (name.equals(employee[k].getName()))
The == operator tests to see if the two strings are the same object (i.e. the strings are at the same location in memory).
if (name == employee[k].getName())
change this to
if (name.equals(employee[k].getName()))
This is a common issue. When you use nextInt() to read an integer value only the integer character is read and the \n is left in the buffer and when you call nextLine() after that, it doesn't prompt for user entry because it already got a '\n'
To avoid this, in the showMenu method do
console.nextLine();
after you get the choice using nextInt().
This last part of showMenu would be:
choice=console.nextInt();
console.nextLine();
return choice;
and you should use .equals() method to compare strings as below.
if (name.equals(employee[k].getName()))
Good luck :)
Related
I am new to programming and got stuck on a task. It says that user should input their name and the size of it and then it would be printed in stars with that size, also it should use loops in this program not just sout stars.
I have no idea on how to approach this problem so I would really appreciate it if anyone could give me an idea :)
What I have tried so far is:
(update):
i was able to do my whole coding and reach the thing i want, but what i'am stuck in a point, where if user update the size which is n , how i can use it in my whole switch while printing where Pattern(A) prints star version of letter
import java.util.Scanner;
public class Project2 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int option = 0;
while (option != 3) {
System.out.println("Hello, Welcome to Işık NameIt program. ");
System.out.println("----------------------------------------------------------------");
System.out.println("The following options are available for you:\n" +
"1) Display a name\n" +
"2) Change the size\n" +
"3) Exit Program");
System.out.print("Choose an option: ");
option = input.nextInt();
int n = 5;
switch (option) {
case 1:
System.out.print("What is your name?! ");
String name = input.next();
for(int i=0; i<=name.length()-1; i++) {
char letter = name.charAt(i);
switch (letter){
case 'a':
PatternA(n);
break;
case 'y':
PatternY(n);
break;
case 'h':
PatternH(n)
break;
case 'm':
PatternM(n)
break;
}
}
break;
case 2:
System.out.print("What is the new size? ");
int nupdate = input.nextInt();
}
}
}
public static void PatternA(int n) {
// Outer for loop for number of lines
for (int i = 0; i < n; i++) {
// Inner for loop for logic execution
for (int j = 0; j <= n / 2; j++) {
// prints two column lines
if ((j == 0 || j == n / 2) && i != 0 ||
// print first line of alphabet
i == 0 && j != 0 && j != n / 2 ||
// prints middle line
i == n / 2)
System.out.print("*");
else
System.out.print(" ");
}
System.out.println();
}
System.out.println("-----------------------------------------------------------------------");
}
I'm not 100% clear on what you are expecting as your output, if you provided a sample of that it would be helpful. However, with the way you have your program implemented right now you will want to throw your switch statement inside of a while loop to continue executing the program until a 3 is input by the user.
while (option != 3)
{
switch (option)
{
// code
}
// code
option = input.nextInt();
}
Within that while block you can execute whatever statements you want when the user inputs their specified option. Depending on the requirements of the code you should also consider validating the user input. What happens if they don't put in a 1, 2, or 3?
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("Hello, Welcome to Işık NameIt program. ");
System.out.println("----------------------------------------");
System.out.println("The following options are available for you:\n" +
"1) Display a name\n" +
"2) Change the size\n" +
"3) Exit Program");
System.out.print("Choose an option: ");
int option = input.nextInt();
int size = option.length;
while(option !=3){
switch (option){
case 1:
for(int index = 0; index <= size; index++) {
System.out.print("*");
}
System.out.println(" ");
case 2:
System.out.print("What is the new size? ");
size = input.nextInt();
input.nextLine();
case 3:
break;
}
}
}
I need my program to detect previous entries in it's contact list and negate the user from inputting two identical entries. I keep trying, but I either allow every entry, or the entry that's invalid is still saved to my list.
What I want is to make it so my program will be a phone book, and no two people in real life should have the same number. This is why I want there to be only one contact with any given number.
Here's my code for checking the entry:
System.out.print("Enter Number: ");
number = stdin.nextLine(); // read the number
while(!number.matches(pattern)) { // as long as user doesnt enters correct format, loop
System.out.println("Error!");
System.out.println("Not proper digit format! Use \"012-3456\", \"(012)345-6789\"" +
", or \"012-345-6789\" format.");
System.out.print("Enter number: ");
number = stdin.nextLine();
}
for (Entry e : contactList) {
if (e.number.equals(number)) {
System.out.println("This phone number already exist. Please check contacts.");
System.out.println("");
return;
}else{
break;
}
}
contactList[num_entries].number = number;
Here's my full code for reference:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Scanner;
class Entry {
public String fname, lname, number, note;
}
class PBN {
public static Entry[] contactList;
public static int num_entries;
public static Scanner stdin = new Scanner(System.in);
public static void main(String args[]) throws Exception{
Scanner s = new Scanner(System.in);
int i;
char C;
String code, Command;
contactList = new Entry[999];
num_entries = 0;
try {
readPhoneBook("PhoneBook.txt");
} catch (FileNotFoundException e) {}
System.out.println("Codes are entered as 1 to 8 characters.\n" +
"Use Commands:\n" +
" \"e\" for enter a new contact,\n" +
" \"f\" for find contact by fist name,\n" +
" \"r\" for find contact by last name,\n" +
" \"y\" for find contact by phone number,\n" +
" \"l\" for listing all the existing contacts,\n" +
" \"d\" for removing contacts by phone number,\n" +
" \"a\" for sort alphabetically by first name,\n" +
" \"n\" for sort alphabetically by last name,\n" +
" \"p\" for sort by number,\n" +
" \"q\" to quit.");
Command = null;
C = ' ';
while(true) { // loop infinitely
System.out.print("Command: ");
Command = stdin.nextLine();
C = Command.charAt(0);
switch (C) {
case 'e': addContact(); break;
case 'f':
System.out.print("Search for contact by first name: ");
code = stdin.next();
stdin.nextLine();
index(code); break;
case 'r':
System.out.print("Search for contact by last name: ");
code = stdin.next();
stdin.nextLine();
index1(code); break;
case 'y':
System.out.print("Search for contact by phone number: ");
code = stdin.next();
stdin.nextLine();
index2(code); break;
case 'l':
listAllContacts(); break;
case 'q': // when user wants to quit
CopyPhoneBookToFile("PhoneBook.txt");
System.out.println("Quitting the application. All the entries are "
+ "stored in the file PhoneBook1.txt");
System.exit(0); // simply terminate the execution
case 'a':
sortList1();
break;
case 'n':
sortList2();
break;
case 'p':
sortListByPhoneNumber();
break;
case 'd': // m for deleting a contact; delete by phone number
System.out.print("Enter the phone number of a contact you wish to delete : ");
String number = stdin.nextLine();// read the contact number
removeEntry1(number); // remove the number from the entries
break;
default:
System.out.println("Invalid command Please enter the command again!!!");
}
}
}
public static void readPhoneBook(String FileName) throws Exception {
File F;
F = new File(FileName);
Scanner S = new Scanner(F);
while (S.hasNextLine()) {
contactList[num_entries]= new Entry();
contactList[num_entries].fname = S.next();
contactList[num_entries].lname = S.next();
contactList[num_entries].number = S.next();
contactList[num_entries].note = S.nextLine();
num_entries++;
}
S.close();
}
public static void addContact() {
System.out.print("Enter first name: ");
String fname = stdin.nextLine();
String lname;
String number;
String pattern = "^\\(?(\\d{3})?\\)?[- ]?(\\d{3})[- ](\\d{4})$";
while (fname.length() > 8 || fname.length() < 1) {
System.out.println("First name must be between 1 to 8 characters.");
System.out.print("Enter first name: ");
fname = stdin.nextLine();
}
contactList[num_entries] = new Entry();
contactList[num_entries].fname = fname;
System.out.print("Enter last name: ");
lname = stdin.nextLine();
while (lname.length() > 8 || lname.length() < 1) {
System.out.println("First name must be between 1 to 8 characters.");
System.out.print("Enter first name: ");
lname = stdin.nextLine();
}
contactList[num_entries].lname = lname;
System.out.print("Enter Number: ");
number = stdin.nextLine(); // read the number
while(!number.matches(pattern)) { // as long as user doesnt enters correct format, loop
System.out.println("Error!");
System.out.println("Not proper digit format! Use \"012-3456\", \"(012)345-6789\"" +
", or \"012-345-6789\" format.");
System.out.print("Enter number: ");
number = stdin.nextLine();
for (Entry e : contactList) {
if (e.number.equals(number)) {
System.out.println("This phone number already exist. Please check contacts.");
System.out.println("");
break;
} else {
return;
}
}
}
contactList[num_entries].number = number;
System.out.print("Enter Notes: ");
contactList[num_entries].note = stdin.nextLine();
num_entries++;
System.out.println();
}
public static void listAllContacts() {
for(Entry e : contactList) {
if(e != null)
displayContact(e);
else
break;
}
}
public static int index(String Key) {
// Function to get the index of a key from an array
// if not found, returns -1
for (int i=0; i < num_entries; i++) {
if (contactList[i].fname.equalsIgnoreCase(Key)) {
if (i >= 0) displayContact(contactList[i]);
//return i;
} // Found the Key, return index.
}
return -1;
}
public static int index1(String Key) {
// Function to get the index of a key from an array
// if not found, returns -1
for (int i=0; i < num_entries; i++) {
if (contactList[i].lname.equalsIgnoreCase(Key)) {
if (i >= 0) displayContact(contactList[i]);
//return i;
} // Found the Key, return index.
}
return -1;
}
public static int index2(String Key) {
// Function to get the index of a key from an array
// if not found, returns -1
for (int i=0; i < num_entries; i++) {
if (contactList[i].number.equalsIgnoreCase(Key)) {
if (i >= 0) displayContact(contactList[i]);
//return i;
} // Found the Key, return index.
}
return -1;
}
public static void displayContact(Entry contact) {
System.out.println("--"+ contact.fname+"\t");
System.out.println("--"+ contact.lname+"\t");
System.out.println("--"+ contact.number+"\t");
System.out.println("--"+ contact.note);
System.out.println("");
}
public static void sortList1() {
int i;
Entry temp;
temp = new Entry();
for (int j = 0; j< num_entries; j++) {
for (i = j + 1; i < num_entries; i++) {
if (contactList[j].fname.compareToIgnoreCase(contactList[i].fname)> 0) {
temp = contactList[j];
contactList[j] = contactList[i];
contactList[i] = temp;
}
}
}listAllContacts();
}
public static void sortList2() {
int i;
Entry temp;
temp = new Entry();
for (int j = 0; j< num_entries; j++) {
for (i = j + 1; i < num_entries; i++) {
if (contactList[j].lname.compareToIgnoreCase(contactList[i].lname)> 0) {
temp = contactList[j];
contactList[j] = contactList[i];
contactList[i] = temp;
}
}
}listAllContacts();
}
public static void CopyPhoneBookToFile(String FileName) throws Exception{
FileOutputStream out = new FileOutputStream(FileName);
PrintStream P = new PrintStream( out );
for (int i=0; i < num_entries; i++) {
P.println(
contactList[i].fname + "\t" +
contactList[i].lname + "\t" +
contactList[i].number + "\t" +
contactList[i].note);
}
}
public static void removeEntry1(String number) {
Entry[] newcontactList = new Entry[contactList.length];
int i = 0;
for(Entry e : contactList) {
if(e == null) break; // if an entry is null then break the loop
if(e.number.equals(number)) // if the given number matches the current number
continue; // then skip
newcontactList[i++] = e;
}
num_entries--; // decrease the number of entries by 1;
contactList = newcontactList;
}
public static void sortListByPhoneNumber() {
int i;
Entry temp;
for (int j = 0; j < num_entries; j++) {
for (i = j + 1; i < num_entries; i++) {
if (contactList[j].number.compareToIgnoreCase(contactList[i].number) > 0) {
temp = contactList[j];
contactList[j] = contactList[i];
contactList[i] = temp;
}
}
}
listAllContacts();
}
}
The problem is that while you are looping through your contactList in for (Entry e : contactList) you are not checking the whole list!
E.g. if in the first cycle e.number doesn't equal the new number it goes to else statement and breaks the loop, then it goes and calls contactList[num_entries].number = number; saving potentially the already existing number;
To fix your code with minimum changes - just remove the else{ break;}
If you want a safer and more performant solution, use HashSet data structure for your contactList or TreeSet if you want it to be sorted - it will make sure that you will never have a duplicate entry, you can use Set.contains(number) to check if the entry already exists, and additionally HashSet will improve the complexity of entry lookups to O(1), TreeSet slightly worse O(logn) - either better then looping through the whole array which is O(n).
One way you can do that by using a boolean
boolean isPresent = false;
for (Entry e : contactList) {
if (e.number.equals(number)) {
System.out.println("This phone number already exist. Please check contacts.");
System.out.println("");
isPresent = true;
break;
}
}
Now check if the variable changed or not and do the entry
if (!isPresent) {
contactList[num_entries].number = number;
//rest of code
}
In Java 8 you could use optional
Optional<String> presentPh = Arrays.stream(contactList).filter(e -> e.number.equals(number)).findAny();
Now check if you find anything in filter
if (!presentPh.isPresent()) {
contactList[num_entries].number = number;
//rest of code
}
This question already has an answer here:
How to use java.util.Scanner to correctly read user input from System.in and act on it?
(1 answer)
Closed 6 years ago.
I'm currently on a project where I'm supposed to create a phonebook in java with eclipse, I'm almost done but there's still one part of my code that I don't understand.
The following code sample is the part giving me some troubles, my condition if(...contains(...)) always answers true even if none of the contact have this part of String in their name. Also the whole contacts of the phone are displayed while I would like only the one that match.
I've tried to do with if(...contains(..) == true) but it's not working either.
On the other hand the second part looking for a matching with ID works perfectly and give back only the concerned "i". Using the same code but adapted to my String also doesn't produce any good result.
public static void display(){
System.out.println("You selected display a contact, choose an option :");
System.out.println("1. by the first name");
System.out.println("2. by the last name");
System.out.println("3. by the ID");
System.out.println("4. by the phone number");
Scanner sc = new Scanner(System.in);
int str3 = sc.nextInt();
if(str3 == 1){
System.out.println("Please enter the first name of the contact");
String fname = sc.nextLine();
sc.nextLine();
for(int i = 0; i <= (phoneBook.size()-1) ; i++){
if(((phoneBook.get(i)).getFirstName()).toLowerCase().contains(fname.toLowerCase()) ){
displayContact(phoneBook.get(i));
}
}}
if(str3 == 2){
System.out.println("Please enter the last name of the contact");
String lname = sc.nextLine();
sc.nextLine();
for(int i = 0; i <= (phoneBook.size()-1) ; i++){
if(((phoneBook.get(i)).getLastName()).toLowerCase().contains(lname.toLowerCase())){
displayContact(phoneBook.get(i));
}
}
}
if(str3 == 3){
System.out.println("Please enter the ID of the contact");
int id = sc.nextInt();
for(int i = 0; i <= (phoneBook.size()-1) ; i++){
if(id == ((phoneBook.get(i)).getID())){
displayContact(phoneBook.get(i));
}
}
}
if(str3 == 4){
System.out.println("Please enter the phone number of the contact");
int phnb = sc.nextInt();
for(int i = 0; i <= (phoneBook.size()-1) ; i++){
if(phnb == phoneBook.get(i).getPhoneNb()){
displayContact(phoneBook.get(i));
}
}
}
System.out.println(" ");
System.out.println("If you want to go back at main menu press 1, else press 2 to quit.");
int str8 = sc.nextInt();
if(str8 == 1){
menu();
}
if(str8 == 2){
quit();
}
}
I think the usage of Scanner, first reading a nextInt, and then twice a nextLine might cause an empty string, and that is always contained. You could take the second nextLine, or alternatively, use a BufferedReader, which is less error prone.
public static void display(){
System.out.println("You selected display a contact, choose an option :");
System.out.println("1. by the first name");
System.out.println("2. by the last name");
System.out.println("3. by the ID");
System.out.println("4. by the phone number");
BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));
int str3 = Integer.parseInt(sc.readLine());
switch (str3) {
case 1:
System.out.println("Please enter the first name of the contact");
String fname = sc.readLine();
for (int i = 0; i < phoneBook.size(); i++) {
if (phoneBook.get(i).getFirstName().toLowerCase().contains(fname.toLowerCase())) {
displayContact(phoneBook.get(i));
}
}
break;
case 2:
System.out.println("Please enter the last name of the contact");
String lname = sc.readLine();
for (int i = 0; i < phoneBook.size(); i++){
if (phoneBook.get(i).getLastName().toLowerCase().contains(lname.toLowerCase())) {
displayContact(phoneBook.get(i));
}
}
break;
case 3:
System.out.println("Please enter the ID of the contact");
int id = Integer.parseInt(sc.readLine());
for (int i = 0; i < phoneBook.size(); i++) {
if (id == phoneBook.get(i)).getID()) {
displayContact(phoneBook.get(i));
}
}
break;
case 4:
System.out.println("Please enter the phone number of the contact");
int phnb = Integer.parseInt(sc.readLine());
for(int i = 0; i < phoneBook.size(); i++){
if(phnb == phoneBook.get(i).getPhoneNb()){
displayContact(phoneBook.get(i));
}
}
break;
}
System.out.println(" ");
System.out.println("If you want to go back at main menu press 1, else press 2 to quit.");
int str8 = Integer.parseInt(sc.readLine());
if(str8 == 1){
menu();
}
if(str8 == 2){
quit();
}
}
As an extra the switch statement.
I am trying to take user input for name, last name, phone number and age.
For some odd reason the scanner is skipping name but none of the other variables.
Can someone point out my mistake please? I can't figure it out.
import java.util.Scanner;
public class Lab2{
String [][] info = new String [10][4];
public static void main(String [] args){
new Lab2();
}
public Lab2(){
Scanner input = new Scanner(System.in);
System.out.println();
System.out.println("Student contact Interface");
System.out.println("Please select a number from the options below:");
while(true){
System.out.println("1: Add a new contact.");
System.out.println("2: Remove an existing contact.");
System.out.println("3: Display the contact list.");
System.out.println("0: Exit the contact list.");
int options = input.nextInt();
String name, lastName, number, age;
switch(options){
case 1:
System.out.println("Please enter the name: ");
name = input.nextLine(); // This is the String var that is not accepting input from...
System.out.println("Please enter the last name: ");
lastName = input.nextLine();
System.out.println("Please enter the phone number: ");
number = input.nextLine();
System.out.println("Please enter the age (eg. 25): ");
age = input.nextLine();
addStudent(name, lastName, number, age);
break;
case 2:
System.out.println("\nEnter the name to remove: ");
String delName = input.nextLine();
System.out.println("\nEnter the last name to remove: ");
String delLastName = input.nextLine();
remove(delName, delLastName);
break;
case 3:
display();
break;
case 0:
System.out.println("Thank you for using the contact Database.");
System.exit(0);
}
}
}
public void addStudent (String name, String lastName, String number, String age){
boolean infoInserted = false;
for(int i = 0; i < 10; i++){
if(info[i][0] == null || info[i][0].equals(null)){
info[i][0] = name;
info[i][1] = lastName;
info[i][2] = number;
info[i][3] = age;
infoInserted = true;
break;
}
}
if(infoInserted){
System.out.println("\nContact saved.\n");
}
else{
System.out.println("\nYour database is full.\n");
}
}
public void remove(String delName, String delLastName){
boolean removed = false;
int i = 0;
for (i = 0; i < 10; i++) {
if (info[i][0] != null && !info[i][0].equals(null)) {
if (info[i][0].equals(delName) && info[i][1].equals(delLastName)) {
while (i < 9) {
info[i][0] = info[i + 1][0];
info[i][1] = info[i + 1][1];
info[i][2] = info[i + 1][2];
info[i][3] = info[i + 1][3];
i++;
}
info[9][0] = null;
info[9][1] = null;
info[9][2] = null;
info[9][3] = null;
removed = true;
break;
}
}
}
if (removed) {
System.out.println("Contact removed.");
}
else {
System.out.println("Contact was not found.");
}
}
public void display (){
for (int i = 0; i < 10; i++) {
if (info[i][0] != null && !info[i][0].equals(null)) {
System.out.println("Contact " + (i + 1)+ ":");
System.out.println("\t" + info[i][0]);
System.out.println("\t" + info[i][1]);
System.out.println("\tPhone Number:" + info[i][2]);
System.out.println("\tAge:" + info[i][3]);
}
}
}
}
Add a
input.nextLine();
after your
int options = input.nextInt();
This is because:
nextInt method does not read the last newline character (of your integer input)
that newline is consumed in the next call to nextLine
causing name 'to be skipped'
so you need to 'flush away' the newline character after getting the integer input
Another option:
Take in the entire line, using input.nextLine()
Get the integer value using Integer.parseInt() to extract the integer value
It is skipping name because , input.nextInt() wont go to next input line.
You can use
int option=Integer.parseInt(input.nextLine());
then it wont skip name.
I'm new to programming and I keep making the mistake of having a method do too much work. My TA gave me some advice that I should aim to make a method reusable enough that I can use it in another program without having to really modify very much. This definitely helped me approach writing methods in a better way, but I'm worried that I might have made my "add" method too meaty. Should I split it up or is it technically doing "one thing" even though it's pretty chunky?
Here's my main class (the referenced classes are just basic templates that don't do anything special aside from having getters and setters so I won't bother posting them here):
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Scanner;
enum ClassStanding{FRESHMAN,SOPHOMORE,JUNIOR,SENIOR,UNKNOWN,MASTERS_STUDIES,PHD_STUDIES};
enum Major{CS,CEG,EE,ISE,BME,ME,MET,UNKNOWN};
enum StudentType{UNDERGRADUATE,GRADUATE,UNDECLARED};
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Scanner stdin = new Scanner(System.in);
ArrayList<Student> studentList = new ArrayList<>();
int counter;
boolean continueInput;
int contCounter;
do {
do {
System.out.print("Please enter what you want to do-ADD, REMOVE, LIST, or SAVE: ");
switch (stdin.next().toLowerCase()) {
case "add": add(stdin, studentList); counter = 0; break;
case "remove": counter = 0; break;
case "list": counter = 0; break;
case "save": counter = 0; break;
default: System.out.println("Improper input, please enter only ADD, REMOVE, LIST, or SAVE."); counter = 1;
}
} while (counter == 1);
do {
System.out.print("\nDo you want to continue? Yes or no: ");
switch (stdin.next().toLowerCase()) {
case "yes": contCounter = 0; continueInput = true; break;
case "no": contCounter = 0; continueInput = false; break;
default: contCounter = 1; continueInput = false; System.out.print("\nPlease only enter 'yes' or 'no'.");
}
} while (contCounter == 1);
} while (continueInput);
} // end main method
public static void add(Scanner stdin, ArrayList<Student> studentList) { // this is the one
String firstName;
String lastName;
String uid;
StudentType studentType;
ClassStanding studentClassStanding;
Major major;
double overallGPA;
double majorGPA;
String majorProfessor;
boolean thesisOption;
System.out.print("Please enter the student's first name: ");
String tempName = stdin.next();
firstName = checkName(tempName);
System.out.print("Please enter the student's last name: ");
tempName = stdin.next();
lastName = checkName(tempName);
System.out.println("Please enter the student's UID in the format 'U####' or 'U#####': ");
String tempUID = stdin.next();
uid = checkUID(tempUID).toUpperCase();
int count;
do {
System.out.print("Please enter the student's status as UNDECLARED, UNDERGRADUATE, or GRADUATE: ");
switch (stdin.next().toUpperCase()) {
case "UNDECLARED":
studentType = StudentType.UNDECLARED;
studentClassStanding = setStudentClassStanding(studentType);
count = 0;
Student student = new Student(firstName, lastName,
uid, studentType, studentClassStanding);
studentList.add(student);
break;
case "UNDERGRADUATE":
studentType = StudentType.UNDERGRADUATE;
major = setMajor();
studentClassStanding = setStudentClassStanding(studentType);
System.out.println("Enter the student's overall GPA below.");
overallGPA = setGPA();
System.out.println("Enter the student's major GPA below.");
majorGPA = setGPA();
count = 0;
UnderGraduate underGraduate = new UnderGraduate(firstName, lastName, uid, studentType,
studentClassStanding, major, overallGPA, majorGPA);
studentList.add(underGraduate);
break;
case "GRADUATE":
studentType = StudentType.GRADUATE;
studentClassStanding = setStudentClassStanding(studentType);
majorProfessor = setMajorProfessor();
thesisOption = setThesisOption();
count = 0;
Graduate graduate = new Graduate(firstName, lastName, uid, studentType,
studentClassStanding, majorProfessor, thesisOption);
studentList.add(graduate);
break;
default:
System.out.println("Please enter either Undeclared, Undergraduate, or Graduate only.");
count = 1;
}
} while (count == 1);
}
public static String checkName(String tempName) {
int a = 1;
String name1;
Scanner scanner = new Scanner(System.in);
do {
name1 = tempName; // hold the value of firstName in name1
for (int i = 0; i < tempName.length(); i++) { // loop to check input consists of letters (is a name)
if (!Character.isLetter(tempName.charAt(i))) { // if non-letters detected, ensure this was intentional
System.out.println("Please ensure you've entered the correct name. Re-enter the name or enter 'continue' to proceed: ");
tempName = scanner.nextLine();
if (tempName.equalsIgnoreCase("continue")) { // if user enters "continue", use original input
a = 0;
tempName = name1; // pass name1 value to firstName
break;
} else {
a = 1; // continue prompting for firstName
}
} else { // accept input
a = 0;
}
}
} while (a == 1); // loop to ensure proper input
return tempName;
} // end checkName method
public static String checkUID(String tempUID) {
Scanner scan = new Scanner(System.in);
int a;
do {
if (tempUID.charAt(0) == 'U' || tempUID.charAt(0) == 'u') {
if (tempUID.length() == 6 || tempUID.length() == 5) {
a = 0;
} else {
a = 1;
System.out.print("Please ensure input is in the form of U#### or U#####. Please re-enter the UID: ");
tempUID = scan.next();
}
} else {
a = 1;
System.out.print("Please ensure input is in the form of U#### or U#####. Please re-enter the UID: ");
tempUID = scan.next();
}
} while (a == 1);
return tempUID;
} // end checkUID method
public static ClassStanding setStudentClassStanding(StudentType studentType) {
Scanner scan = new Scanner(System.in);
int count;
ClassStanding studentTempClassStanding = null;
do {
if (studentType == StudentType.UNDECLARED || studentType == StudentType.UNDERGRADUATE) {
System.out.print("Please enter the student's class standing as either Freshman, Sophomore, Junior, Senior, or Unknown: ");
switch (scan.next().toUpperCase()) {
case "FRESHMAN":
studentTempClassStanding = ClassStanding.FRESHMAN;
count = 0;
break;
case "SOPHOMORE":
studentTempClassStanding = ClassStanding.SOPHOMORE;
count = 0;
break;
case "JUNIOR":
studentTempClassStanding = ClassStanding.JUNIOR;
count = 0;
break;
case "SENIOR":
studentTempClassStanding = ClassStanding.SENIOR;
count = 0;
break;
case "UNKNOWN":
studentTempClassStanding = ClassStanding.UNKNOWN;
count = 0;
break;
default:
System.out.println("Please enter only Freshman, Sophomore, Junior, Senior, or Unknown.");
count = 1;
}
} else {
System.out.print("Please enter the student's class standing as either 'Masters' for Masters Studies or 'PhD' for PhD Studies: ");
switch (scan.next().toUpperCase()) {
case "MASTERS": studentTempClassStanding = ClassStanding.MASTERS_STUDIES; count = 0; break;
case "PHD": studentTempClassStanding = ClassStanding.PHD_STUDIES; count = 0; break;
default: System.out.println("Please enter only 'Masters' or 'PhD'.");
count = 1;
}
}
} while (count == 1);
return studentTempClassStanding;
} // end setStudentClassStanding method
public static Major setMajor() {
Major tempMaj = null;
Scanner s = new Scanner(System.in);
int c;
do {
System.out.print("Please enter the student's major as either CS, CEG, EE, ISE, BME, ME, MET, or Unknown: ");
switch (s.next().toUpperCase()) {
case "CS":
tempMaj = Major.CS;
c = 0;
break;
case "CEG":
tempMaj = Major.CEG;
c = 0;
break;
case "EE":
tempMaj = Major.EE;
c = 0;
break;
case "ISE":
tempMaj = Major.ISE;
c = 0;
break;
case "BME":
tempMaj = Major.BME;
c = 0;
break;
case "ME":
tempMaj = Major.ME;
c = 0;
break;
case "MET":
tempMaj = Major.MET;
c = 0;
break;
case "UNKOWN":
tempMaj = Major.UNKNOWN;
c = 0;
break;
default:
System.out.println("Please enter only the specified values. ");
c = 1;
}
} while (c == 1);
return tempMaj;
} // end setMajor method
public static double setGPA() {
Scanner s = new Scanner(System.in);
double gpa;
int a;
do {
try {
System.out.print("Please enter the student's GPA: ");
gpa = s.nextDouble();// read in the gpa
if (gpa < 0.0 || gpa > 4.0) { // ensure the gpa is in the correct range
System.out.println("Invalid input, please enter a positive value between 0.0 and 4.0.");
a = 1;
} else {
a = 0;
}
} catch (InputMismatchException ex) { //catch any exceptions, prompt for correct input
a = 1;
gpa = 0.0;
System.out.println("Sorry, please enter a double value.");
s.nextLine(); // skip the last input
}
} while (a == 1 || gpa < 0.0 || gpa > 4.0); //loop while gpa is negative or incorrect input is received
return gpa;
} // end setGPA method
private static String setMajorProfessor() {
Scanner s = new Scanner(System.in);
String prof;
System.out.print("Please enter the name of the major professor: ");
String tempName = s.nextLine();
prof = checkName(tempName);
return prof;
} // end setMajorProfessor method
private static boolean setThesisOption() {
Scanner s = new Scanner(System.in);
boolean thesis = false;
int a;
do {
System.out.print("Please enter 'yes' if a thesis will be written, otherwise enter 'no': ");
switch (s.next().toUpperCase()) {
case "YES": thesis = true; a = 0; break;
case "NO": thesis = false; a = 0; break;
default: System.out.println("Please enter only 'yes' or 'no'."); a = 1;
}
} while (a == 1);
return thesis;
} // end setThesisOption method
}
The focus of this project is to have a menu of options for the user (add, list, save, sort, remove) that will allow them perform a series of operations on an arraylist they supply (through the add function). Obviously I'm not done and I'm not looking for help on my project, I'm just wondering if I made my "add" method too meaty. I tried to break it up as best I could by calling other methods to do a lot of the work in it, but I still feel like it might be too much work for the method. But then again it could be fine, I really don't know-I haven't yet gotten a feel for how much a method should really do.
Yes, this definitely does too much.
In software design, people have introduced what they call bad smells, GRASP patterns and design patterns to give more scientific arguments to a discussion.
Bad smells: also called antipatterns. They include for instance god class (a class that does everything), seems very applicable here. These are alarms that you should refactor your code.
GRASP patterns: these are more or less the directions in which your code should move. Two applicable here are controller and low coupeling: split I/O and data manipulation from each other and definitely make sure that most methods don't need data provided/stored by other methods/classes.
Design patterns: these are a set of patterns one can apply to achieve the GRASP patterns. For instance you can use a Factory to built new instances, or use a Chain of Responsiblity to split a problem into small subproblems that are handled separately.
Some final advices by quotes:
"Two or more, use a for" - E. W. Dijkstra
"A method should in most circumstances not contain more than 15 lines" - Some of my teachers
There are some rules and there are some tools to help with those rules. Basically using a static code analyzer helps to determine whether the method is too big or doing too many things. Findbugs is one of the famous static code analyzer.