Best practice for getting user input from multiple methods in Java? - java

I have a relatively basic program in which I have several methods getting input from the user (using a Scanner object). I am looking to see which of these techniques (if either) is considered standard or best practice. Here I will use one method just as an example.
Create a new scanner object in each method separately:
// Get date from user
public static LocalDate getDateFromUser(String date_request_label){
Scanner inputScan = new Scanner (System.in);
System.out.print(date_request_label + " (YYYYMMDD): ");
String input_string = inputScan.nextLine();
// Split input into year/month/day
int year = Integer.parseInt(input_string.substring(0,4));
int month = Integer.parseInt(input_string.substring(4,6));
int day = Integer.parseInt(input_string.substring(6,8));
return LocalDate.of(year,month,day);
}
Create a single scanner object in main and call it in each method:
// Get date from user
public static LocalDate getDateFromUser(Scanner inputScan, String date_request_label){
System.out.print(date_request_label + " (YYYYMMDD): ");
String input_string = inputScan.nextLine();
// Split input into year/month/day
int year = Integer.parseInt(input_string.substring(0,4));
int month = Integer.parseInt(input_string.substring(4,6));
int day = Integer.parseInt(input_string.substring(6,8));
return LocalDate.of(year,month,day);
}
Thanks!

IMHO reusing an object is preferable as long as it does not reduce the readability of the code.
So I'd go with option two.

Related

Copy a string of words to an array in Java

Ive been writing a program that is able to calculate a person's grades, but Im unable to turn a string into an String array (it says the array length is 1 when i put in 3 words). Below is my code. Where am I going wrong??
protected static String[] getParts(){
Scanner keyboard = new Scanner(System.in);
System.out.println( "What assignments make up your overall grade? (Homework, quizzes, etc)" );
String parts = keyboard.next();
Pattern pattern = Pattern.compile(" ");
String[] assignments = pattern.split(parts);
// to check the length
for ( int i = 0; i < assignments.length; i++ )
System.out.println(assignments[i]);
return assignments;
}
Scanner::nextLine
Scanner::next() only consumes one word (it stops at whitespace). You want Scanner::nextLine, which consumes everything until the next line, and will pick up all your words.
Use keyboard.nextLine instead:
static String[] getParts()
{
Scanner keyboard = new Scanner(System.in);
System.out.println("What assignments make up your overall grade? (Homework, quizzes, etc)");
String[] assignments = keyboard.nextLine().split(" ");
for (String i : assignments)
System.out.println(i);
return assignments;
}
NOTE: You also do not need to define a Pattern. You also do not need to return anything since the method already prints the strings. Unless of course you plan on using the values elsewhere

"How to pass GregorianCalendar class object to a different class method ?"

