170 likes | 381 Views
Displaying a calendar. A worked example From Liang, Example 4.6, Pp136-141. The goal. Enter full year: 2000 Enter month as a number from 1..12: 6 June, 2000 ------------------------------------- Sun Mon Tue Wed Thu Fri Sat 1 2 3
E N D
Displaying a calendar A worked example From Liang, Example 4.6, Pp136-141
The goal...... Enter full year: 2000 Enter month as a number from 1..12: 6 June, 2000 ------------------------------------- Sun Mon Tue Wed Thu Fri Sat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Conventions used: • January == 1,...December==12 • Sunday==0, ..., Saturday==6 • Year >= 1800
How to proceed? • Divide and conquer • Don’t start coding yet • Identify sub-problems...assign them to methods • Solve problems one at a time
Initial decomposition printCalendar (main) readInput printMonth
Overview of PrintCalendar public class PrintCalendar{ // main method public static void main(String[] args){ // gets the year and month for which calendar is needed String yearString = JOptionPane.showInputDialog(null, “enter year”, “Example 4.6 input”, JOpotionPane.QUESTION_MESSAGE); int year = Integer.parseInt(yearString); String monthString=JOptionPane.showInputDialog(null, “enter month”, “Example 4.6 input”, JOpotionPane.QUESTION_MESSAGE); int month = Integer.parseInt(monthString); // now display the calendar for that month: use a method!! printMonth(year, month); } // other method definitions (e.g. printMonth) go here }
Method “stub” • Don’t try to solve all problems at once • Before fully implementing a method, feel free to use a “stub” instead. • This will allow you to get the overall structure of your program correct // just a stub for now: this is a method in our class public static void printMonth(int year, int month) { System.out.println(“year “ + year, “ month” + month); }
decomposing printMonth static void printMonth(int year, int month) { // which day of week is first day of this month? int startDay = getStartDay(year, month); // how many days in the month? int numOfDaysInMonth = getNumOfDaysInMonth(year,month); // print the headings printMonthTitle(year, month); // print the month body printMonthBody(startDay, numOfDaysInMonth); } We write other methods to do these things…
printMonthTitle (easy) static void printMonthTitle(int y, int m) { System.out.println(“ “ + getMonthName(m) + “, “ + y); System.out.println(“-----------------------------”); System.out.println(“Sun Mon Tue Wed Thu Fri Sat”); } Again, this uses another method getMonthName which takes in a month number and returns the name of that month. Notice that printMonthTitle is not public! (We don’t need other programs to use this method – its internal to the calendar program).
getMonthName public static String getMonthName(int month) { String monthName = null; switch(month) { case 1: monthName=“January”; break; case 2: monthName=“February”; break; .... } return monthName; } This is a simple method, which just converts a number (1..12) into a month name. Notice that this returns a String, and is not public!
static int getNumOfDaysInMonth(int y, int m) { if(month==1 || month==3 || month==5.......) return 31; if(month==4 || month==6 || month==9.......) return 30; if(month==2) { if(isLeapYear(y)) { return 29; } else { return 28; } } return 0; // If month is incorrect! } This is a simple method which takes a year and a month number as arguments and returns the number of days in that month. Notice that this returns an int, and is not public! This uses another method isLeapYear(y)which we have to write and which will tell us if a year is a leap year or not.
A method that returns true or false static boolean isLeapYear(int year) { if((year%400 == 0) || ((year%4 == 0) && (year%100 !=0))) { return true; } return false; } This is a boolean method: it returns a boolean value, either true or false. It takes a year number as argument and returns true if that year is a leap year and false otherwise.
How do we find out what day the 1st of a given month is? • int startDay is going to hold the day number (from 0..6, where 0 means Sunday, 1 means Monday etc.) for the first day in the month we’ve been asked about. • How do we figure out what this day number should be? • One possible solution: work from a known start day in the past. • Compute number of days since 1/1/1800 to our starting day: getTotalNumOfDays(year, month). • Find out what day 1/1/1800 was (it was a Wednesday). • Convert that day into a number (startDay1800 = 3;) • Add that num to the total, and take mod 7, to get the day number for the first day in the month we’ve been asked about: • startDay = (total + startDay1800) % 7;
getStartDay (get the day that 1st of the month falls on) static int getStartDay(int year, int month) { int startDay1800 = 3; // get total number of days since 1/1/1800 long totalNumOfDays = getTotalNumOfDays(year, month); // get the start day for the month we’ve been asked about int startDay = (totalNumOfDays + startDay1800) % 7; return startDay; } This method gets the day (Sun, Mon, Tue etc) that the month we’ve been asked about starts on, returning the day as a number (0..6). It works out the start day by getting the total number of days that have passed since 1/1/1800, for which the day is known.
getTotalNumberOfDays (since 1/1/1800) static long getTotalNumOfDays(int year, int month) { long total = 0; // for each year from 1800..last year add 365 or 366 for (int i = 1800; i< year; i++){ if ( isLeapYear(i) ) { total = total + 366; } else { total = total + 365; } // for this year, add days in all months to this month for (int i = 1; i< month; i++){ { total = total + getNumOfDaysInMonth(year, i); } return total; } This method gets the total number of days passed since 1/1/1800 and the month we’ve been asked to draw a calendar for.
How to design a program Only do very simple things directly in the main method of a program. For anyting that is slightly complicated, write a method. For slightly complicated things inside that method, write another method, and so on. This is called top-down design. Write and test each method one at a time. Do not write the entire program at once. Test a method by calling it in the main body of the program. Once you are sure a method is working correctly, you can call it in other parts of the program. A program written as a collection of short methods is easier to understand than one where everything is “bunched” into the main part of the program. It is also easier to write, debug, and modify.