Solving Problems that involve decisions Topics Normal execution order Conditional statements Relational operators & Boolean expressions Enumerations Objectives At the completion of this topic, students should be able to: Describe the normal flow of control through a C# program Correctly use if statements in a C# program Explain how to use relational operators to write a Boolean expression and use them correctly in a C# program Correctly use if/else statements in a C# program Correctly use blocks in if/else statements Correctly use a switch statement in a C# program Describe enumerations and use them in a C# program Correctly use the logical operators to make complex Boolean expressions The order in which statements in a program are executed is called the flow of control. Methods that we have written so far begin with the first line in the method, and continue line by line until control reaches the end of the method. Example of Sequential Flow F l o w o f using System; class Program { static void Main() { const int MINS_PER_HOUR = 60, SPLITTER = 100, PERCENT_BETTER = 1.25;; int startTime, endTime; int endTime; // Prompt for input and get start time Console.WriteLine("Enter in the start time for this trip in 24 hour clock time"); Console.Write("in the form hhmm: "); startTime = int.Parse(Console.ReadLine()); c o n t r o l // Prompt for input and get end time Console.WriteLine("Enter in the end time for this trip in 24 hour clock time"); Console.Write("in the form hhmm: "); endTime = int.Parse(Console.ReadLine()); // calculate the start and end time with minutes as integers int startMmm = startTime / SPLITTER * MINS_PER_HOUR + startTime % SPLITTER; int endMmm = endTime / SPLITTER * MINS_PER_HOUR + endTime % SPLITTER; …etc } } // end of Main There are many problems that cannot be solved using methods that execute in this line-by-line fashion from beginning to end. Some problems require the program to take different actions, depending upon conditions that exist in the program at the time. Examples A More Accurate GoodGuys Program GoodGuy's Delivery service operates a fleet of delivery vehicles that operate between Provo and Salt Lake City. With the I-15 construction work scheduled for Utah County, Goodguys wants you to create a program for them that will compute the new arrival times for deliveries. Once the work on the interstate begins, GoodGuys estimates that their delivery times will increase based on the following table: midnight to 6:00am 6:01am to 9:30am 9:31am to 3:00am 3:01pm to 7:00pm 7:01pm to 10:00pm 10:01pm to midnight no increase 30% increase 10% increase 30% increase 10% increase no increase The U.S. Widget company runs its payroll program at the end of every two week period. If an employee gets paid by the hour, that employee’s gross pay is equal to hoursWorked * hourlyWage; However, if an employee gets paid a salary, that employee’s gross pay is calculated differently yearlySalary / 26.0; In a computer chess game, the computer might calculate its move in a number of different ways, depending upon where all of the various pieces on the chessboard. How can you tell if a problem requires a program that includes this kind of logic? When the problem statement includes the word “if” If this employee gets an hourly wage If the King is in check If today is a weekday If the balance in the account is less than $1,000 Sometimes the problem statement will use the word “when” When an employee gets an hourly wage When the King is in check When the day is a weekday When the balance in the account is less than $1,000 GoodGuys If the delivery truck leaves between midnight and 6:00am 6:01am and 9:30am 9:31am and 3:00am 3:01pm and 7:00pm 7:01pm and 10:00pm 10:01pm and midnight Then the delivery time increases by 0% 30% 10% 30% 10% 0% These are all examples of Conditional Statements, i.e. do something if a condition is true. In programming we often take a different action based on whether or not a condition is true. Conditional statements are shown in an activity diagram by using a diamond. ( balance < LIMIT ) balance < LIMIT ? Conditional statements are shown in an activity diagram by using a diamond. Arrows show the execution path that the program takes when the statement is true and when it is false. if ( balance < LIMIT ) balance < LIMIT ? false true Conditional statements are shown in an activity diagram by using a diamond. Arrows show the execution path that the program takes when the statement is true and when it is false. if ( balance < LIMIT ) The “if” statement tests the condition. balance < LIMIT ? false true The if Statement The if statement allows us to execute a statement only when the condition is true. if ( balance < LIMIT ) balance = balance – CHARGE; balance < LIMIT ? false note how we have indented the statement to be executed when the condition is true. Although the compiler doesn’t care about indentation, it makes it easier to read the code. true balance = balance – CHARGE; The if Statement The if statement allows us to execute a statement only when the condition is true. if ( balance < LIMIT ) { balance = balance – CHARGE; } Use curly braces to clearly define what actions Are taken when the condition is true balance < LIMIT ? false true balance = balance – CHARGE; Problem Statement Write a program that prompts the user to enter in his or her age. Ifthe person is under 21, print a message that says “Youth is a wonderful thing … enjoy it.” Prompt user to Enter in their age Store input in the variable age age < 21 ? false end true Print “Youth is a …” using System; class Program { const int MINOR = 21; static void Main() { int age = 0; Console.Write("How old are you? "); age = int.Parse(Console.ReadLine()); Notice how this block of code is executed if the condition is true, but the block is skipped if the condition is false. if (age < MINOR) { Console.WriteLine("Youth is a wonderful thing ... enjoy it."); } Console.WriteLine(“Goodbye!”); Console.ReadLine(); }//End Main() }//End class Program The expression inside the if( … ) statement is called a Boolean expression, because its value must be either true or false. Relational Operators relational operators are used to write Boolean expressions Operator == != < <= > >= Meaning equal not equal less than less than or equal (not greater than) greater than greater than or equal (not less than) Note: The precedence of relational operators is lower than arithmetic operators, so arithmetic operations are done first. Warning: Don’t confuse = and == Note that the following expression will not compile in C#… if ( age = myNewAge) { ... } This is an assignment, not a comparison The if/else statement This construct allows us to do one thing if a condition is true, and something else if the condition is false. if (height > MAX) adjustment = MAX – height; else adjustment = 0; Console.WriteLine(adjustment); true height > MAX ? false adjustment =0 adjustment = MAX - height Problem Statement Write a program that prompts the user to enter in his or her age. If the person is under 21, print a message that says “Youth is a wonderful thing … enjoy it.” Otherwise, print a message that says “Old age is a state of mind.” Prompt user to Enter in their age Store input in the variable age age < 21 ? true Print “Youth is a …” false Print Old age is a…” end using System; class Program { const int MINOR = 21; static void Main() { int age; Console.Write("How old are you? "); age = int.Parse(Console.ReadLine()); if (age < MINOR) { Console.WriteLine("Youth is a wonderful thing ... enjoy it."); } else { Console.WriteLine("Old age is a state of mind...!"); } Console.ReadLine(); }//End Main() }//End class Program Executing a Block of Statements Sometimes we want to execute more than one statement when a condition is true ( or false ). In C#, we can use a block of statements, delimited by { and } anyplace where we would normally use a single statement. if ( a < b ) { a = 0; b = 0; Console.WriteLine(“Sorry …”); } ... using System; class Program { const int MINOR = 21; static void Main() { int age; Console.Write("How old are you? "); age = int.Parse(Console.ReadLine()); if (age < MINOR) { Console.WriteLine("**********************************"); Console.WriteLine("* Youth is a wonderful thing *"); Console.WriteLine("* Enjoy it! *"); Console.WriteLine("**********************************"); } else { Console.WriteLine("***********************************"); Console.WriteLine("* Old age is a *"); Console.WriteLine("* state of mind...! *"); Console.WriteLine("***********************************"); } Console.ReadLine(); }//End Main() }//End class Program Nested if/else Statements In C#, the statement to be executed as the result of an if statement could be another if statement. In a nested if statement, an else clause is always matched to the closest unmatched if. using System; class Program { static void Main() { int a, b, c, min = 0; Console.WriteLine("Enter three integer values - each on a separate line."); a = int.Parse(Console.ReadLine()); b = int.Parse(Console.ReadLine()); c = int.Parse(Console.ReadLine()); if (a < b) if (a < c) min = a; else min = c; else if (b < c) min = b; else min = c; keep track of which if an else goes with! Console.WriteLine("The smallest value entered was {0}", min); Console.ReadLine(); }//End Main() }//End class Program using System; class Program { static void Main() { int a, b, c, min = 0; Console.WriteLine("Enter three integer values - each on a separate line."); a = int.Parse(Console.ReadLine()); b = int.Parse(Console.ReadLine()); c = int.Parse(Console.ReadLine()); if (a < b) if (a < c) min = a; else min = c; else if (b < c) min = b; else min = c; Hmmm … it’s hard without indenting code Console.WriteLine("The smallest value entered was {0}", min); Console.ReadLine(); }//End Main() }//End class Program using System; class Program { static void Main() { int a, b, c, min = 0; Console.WriteLine("Enter three integer values - each on a separate line."); a = int.Parse(Console.ReadLine()); b = int.Parse(Console.ReadLine()); c = int.Parse(Console.ReadLine()); if (a < b) if (a < c) min = a; else Hmmm … it’s worse if you indent wrong min = c; else if (b < c) min = b; else min = c; Console.WriteLine("The smallest value entered was {0}", min); Console.ReadLine(); }//End Main() }//End class Program Another Example char direction = ‘n’; Console.WriteLine("Press a direction key(n, s, e, or w) and Enter"); direction = char.Parse(Console.ReadLine()); if (direction == 'n') Console.WriteLine("You are now going North."); else if (direction == 's') Console.WriteLine("You are now going South."); else if (direction == 'e') Console.WriteLine("You are now going East."); else if (direction == 'w') Console.WriteLine("You are now going West."); else Console.WriteLine("You don't know where you are going!"); Console.ReadLine(); if (direction == 'n') Console.WriteLine(“…going North."); else if (direction == 's') Console.WriteLine(“…going South."); else if (direction == 'e') Console.WriteLine(“…going East."); else if (direction == 'w') Console.WriteLine(“…going West."); else Console.WriteLine("You don't know…!"); These are exactly the same. The only difference is how the code is indented. if (direction == 'n') Console.WriteLine(“…going North."); else if (direction == 's') Console.WriteLine(“…going South."); else if (direction == 'e') Console.WriteLine(“…going East."); else if (direction == 'w') Console.WriteLine(“…going West."); else Console.WriteLine("You don't know…!"); if (direction == 'n') Console.WriteLine(“…going North."); else if (direction == 's') Console.WriteLine(“…going South."); else if (direction == 'e') Console.WriteLine(“…going East."); else if (direction == 'w') Console.WriteLine(“…going West."); What’s the difference? if (direction == 'n') Console.WriteLine(“…going North."); if (direction == 's') Console.WriteLine(“…going South."); if (direction == 'e') Console.WriteLine(“…going East."); if (direction == 'w') Console.WriteLine(“…going West."); if (direction == 'n') Console.WriteLine(“…going North."); else if (direction == 's') Console.WriteLine(“…going South."); else if (direction == 'e') Console.WriteLine(“…going East."); else if (direction == 'w') Console.WriteLine(“…going West."); Suppose that ‘n’ was entered. if (direction == 'n') Console.WriteLine(“…going North."); if (direction == 's') Console.WriteLine(“…going South."); if (direction == 'e') Console.WriteLine(“…going East."); if (direction == 'w') Console.WriteLine(“…going West."); if (direction == 'n') Console.WriteLine(“…going North."); else if (direction == 's') Console.WriteLine(“…going South."); else if (direction == 'e') Console.WriteLine(“…going East."); else if (direction == 'w') Console.WriteLine(“…going West."); This statement is executed and all of the others are skipped. Suppose that ‘n’ was entered. Suppose that ‘n’ was entered. The first output statement is executed, then each of the other if statements is executed in turn. There is no else clause to cause control to skip these. if (direction == 'n') Console.WriteLine(“…going North."); if (direction == 's') Console.WriteLine(“…going South."); if (direction == 'e') Console.WriteLine(“…going East."); if (direction == 'w') Console.WriteLine(“…going West."); Dangling else clauses An else is always matched to the closest unmatched if Will this code do what you expect? const int R_LIMIT = 40; const int O_LIMIT = 20; ... If an employee works more than 40 hours a week, then make sure that they don’t work more than 20 hours of overtime if (regTime > R_LIMIT) if (overTime > O_LIMIT) Console.WriteLine(“Overtime hours exceed the limit.”); else Console.WriteLine(“no overtime worked.”); Will this code do what you expect? const int R_LIMIT = 40; const int O_LIMIT = 20; ... if (regTime > R_LIMIT) if (overTime > O_LIMIT) Console.WriteLine(“Overtime hours exceed the limit.”); else Console.WriteLine(“no overtime worked.”); This else goes with The second if statement ... If regTime were 50 and overTime were 10, the message “no overtime worked” would be displayed. The code should be written this way. const int R_LIMIT = 40; Const int O_LIMIT = 20; ... if (regTime > R_LIMIT) { if (overTime > O_LIMIT) Console.WriteLine(“Overtime hours exceed the limit.”); } else Console.WriteLine(“no overtime worked.”); Practice: Write a program that takes a temperature in degrees Celsius. Then output whether or not water is a solid, liquid, or vapor at that temperature at sea level. Example: Input: -5 Output: Water is solid Designing programs that use conditional statements 1. Carefully inspect the problem statement. If word “if” is used or the word “when” is used to describe different situations that might exist, then the program probably will need to use conditional statements. 2. After determining that several different situations might exist, try to identify each unique situation. Write down the condition that makes this situation unique. Carefully check that each condition is unique - there should be no overlaps. Be sure that the boundary conditions are correctly stated. 3. Write down exactly what the program should do differently in each of the unique situations that you have identified. 4. Formulate the if/else statements that reflect this set of conditions. Make them as simple as possible. Watch for dangling else’s. Example Slick Guys Used Car Sales gives their sales people a commission, based on the value of the sale. If the sale was made at or above the sticker price, the sales person gets a 20% commission. If the sale was less than the full sticker price, but greater than the blue book price, the sales commission is 10%. If the sale price is equal to the blue book price, the sales person gets a 5% commission. Slick Guys never sells a car for less than the blue book price. How many conditions are there? What are the conditions? 4 Conditions 1. The sales price is GREATER than or EQUAL to the sticker price. 2. The sales price is LESS than the sticker price but GREATER than the blue book price. 3. The sales price EQUALS the blue book price. 4. The sales price cannot be less than blue book. What do you do for each situation? 1. The sales price is GREATER than or EQUAL to the sticker price. Set commission = 20% of sales price 2. The sales price is LESS than the sticker price but GREATER than the blue book price. Set commission = 10% of sales price 3. The sales price EQUALS the blue book price. Set commission = 5% of sales price 4. The sales price cannot be less than blue book Message: Cannot sell for less than blue book Boundary Conditions 5% no sale Blue Book Price 10% 20% Sticker Price Boundary Condition 5% no sale Blue Book Price 10% 20% Sticker Price Put your conditions in order … start with the most likely is true sale >= sticker ? commission = 0.20 false is sale > bluebk ? true commission = 0.10 true commission = 0.05 false is Sale = bluebk ? false No sale is true sale >= bluebk ? commission = 0.10 What happens if you put the conditions in the wrong order? false is true sale > sticker ? commission = 0.20 false is sale = bluebk ? false No sale true commission = 0.05 Suppose that the sticker price = 20,000, the blue book price = 19,000, and the sale price = 21,000. What will the commission be? What should it be? if ( salesPrice >= STICKER_PRICE) commissionRate = 0.20; else if ( salesPrice > BLUE_BOOK) commissionRate = 0.10; else if (salesPrice == BLUE_BOOK) commissionRate == 0.05; else Console.WriteLine(“No Sale!”); The Switch Statement The switch statement allows a program to take one of several different paths, based on the value given to the switch statement. switch ( numValues ) { must be an integer or a character literal case 0: Console.WriteLine(“No values were entered”); break; without the break case 1: statement, you will get Console.WriteLine(“One value was entered”); a compile error. break; case 2: Console.WriteLine(“Two values were entered”); if numValues is not break; 0, 1, or 2, execution goes here. default: Console.WriteLine(“Too many values were entered”); break; } Enumerations An enumeration type is a user defined data type whose valid values are defined by a list of constants of type int. enum DayOfWeek { SUN=0, MON=1, TUE=2, WED=3, THU=4, FRI=5, SAT=6 }; if values are not explicitly given, then the first constant is assigned zero, and then each is incremented by one. So the following is equivalent to the above example: enum DayOfWeek { SUN, MON, TUE, WED, THU, FRI, SAT }; Enumerations are often used to label the cases in a switch statement: enum Days { MON = 1, TUE = 2, WED = 3}; { --switch ( (Days)whichDay ) { case Days.MON: Console.WriteLine("Today is Monday"); break; case Days.TUE: Console.WriteLine("Today is Tuesday"); break; case Days.WED: Console.WriteLine("Today is Wednesday"); break; default: Console.WriteLine("What day is it?"); break; } } Console.ReadLine(); Handling Complex Conditions Consider the following situation: If it is Friday night and you have no homework then go to the movies. These two conditions can be combined using logical operators. Logical Operators Operator ! && || Description Example logical NOT logical AND logical OR !a a && b a || b the results of logical operations are defined in truth tables Logical NOT a !a false true true false Logical AND the evaluation of && is short circuited if a is false. a b a && b false false false false true false true false false true true true Logical OR the evaluation of || is short circuited if a is true. a b a || b false false false false true true true false true true true true Consider the following situation: If it is Friday night and you have no homework then go to the movies. if ( today == FRIDAY && homework == NO) goToMovie( ); Simplifying complex relationships using logical operators Consider the following problem: Given three values, x, y, and z, find out if y lies in between x and z. y <x y>z y > x and y < z x z Consider the following problem: Given three values, x, y, and z, find out if y lies in between x and z. y <x y > x and y < z y>z z x We could write the conditions as follows: if ( y > x) if ( y < z) Console.WriteLine(“\n the value of y lies between x and z.”); else Console.WriteLine( “\n the value of y does not lie between x and z.”); else Console.WriteLine( “\n the value of y does not lie between x and z.”); Consider the following problem: Given three values, x, y, and z, find out if y lies in between x and z. y <x y>z y > x and y < z x z But the following is simpler and eliminates one else clause: if ( y > x && y < z ) Console.WriteLine( “\n the value of y is between x and z.”); else Console.WriteLine( “\n the value of y is not between x and z.”); Operator Precedence (again) higher precedence lower precedence + ! unary plus unary minus Not * / % multiplication division remainder + - addition subtraction higher precedence lower precedence < > <= >= less than greater than less than or equal greater than or equal == != equal not equal && and || or = += -= *= /= %= assignment add and assign subtract and assign multiply and assign divide and assign modulo and assign Comparing Characters Characters in the ASCII standard are arranged so that they compare in alphabetical order (collating sequence). Lower case characters are not equal to their upper case counterparts. As a matter of fact lower case characters are greater in value than upper case characters. The ASCII Code Table cat car 99 97 116 99 97 114 Cat 67 97 116 CAR 67 65 82 Comparing Real Numbers Because of the way that real numbers are represented in the computer, you cannot be guaranteed that two real numbers are exactly equal to one another. The best way to handle this situation is to subtract one Real number from the other and see if the absolute value of their difference is smaller than some tolerance value. Testing to see if two floating point values are equal const double EPS = 0.0001; ... if ( (a – b) < EPS) ) Console.WriteLine(“\nThey are equal…”); Practice What is the value of the following, given that the value of count = 0, and the value of limit = 10? We don’t know what x and y are. (count == 0 ) && (limit < 20) true (count == 0 && limit < 20) true (limit > 20 || count < 5) true !(count == 12) true (count == 1 && x < y) false (count < 10 || x < y) true (limit / count > 7 && limit < 0) divide by zero error! (limit < 20 || limit / count > 7) true Not all problems requiring decisions will use the word “if” or “when” in the problem description. Learn to identify problems that may contain choices. For example … A triangle whose sides are all of equal length is called an equilateral triangle. A triangle with two equal sides is called an isosceles triangle. A triangle whose sides are all of different lengths is called a scalene triangle. Write a program that asks for the lengths of the three sides of a triangle, and then tells the user what kind of triangle it is. Groups of four * Design and code these programs Practice Problem: Allow the user to type in two integers. Print out the value of the highest number. Numbers may be negative. If they are equal, say so. Practice Obe Wan Kenobi is in charge of reviewing the applications of this years candidates for Jedi Knight school. Candidates must be at least 3’ high, but less than 8’. However, an exception has been made for Federation pilots, who can be of any height. Candidates under 3’ can go to Jr. Jedi Knight School. Write a program that * gets a candidate’s height * asks if they are a federation pilot, * Then prints one of the following messages, as appropriate: - This candidate is accepted into Jedi Knight School - This candidate is accepted into Jr. Jedi Knight School - This candidate is not accepted. Practice The DeepPockets Savings Bank computes the monthly interest rate on an account, based on the following: Super Saver Account 5% interest on the balance as long as it is more than $5,000. Otherwise pay 3%. Standard Account Always pay 3% interest on the balance. Write a program that computes the interest on an account, given the balance on the account and the type of account. Practice Write a tollbooth program that calculates the toll required to use the highway, based on the class of vehicle. Passenger cars $2.00 Busses $3.00 Trucks $5.00 Use a switch statement and an enumeration.