I want to create a student record using a method that is able to
take input from user about student details . My class Student should
consists of following fields : short semester,
full name,
registration number etc
.registration number of a student = concatenation of year and student number.
Eg year at which student joined = 2023,
student no. = 80,
So registration number = 2380
Plus I have been tasked to input date using class GregorianCalendar
INSIDE STUDENT CLASS:
import java.util.*;
class Student2{
String fullname;
GregorianCalendar date;
short semester;
Student2()
{
}
Student2(String name,short sem, GregorianCalendar Date)
{
fullname = name;
semester=sem;
date = Date;
}
int years = date.get(Calendar.YEAR);
String year = Integer.toString(years);
String Studno = Integer.toString(80);
String y1= year.substring(0,3);
String Reg = y1.concat(Studno);
int reg = Integer.parseInt(Reg);
void Studarry()
{
int n=5,i;
Student2[] stuarry = new Student2[10];
for(i=0;i<n;i++)
{
System.out.println("Enter name sem year month day gpa cgpa\n");
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
short sem2 = sc.nextShort();
int year2 = sc.nextInt();
int month2 = sc.nextInt();
int day2=sc.nextInt()
GregorianCalendar gc2 = new GregorianCalendar(year2,month2,day2);
stuarry[i] = new Student2(name,sem2,gc2);
}
}
void Display()
{
}
}
INSIDE DRIVER CLASS:
public class Greg2{
public static void main(String[] args)
{
Student2 starr = new Student2();
starr.Studarry();
}
}
ERRORS :
Exception in thread "main" java.lang.NullPointerException
at oop2/lab5.Student2.<init>(Greg2.java:23)
at oop2/lab5.Greg2.main(Greg2.java:68)
Class name versus variable name
date = Date;
Date with an uppercase D is the name of a class, not a variable. Instead you should have defined the name of the argument being passed as date not Date. This line becomes date = date ;. The compiler can distinguish between the argument and the member variable. If you want more clarity for the reader, you can say this.date = date ;.
But that is a poor name for a variable. Because there is indeed two classes bundled with Java named Date, both related to GregorianCalendar, I suggest avoiding the use of date as a variable name for GregorianCalendar object – just too confusing.
java.time
The GregorianCalendar is a terrible class. It was supplanted entirely years ago by the java.time classes. Specifically, ZonedDateTime. Both classes represent a moment as seen through the wall-clock time of some particular region (a time zone).
However, both classes are not meant for your purpose. You want only a date, without a time-of-day and without the context of a time zone or offset-from-UTC. So LocalDate fits your needs.
LocalDate ld = LocalDate.of( year , month , day ) ;
Constructor
int years = date.get(Calendar.YEAR);
String year = Integer.toString(years);
String Studno = Integer.toString(80);
…
These lines are floating around, not placed inside a method. They should have been put inside the constructor of your method.
Why is there a class named Greg2? Did you mean a specific student? If so, Greg should be represented by values assigned to an instance of a Student class.
What is with all the 2 characters at the end of names? Naming is important; get that straight and you will be half-way to a solution.
So most of this code is a mess. Try again from scratch. Look up other code examples, such as on Stack Overflow, in the Oracle Tutorial, or in the textbook for your class of this homework assignment.
Learn about separation of concerns. One class should be just about representing a student. Another class should represent your app, and hold the main method. Use a Collection to gather the newly instantiated Student classes into a roster, possibly making a class Roster if you have other roster-related responsibilities.
Lastly, take baby steps. Add one little thing at a time, see that it runs properly. Use System.out.println to verify values. Do not try to write all the code at once.
Your NullPointerException comes from this line:
int years = date.get(Calendar.YEAR);
Field initializers like this one are executed before the constructor. So when you create a Student2 object using new Student2(), the above line is created while the date field is still null, and therefore the call to date.get() throw the exception.
Instead move the initialization of years into the constructor, after you have assigned an object to date.
As others have said too, the GregorianCalendar class is poorly designed and long outdated. If it wasn’t for a lazy teacher apperently with no clue of what has been going on with Java the last more than 5 years, you shouldn’t use it. Never ever.
Mistakes corrected as-
1) Bought field initializers inside my constructor to get rid of NullpointerException as said by ( Basil Bourque , Ole V.V. )
2) created array of student objects in main and called method Stduarry on them .
3) Variable name Date changed to gc
import java.util.*;
INSIDE STUDENT CLASS:
class Student22{
String fullname;
GregorianCalendar date;
short semester;
int reg;
Student22()
{
}
Student22(String name,short sem, GregorianCalendar gc)
{
fullname = name;
semester=sem;
date = gc;
int years = date.get(Calendar.YEAR);
String year = Integer.toString(years);
System.out.println(year);
String Studno = Integer.toString(80);
String y1= year.substring(2,4);
System.out.println(y1);
String Reg = y1.concat(Studno);
System.out.println(Reg);
reg = Integer.parseInt(Reg);
System.out.println(reg);
}
void Studarry(int n)
{
System.out.println("Enter name sem year month day \n");
Scanner sc = new Scanner(System.in);
fullname = sc.nextLine();
System.out.println(fullname);
semester = sc.nextShort();
int year2 = sc.nextInt();
int month2 = sc.nextInt();
int day2=sc.nextInt();
GregorianCalendar gc2 = new GregorianCalendar(year2,month2,day2);
date= gc2;
int years = date.get(Calendar.YEAR);
String year = Integer.toString(years);
String Studno = Integer.toString(n);
String y1= year.substring(0,3);
String Reg = y1.concat(Studno);
reg = Integer.parseInt(Reg);
Display();
}
void Display()
{
System.out.println(fullname);
System.out.println(semester);
System.out.println(reg);
System.out.println(date.get(Calendar.YEAR));
}
}
INSIDE DRIVER CLASS:
public class Greg2{
public static void main(String[] args)
{
System.out.println("Please enter a Firstname , MiddleName & Lastname separated by spaces");
Scanner sc = new Scanner(System.in);
String name = sc.nextLine();
GregorianCalendar gc = new GregorianCalendar(2018,7,22);
Student22 s = new Student22(name,(short)3,gc);
s.Display();
int i,j,n;
System.out.println("Enter n\n");
n = sc.nextInt();
Student22[] starr = new Student22[n+1];
for(j=1;j<=n;j++)
{
starr[j]= new Student22();
starr[j].Studarry(j);
}
}
}

