I'm a beginner learning Java, and I'm trying to write a program to convert a user-inputted time to 12-hour time, or if it is supplied in 12-hour time format, to convert it to 24 hour time.
I have written some code, which worked as I tested it step by step, until I tried to modify to convert time from 12 hour to 24 hour format.
My code is below. I apologize for the redundancies and highly inefficient technique, but hey, I have to start somewhere. I believe my issue is in separating blocks of code, as I am trying to have a primary if statement to test whether the input ends with 'm' (i.e. if it's in 12 hour or 24 hour time when inputted), and then several nested if, else and else if statements.
import java.util.Scanner;
public class TimeConverter
{
public static void main ( String [] args )
{
Scanner ask_user = new Scanner (System.in);
System.out.println("Enter a time ([h]h:mm [am|pm]): ");
String enter_time = ask_user.nextLine ();
String am_pm = enter_time.substring(6);
String am = ("am");
String pm = ("pm");
if (enter_time.substring(7).equals("m"))
{
if (am_pm.equals(am))
{
String am_12 = enter_time.substring(0, 2);
String mins = enter_time.substring(2,5);
int am_12i = Integer.parseInt(am_12);
if (am_12i != 12)
{
String am_sub = enter_time.substring(0,5);
System.out.println(am_sub);
}
else if (am_12i == 12)
{
System.out.println("00" + mins);
}
}
else if (am_pm.equals(pm))
{
if (enter_time.equals("12:00 pm"))
{
System.out.println(enter_time);
}
else
{
String minutes = enter_time.substring(2,5);
String pm_add = enter_time.substring(0,2);
int pm_add_i = Integer.parseInt(pm_add);
int pm_add_fin = pm_add_i + 12;
String pm_add_finS = Integer.toString(pm_add_fin);
String converted_pmtime = (pm_add_finS + minutes);
System.out.println(converted_pmtime);
}
else if (enter_time.substring(7) != ("m"))
{
String 24hour = enter_time.substring(0,2);
String 12hourmins = enter_time.substring(2,7);
int 24hournum = Integer.parseint(24hour);
if (enter_time.equals("00:00"))
{
System.out.println("12" + 12hourmins);
}
else if (24hournum <= 11)
{
String hour = Integer.toString(24hournum);
String minute = enter_time.substring(2,4);
String fin = (hour + minute + "am");
}
}
}
}
The real problem is that you didn't indent your code properly. Once you do that, it will be a lot easier for you to detect the problems by yourself.
A few bugs I found from just quickly looking at your code:
You are missing a few parentheses. (Again, proper indentation will help with this a lot.)
if (enter_time.equals("12:00 pm"))
{
System.out.println(enter_time);
}
else
{
String minutes = enter_time.substring(2,5);
String pm_add = enter_time.substring(0,2);
int pm_add_i = Integer.parseInt(pm_add);
int pm_add_fin = pm_add_i + 12;
String pm_add_finS = Integer.toString(pm_add_fin);
String converted_pmtime = (pm_add_finS + minutes);
System.out.println(converted_pmtime);
}
else if (enter_time.substring(7) != ("m"))
{
You have a if statement. You then end the block with an else statement. There, however, is then and else if statement following the else. else if statements needs to be placed after the if statement and before the else statement. Either, the order of the else and else if statements are mixed up, or you are missing a closing bracket, }, after the else statement, and the else if part is really supposed to be part of the previous block.
You are also missing a closing bracket at the end of your code.
Variables cannot start with a number. All your variables like 24hournum and 24hour are invalid.
In the following line, int 24hournum = Integer.parseint(24hour);, you use parseint instead of parseInt.
My advice is to:
Properly indent all your code. Most IDEs come with shortcuts to easily do this.
Read and research all error and warning messages shown in your console.
Debug and step through your code to find what part exactly is causing the error.
Related
New to Java. I'm having a hard time understanding why my code isn't running. I'm getting a InputMismatchException when I try to run my code.
I did some testing and problems occur if there's white space in my file such as "New York." I've been trying different things such as looping with .hasNextLine() instead of .hasnext() as suggested in other threads but to no avail. Sometimes I can get it to run until the end it gives me a NoSuchElementException. If you could please put me in the right direction, that would help a lot thank you!
import java.util.*;
import java.io.*;
public class StandaloneReport {
public static void main(String[] args) {
String fileInputName;
String fileOutputName;
String firstName;
String lastName;
String houseNumber;
String street;
String city;
String state;
String zip;
String productDescription;
double productPrice;
//Scanner obj1
Scanner input = null;
input = new Scanner(System.in);
System.out.printf("What is the file name?\n");
fileInputName = input.nextLine();
//Print out the name user inputed
System.out.println("File name is: " + fileInputName);
//Read the file
FileReader filereader;
Scanner readInput = null;
try {
readInput = new Scanner(filereader = new FileReader(fileInputName));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (readInput.hasNext())
{
firstName = readInput.next();
lastName = readInput.next();
houseNumber = readInput.next();
street = readInput.next();
city = readInput.nextLine();
state = readInput.next();
zip = readInput.next();
productDescription = readInput.nextLine();
productPrice = readInput.nextDouble();
Textfile looks like this:
Jane
Doe
10
Broadway
New York
NY
10001
Galaxy S10
199.99
2
Samsung Bluetooth
29.99
1
Slim Fit Hard Plastic Case
2.99
2
Charger
17.99
3
Error I get:
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at java.util.Scanner.nextDouble(Unknown Source)
at hey.bcs.hwk.purchases.standalonereport.StandaloneReport.main(StandaloneReport.java:55)
I expected it to read it smoothly so I can print it using PrintStream in another file but I cannot even get past this part.
To be honest your program is problematic in so many ways. But here's an explanation to fix the mismatch issue you mentioned.
readInput.nextLine()
will read the remainder of the current line. So after reading "Broadway" the Scanner stays in the same line and when you call nextLine, the Scanner yields whatever is left in the line for "Broadway", which is an empty String.
To avoid this situation, do
street = readInput.next();
readInput.nextLine();
To drop the current line("Broadway" for example). And then call
city = readInput.nextLine();
That way the program will read "New York" as you expected. As Tom mentioned in the comments, for more details, look at the question asked here.
Apart from the Scanner issue, your program is ambiguous as to where it ends – you did not provide closing brackets. That while loop seems redundant considering that your input is broken: it ceases to match what you have in your code after the "199.99" line. Please put your complete code on there and revise your sample input.
This is for one set of data, one data item per line. You have to make adjustments for multiple sets of data.
int i = 0;
while (readInput.hasNext())
{
if (i == 0)
{
firstName = readInput.nextLine();
}
else if (i == 1)
{
lastName = readInput.nextLine();
}
else if (i == 2)
{
houseNumber = readInput.nextLine();
}
else if (i == 3)
{
street = readInput.nextLine();
}
else if (i == 4)
{
city = readInput.nextLineLine();
}
else if (i == 5)
{
state = readInput.nextLine();
}
else if (i == 6)
{
zip = readInput.nextLine();
}
else if (i == 7)
{
productDescription = readInput.nextLine();
}
else if (i == 8)
{
productPrice = readInput.nextDouble();
}
i += 1;
} // End while
I am building a parser that recognizes simple commands such as "DOWN.", "UP." and "REP 3.". It must be able to parse the commands rather freely. It should be legal to write
"DOWN % asdf asdf asdf
."
Where % represents a comment and the fullstop signifying end-of-command. This fullstop can be on the next line.
This is all good and well so far, however I'm struggling with the Rep part (represents Repeat.)
I should be able to issue a command as follows:
DOWN .DOWN. REP 3 " DOWN. DOWN.
DOWN . % hello this is a comment
REP 2 " DOWN. ""
This should give me 17 DOWNS. The semantics is as follows for repeat: REP x " commands " where x is the amount of times it shall repeat the commands listed inside the quotation marks. Note that REP can be nested inside of REP. The following code is for handling the DOWN command. The incoming text is read from System.in or a text file.
public void repeat(String workingString) {
if (workingString.matches(tokens)) {
if (workingString.matches("REP")) {
repada();
} else
if (workingString.matches("(DOWN).*")) {
String job = workingString.substring(4);
job = job.trim();
if (job.equals("")) {
String temp= sc.next();
temp= temp.trim();
// Word after DOWN.
if (temp.matches("\\.")) {
leo.down()
// If word after DOWN is a comment %
} else if (temp.matches("%.*")) {
boolean t = comment();
} else {
throw SyntaxError();
}
} else if (job.matches("\\..*")) {
workingString += job;
System.out.println("Confirm DOWN with .");
}
} else if (workingString.matches("\\.")) {
instructions += workingString;
System.out.println("Fullstop");
} else if (workingString.matches("%.*")) {
comment();
} else {
// work = sc.next();
work = work.trim().toUpperCase();
System.out.println(work);
}
} else {
System.out.println("No such token: " + workingString);
}
}
I got a working start on the repeat function:
public String repada(){
String times = sc.next();
times.trim();
if (times.matches("%.*")) {
comment();
times = sc.next();
}
String quote = sc.next();
quote.trim();
if(quote.matches("%.*")){
comment();
quote = sc.next();
}
String repeater = "";
System.out.println("REP " + times + " "+quote);}
However I'm thinking my whole system of doing things might need a rework. Any advice on how I could more easily solve this issue would be greatly appreciated!
What I'm trying to do:
I'm trying to convert a 4-digit military time into the standard 12 hour time format, with a colon and an added PM or AM without the use of importing anything before my code (I'm making a method that requires nothing other than java 101 techniques).
My situation:
I have milTime, which I manually change around for now every time I run it(as declared up top, currently at 1100), until I convert it into a method and submit the assignment, in which it will take in milTime, and will return milTimeString for the main program to print. I'm currently using BlueJ as an IDE, (I'm not sure if that's the best one to use?)
Example of input and output:
If 0056 were given, I would have to return 12:56am.
If 1125 were given, I would have to return 11:25am.
If 2359 were given, I would have to return 11:59pm.
Issues I need help with
When I execute, my am / pm boolean fails somewhere and it always outputs pm, no matter if I input 11:24 or 23:24.
It's probably obvious I'm working too hard to generate the output, but I don't know an easier way (Other than importing something to do it for me, which I don't want to do).
I humbly submit to any criticism on my bloated current code, and any corrections in my long-winded request. I've looked around for alternate answers, and everything involved importing or knowledge beyond me. Thanks for your time so far, and thanks in advance everyone.
public class timeTest
{
public static void main(String []args)
{
/*Declare my variables*/
int milTime = 2400;
String timeString = "";
boolean pm;
/*determine AM or PM and convert over 1200 into a clock's digits */
if (milTime >1259)
{
if (milTime <1200)
{
pm = false;
}
else
{
pm = true;
}
milTime = (milTime - 1200);
}
else
{
}
/*figure out my digits*/
int fourthDigit = milTime%10;
milTime = milTime/10;
int thirdDigit = milTime%10;
milTime = milTime/10;
int secondDigit = milTime%10;
milTime = milTime/10;
int firstDigit = milTime%10;
/*build each side of the colon*/
String hoursString = thirdDigit + "" + fourthDigit;
String minutesString = firstDigit + "" + secondDigit;
/*determine if the first digit is zero and if so, omit it*/
if (firstDigit == 0 )
{
minutesString = "" + secondDigit;
}
else
{
}
if (secondDigit == 0)
{
minutesString = "12";
}
else
{
}
/*build the total string and return the result with AM or PM based on conditional boolean.*/
if (pm = true)
{
timeString = (minutesString + ':' + hoursString + "pm");
}
else
{
}
if (pm = false)
{
timeString = (minutesString + ':' + hoursString + "am");
}
else
{
}
System.out.println(timeString);
}
}
Your problem is screaming out that you should be using your own custom data formatter. I like using the Joda Time library and its DateTime class instead of the built-in Java Date and Calendar classes. Therefore, instead of SimpleDateFormat, I recommend that you use a DateTimeFormat to create a DateTimeFormatter, which you will then use to convert your String into a DateTime. You will need one DateTimeFormatter for each of input and output. For example:
String rawTimestamp = "2300"; // For example
DateTimeFormatter inputFormatter = DateTimeFormat.forPattern("HHmm");
DateTimeFormatter outputFormatter = DateTimeFormat.forPattern("hh:mm a");
DateTime dateTime = inputFormatter.parseDateTime(rawTimestamp);
String formattedTimestamp = outputFormatter.print(dateTime.getMillis());
return formattedTimestamp;
Try this out!
You can do this much, much simpler, using a clever string conversion and SimpleDateFormat, here is the example but parsed in two lines:
// Heres your military time int like in your code sample
int milTime = 56;
// Convert the int to a string ensuring its 4 characters wide, parse as a date
Date date = new SimpleDateFormat("hhmm").parse(String.format("%04d", milTime));
// Set format: print the hours and minutes of the date, with AM or PM at the end
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm a");
// Print the date!
System.out.println(sdf.format(date));
// Output: 12:56 AM
if (pm = true)
if (pm = false)
A single equal sign is an assignment. You want to do a comparison:
if (pm == true)
if (pm == false)
These could also be written more idiomatically as:
if (pm)
if (!pm)
That's the main problem. Another is your logic for setting pm. You only need a single if statement, with the line subtracting 1200 placed inside the pm = true block.
if (milTime < 1200)
{
pm = false;
}
else
{
pm = true;
milTime -= 1200;
}
There are a few other bugs that I'll leave to you. I trust these corrections will get you a bit further, at least.
public static String convert24HourToAmPm(String time) {
if (time == null)
return time;
// Convert time where time is like: 0100, 0200, 0300....2300...
if (time.length() == 4 && Helper.isInteger(time)) {
String hour = time.substring(0,2);
String minutes = time.substring(2,4);
String meridian = "am";
if (hour.substring(0,2).equals("00")) {
hour = "12";
} else if (hour.substring(0,1).equals("1") || hour.substring(0,1).equals("2")) {
meridian = "pm";
Integer militaryHour = Integer.parseInt(hour);
Integer convertedHour = null;
if (militaryHour > 12) {
convertedHour = (militaryHour - 12);
if (convertedHour < 10)
hour = "0" + String.valueOf(convertedHour);
else
hour = String.valueOf(convertedHour);
}
}
time = hour + ":" + minutes + " " + meridian;
}
// TODO - Convert time where time is like 01:00...23:00...
return time;
}
I'm trying to multiply the value of my chronometer or just try to get the value to be a string.
Every time I try to make it a string and use toast.show() to view it, my application crashes. I can get the value of my EditText to show up but I can't seem to get my chronometer to work. Both the strings time and fin make it crash. Here's the code:
String hour = String.valueOf(mText.getText());
String time = String.valueOf(mChronometer.getBase() - stoppedMilliseconds);
int h = java.lang.Integer.parseInt(hour) / 60;
int t = java.lang.Integer.parseInt(time) * 1000 / 60;
int mm = h * t;
mon.setText(Integer.toString(mm));
String fin = "" + mm;
Toast.makeText(PoopActivity.this,
"Money made: " + fin, Toast.LENGTH_LONG).show();
There are several defects obscuring the function of this code.
time is always negative. Swap the subtraction arguments.
When converting hour from hours to minutes, multiply rather than divide by 60.
When converting time from milliseconds to minutes, divide rather than multiply by 1000.
Computation of mm yields a quantity in minutes squared. This can hardly have any meaning.
Use getApplicationContext instead of PoopActivity. Some application other than PoopActivity may be running.
There is no exception handling. For all we know, mon may be null and the setText throw an exception. Wrap your code in a try - finally block:
String fin = "";
try
{
// most of your code goes here
mon.setText(Integer.toString(mm));
String fin += mm;
}
catch (Exception e)
{
// display the exception here if so inclined
}
finally
{
Toast.makeText(PoopActivity.this,
"Money made: " + fin, Toast.LENGTH_LONG).show();
}
However, fin is a string containing a negative number just fine.
I am working on a homework assignment, and I am going a little "above and beyond" what is called for by the assignment. I am getting a run-time error in my code, and can not for the life of me figure out what it is that I have done wrong.
Here is the assignment:
Write a program that displays a simulated paycheck. The program should ask the user to enter the date, the payee’s name, and the amount of the check. It should then display a simulated check with the dollar amount spelled out.
Here is my code:
CheckWriter:
/* CheckWriter.java */
// Imported Dependencies
import java.util.InputMismatchException;
import java.util.Scanner;
public class CheckWriter {
public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
// Try to get the name
String name = "";
NameValidator validateName = new NameValidator();
while (validateName.validate(name) == false) {
System.out.println("Enter the name: ");
name = keyboard.nextLine();
if (validateName.validate(name) == false) {
System.out.println("Not a valid name.");
}
}
// Get the date
String date = "";
DateValidator validateDate = new DateValidator();
while (!validateDate.validate(date)) {
System.out.println("Enter the date (dd/mm/yyyy): ");
date = keyboard.nextLine();
if (!validateDate.validate(date)) {
System.out.println("Not a valid date.");
}
}
// Try to get the amount of the check
String checkAmount = "";
CurrencyValidator validateCurrency = new CurrencyValidator();
while (!validateCurrency.validate(checkAmount)) {
System.out.print("Enter the Check Amount (XX.XX): $");
checkAmount = keyboard.nextLine();
if (!validateCurrency.validate(checkAmount)) {
System.out.println("Not a valid check amount.");
}
}
String checkWords = checkToWords(checkAmount); // ERROR! (48)
System.out
.println("------------------------------------------------------\n"
+ "Date: "
+ date
+ "\n"
+ "Pay to the Order of: "
+ name
+ " $"
+ checkAmount
+ "\n"
+ checkWords
+ "\n"
+ "------------------------------------------------------\n");
}
private static String checkToWords(String checkAmount) {
/**
* Here I will use the string.split() method to separate out
* the integer and decimal portions of the checkAmount.
*/
String delimiter = "\\.\\$";
/* Remove any commas from checkAmount */
checkAmount.replace(",", "");
/* Split the checkAmount string into an array */
String[] splitAmount = checkAmount.split(delimiter);
/* Convert the integer portion of checkAmount to words */
NumberToWords intToWord = new NumberToWords();
long intPortion = Long.parseLong(splitAmount[0]); // ERROR! (84)
intToWord.convert(intPortion);
String intAmount = intToWord.getString() + " dollars";
/* Convert the decimal portion of checkAmount to words */
String decAmount = "";
long decPortion = Long.parseLong(splitAmount[1]);
if (decPortion != 0) {
NumberToWords decToWord = new NumberToWords();
decToWord.convert(Long.parseLong(splitAmount[1]));
decAmount = " and " + decToWord.getString() + " cents.";
}
return (intAmount + decAmount);
}
}
Note that I am using external class files to handle validation of the name, date, currency, and conversion from numbers to words. These class files all work as intended.
The error I am getting is:
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Long.parseLong(Unknown Source)
at java.lang.Long.parseLong(Unknown Source)
at CheckWriter.checkToWords(CheckWriter.java:82)
at CheckWriter.main(CheckWriter.java:46)
I have commented the lines in my code that are causing the errors that I am experiencing.
Could someone please assist me in figuring where my code is going wrong? I can include the other class files if you feel that it would be needed.
EDIT: When I run the code, it asks for the name and date. Before asking for the check amount is when it throws the error.
EDIT 2: A huge thank you to cotton.m! Thanks to his advice, I have changed the while statements to look like this:
while(!validateDate.validate(date) && date == "")
This has now fixed my issue. It would appear that when validating data with a regex expression, an empty string will return true.
The String you are trying to parse in an empty length string.
My suggestion would be to
1) Check the value of checkAmount at the start of checkToWords - if it is blank there's your problem
2) Don't do that split. Just replace the $ like you did the , (I think this is your real problem)
Also you are going to have another issue in that 10000.00 is not a long. I see you are splitting out the . but is that really what you want?
It is NumberFormatException, the value in checkAmount (method parameter) is not a valid Number.
You need to set checkAmount=checkAmount.replace(",", "");
Otherwise checkAmount will still have , inside and causes NumberFormatExcpetion.
Your issue is with your delimiter regex, currently you are using \.\$ which will split on a literal . followed by a literal $. I'm assuming that what you are actually intending to do is to split on either a . or a $, so change your delimiter to one of the following:
String delimiter = "\\.|\\$"
or
String delimiter = "[\\.\\$]"
As your code is now, checkAmount.split(delimiter) is not actually successfully splitting the string anywhere, so Long.parseLong(splitAmount[0]) is equivalent to Long.parseLong(checkAmount).
It should be:
String delimiter = "[\\.\\$]";
and then you have to check that splitWord[i] is not empty.