이 글은 만들어 가면서 배우는 JAVA 플레이그라운드를 수강하고 공부한 내용을 정리하는 용도로 작성되었습니다.
- 연도, 월, 1일이 시작하는 요일을 입력 시 윤년을 고려하여 달력을 출력하는 기능
- [예외처리] : 1월~12월 이외의 달을 입력한 경우 -> 재입력
- [예외처리] : 연도를 입력할 때 -1을 입력한 경우 -> 종료
private static final int[] MAX_DAYS = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private static final int[] LEAP_MAX_DAYS = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
public static int getMaxDaysOfMonth(int year, int month) {
if((year % 4 == 0 && year % 100 != 0) || (year % 400 ==0))
return LEAP_MAX_DAYS[month-1];
return MAX_DAYS[month-1];
}
각 월의 마지막 날을 담은 배열을 final로 선언하였다. 일수는 한번 초기화된 변수는 변경할 수 없는 상수값이기 떄문에 final로 선언하였다.
getMaxDaysOfMonth 함수는 year를 입력 받고 윤년을 고려하여 해당 연도의 마지막 날을 반환해주는 함수이다.
public void printCalendar(int year, int month, String weekday) {
int lastDay = getMaxDaysOfMonth(year, month);
int count = 0;
HashMap<String, Integer> day = new HashMap<>();
day.put("SU", 0);
day.put("MO", 1);
day.put("TU", 2);
day.put("WE", 3);
day.put("TH", 4);
day.put("FR", 5);
day.put("SA", 6);
System.out.printf(" <%d년 %d월> \n", year, month);
System.out.println("SU MO TU WE TH FR SA");
System.out.println("---------------------");
for(int i = 0; i < day.get(weekday); i++) {
System.out.print(" ");
count++;
}
for(int i = 1; i <= lastDay; i++) {
System.out.printf("%2d ", i);
count++;
if(count % 7 == 0)
System.out.println();
}
System.out.println();
}
printCalendar 함수는 사용자가 입력한 요일부터 1일이 시작하는 달력을 출력하는 함수이다. HashMap을 사용하여 key 값에는 요일 value에는 숫자를 넣어 해당 숫자만큼 공백이 되도록 구현하였다.
package Calendar;
import java.util.HashMap;
import java.util.Scanner;
public class Calendar {
private static final int[] MAX_DAYS = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private static final int[] LEAP_MAX_DAYS = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
public static int getMaxDaysOfMonth(int year, int month) {
if((year % 4 == 0 && year % 100 != 0) || (year % 400 ==0))
return LEAP_MAX_DAYS[month-1];
return MAX_DAYS[month-1];
}
public void printCalendar(int year, int month, String weekday) {
int lastDay = getMaxDaysOfMonth(year, month);
int count = 0;
HashMap<String, Integer> day = new HashMap<>();
day.put("SU", 0);
day.put("MO", 1);
day.put("TU", 2);
day.put("WE", 3);
day.put("TH", 4);
day.put("FR", 5);
day.put("SA", 6);
System.out.printf(" <%d년 %d월> \n", year, month);
System.out.println("SU MO TU WE TH FR SA");
System.out.println("---------------------");
for(int i = 0; i < day.get(weekday); i++) {
System.out.print(" ");
count++;
}
for(int i = 1; i <= lastDay; i++) {
System.out.printf("%2d ", i);
count++;
if(count % 7 == 0)
System.out.println();
}
System.out.println();
}
public void runPrompt() {
Scanner sc = new Scanner(System.in);
Calendar cal = new Calendar();
int year, month;
String weekday;
while(true) {
System.out.println("연도를 입력하세요.");
System.out.print("YEAR> ");
year = sc.nextInt();
System.out.println("월을 입력하세요.");
System.out.print("MONTH> ");
month = sc.nextInt();
System.out.println("첫 번째 요일을 입력하세요. (SU, MO, WE, TH, FR, SA)");
System.out.print("WEEKDAY> ");
weekday = sc.next();
if(year == -1) {
System.out.println("The End.");
break;
}
if(month > 12) {
System.out.println("잘못된 입력입니다.");
continue;
}
cal.printCalendar(year, month, weekday);
}
sc.close();
}
public static void main(String[] args) {
Calendar cal = new Calendar();
cal.runPrompt();
}
}
처음에 runPrompt() 함수에서 weekday = sc.nextLine();
으로 작성하였는데, Exception in thread "main" java.lang.NullPointerException
에러가 발생하였다. 찾아보니 자신이 넘겨주려는 변수가 null인데 그것이 아닌 것처럼 사용하려고 해서 발생한 에러였다.
직관적으로 설명하자면 month를 입력하고 <엔터>를 쳤다면 버퍼에 12\n이 존재한다. 이 때 nextInt()가 버퍼의 내용을 가져올 때 공백, 탭문자, 개행문자(엔터)를 제외하고 가져오기 때문에 12만 가져오게 된다. 그러면 버퍼에 \n만 남아있는데 nextLine()은 공백, 탭문자, 개행문자(엔터)를 포함시키기 때문에 \n만 가져오고 프로그램이 종료되는 것이다. 여기에서 nextLine()은 개행문자를 버리게 되고 개행문자 이전 문자열(null)만 반환된다. 그래서 weekday = sc.nextLine()
대신에 weekday = sc.next()
으로 선언하였더니 의도한대로 잘 작동하였다.