Accumulate Strings in Loop and Print Out all of them

I am trying to figure out how to accumulate user inputs in for loop and then to print them out with one system.out.print. This is my test code for the problem.
So for example if a user type : Mike for his name and Joe,Jack,Dave for other names, how to print them all just having one variable because amount of variables are not known since a user has that decision. Also is it possible to do that without stringbuilder and without arrays?
import java.util.Scanner;
public class Accumulate {
public static void main(String[] args) {
String othernames = " ",name;
int count,n;
Scanner kybrd = new Scanner(System.in);
System.out.println("Enter your name ");
name = kybrd.nextLine();
System.out.println("How many other names would you like to add ? ");
count = kybrd.nextInt();
kybrd.nextLine();
for(n=0;n<count;++n){
System.out.println("Enter other names ");
othernames = kybrd.nextLine();
}
System.out.println("Other names are "+othernames + " And your name is "+ name);
}
}
You can call it recursively, for instance:
Scanner sc = new Scanner(System.in);
String s;
while(condition) {
s = s + sc.nextLine();
}
this will always concat the lines you enter, you can also add commas, or spaces, or whatever you want to add.
as for your question about using Objects other than StringBuilder you can use List<String> and build a string for it at the final step.
you can use Map<String, String> if you need more complex data structure.

I'm following a template for a java program and I can't find out why I'm getting the ';' expected error

I have about 3 weeks java experience so bear with me. I'm trying to make a program that calculates how many days I've been alive by following my teachers template but for the life of me I can't figure out why I keep getting the "error ';' expected.
public class age {
public static void main(String[] args) {
System.out.print("Enter your date of birth");
int calcDays = (String birthdate);{
String m1 = birthdate.substring(0,1);
String m2 = birthdate.substring(3,4);
String m3 = birthdate.substring(6,9);
int month = Integer.parseInt(m1);
int day = Integer.parseInt(m2);
int year = Integer.parseInt(m3);
int dd = year * 365 + month * 30 + day;
return(dd);
}
System.out.print("This is a test" + dd);
}
}
It looks like you wandered from the template a bit. Here's what I think was meant:
import java.util.Scanner;
public class age {
public static void main(String[] args) {
Scanner sysin = new Scanner(System.in);
System.out.print("Enter your date of birth");
String birthdate = sysin.next();
int dd = calcDays(birthdate);
System.out.print("This is a test" + dd);
}
static int calcDays(String birthdate) {
String m1 = birthdate.substring(0, 1);
String m2 = birthdate.substring(3, 4);
String m3 = birthdate.substring(6, 9);
int month = Integer.parseInt(m1);
int day = Integer.parseInt(m2);
int year = Integer.parseInt(m3);
int dd = year * 365 + month * 30 + day;
return (dd);
}
}
The output from a sample run:
Enter your date of birth: 12/25/2000
This is a test73032
Notes:
The import statement makes the Scanner class visible.
The class statement begins the definition of a class named "age". Normal Java conventions are to capitalize the names of classes (as in "Age"), but I kept your names. The class contains two static methods named main() and calcDays().
The main() method is the starting point. It is executed by the Java runtime when you run the Age class (either through "java Age" at the command line, or by clicking on "Go" in an interactive development environment.)
main() prints a prompt, uses a Scanner to read a string, passes that string to the calcDays() method, and prints the integer value returned by calcDays().
The calcDays() methods accepts a string argument, dices that up into substring for month, day and year, converts those to integer values and computes a day number to return as a result.
Experiment with this. You'll find that even a small change in format will cause an exception and a lot of noisy-looking output. As you develop more technique, you'll find ways to adapt to reasonable variations, and politely reject unreasonable ones. The suggestion to look at the Java Tutorials is a good one, but if this is your first stab at programming in any language, then you might want to invest in a beginner's book (Head First Java, Java for Dummies, etc.) and THEN come back to the Tutorials to see the same material developed at greater depth.

