Download presentation
Presentation is loading. Please wait.
1
17. Unusual Control Structures
CSC-3004 Introduction to Software Development Spring 2015 Dr. James Skon
2
Topics Multiple Returns from a Routine Recursion goto
Perspective on Unusual Control Structures
3
Multiple Returns from a Routine
The return and exit statements are control constructs that enable a program to exit from a routine at will. Use a return when it enhances readability. In certain routines, once you know the answer, you want to return it to the calling routine immediately.
4
Example of a Good Multiple Return from a Routine
Comparison Compare( int value1, int value2 ) { if ( value1 < value2 ) { return Comparison_LessThan; } else if ( value1 > value2 ) { return Comparison_GreaterThan; return Comparison_Equal; returns a Comparison enumerated type
5
Code that obscures Nominal Case
If file.validName() { If file.Open() { If encryptionKey.valid() { If file.Decrypt( encryptionKey ) { // lots of code ... } CODE FOR NOMINAL CASE
6
Code That Uses Guard Clauses to Clarify the Nominal Case
int doEncryption(…) { // set up, bailing out if errors are found if (!file.validName()) return; if (!file.Open()) return; if (!encryptionKey.valid()) return; if (!file.Decrypt( encryptionKey )) return; // lots of code … return success; }
7
Recursion In recursion, a routine solves a small part of a problem itself, divides the problem into smaller pieces, and then calls itself to solve each of the smaller pieces.
8
Recursion
9
Recursion void QuickSort( int firstIndex, int lastIndex, String [] names ) { if ( lastIndex > firstIndex ) { int midPoint = Partition( firstIndex, lastIndex, names ); QuickSort( firstIndex, midPoint-1, names ); QuickSort( midPoint+1, lastIndex, names ) } }
10
EXAMPLE OF RECURSION Trying to find path through a maze
Recursive Solution: Try every path: Left, Up or Down, Right As you visit each place, drop a bread crumb to you know you were there, and don’t try it again.
11
MAZE bool FindPathThroughMaze( Maze maze, Point position ) { // if the position has already been tried, don't try it again if ( AlreadyTried( maze, position ) ) { return false; } // if this position is the exit, declare success if ( ThisIsTheExit( maze, position ) ) { return true; // remember that this position has been tried RememberPosition( maze, position ); // check the paths to the left, up, down, and to the right; if // any path is successful, stop looking if ( MoveLeft( maze, position, &newPosition ) ) { if ( FindPathThroughMaze( maze, newPosition ) ) {
12
MAZE if ( MoveUp( maze, position, &newPosition ) ) { if ( FindPathThroughMaze( maze, newPosition ) ) { return true; } if ( MoveDown( maze, position, &newPosition ) ) { if ( MoveRight( maze, position, &newPosition ) ) { return false;
13
TIPS FOR USING RECURSION
Make sure the recursion stops. Use safety counters to prevent infinite recursion. RecursiveProc( int safetyCounter ) If ( safetyCounter > SAFETY_LIMIT ) { return; } safetyCounter = safetyCounter + 1 ... RecursiveProc( safetyCounter ) End Sub
14
TIPS FOR USING RECURSION
Limit recursion to one routine. Keep an eye on the stack. Safety Counter can help limit stack use Also consider heap allocation Don’t use recursion for simple tail recursion (like factorials or Fibonacci)
15
TIPS FOR USING RECURSION
int Factorial( int number ) { if ( number == 1 ) { return 1; } else { return number * Factorial( number - 1 );
16
TIPS FOR USING RECURSION
int Factorial( int number ) { int intermediateResult = 1; for ( int factor = 2; factor <= number; factor++ ) { intermediateResult = intermediateResult * factor; } return intermediateResult;
17
goto Edsger Dijkstra: Go To Statement Considered Harmful (1968)
Very difficult to showcode with goto’s is correct. Whereas code without goto’s can be proven correct!
18
Goto – hard to read Code containing gotos is hard to format
Indentation should be used to show logical structure, and gotos have an effect on logical structure. Using indentation to show the logical structure of a goto and its target, however, is difficult or impossible.
19
Goto – compiler optimization
Use of gotos defeats compiler optimizations. An unconditional goto makes the flow harder to analyze and reduces the ability of the compiler to optimize the code. People THINK gotos are smaller and faster, but the opposite is often true!
20
Goto – structural nightmare
use of gotos leads to the violation of the principle that code should flow strictly from top to bottom.
21
goto – Spaggetti code Job Security???
22
goto – support? Is there a place for it??
A well-placed goto can eliminate the need for duplicate code. Duplicate code leads to problems if the two sets of code are modified differently. Duplicate code increases the size of source and executable files.
23
goto – support? In some cases, the goto can result in faster and smaller code. Good programming doesn't mean eliminating gotos. (just using them when they improve the code) Decades' worth of research with gotos failed to demonstrate their harmfulness. goto has been incorporated into many modern languages (C++)
24
THE PHONY GOTO DEBATE Arguers' set up straw man arguments:
Simple examples to prove a point without really having any generalizable merit Often show code using goto, and then show how to rewrite without.
25
ERROR PROCESSING AND GOTOS
Writing highly interactive code calls for paying a lot of attention to error processing and cleaning up resources when errors occur.
26
Processing errors goto
' This routine purges a group of files. Sub PurgeFiles( ByRef errorState As Error_Code ) Dim fileIndex As Integer Dim fileToPurge As Data_File Dim fileList As File_List Dim numFilesToPurge As Integer MakePurgeFileList( fileList, numFilesToPurge ) errorState = FileStatus_Success fileIndex = 0 While ( fileIndex < numFilesToPurge ) fileIndex = fileIndex + 1 If Not ( FindFile( fileList( fileIndex ), fileToPurge ) ) Then errorState = FileStatus_FileFindError GoTo END_PROC End If goto
27
Processing errors goto goto goto Goto target
If Not OpenFile( fileToPurge ) Then errorState = FileStatus_FileOpenError GoTo END_PROC End If If Not OverwriteFile( fileToPurge ) Then errorState = FileStatus_FileOverwriteError if Not Erase( fileToPurge ) Then errorState = FileStatus_FileEraseError End While END_PROC: DeletePurgeFileList( fileList, numFilesToPurge ) End Sub goto goto goto Goto target
28
No goto ' This routine purges a group of files. Sub PurgeFiles( ByRef errorState As Error_Code ) Dim fileIndex As Integer Dim fileToPurge As Data_File Dim fileList As File_List Dim numFilesToPurge As Integer MakePurgeFileList( fileList, numFilesToPurge ) errorState = FileStatus_Success fileIndex = 0 While ( fileIndex < numFilesToPurge And errorState = FileStatus_Success ) fileIndex = fileIndex + 1
29
No goto If FindFile( fileList( fileIndex ), fileToPurge ) Then If OpenFile( fileToPurge ) Then If OverwriteFile( fileToPurge ) Then If Not Erase( fileToPurge ) Then errorState = FileStatus_FileEraseError End If Else ' couldn't overwrite file errorState = FileStatus_FileOverwriteError Else ' couldn't open file errorState = FileStatus_FileOpenError Else ' couldn't find file errorState = FileStatus_FileFindError <-- 2 End While DeletePurgeFileList( fileList, numFilesToPurge ) End Sub
30
No goto – status variable
' This routine purges a group of files. Sub PurgeFiles( ByRef errorState As Error_Code ) Dim fileIndex As Integer Dim fileToPurge As Data_File Dim fileList As File_List Dim numFilesToPurge As Integer MakePurgeFileList( fileList, numFilesToPurge ) errorState = FileStatus_Success fileIndex = 0
31
No goto – status variable
While ( fileIndex < numFilesToPurge ) And ( errorState = FileStatus_Success ) fileIndex = fileIndex + 1 If Not FindFile( fileList( fileIndex ), fileToPurge ) Then errorState = FileStatus_FileFindError End If If ( errorState = FileStatus_Success ) Then If Not OpenFile( fileToPurge ) Then errorState = FileStatus_FileOpenError
32
No goto – status variable
If ( errorState = FileStatus_Success ) Then If Not OverwriteFile( fileToPurge ) Then errorState = FileStatus_FileOverwriteError End If If Not Erase( fileToPurge ) Then errorState = FileStatus_FileEraseError End While DeletePurgeFileList( fileList, numFilesToPurge ) End Sub
33
No goto - try ' This routine purges a group of files. Exceptions are passed to the caller. Sub PurgeFiles() Dim fileIndex As Integer Dim fileToPurge As Data_File Dim fileList As File_List Dim numFilesToPurge As Integer MakePurgeFileList( fileList, numFilesToPurge )
34
No goto - try Try fileIndex = 0 While ( fileIndex < numFilesToPurge ) fileIndex = fileIndex + 1 FindFile( fileList( fileIndex ), fileToPurge ) OpenFile( fileToPurge ) OverwriteFile( fileToPurge ) Erase( fileToPurge ) End While Finally DeletePurgeFileList( fileList, numFilesToPurge ) End Try End Sub
35
SUMMARY OF GUIDELINES FOR USING GOTOS
Use gotos to emulate structured control constructs in languages that don't support them directly. Don't use the goto when an equivalent built- in construct is available. Measure the performance of any goto used to improve efficiency. Limit yourself to one goto label per routine unless you're emulating structured constructs.
36
SUMMARY OF GUIDELINES FOR USING GOTOS
Limit yourself to gotos that go forward, not backward, unless you're emulating structured constructs. Make sure all goto labels are used. Make sure a goto doesn't create unreachable code. If you're a manager, adopt the perspective that a battle over a single goto isn't worth the loss of the war.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.