In the previous laboratory session, we
developed a number of methods for the SimpleDate
class,
progressing from simple methods to more advanced methods. In this
laboratory, we will continue with our exploration of the
SimpleDate
class. We will begin by looking at a
dayOfYear
method which determines which day of the year it
is. From that method, we will develop a daysUntil
method
that determines the number of days until a particular date. Using that
method, in the experiments you will develop a dayOfWeek
method that determines the day of the week a date falls on.
How do we determine what day of the year a particular date is? We can determine the number of days between the first day of the year and the first day of the month, and then add which day of the month it is. For example, consider February 3. The zeroth day of February is 31 days from the beginning of the year. February 3 comes three days later, so February 3 is 34 days from the beginning of the year.
Unfortunately, the computation for later months is not so easy. For example, how many days is August 1 from the beginning of the year? It may be possible to precompute all of those numbers, as in
/** * Compute the position of this day within the current year. */ public int dayOfYear() { int to_start_of_month; switch (this.month) { case 1: // January to_start_of_month = 0; break; case 2: // February to_start_of_month = 31; break; case 3: // March to_start_of_month = 59; // We'll deal with leap years later in this function. break; ... } // switch(this.month) // Handle leap years if (this.isLeapYear() && this.month > 2) { to_start_of_month = to_start_of_month + 1; } // After February in a leap year // Add the days in this month return to_start_of_month + this.day; } // dayOfYear()
However, the work precomputing the position of the beginning of each
month from the beginning of the year is painful and prone to simple
errors in calculation if done by hand. Hence, we'd prefer to have the
computer do such computation. How do we compute the number of days
until the first of month m
? We sum the number of days in
each of the previous months. Algorithmically, we might write
// Compute the number of days until the start of month m daysUntilStartOfMonth(m) sum the number of days in each month, p, that precedes m if it's a leap year and after February, add 1 return the result
The sum
command in that algorithm is vague and is not
included in most programming languages. Hence, we must expand it to
work out the details. How do we compute the sum? By explicitly adding
the days in each prior month.
// Compute the number of days until the start of month m daysUntilStartOfMonth(m) days = 0 for each month, p, that precedes m add the number of days in month p to days end for if it's a leap year and after February, add 1 to days return days
The ``for each month'' is also vague. It may be better to make it explicit by using a counter.
// Compute the number of days until the start of month m daysUntilStartOfMonth(m) days = 0 p = 1 while p < m add the number of days in month p to days add 1 to p end for if it's a leap year and after February, add 1 to days return days
Rewriting this in Java-like syntax, we get
//**
* Compute the number of days until the start of the month.
*/
public int daysUntilStartOfMonth(int m) {
int prev = 1; // A previous month
int days = 0; // Total number of days
// Sum the days in the previous months. We assume that the
// daysInMonth
method handles leap years
// correctly.
while (prev < m) {
days = days + this.daysInMonth(prev);
prev = prev + 1;
} // while
// And that's it.
return days;
} // daysUntilStartOfMonth(int)
In fact, this is legal Java. Java provides a
while
statement with the following
form.
while (test) { body } // while
The test is executed. If it fails, the while loop terminates and control passes to the subsequent statement. If the test holds, then the statements in the body are executed. After the body is executed, the test is done again. The test and body are repeatedly executed until the test no longer holds.
Note that the test is done once per repetition, which means that the test need hold only at the beginning of the body. If, during the body, the test would no longer hold, execution of the body still continues until the end.
In Experiment J5.1 you will experiment with some basic looping examples.
Wait! Something seems wrong with the code above. It
uses a daysInMonth(int)
method, and you
may recall that we designed daysInMonth
to take no
parameters. What do we do? Once again, this is an instance of
overloading method names: providing multiple methods with
the same name, but different types of parameters.
Using overloading, we might extend our old SimpleDate
class with the new, parameterized daysInMonth
. We can
also have the old daysInMonth
use the new one, as in
/** * Compute the number of days in the current month. */ public int daysInMonth() { return this.daysInMonth(this.month); } daysInMonth() /** * Compute the number of days in month m. */ public int daysInMonth(int m) { switch (m) { case 1: case 3: ... return 31; break; case 2: if (this.isLeapYear()) { return 29; } // February in a leap year else { return 28; } // February, but not a leap year break; ... } // switch } // daysInMonth(int)
In Experiment J5.2 you will consider how to use loops to count days in the year.
for
loops
Is the while
loop the only looping
mechanism that Java provides? No. Because so many algorithms naturally
include a section that reads for every value of n between
a and b do ... that Java includes a
for
control structure to make it more convenient to
express such algorithms.
The for
loop has the following form
for (initialization; test; increment) { body } // for
In effect, this is a shorthand for the following
while
loop.
initialization; while (test) { body; increment; } // while
That is, a for
loop begins by executing
the initialization portion. Traditionally, this sets the initial
value for a counter variable. Next, it executes the test. If
the test fails, the loop terminates and control moves on to the next
statement. If the test succeeds, the body is executed. After
the body is done, the increment is executed. The test
is done again, and the cyclic process continues.
For example, we might rewrite our daysUntilStartOfMonth
method as
//** * Compute the number of days until the start of the month. */ public int daysUntilStartOfMonth(int m) { int prev = 1; // A previous month int days = 0; // Total number of days // Sum the days in the previous months for (prev = 1; prev < m; prev = prev + 1) { days = days + this.daysInMonth(prev); } // for // Deal with leap years if (this.isLeapYear() && m > 2) { days = days + 1; } // After February in a leap year // And that's it. return days; } // daysUntilStartOfMonth(int)
In Experiment J5.3
you will consider some simple examples of for
loops.
As you read other people's Java code (or C code or C++ code or ...),
you will find many shorthand expressions for common
arithmetic expressions. For example, it is so typical to add one to
a variable that Java includes a ++
operator that does
just that. In particular,
++i;
is the same as
i = i + 1;
Hence, you will often see for
loops
that look like
for (i = 0; i < n; ++i)
The prefix ++
(also called preincrement) differs
from the longer form in that it can be more easily used as part of
larger expressions. For example,
j = ++i + 3;
represents ``Add 1 to i
. Add 3 to the
updated i
, and store the result in j
.''
There is also a postfix ++
(also called postincrement)
that adds 1 to the argument, but returns the old value. For example,
j = i++ + 3;
represents ``Add 1 to i
; add 3 to the
old value of i
; store the result in j
''.
As you might guess, there are also prefix and postfix --
operators (predecrement and postdecrement), with the intended meaning of
decrementing the corresponding variable.
Finally, Java also provides a +=
assignment which
has the affect of adding the right-hand-side to the left-hand-side.
For example,
k += 5;
represents ``Add 5 to k
''.
In Experiment J5.4 you will consider Java's various arithmetic shorthands.
This section is optional and is intended for classes emphasizing applets or pursuing a simultaneous discussion of applications and applets.
Loops have many applications for applets, particularly with regards to
drawing regular and repetitious figures, such as sequences of images.
In Experiment J5.5, you will use
for
loops to create a rainbow text effect.
In Experiment J5.6, you will track down
errors in an applet designed to draw a regular grid using a
for
loop.
In Experiment J5.7, you will attempt a more complicated task: showing the positions of a bouncing ball. In order to make the ball bounce, you need to be able to determine the area available to the applet.
You may have noted that the dimensions (width and height) of the area reserved for an applet are set within the HTML files that loads the applet and not within the applet itself. Clearly, it is possible to load the same applet with different dimensions and different pages may therefore choose different dimensions for the same applet. For many applets, it becomes important for the applet designer to be able to determine these dimensions. This is particularly true of our bouncing ball applet, in which the ball must change direction
Fortunately, Java provides a mechanism for the applet author to determine
the dimensions given for the applet. You can call
this.getSize()
to obtain a java.awt.Dimension
object.
You can then get the width of that object by referring to its
width
and height
fields.
For example, you might write the following to set the right and bottom edges of the area allocated to the applet. Note that since the area begins at (0,0), the width of the applet gives the horizontal offset of the right edge, and the height of the applet gives the vertical offset of the bottom edge.
int right; // The right edge of the area allocated to the applet. int bottom; // The bottom edge of the area allocated to the applet. Dimension dim = this.getSize(); right = dim.width; bottom = dim.height;
Now, how do you make the ball bounce? We'll explore that issue in Experiment J5.7.
[Front Door] [Introduction] [Code]
Copyright (c) 1998 Samuel A. Rebelsky. All rights reserved.
Source text last modified Mon Oct 25 16:21:05 1999.
This page generated on Tue Oct 26 15:38:16 1999 by Siteweaver.
Contact our webmaster at rebelsky@math.grin.edu