Splitting a string into different array indexes Java?

I am trying to split a string into different array indexes. This string is coming from user input (through java.util.Scanner) and is being loaded into a String variable. How can I split the input from the string into different array indexes?
Also, how can I do the math functions that are implied by DOBbeing an int?
Here is my code:
import java.util.Scanner;
public class main {
public static void main(String args[]) {
Scanner input = new Scanner(System.in);
System.out.println("Enter date of birth (MM/DD/YYYY):");
String DOB;
DOB = input.next();
int age = 0;
age = 2013 - DOB - 1;
int age2 = 0;
age2 = age + 1;
System.out.println("You are " + age + " or " + age2 + " years old");
}
}
String[] parts = DOB.split("/");
int months = Integer.parseInt(parts[0]);
int days = Integer.parseInt(parts[1]);
int years = Integer.parseInt(parts[2]);
Then just use years instead of DOB in your calculations.
Better yet, use new Calendar() to get today's precise date, and compare against that.
Use DateTimeFormat as shown in Parse Date String to Some Java Object to parse your string into a DateTime object, and then access the members.
DateTimeFormatter format = DateTimeFormat.forPattern("MM/dd/yyyy");
DateTime dateTime = format.parseDateTime(DOB);
This uses Joda Time library.
Alternatively you can use SimpleDateFormat in a similar manner, to parse it into a Date object.
I notice you're using keyboard input to recognize the string. If the user doesn't input what you expect it will crash your program. (If you're just starting Java, this is fine; you can just run it again)
You can make it easier to split by asking them thrice too eg:
int dob[] = new Integer[3]; // integer array made from Integer class-wrapper
System.out.println("Input day");
dob[0] = Integer.parseInt(input.next());
System.out.println("Input month");
dob[1] = Integer.parseInt(input.next());
System.out.println("Input year");
dob[2] = Integer.parseInt(input.next());
You now have three integers in an array, split and ready to manipulate.
If Integer can't parse the text input as a number you'll get a NumberFormatException.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
public class main {
public static void main(String args[]) {
// Man you should look onto doing your
// homework by yourself, ijs.
// But here it goes, hope i make myself clear.
Scanner input = new Scanner(System.in);
System.out.println("Enter date of birth (MM/DD/YYYY):");
String DOB;
DOB = input.next();
//
int age;
// You need to know when it is today. Its not 2013 forever.
java.util.Calendar cal = java.util.Calendar.getInstance();
// ^ The above gets a new Calendar object containing system time/date;
int cur_year = cal.get(Calendar.YEAR);
int cur_month = cal.get(Calendar.MONTH)+1; // 0-indexed field.
// Cool we need this info. ill skip the day in month stuff,
// you do that by your own, okay?
SimpleDateFormat dfmt = new SimpleDateFormat("MM/dd/yyyy");
int bir_year;
int bir_month;
try {
// If you wanna program, you must know that not all functions
// will exit as it's intended. Errors happen and YOU should deal with it.
// not the user, not the environment. YOU.
Date d = dfmt.parse(DOB); // This throws a parse exception.
Calendar c = Calendar.getInstance();
c.setTime(d);
bir_year = c.get(Calendar.YEAR);
bir_month = c.get(Calendar.MONTH)+1; // 0-indexed field;
age = cur_year - bir_year;
// Well, you cant be a programmer if you dont think on the logics.
if(cur_month < bir_month ) {
age -= 1;
// If the current month is not yet your birth month or above...
// means your birthday didnt happen yet in this year.
// so you still have the age of the last year.
}
// If code reaches this point, no exceptions were thrown.
// and so the code below wont execute.
// And we have the variable age well defined in memory.
} catch(ParseException e) {
// But if the date entered by the user is invalid...
System.out.println("The date you typed is broken bro.");
System.out.println("Type a date in the correct format MM/DD/YYYY and retry.");
return; // Got errors? tell the program to quit the function.
}
// Well now we can say to the user how old he is.
// As if he/she didnt know it ^^'
System.out.println(String.format("You are %d years old", age));
// **Not tested.
}
}

Categories

Resources