Find next character in a string? - java

I have a java programming assignment where you have to input a date on a single line and it gives you a numerology (horoscope-like) report based on the date. It is assumed that the user will enter a formatted date, separated with spaces.
I can retrieve the month, day, and year of the input by using in.nextInt(). However, I also have to check that the user used a correct separating character for each part of the date, which means I just have to check whether the user used forward slashes.
When looking at my code below, I currently use charAt() to find the separating characters. The problem is that the date won't always be 14 characters long. So a date in the form of 10 / 17 / 2004 is 14 characters long, but a date of 4 / 7 / 1992 is only 12 characters long, meaning that "slash1" won't always be in.charAt(3), in the latter situation it would be in.charAt(2).
Does java have a method that allows something like in.nextChar()? I know that it doesn't, but how could I just find a next character in the date?
EDIT: I forgot to reflect this originally, but my professor said that we are NOT allowed to use the String.split() method, for some reason. The thing is, I get the month, day, and year perfectly fine. I just need to check that the person used a forward slash to separate the date. If a dash is entered, the date is invalid.
public void getDate()
{
char slash1, slash2;
do
{
System.out.print("Please enter your birth date (mm / dd / yyyy): ");
Scanner in = new Scanner(System.in);
String date = in.nextLine();
month = in.nextInt();
day = in.nextInt();
year = in.nextInt();
slash1 = date.charAt(3);
slash2 = date.charAt(8);
} while (validDate(slash1, slash2) == false);
calcNum();
}

you could consider to split the input date string with " / ", then you get a String array. the next step is converting each string in that array to int.

I would use Scanner just to get a line. Then split() the line on whitespace and check the fields:
import java.util.Scanner;
import java.util.regex.Pattern;
public class GetDate {
int month, day, year;
public static void main(String[] args)
{
GetDate theApp = new GetDate();
theApp.getDate();
}
public void getDate()
{
String date;
do
{
System.out.print("Please enter your birth date (mm / dd / yyyy): ");
Scanner in = new Scanner(System.in);
date = in.nextLine();
} while (validDate(date) == false);
calcNum();
}
boolean validDate(String date)
{
// split the string based on white space
String [] fields = date.split("\\s");
// must have five fields
if ( fields.length != 5 )
{
return false;
}
// must have '/' separators
if ( ! ( fields[1].equals("/") && fields[3].equals("/") ) )
return false;
// must have integer strings
if ( ! ( Pattern.matches("^\\d*$", fields[0]) &&
Pattern.matches("^\\d*$", fields[2]) &&
Pattern.matches("^\\d*$", fields[4]) ) )
return false;
// data was good, convert strings to integer
// should also check for integer within range at this point
month = Integer.parseInt(fields[0]);
day = Integer.parseInt(fields[2]);
year = Integer.parseInt(fields[4]);
return true;
}
void calcNum() {}
}

