0

For a program I'm writing, I need to read in a user-inputted time with the format HH:MM:SS AM (or PM). The program must exit when the user types "quit". I must use a delimiter to initialize the hours, minutes, seconds, and AM/PM variables from the user-inputted String.

In order to check that the user did not type "quit" I first read in the String and did a standard check using the equalsIgnoreCase("quit") method. However, I need to be able to use a delimiter on the String if the "quit" check passes. Since my initial scanner is reading input from the System.in stream, how would I use a delimiter on the String I have already read in without creating another Scanner object like this: Scanner input = new Scanner(s).useDelimiter(":|\\s+");?

My code is below:

import java.util.Scanner;

public class Delimiter
{
    public static void main(String[] args)
    {
        int hours, minutes, seconds = 0;
        String ampm, s = "";

        Scanner scan = new Scanner(System.in);

        while (true)
        {
            s = scan.nextLine();   //scans input
            if (s.equalsIgnoreCase("quit"))  //checks if input is "quit"
            {
                System.out.println("Exiting program.");  
                return;        //exits method
            }
            else 
            {
                Scanner input = new Scanner(s).useDelimiter(":|\\s+");  //This is what I want to avoid
                hours = input.nextInt();
                minutes = input.nextInt();
                seconds = input.nextInt();
                ampm = input.nextLine().trim();
            }

            System.out.println("Hours = " + hours);
            System.out.println("Minutes = " + minutes);
            System.out.println("Seconds = " + seconds);
            System.out.println("Morning or Afternoon = " +ampm);
        }
    }
}
Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
  • Closing `System.in` at the end of a console application is not necessary, and also not useful. I don't understand why people keep saying you should close `System.in`; nobody has the same belief about `System.out`. The JVM opened it, so the JVM will close it, too. – kaya3 Mar 02 '20 at 21:51
  • Closing `System.in` is the only effect of calling `close()` on the Scanner in this code. – kaya3 Mar 02 '20 at 21:57
  • That one doesn't hold a reference to any closeable resource, so calling `close()` on it has no effect at all. It sets a boolean flag internally in the Scanner that is going to be garbage-collected anyway. See the [source](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/8cc500af2454/src/share/classes/java/util/Scanner.java#l1120) if you are unconvinced. – kaya3 Mar 02 '20 at 22:01
  • Or it does harm like closing `System.in` before you are actually finished with it, leading to questions like [this one](https://stackoverflow.com/questions/14142853/close-a-scanner-linked-to-system-in) and [this one](https://stackoverflow.com/questions/14962082/close-scanner-without-closing-system-in) where the askers think it's necessary to call `Scanner.close()` even though they actually don't want anything to be closed, and the answers obligingly offer ways to make `Scanner.close()` do nothing so that it can be called with no effect. – kaya3 Mar 02 '20 at 22:13

1 Answers1

0

How about something like this? Does this help?

import java.util.Scanner;

public class Delimiter {
    public static void main(String[] args) {
        int hours, minutes, seconds;
        String ampm;

        Scanner scan = new Scanner(System.in);

        while (true) {
            String s = scan.nextLine();
            if ("quit".equalsIgnoreCase(s))
                break;

            String[] split = s.split(":|\\s+");
            hours = Integer.parseInt(split[0]);
            minutes = Integer.parseInt(split[1]);
            seconds = Integer.parseInt(split[2]);
            ampm = split[3];
        }

        System.out.println("Exiting program.");
    }
}

I am sure there can be other approaches, but what you have does not look so bad either. Why do you want to avoid the second Scanner?

Koray Tugay
  • 22,894
  • 45
  • 188
  • 319
  • That's an interesting solution. I'll have to try it later to see how that works. I've read that opening multiple scanner objects in a program is not a good idea and can lead to problems down the road in larger programs, so I wanted to see if there were better ways to accomplish what I want to do without opening a second scanner. – Jonathan Mar 02 '20 at 22:00