Download presentation
Published byMagdalen Young Modified over 9 years ago
1
Control Structures Programs have 4 basic control structures:
Sequential Selection Repetition Unconditional Branching we can break unconditional branches into those that pass parameters (function calls) and those that do not, and whether they return to the current location (function calls) or not (GO TO types) For purposes of local scope and easier syntax, we can add blocks or compound statements ALGOL 60 - first language to introduce blocks using begin-end statements (also used in Pascal, Ada, Modula, etc) C, C++, Java, PHP, JavaScript, Perl - uses { } as delimiters Lisp uses ( ) Control statements are essential for any programming language The last statement is interesting when looking at two classes of languages: Early languages had an incomplete set of control statements leading to free use of goto statements. This was particularly true of FORTRAN which had no logical if and no logical while loop. Instead, a programmer would construct their own by using the 3-way If statement and GO TO statements. COBOL also lacked in proper looping mechanisms. PROLOG has all control built-in so that there are explicit control statements.
2
Selection Statements Gives a program the ability to choose which instruction(s) to next execute based on conditions Types: 1-Way selection (if statement) 2-Way selection (if-else statement) 3-Way selection (FORTRAN had a peculiar arithmetic-based selection statement) multiple selection (or n-way selection, switch/case) Design issues: what is the form and type of expression that controls the selection? (C allows 0/non-0, Java/C# allow only boolean) how are clauses specified if at all? if nesting is allowed, how is it specified and implemented? In Lisp, instead of 0 and non-0, the values are T (true) and nil. If the condition evaluates to anything other than nil, the condition is treated as true and the then clause is executed.
3
One-way and Two-way Selections
One-way: if without else if condition is true then execute next statement, otherwise skip over it FORTRAN’s IF statement was a One-Way (no Else clause, no nesting) if the then clause has more than 1, instruction, we alter the semantics of the statement, to what is in essence an “else-goto” rather than, an “if-then” nearly every language since has allowed two-way selections ALGOL 60 introduced the first true two-way selection terms “then-clause” & “else-clause” introduced clauses are expected to be a single instruction to easily detect the end of each clause, otherwise, must use blocks ALGOL 60 allowed more than one entry into the two-way selection clauses! in languages where the “then” is omitted, the condition must be placed in ( ) to denote its end If (.NOT. Condition) GOTO 20 I = 1 J = 2 20 Continue Original FORTRAN was implemented too close to assembly language, the idea of a “block” of code was not thought of at that time, so you would directly control the flow of a selection statement with GOTO statements NOTE: Continue in FORTRAN was used as a placeholder (like a no-op). It was more commonly used in the FORTRAN DO loop To denote a clause (or block) in Python, you use indentation. This makes Python unique among programming languages – white space does matter. However, this simplifies some of the issues – you do not need explicit block delimiters, and as we see in the next slide, the indentation controls unmatched else clauses, rather than requiring explicit end statements or a default compiler rule.
4
Blocks ALGOL introduced the block structure in part to permit multiple instructions being part of the then or else clauses these required delimiters – begin .. end, { }, ( ) in Algol 60: If (Boolean expression) then begin statement 1; statement n end; Perl goes one step further and requires that all clauses be placed into blocks (even if the clause is a single instruction) Ada and FORTRAN 95 have explicit end of blocks but not explicit beginnings by using end if or end for statements Ada used specific end statement based on the type of block (e.g., end loop, end if, etc) making it more readable than the other languages.
5
Nesting Nested If-Then-Else statements can lead to ambiguity if there is a miss-match between conditions and else clauses if(sum = = 0) if (count = = 0) result = 0; else result = 1; Which condition does the else go with? Is result = 1 if sum != 0 or if sum = = 0 and count != 0? if sum = = 0 then if count = = 0 then result = 0 else result = 1 end In ALGOL 60, nested if-then-else clauses must use an explicit end statement this is also the case for FORTRAN 77/90/95, Modula-2 and Ada In Ruby, all clauses must have explicit end statements (even if there is only a single statement in the clause) In C/C++/Java/C# and Pascal, the compiler rule matches mismatched elses with the last unmatched condition the rule can be overridden using blocks In C/C++/Java, the compiler interprets code for us as follows Example: if (sum == 0) if (count==0) result = 0; else result = 1; With this compiler rule we can do this if (sum==0) { if (count==0) result = 0; } else result = 1; Without it, we would have to do this
6
Multiple Selection Constructs
FORTRAN offers a 3-way selection IF (expression) N1, N2, N3 if expression < 0 then goto N1, if = 0 goto N2, if > 0 goto N3 this was FORTRAN I-IVs only IF statement! ALGOL-W introduced the case statement Pascal, Modula and Ada, FORTRAN 90/95 all use this C/C++/Java/C# use the switch statement the main difference is that after a condition is found true in the switch statement, the next condition is tested such that the switch statement is not exited until all cases have been tested, to avoid this, you must use break statements however, to fix this oddity, in C# you must end each case with a break or goto Lisp uses the COND statement all of these allow for a default if none of the cases is selected default in C-languages, else in Pascal, when others in Ada Perl/Python don’t have a multi-selection statement at all! The case/switch statement has a couple of weaknesses over the nested if-else There is only one value being tested (whereas in a nested if-else, you can have anything you want in the condition) The value being tested MUST be an ordinal type in most languages Lisp’s cond statement is far more flexible and allows any type of condition. The cond statement looks like a switch/case statement, but in actuality is much like any nested if-else.
7
Nested If-Else Constructs
Cond in Lisp is really a nested if-then-else function Lisp also provides a “default” by using T as the final condition Other languages have provided a specific if-then-else nested construct for convenience Ada uses elsif if the intention is to do “else if” so that you do not have to explicitly end each if statement with an end if Python uses elif so that you don’t have to continue to indent Ada without elsif: if Count < 10 then Bag1 := True; else if Count < 100 then Bag2 := True; if Count < 1000 then Bag3 := True; end if; Ada with elsif: if Count < 10 then Bag1 := True; elsif Count < 100 then Bag2 := True; elsif Count < 1000 then Bag3 := True; end if;
8
Repetition Statements
Every language has included some form of repetition, either counter-controlled (early FORTRAN) or logically-controlled, or both Issues: how is repetition controlled? is testing before or after the loop body? (pre vs. post test) where should the control mechanism appear in the loop? for counter-controlled loops what are legal types and the scope of the loop control variable? what happens to the variable when the loop terminates? can the loop’s controlling variables (terminating value, step-size) be altered during execution? are the loop controlling variables (terminating value, step-size) evaluated once (before executing the loop) or after each iteration? what are legal step-sizes (for counter-controlled loops)
9
FORTRAN’s DO statement
DO label variable = initial, terminal [,step] example: Do 10 K = 1, 10 FORTRAN I – IV: a posttest loop, stepsize defaults to 1 label is a line number that indicates the last instruction in the loop body FORTRAN 77, 90 and 95: pretest loop Integers (literals or variables) only for initial, terminal, step these values are computed prior to loop execution so that, if a variable changes values in the loop, it does not affect the number of loop iterations initvalue = J terminalvalue = K * 10 stepvalue = L iterationcount = max(int((K*10 – J) / L), 1*) DO 10 I = J, K * 10, L K = K + 1 L = L + 2 10 CONTINUE If J = 1, K = 5, L = 2, the loop would iterate 25 times in spite of K and L changing in the loop body * - in FORTRAN I-IV, this is a post-test loop so it must iterate at least 1 time, in later FORTRANs, this would become 0
10
ALGOL For Loop ALGOL 60 introduced an extremely flexible for loop as a reaction to FORTRAN’s primitive and restrictive Do the programmer controls the number of iterations by a counter controlled mechanism like FORTRAN’s DO but where the step size and terminating value could change during iterations enumerating a list of values to iterate through using a logical statement to control termination or any combination thereof Basic form: for <var> := <list>{,<list>} | <list> <expr> | <expr> while <boolean> | <expr> step <expr> until <expr> do <stmt> examples: for count :=1, 2, 3, 4, 5, 6, 7 do list[count]:=0 for count:= 1 step 1 until 7 do list[count]:=0 for count:=1, count+1 while (count <=7) do list[count]:=0 for I := 1, 4, 13, step 5 until 23, 3*I while I < 300, 8, -4 do … the values for I iterate through: 1, 4, 13, 18, 23, 69, 207, 8, -4
11
Other Languages For Loops
COBOL: Perform <expr> Times <statements> End-Perform Perform Varying <var> From <expr> By <expr> Until <expr> <statements> End-Perform PL/I: DO <var> = <start> TO <stop> {BY <stepsize>}; <statements> END; <start>, <stop> and <stepsize> can be int or float values like FORTRAN though, the values are only evaluated once before the loop starts can have multiple lists of <start> TO <stop> values DO I = 1 TO 10, 20 to 30, 50 TO 100; … Pascal: for <var> := <init> (to | downto) <final> do <var>, <init>, <final> are any ordinal type but are evaluated prior to the start of the loop, step size is fixed as 1 or -1 depending on whether you use to or downto Ada: for <var> in [reverse] <range> loop ... end loop <range> is a subrange as in (the values can be ints or enumerated types)
12
Continued Common Lisp: (do ((<var> <init> <step>) (<endtest> {. <result>})) <statements>) <init>, <step>, <endtest> and <result> can all be functions or atoms, <result> if specified is returned when the loop exits rather than the value returned by the last <statements> and <var>’s scope is only for the loop itself C’s for loop for (expr1; expr2; expr3) statement expr1 is the initialization, expr2 is the test, expr3 is the step increment each of these can be multiple terms separated by commas as in for (c1=0,c2=1; c1<=10 && c2<=100; c1++, c2*=2) notice a C for-loop does not need a loop body as actions can take place in the expr3 component, or can omit one or more clauses, and can also be used like a logical loop for(x=1; x<=n; x++, factorial *= x); for(temp = head; temp != NULL; temp = temp->next) {…} unlike the previous languages (except for Algol and Common Lisp), the increment and terminating conditions can change making these loops more writable but less readable Example Common Lisp loop: (do ((i 1 (+ i 1)) ((= i n) . (print x))) (setf x (+ x i))) Let’s take a closer look at the code to understand the parts and the use of the ( )s (do …) ( (i – use i as the loop variable 1 – initialize i to 1 (+ i 1) -- increment) i by 1 after each iteration) ( (= i n) – terminating condition . (print x) – what to do after terminating )) (setf x (+ x i)) – loop body ) – end do loop paren
13
Iterator Loops A variation of the counting loop is a loop that iterates once for each item in the list (or data structure) provided Algol’s for loop has the capability of iterating over a list, but the list must be explicitly enumerated Python: for <var> in <range>: <range> will be a tuple or range(value [, value] [, value]) note that Python’s for loop can also be a counting loop by using the range function as in for x in range(0, 10, 2) which iterates over 0, 2, 4, 6, 8, 10 C# has a foreach statement which can iterate across array elements Java 5.0’s for loop has been enhanced to work on objects of type Iterable Common Lisp has a dolist statement much like C#’s foreach
14
Logically Controlled Loops
For situations where the number of repetitions is not based on counting, we use logically controlled loops Issues pretest vs. posttest (test condition before entry or after execution?) pre-test can block entry to loop body post-test must execute body at least once in C, C++ and Java, the post-test loop has the same semantics as the pre-test loop: repeat while the condition is true in Pascal, the semantics change: repeat until condition becomes false is this type of statement separate from a special kind of counter-controlled loop? C/C++/Java/C#, Pascal, Modula-2 have both pretest and posttest loops Ada only has posttest FORTRAN has no logically controlled loop (even FORTRAN 95)
15
Exiting Loops Should exiting a loop only be permitted at the end when the test returns false, or can premature exiting (and returning) be permitted? Ada has a conditional-less loop (infinite loop) loop ... end loop to use this, it requires that a GOTO statement be used to break out of the loop, for instance in an if statement C/C++/Java/C# and Modula-2 have unconditional exit statements break, continue, exit these are forms of GO TO statements Java has break and exit but not continue COBOL uses Perform <paragraph> Thru <paragraph> both paragraphs are executed but if an error arises in the first paragraph, control exits to the second paragraph Multiple exits harm readability exception throwing (and catching) are forms of pre-maturely exiting a block (including possibly inside a loop) again, these are forms of GO TO statements I personally am opposed to using break and continue statements in C-language code because it is equivalent to using GO TO statements and demonstrates laziness in programming. Consider these loops: while(x > 0) { scanf(“%d”, &x); if(x= = 0) break; printf(“%f\n”, 1 / x); } Why use a break statement when the programmer could just rearrange the loop to work appropriately? while(x != 0) { if(x < 0) continue; sum+=x; Again, better logic would allow us to skip the continue statement. Programmers, especially C hackers, tend to be lazy and find the use of break and continue to be irresistible. But it fosters poor logic.
16
Problems with Unconditional Branching
Can make programs unreadable Creates problems with maintenance thus harming reliability, especially of very large programs The GO TO statement is too primitive “it is an invitation to make a mess of one’s program” Most languages have some form of GOTO statement Modula-2, Bliss, CLU, Euclid, Gypsy do not! Java has a GOTO, but it hasn’t been implemented (yet) Without a GOTO, the language must have other control mechanisms, usually in the form of loops and subprograms with their own ability to enter and exit if you think about it, GOTO statements are required in assembly/machine code because they do not have the high-level language constructs, but the high level languages should offer these constructs and let the compiler do the work Note: we are skipping section 8.5 on Guarded Commands. Graduate students should read the material, you might find it interesting. As an example to understand the dangers of the GO TO statement, rewrite the following C code in FORTRAN IV using GO TO statements to denote how awkward GO TOs can be in terms of writability. Then, compare the two sets of code for readability. if(x > y) if(z > 0) { x++; y--; } else if(z != x) { x++; y++; z++; } } else { x = 0; y=1; if(z==0) { z=1; y++; }
17
GOTO Labels Used in ALGOL 60, C, FORTRAN and Ada as locations for GOTO commands in Ada, <<label>> in FORTRAN and Pascal, unsigned integer constant (20, 100, etc...) in Pascal, labels must be declared as if they were variables (but cannot be modified or passed as a parameter) in C, ALGOL 60, any legal identifier Most languages restrict the use of unconditional branches with respect to which label can be reached in Pascal, the scope of the label is the same as the scope of a variable and the target of the GOTO must be within the control statement that includes the GOTO or a statement in the same group that contains the GOTO or in a statement in an enclosing subprogram scope
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.