Rather than thinking about what characters are used as separators, focus on the content you want, which is digits.
This code splits on non digits, do it doesn't matter how many digits are in each group or what characters are used as separators:
String[] parts = input.split("\\D+");
It's also hardly any code, so there's much less chance for a bug.
Now that you have the numerical parts in the String[], you can get on with your calculations.
Here's some code you could use following the above split:
if (parts.length != 3) {
// bad input
}
// assuming date entered in standard format of dd/mm/yyyy
// and not in retarded American format, but it's up to you
int day = Integer.parseInt(parts[0];
int month = Integer.parseInt(parts[1];
int year = Integer.parseInt(parts[2];

Look ahead in the stream to make sure it contains what you expect.
private static final Pattern SLASH = Pattern.compile("\\s*/\\s*");
static SomeTypeYouMadeToHoldCalendarDate getDate() {
while (true) { /* Might want to give user a way to quit. */
String line =
System.console().readLine("Please enter your birth date (mm / dd / yyyy): ");
Scanner in = new Scanner(line);
if (!in.hasNextInt())
continue;
int month = in.nextInt();
if (!in.hasNext(SLASH)
continue;
in.next(SLASH);
...
if (!validDate(month, day, year))
continue;
return new SomeTypeYouMadeToHoldCalendarDate(month, day, year);
}
}

This uses Scanner methods to parse:
import java.util.Scanner;
import java.util.InputMismatchException;
public class TestScanner {
int month, day, year;
public static void main(String[] args)
{
TestScanner theApp = new TestScanner();
theApp.getDate();
theApp.calcNum();
}
public void getDate()
{
int fields = 0;
String delim1 = "";
String delim2 = "";
Scanner in = new Scanner(System.in);
do
{
fields = 0;
System.out.print("Please enter your birth date (mm / dd / yyyy): ");
while ( fields < 5 && in.hasNext() )
{
try {
fields++;
switch (fields)
{
case 1:
month = in.nextInt();
break;
case 3:
day = in.nextInt();
break;
case 5:
year = in.nextInt();
break;
case 2:
delim1 = in.next();
break;
case 4:
delim2 = in.next();
break;
}
}
catch (InputMismatchException e)
{
System.out.println("ERROR: Field " + fields + " must be an integer");
String temp = in.nextLine();
fields = 6;
break;
}
}
} while ( fields != 5 || validDate(delim1, delim2) == false);
in.close();
System.out.println("Input date: " + month + "/" + day + "/" + year);
}
boolean validDate(String delim1, String delim2)
{
if ( ( ! delim1.equals("/") ) || ( ! delim2.equals("/") ) )
{
System.out.println("ERROR: use '/' as the date delimiter");
return false;
}
if ( month < 1 || month > 12 )
{
System.out.println("Invalid month value: " + month);
return false;
}
if ( day < 1 || day > 31 )
{
System.out.println("Invalid day value: " + day);
return false;
}
if ( year < 1 || year > 3000 )
{
System.out.println("Invalid year: " + year);
return false;
}
return true;
}
void calcNum()
{
}
}

Related

Why won't this loop break even after the boolean value is set to true? [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 1 year ago.
This program is supposed to add the hours from the input until the input ='s "done" but even after the input ='s "done" and the boolean is set to true in the while loop, it doesn't end the loop, and I can't figure out why. If someone inputs for example,
Friday
4
done
the code should output the day total and 4 as a result but it doesn't break the loop, and multiple inputs don't add the number of hours.
import java.util.Scanner;
public class SuperMarket
{
public static void main(String args[]) throws Exception
{
// Declare variables.
final String HEAD1 = "WEEKLY HOURS WORKED";
final String DAY_FOOTER = " Day Total "; // Leading spaces are intentional.
final String SENTINEL = "done"; // Named constant for sentinel value.
double hoursWorked = 0; // Current record hours.
String hoursWorkedString = ""; // String version of hours
String hoursTotalString = "";
String dayOfWeek; // Current record day of week.
double hoursTotal = 0; // Hours total for a day.
String prevDay = ""; // Previous day of week.
boolean done = false; // loop control
Scanner input = new Scanner(System.in);
// Print two blank lines.
System.out.println();
System.out.println();
// Print heading.
System.out.println(HEAD1);
// Print two blank lines.
System.out.println();
System.out.println();
// Read first record
System.out.println("Enter day of week or done to quit: ");
dayOfWeek = input.nextLine();
if(dayOfWeek.compareTo(SENTINEL) == 0)
done = true;
else
{
System.out.print("Enter hours worked: ");
hoursWorkedString = input.nextLine();
hoursWorked = Integer.parseInt(hoursWorkedString);
hoursTotal= hoursTotal+hoursWorked;
prevDay = dayOfWeek;
System.out.println("\t" + DAY_FOOTER + String.valueOf(hoursTotal));
}
while(done == false){
System.out.println("Enter day of week or done to quit: ");
dayOfWeek = input.nextLine();
if( prevDay != dayOfWeek){
hoursTotal =0;
}
System.out.print("Enter hours worked: ");
hoursWorkedString = input.nextLine();
prevDay = dayOfWeek;
hoursTotal= hoursTotal+hoursWorked;
System.out.println("\t" + DAY_FOOTER + String.valueOf(hoursTotal));
if(dayOfWeek == "done"){
done = true;
break;
}
}
System.out.println(DAY_FOOTER + "(" + prevDay + ") " + hoursTotal);
System.exit(0);
} // End of main() method.
} // End of SuperMarket class.
The problem is your String comparetion, you shouldn't really compare two Strings with ==, but with .equals() method.
Just change this line:
if(dayOfWeek == "done") ...
to:
if(dayOfWeek.equals("done")) ...

Why is my code is outputing thousands of times?

I am supposed to make this code output Day total and then the number of hours worked for that day. The code is currently displaying the day and the total. But it is displaying too many times for the program to even register. For instance, it asks to input a day, and I'll put in Monday. Then the number of hours worked, and I'll put 6. It will then output Monday 6.0 thousands of times. The expected output should be Day Total 6. What am I missing or is added to cause this?
// SuperMarket.java - This program creates a report that lists weekly hours worked
// by employees of a supermarket. The report lists total hours for
// each day of one week.
// Input: Interactive
// Output: Report.
import java.util.Scanner;
public class SuperMarket
{
public static void main(String args[])
{
// Declare variables.
final String HEAD1 = "WEEKLY HOURS WORKED";
final String DAY_FOOTER = " Day Total "; // Leading spaces are intentional.
final String SENTINEL = "done"; // Named constant for sentinel value.
double hoursWorked = 0; // Current record hours.
String hoursWorkedString = ""; // String version of hours
String dayOfWeek; // Current record day of week.
double hoursTotal = 0; // Hours total for a day.
String prevDay = ""; // Previous day of week.
boolean done = false; // loop control
Scanner input = new Scanner(System.in);
// Print two blank lines.
System.out.println();
System.out.println();
// Print heading.
System.out.println(HEAD1);
// Print two blank lines.
System.out.println();
System.out.println();
// Read first record
System.out.println("Enter day of week or done to quit: ");
dayOfWeek = input.nextLine();
if(dayOfWeek.compareTo(SENTINEL) == 0)
done = true;
else
{
System.out.print("Enter hours worked: ");
hoursWorkedString = input.nextLine();
hoursWorked = Integer.parseInt(hoursWorkedString);
prevDay = dayOfWeek;
}
while(done == false)
{
System.out.println(dayOfWeek + " " + hoursWorked);
hoursTotal = 0;
prevDay = hoursWorkedString;
}
System.out.println(dayOfWeek + " " + hoursWorked + hoursTotal);
hoursTotal++;
if(dayOfWeek.compareTo(SENTINEL) == 0)
{
hoursWorked = dayOfWeek.compareTo(SENTINEL);
prevDay = dayOfWeek;
done = true;
}
else
done = false;
// Include work done in the dayChange() method
if(dayOfWeek.compareTo(SENTINEL) == 0)
System.out.println(DAY_FOOTER + hoursTotal);
System.exit(0);
} // End of main() method.
} // End of SuperMarket class.
while(done == false)
{
System.out.println(dayOfWeek + " " + hoursWorked);
hoursTotal = 0;
prevDay = hoursWorkedString;
}
In this code block, you aren't changing done variable, so it is an infinite loop.

NumberFormatException when trying to read dates from console input

So I'm trying to find the latest date from a list of dates, but I keep getting a NumberFormatException. Is there any way of resolving this?
import java.util.*;
public class Date
{
private String date;
private int day;
private int month;
private int year;
public Date(String date)
{
String [] newDate = date.split(" ");
this.day = Integer.parseInt(newDate[0]);
this.month = Integer.parseInt(newDate[1]);
this.year = Integer.parseInt(newDate[2]);
}
public boolean isOnOrAfter(Date other)
{
if(this.day < other.day)
{
return true;
}
else if(this.day == other.day && this.month < other.month)
{
return true;
}
else if(this.day == other.day && this.month == other.month && this.year < other.year)
{
return true;
}
return false;
}
public String toString()
{
return day + "/" + month + "/" + year;
}
public static void main(String [] args)
{
Scanner in = new Scanner(System.in);
System.out.print("How many dates: ");
int num = in.nextInt();
System.out.println("Enter " + num + " dates: ");
String [] dates = new String[num];
for(int i = 0; i < dates.length; i++)
{
dates[i] = in.nextLine();
}
Date latest = new Date(dates[0]);
for(int i = 0; i < dates.length; i++)
{
Date newDates = new Date(dates[i]);
if(latest.isOnOrAfter(newDates))
{
latest = newDates;
}
}
System.out.println(latest);
}
}
I think its just a tiny problem, but I can't seem to find it. Thanks in advance.
I have a method that checking for the latest date, the logic of the code seems fine to me, if you see any problems in the logic, let me know.
The dates will be input one line at a time, for example:
1 1 1890
1 1 2000
2 1 2000
30 12 1999
The output should be 2/1/2000.
There are two reasons for the NumberFormatException here:
1.You have multiple spaces in your input between the day, month and the year.
2. Scanner's nextInt does not consume the newline. Hence you need to include a dummy nextLine after it. You can read more about this here.
int num = in.nextInt();
in.nextLine(); //To consume the new line after entering the number of dates
System.out.println("Enter " + num + " dates: ");
String [] dates = new String[num];
...
NumberFormatException is caused by Integer.parseInt() trying to parse string that is not an integer.
Your example input contains consecutive spaces and if you split input by space and there are multiple consecutive spaces in the input the resulting array will contain empty strings. Integer.parseInt() is trying to parse one of these empty Strings and that is causing the exception.
instead of
String [] newDate = date.split(" ");
use
String [] newDate = date.split(" +");
This will consider multiple spaces as a split token and return only the non space characters.

NumberFormatException for Input String Java

I am writing an appointment program in Java and am coming across an error which is
Exception in thread "main" java.lang.NumberFormatException: For input string : ""
for the following lines :
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:470)
at java.lang.Integer.parseInt(Integer.java:499)
at AppointmentNew.main(AppointmentNew.java:24)
The program is going through once, but once it gets to the end of its first run it gives me those errors.... For instance when I run the program as follows : I make the choice of "1" to make a new appointment, I then enter the date of my new appointment "mm/dd/yyyy", then I add an appointment description, and lastly I enter the type "Once, Daily, or Monthly". After that finishes it should start back over with the very first line of "Make Choice (1: New, 2: Print Range, 3: Print All, quit):" But instead it gives me the errors I described above...
Here is my code I have.
import java.util.*;
public class AppointmentNew
{
public static void main (String[] args)
{
ArrayList<String> list = new ArrayList<String>();
Scanner stdin = new Scanner(System.in);
String choice = "";
int choiceNum = 0;
String date = "";
String descrip = "";
int type = 0;
String typeChose = "";
System.out.println("Welcome to Appointment App!\n");
System.out.println("\t============================\n");
do
{
System.out.print("\tMake Choice ( 1: New, 2: Print Range, 3: Print All, quit): ");
choice = stdin.nextLine();
choiceNum = Integer.parseInt(choice);
if (choiceNum == 1)
{
System.out.print("\n\n\tEnter New Appointment Date in mm/dd/yyyy format: ");
date = stdin.nextLine();
System.out.print("\n\n\tEnter New Appointment Description: ");
descrip = stdin.nextLine();
System.out.print("\n\n\tEnter Type (1 = Once, 2 = Daily, 3 = Monthly): ");
type = stdin.nextInt();
if (type == 1)
{
Once once = new Once(date, descrip);
typeChose = "One-Time";
}
else if (type == 2)
{
Daily daily = new Daily(date, descrip);
typeChose = "Daily";
}
else
{
Monthly monthly = new Monthly(date, descrip);
typeChose = "Monthly";
}
String stringToAdd = "";
stringToAdd = ("\n\n\tNew " + typeChose + " Appointment Added for " + date + "\n");
list.add(stringToAdd);
System.out.println(stringToAdd);
System.out.println("\t============================\n");
}
if (choiceNum == 2)
{
System.out.print("\n\n\tEnter START Date in mm/dd/yyyy format: ");
String lowDate = stdin.nextLine();
System.out.print("\n\n\tEnter END Date in mm/dd/yyyy format: ");
String highDate = stdin.nextLine();
for(int i = 0; i < list.size(); i++)
{
int dateSpot = list.get(i).indexOf(" ");
if (list.get(i).compareTo(lowDate) <= 0 && list.get(i).compareTo(highDate) >= 0)
{
System.out.println(list.get(i));
}}
}
if (choiceNum == 3)
{
for(int i = 0; i < list.size(); i++)
{
System.out.println(list.get(i));
}
}
}while (choice != "quit");
}
}
Any help would be great!
You need to add another call to nextLine() after this statement here:
type = stdin.nextInt();
// ED: stdin.nextLine();
This is because, when you grab an int from the Scanner, it doesn't consume the '\n' character that gets put on the input stream when the user hits enter.
Thus, when stdin.nextLine() is called again, the String "" is returned (everything not yet processed up to the next '\n' character), and Integer.parseInt doesn't know how to handle that, so you get an error.
Surround the code with an if statement to check if the value is not quit before trying to Parse it.

Problems with exception handling using try and catch

I'm trying to use try and catch. If the entered input isn't valid the loop sould repeat and ask the user for input again, but it's not working. When I type something wrong it just repeats the System.out.println.
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
public class Price
{
public static void main(String[] args)
{
userInput();
}
public static void userInput()
{
Scanner scan = new Scanner(System.in);
int x = 1;
int month, day, year;
do {
try {
System.out.println("Please enter a month MM: ");
month = scan.nextInt();
if(month>12 && month<1)
{
System.out.println("FLOP");
}
x=2;
}
catch(Exception e){
System.out.println("not today mate");
}
}
while(x==1);
}
}
this is a working solution to your problem
public static void userInput(){
Scanner scan = new Scanner(System.in);
int x = 1;
int month, day, year;
System.out.println("Please enter a month MM: ");
month = scan.nextInt();
boolean i = true;
while(i == true)
{
if(month < 12 && month > 1)
{
System.out.println("FLOP");
i = false;
}
else if(month >= 12 || month <= 1)
{
System.out.println("not today mate");
month = scan.nextInt();
}
}
}
As a general rule, exceptions are used for exceptional circumstances, not to drive the logic of a program. Validating inputted data is not an exceptional circumstance in this case. It's a normal state of affairs that a user might make an error and enter an incorrect number. Put the input in a loop and repeat until a correct value is entered (perhaps with an option for the user to cancel).
First your condition is wrong.
You have:
if(month>12 && month<1)
{
System.out.println("FLOP");
}
So month cannot be bigger than 12 and at the same time less than 1.
I think you wanted to put OR instead of AND, e.g.
if(month > 12 || month < 1)
{
System.out.println("FLOP");
}
As for the exception, it might occur when user enters non numeric value or input is exausted.
Throws:
InputMismatchException - if the next token does not match the Integer regular expression, or is out of range
NoSuchElementException - if input is exhausted
IllegalStateException - if this scanner is closed

Categories