homersimpson
homersimpson

Reputation: 4263

Find next character in a string?

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();
}

Upvotes: 1

Views: 13032

Answers (5)

Scooter
Scooter

Reputation: 7059

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()
   {

   }

}

Upvotes: 0

Scooter
Scooter

Reputation: 7059

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() {}
}

Upvotes: 0

erickson
erickson

Reputation: 269807

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);
  }
}

Upvotes: 0

Bohemian
Bohemian

Reputation: 425228

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];

Upvotes: 0

Kent
Kent

Reputation: 195209

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.

Upvotes: 1

Related Questions