if, if/else, and Nested if/else Statements
An
if statement executes a controlled statement (or a group of
controlled statements) only if a
test is true. A test can
also be called a
condition or a
Boolean
expression. Here is an example of an if statement:
System.out.print("Enter your GPA: ");
double gpa = console.nextDouble();
if (gpa >= 2.0) {
System.out.println("Good Standing");
}
The test
(gpa >= 2.0) determines whether the
value of
gpa is greater than or equal to 2.0. If true,
Good Standing is printed. If false, then
this if statement does nothing.
The syntax of an if statement is:
if (test) {
statement(s);
}
An
if/else statement executes one
branch (one
alternative) if a test is true, or another branch the test is
false. For example:
System.out.print("Enter your GPA: ");
double gpa = console.nextDouble();
if (gpa >= 2.0) {
System.out.println("Good Standing");
} else {
System.out.println("Academic Warning, Probation, or Dismissal");
}
In this example, if
(gpa >= 2.0) is false, then
Academic Warning, Probation, or Dismissal
is printed.
The syntax of an if/else statment is:
if (test) {
statement(s);
} else {
statement(s);
}
A
nested if/else statement performs a series of tests.
The code below executes the branch that corresponds to
the first test that is true. If no test is true, this statement
executes the branch that corresponds to the else.
For example:
System.out.print("Enter your GPA: ");
double gpa = console.nextDouble();
if (gpa > 4.0) {
System.out.println("Your GPA cannot be higher than 4.0");
} else if (gpa >= 2.0) {
System.out.println("Good Standing");
} else if (gpa >= 0.0) {
System.out.println("Academic Warning, Probation, or Dismissal");
} else {
System.out.println("Your GPA cannot be lower than 0.0");
}
This example has four branches, only one of which will be
executed. Determining which one requires more complex reasoning.
- If (gpa > 4.0) is true, then
Your GPA cannot be higher than 4.0 is printed.
- If (gpa > 4.0) is false and (gpa >= 2.0) is true,
then Good Standing is printed.
- If (gpa > 4.0) and (gpa >= 2.0) are both false and
(gpa >= 0.0) is true, then Academic Warning, Probation,
or Dismissal is printed. If this branch is executed, we
know that gpa is also lower than 2.0 because, to get to
this branch, (gpa >= 2.0) must have been false.
- If (gpa > 4.0), (gpa >= 2.0), and
(gpa >= 0.0) are all false, then Your GPA cannot be lower
than 0.0 is printed. If this branch is executed, we know
that gpa is less than zero because, to get to this branch,
(gpa >= 0.0) must have been false.
The syntax of a nested if/else statment is:
if (test) {
statement(s);
} else if (test) {
statement(s);
} ...
else {
statement(s);
}
Simple if/else
Activity: Midterm Grades
Midterm grades are calculated from a
courseAvg which is of type
double.
At a given time in the semester, the
courseAvg will have a maximum value that depends on how many
quizzes, labs, projects, and exams have been done.
Midterm grades are calculated using the following cutoffs:
At least | Midterm Grade |
90% | A |
80% | B |
70% | C |
65% | C- |
60% | D |
Any average below 60% of the maximum grade is an F.
- Write a code segment that prints the grade if the maximum value of courseAvg is 31.0.
- Write a method that takes two double parameters, a course average and a maximum course average,
and returns a String representing the corresponding letter grade.
Relational Operators
Two numbers can be compared using relational operators. You can
also compare an
int or
double variable to a number
or compare two
int or
double variables. In general,
you can compare any two numeric expressions.
Operator | Meaning |
Example True | Example False |
== | equals |
2 == 2 | 3 == 4 |
!= | not equal |
3 != 4 | 2 != 2 |
< | less than |
3 < 4 | 2 < 2 |
<= | less than or equal to |
2 <= 2 | 4 <= 3 |
> | greater than |
4 > 3 | 2 > 2 |
>= | greater than or equal to |
2 >= 2 | 3 >= 4 |
Activity: Relational Operators Given
int x = 4;
int y = -3;
int z = 4;
What is the result of each of the following expressions? Note
that the relational operators have a lower precedence than
the arithmetic operators.
a) x == 4
b) x == y
c) x == z
d) y == z
e) x + y > 0
f) x - z != 0
g) y * y <= z
h) y / y == 1
i) x * (y + 2) > y - (y + z) * 2
Try to come up with different values
for
x,
y, and
z that will have the opposite
results.
Activity: Relational Operators
Logical Operators
Tests can be combined using the logical operators
&& (AND)
and
|| (OR). The
&& operator requires
that both tests be true. One common use of
&& is
to test if a value is within some range, for example, the following
test is true if
score is between 0 and 100.
(score >= 0 && score <= 100)
The
|| operator requires that one or both tests be
true. A common use of
|| is to test whether a value is
equal to one of several alternatives. For example, the following test
is true if
score is equal to 99 or equal to 100.
(score == 99 || score == 100)
Another common use of
|| is
to test if a value is outside some range, for example, the following
test is true if
score is less than 0 or greater than 100
(that is, not between 0 and 100).
(score < 0 || score > 100)
In the above examples, note that the logical
operators
&& and
|| have a lower precedence
than the relational operators. Here is a revised GPA program
using various relational and logical operators.
import java.util.*;
public class GPA {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("Enter your GPA: ");
double gpa = console.nextDouble();
if (gpa > 4.0 || gpa < 0.0) {
System.out.println(gpa + " is an invalid value for GPA");
} else {
System.out.println(gpa + " is an valid value for GPA");
if (gpa <= 4.0 && gpa >= 2.0) {
System.out.println("Good Standing");
} else {
System.out.println("Academic Warning, Probation, or Dismissal");
}
}
}
}
Activity: UTSA BulleitnUse the information in
the
UTSA
Information Bulletin to write programs for one or
more of the following tasks:
- Classify an undergraduate student as a senior, junior, sophomore, or
freshman.
- Determine the undergraduate time status of a student.
- Determine the level of a course from its number.
- Determine whether a student makes the President's List, Dean's
List, or Honor Roll.
- Determine whether a student graduates cum laude, magna cum laude,
or summa cum laude.
Be sure to ask the user for the information that is needed for the
task. Also, be sure to identify invalid values.
Logical Operators
Today's News: October 15
Quiz 6 is available, due Saturday
Cumulative Algorithms
Cumulative sum
How would you find the sum of all integers from 1 to 1000?
int sum = 1 + 2 + 3 + 4 + ... ; // How long is this line?
System.out.println("The sum is " + sum);
What if we want the sum from 1 to 1,000,000?
Consider the pseudocode to add one number at a time to
sum.
Initialize sum to 0.
Add 1 to sum.
Add 2 to sum.
...
Add 1000 to sum.
Clearly, counting from 1 to 1000 can be performed in a for loop.
Initialize sum to 0.
For the numbers from 1 to 1000:
Add the number to sum.
This pseudocode can be translated into a few short lines of Java.
int sum = 0;
for (int i = 1; i <= 1000; i++) {
sum += i; // why not sum = i;
}
Activity: SumNumbers
Write a SumNumbers class that inputs two numbers
from the user and sums the numbers from the first number to the second
number.
Note: Strange things will happen if the sum exceeds 2,147,483,647.
Sum of odd
More generally, we want to sum numbers that may not be in consecutive
sequence. In this case, the pseudocode is:
Initialize sum to 0.
For however many numbers we want to sum:
Obtain the next number.
Add the number to sum.
The book includes a program that adds numbers from user input.
Here is a variation.
import java.util.*;
public class SumInput {
public static void main(String[ ] args) {
System.out.println("This program adds a sequence of numbers.\n");
Scanner console = new Scanner(System.in);
System.out.print("How many numbers do you have? ");
int totalNumber = console.nextInt( );
double sum = 0.0;
for (int i = 1; i <= totalNumber; i++) {
System.out.print("Enter the next number: ");
double next = console.nextDouble( );
sum += next;
}
System.out.println("\nsum is " + sum);
}
}
You should trace the program for an example sequence of inputs,
keeping track of the values of the variables (including
i and
next). What will happen if the user enters a zero or a
negative number?
Activity: Modify SumInput 1
Modify the SumInput program so it computes the
average. Beware of dividing by zero.
Activity: Modify SumInput 2
Modify the SumInput program so it also finds the
product of the inputs (all the inputs multiplied together).
Often, we want to do additional processing in a cumulative
algorithm. For example, we want might to count how many inputs
are negative.
Counting the values that satisfy a test can be accomplished with an
integer variable called a
counter and an if statement:
- Declare and initialize the counter before the loop.
-
Increment the counter inside a loop if the number satisfies the test.
if (next < 0) {
negatives++;
}
-
Report (or return or use in some way) the value of the counter
after the loop.
System.out.println("There are " + negatives + " negative numbers.");
Activity: Modify SumInput 3
Modify the SumInput program to count negative
numbers. Also, use an if statement so the report is grammatical
if there is one negative number.
Activity: Modify SumInput 4
Modify the SumInput program to count other kinds of
numbers.
Book:
Read the subsection on roundoff error. Use
the SumInput program to experiment with roundoff errors.
Min/Max Loops
Consider finding the maximum and/or minimum value of a sequence of
numbers. If we look at one number at a time, we can keep track
of the largest value so far and update it if the current number is
larger.
Traditionally,
max is used as the variable name for the
largest value so far (likewise
min for the smallest so
far). What should
max be initialized to?
Initializing
max to zero would be a mistake if all of the
numbers are negative.
Similarly, initializing
min to zero would be a mistake if all of the
numbers are positive. The safest solution is to initialize
max (or
min) to the first number. This leads
to the following pseudocode.
Initialize max to the first number.
For the remaining numbers:
Obtain the next number.
If this number is larger than max:
then assign this number to max.
The following program finds the maximum of numbers input by the
user. Trace the program for an example sequence of inputs,
keeping track of the values of the variables (including
i and
next). What will happen if the user enters a zero or a
negative number?
public class MaxInput {
public static void main(String[ ] args) {
System.out.println("This program finds the maximum of a sequence of numbers.\n");
Scanner console = new Scanner(System.in);
System.out.print("How many numbers do you have? ");
int totalNumber = console.nextInt( );
System.out.print("Enter the first number: ");
double max = console.nextDouble( );
for (int i = 2; i <= totalNumber; i++) {
System.out.print("Enter the next number: ");
double next = console.nextDouble( );
if (max < next) {
max = next;
}
}
System.out.println("\nmax is " + max);
}
}
Activity: Modify MaxInput 1
Modify the MaxInput program so it also finds the minimum.
Activity: Modify MaxInput 2
Modify the MaxInput program so it also finds the second largest number.
Max and Min
Today's News: October 17
Quiz 6 is available, due Saturday
Lab 5 due on Tuesday
Text Processing
The char Type
The primitive type
char represents one character.
Literal values are expressed by a character within single quotes, for
example:
'A', '7', '#'.
Values of type
char are represented by integers, and
arithmetic operators can be applied to
chars, but generally
this is not considered good practice (exceptions include
using
++ to get the next
char).
A
char can be stored in an
int, but a cast is
required to store an
int in a char.
int code = 'a';
char c = (char) 65;
Activity: Write a program that prints the characters
corresponding to the integers from 32 to 126.
The
Character class has many useful functions for operating
on
chars. These methods are called by
putting
Character. in front and including the
char
as a parameter (similar to how
Math methods are called).
Method Name |
Return Type |
Description |
getNumericValue(ch) |
int |
returns a number if ch is a digit |
isDigit(ch) |
boolean |
returns true if ch is a digit |
isLetter(ch) |
boolean |
returns true if ch is in 'A' to 'Z'
or 'a' to 'z' |
isLowerCase(ch) |
boolean |
returns true if ch is a lowercase letter |
isUpperCase(ch) |
boolean |
returns true if ch is an uppercase letter |
toLowerCase(ch) |
char |
returns the lowercase version of ch |
toUpperCase(ch) |
char |
returns the uppercase version of ch |
chars are primitive types, and
Strings are objects in
Java, and it can be confusing for beginners to keep track of the
differences. Here are some important things to remember.
- Use == to test equality of chars. Use the
equals method to test equality of Strings.
char c = 'y';
String s = c + "es";
System.out.println(c == 'y'); // prints true
System.out.println(s == "yes"); // prints false!
System.out.println(s.equals("yes")); // prints true
- Use Character.method(charVariable) notation
for Character methods.
Use stringVariable.method( ) notation
for String methods.
char c = 'y';
String s = "yes";
System.out.println(Character.toUpperCase(c)); // prints Y
System.out.println(s.toUpperCase( )); // prints YES
- Use the charAt method to extract a single character from
a String. Recall that Strings use zero-based indexing.
String s = "yes";
char c0 = s.charAt(0);
char c1 = s.charAt(1);
char c2 = s.charAt(2);
System.out.println(c0); // prints y
System.out.println(c1); // prints e
System.out.println(c2); // prints s
char c3 = s.charAt(3); // causes an error
Activity: Write a program to try out the
other Character methods and the corresponding String
methods.
char type
Cumulative Text Algorithms
We can process each character of a
String by calling
the
charAt method for each index from 0 up to (but not
including) the length of the
String.
String string1 = "Four score and seven years ago";
for (int i = 0; i < string1.length( ); i++) {
char c = string1.charAt(i);
System.out.println("char '" + c + "' is at index " + i);
}
For example, we might to count the number of times a particular
character occurs in a
String. Recall that to use a
counter, we need to initialize the counter before the loop,
increment the counter inside the loop if a test is satisfied, and
use the value of the counter after the loop. A method that
returns the count would have the following pseudocode.
- Initialize the counter to 0.
- For each char in the String:
- Obtain the next char.
- If this char is equal to the one we want to count:
- then increment the counter.
- Return the value of the counter.
The
String to be searched and the
char to look for
need to be parameters. Otherwise, how do we know what to search
and what to search for? This leads to the following method.
public static int countChar(String s, char c) {
int count = 0;
for (int i = 0; i < s.length( ); i++) {
if (c == s.charAt(i)) {
count++;
}
}
return count;
}
Activity: Write a program to ask the user for a String
and a char, to call the countChar method, and print
the result. Use the nextLine method of
the Scanner class to read the String.
Activity: Modify the countChar method so it counts both
lowercase and uppercase versions of a char.
Activity: Write a countDigits method that counts the number
of digits in a String.
For another example, consider converting a
String to "leet",
a geeky variation of spelling sometimes seen on the internet.
Part of the conversion is substitutions, for example: 'e' to '3', 'l'
to '1', and 't' to '7'. Given "turtle", we want to return
"7ur713". As we examine the
String parameter one letter
at a time, we want to add one letter (or a substitution) to
the
String we want to return.
Initialize the result to "".
For each char in the String:
Obtain the next char.
If this char needs to be substituted:
then assign the substitution to the char.
Add (concatenate) the char to the end of the result.
Return the result.
The pseudocode only has one "if statement", but in Java we will need
three different conditions for 'e', 'l', and 't'. Recall that we
can use the
+ operator to produce a
String from two
other
Strings (or a
String and any other type).
public static String partialLeet(String str) {
String result = "";
for (int i = 0; i < str.length( ); i++) {
char c = str.charAt(i);
if (c == 'e' || c == 'E') {
c = '3';
} else if (c == 'l' || c == 'L') {
c = '1';
} else if (c == 't' || c == 'T') {
c = '7';
}
result = result + c;
}
return result;
}
First look at how the
String variable
result behaves
like a counter. Before the loop,
result is initialized
to
"", aka the empty string, a
String with zero
characters. Inside the loop, the
char
variable
c is added (concatentated) to the end
of
result. After the loop,
result is
returned.
Next look at how the
char variable
c is manipulated
in the loop. In each iteration,
c is initialized to
the
char at index
i. The if statement changes
the value of
c under certain conditions. Changing the
value of
c does not change
str; a primitive type is
a copy of the original value. In the tests, note that lower case
and upper case letters are checked. If none of the tests are
true,
c's value will stay the same.
Activity: Write a program to ask the user for a String,
to call the partialLeet method, and print
the result.
Activity: Modify the partialLeet method so it includes
the substitutions: 's' to 5 and 'z'
to 2. Look up some other substitutions and add them to
your method.
Activity: Write and test a switchCase method to
reverse lowercase and uppercase in a String. For example,
it should convert "Java" to "jAVA".
Cumulative Text Algorithms
Today's News: October 20
Lab 5 due on Tuesday
Methods with Conditional Execution
Preconditions, Postconditions, and Exceptions
When you write a method, you should consider what needs to be true for
the method to work and what it means for the method to accomplish its
task. For example, a method that finds the square root of a
number might need the number to be zero or positive, and its return
value, when multiplied by itself, should be equal to (or be very close
to) the number.
A
precondition is a condition that must be true when the
method is called so that the method can perform its task.
A
postcondition is a condition that will be true when
the method is finished as long as the method's preconditions were
true.
Consider writing a method that is supposed to return the sum of the
integers from 1 up to a given value. For example, if the
parameter is 7, the method should return the value of
1+2+3+4+5+6+7. Note that stating what a method is supposed to do
usually describes its postcondition.
public static int sumUpTo(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
return sum;
// postcondition: sum is the sum of the integers from 1 up to n
}
What should this method do if the parameter is zero or negative?
It doesn't make sense to add up the integers from 1 up to -5. If
we think that a zero or negative parameter is a programming error,
then we should state that a positive parameter is a precondition of
this method.
public static int sumUpTo(int n) {
// precondition: n >= 1
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
return sum;
// postcondition: sum is the sum of the integers from 1 up to n
}
Unfortunately, comments don't do anything when the code is
executed. This method will return 0 if the precondition is not
satisfied. If this is a serious enough error, then we want
to
throw an exception, which will force the programmer to fix
the bugs.
public static int sumUpTo(int n) {
// precondition: n >= 1
if (n < 1) {
throw new IllegalArgumentException(n + " is not positive");
}
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
return sum;
// postcondition: sum is the sum of the integers from 1 up to n
}
You see the
new keyword because an exception is an object in
Java. There are many different kinds of exceptions in Java, but
using
IllegalArgumentException should be sufficient for now.
Activity: Square Root
Write and test a squareRoot method that
returns the value of Math.sqrt, but throws an exception
whenever the parameter is negative.
Activity: Percent Correct
Write and test a percentCorrect method that
has two int values as parameters: the number of questions on
the test and the number of correct answers by a student. The
method should return the percentage of correct answers. Identify
the postcondition(s) and precondition(s). Your method should
throw an exception if any precondition is not satisfied.
Activities: Square Root and Percent Correct
Today's News: October 22
Quiz 7 is available, due Saturday
Return Values and Code Paths
One of the interesting features of the return statement is that when a
return statement is run, the method does not run any more code.
For example, consider this method which behaves like
Math.max.
public static double max(double a, double b) {
if (a > b) {
return a;
}
return b;
}
This method returns the larger of the two
doubles. It
looks like the method will always return
b because that is
what the last statement does. However, if the test
a >
b is true, then the first return statement is executed and any
code following the if statement is skipped. There are two
different paths in the code that could be executed: one path is
executed if
a > b, and the other path is executed if
a <= b.
Activity: Identify the four different code paths in the
following method. Generate examples that go down each
path. Be sure to consider examples where all three parameters
are different, where all three parameters are equal, and where two of
the three parameters are equal. Determine the conditions that
correspond to each path.
public static double max(double a, double b, double c) {
if (a > b) {
if (c > a) {
return c;
} else {
return a;
}
}
if (c > b) {
return c;
}
return b;
}
Activity: Write and test a method to perform
one of the following tasks.
- Return the minimum of two numbers.
- Return the minimum of three numbers.
- Given two numbers, return the number closest to zero.
- Given three numbers, return the number closest to zero.
- Return the median of three numbers.
Reasoning about code paths is usually done when you are planning how
to write a method.
Suppose we want to write a method that returns the first digit in
a
String. This will probably involve a loop that
obtains and examines each
char in the
String.
For each char in the String:
Obtain the next char.
Process the char
Note that if the first
char in the
String is a
digit, the method can return that
char and does not need to
look at the remaining characters. In general, once the method
finds a digit, we can return it without looking at any remaining
characters.
For each char in the String:
Obtain the next char.
If the char is a digit:
Return that char.
Having a return statement in a loop creates many different code
paths. For example, if the steps return on the fourth iteration,
then, the fourth character must be a digit, and, in addition, the
first three characters were not digits.
What should we do if the
String has no digits? Because
the method will be returning a
char, we could return a
non-digit
char (a
'?', for example) to indicate that
no digit was found (throwing an exception is another
possibility). Note that the method should not return
a
'?' until all the
chars have been examined.
This is not something we can do before the loop (haven't examined any
chars yet) or inside the loop (there might be
more
chars to examine), so it must be done after the
loop. That is, if the loop ends without a return, that means
there were no digits found.
For each char in the String:
Obtain the next char.
If the char is a digit:
Return that char.
Return '?' if the method gets to this point.
With all these considerations, we can convert the pseudocode
into a method.
public static char firstDigit(String s) {
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
return c;
}
}
// to get to this point,
// no return statements have been executed,
// so none of the chars was a digit
return '?';
}
Activity: Finding First or Last
Write and test a method to perform
one of the following tasks.
- Return the first lowercase letter in a String.
- Return the first even digit in a String.
- Return the position of the first digit in a String.
- Return the last digit in a String.
Activity: Finding First or Last