Break and Continue Statement The break and continue statements are used to alter the flow of control. The break statement, when executed in the while, for, do/while, or switch structures, causes immediate exit from the structure in which it is contained. A break statement terminates the nearest enclosing while, do while, for, or switch statement. Execution resumes at a statement immediately following the terminated statement. For example, the following function searches an integer array for the first occurrence of a particular value. If it is found, the function returns its index; otherwise the function returns -1. This is implemented as follows: // val in ia? return index; otherwise, -1 int search( int *ia, int size, int value) { // confirm ia != 0 and size > 0 ... int loc = -1; for ( int ix = 0 : ix < size; ++ix ) { if ( value == ia [ ix ] ) { // ok: found it! // set the location and leave loc = ix; break; } }// end of for loop // break to here... return loc; } In our example, break terminates the for loop. Execution resumes at the return statement immediately following the for loop. In this example, the break terminates the enclosing for loop and not the if statement within which it occurs. The presence of a break statement within an if statement not contained within a switch or loop statement is a compile-time error. For example: // error: illegal presence of break statement if (ptr) { if ( *ptr == "quit") break; // ... } In general, a break statement can legally appear only somewhere within a loop or switch statement. When a break occurs in a nested switch or loop statement, the enclosing loop or switch statement is unaffected by the termination of the inner switch or loop. For example: Example in C++ while ( cin >> inBuf ) { switch(inBuf[ 0 ] { case '-': for ( int ix = 1; ix < inbuf.size ( ) ; ++ix ) { if ( inbuf[ ix ] == ' ' ) break; // #1 // ... // ... } break; // #2 case '+' : // ... } } The break labeled //#1 terminates the for loop within the hyphen case label but does not terminate the enclosing switch statement. Similarly, the break labeled//#2 terminates the switch statement on the first character of inBuf but does not terminate the enclosing while loop, reading one string at a time from standard input. The continue statement, when executed in the while, for, or do/while structures, skips the remaining statements in the body of the structure, and performs the next iteration of the loop. In while and do/while, the continuation test is evaluated immediately after the continue statement is executed. In the for structure, the increment expression is executed, and then the repetition-continuation test is evaluated. Example in C++ while ( cin >> inBuf ) { if (inbuf [ 0 ] != '-' ) continue; // terminate iteration // still there? process string ... } A continue statement causes the current iteration of the nearest enclosing loop statement to terminate. Execution resumes with the evaluation of the condition. Unlike the break statement, which terminates of the loop, the continue statement terminates only the current iteration. For example, the following program fragment reads a program text file one word at a time. Every word that begins with a underscore will be processed; otherwise, the current loop iteration is terminated: The continue Statement This is similar to break but is less frequently encountered. It only works within loops where its effect is to force an immediate jump to the loop control statement. In a while loop, jump to the test statement. In a do while loop, jump to the test statement. In a for loop, jump to the test, and the iteration. Like a break, continue should be protected by an if statement. You are unlikely to use it very frequently. C Examples Using the continue Statement In an iteration loop the continue statement forces the start of the next iteration or loop-continuation of the inner most while, do...while or for loop. The following two examples show a continue statement in a for statement. 1. A continue statement in for loop example segment: for(x = 10; x > 0; x = x - 1) { if(x > 5) continue; printf("x = %d\n",x); } Only allows the numbers 5,4,3,2 and 1 to be printed out. The next iteration resumes only after evaluation of the current iteration expr3. 2. A continue statement in a complete for loop example: The continue statement causes processing to skip over those elements of the array rates that have values less than or equal to 1. #include < stdio.h > #define SIZE 5 int main(void) { int i; static float rates[SIZE] = { 1.45, 0.05, 1.88, 2.00, 0.75 }; printf("Rates over 1.00\n"); for (i = 0; i < SIZE; i++) { if (rates[i] <= 1.00) /* skip rates <= 1.00 */ continue; printf("rate = %.2f\n", rates[i]); } return(0); } The program produces the following output: Rates over 1.00 rate = 1.45 rate = 1.88 rate = 2.00 3. A continue statement in while loop example segment: while (a < b) { a = a + 1; //if a is greater than 4.5, control will be transferred to the top of the loop, while (a < b) if(a > 4.5) continue; printf("\n the value of a is %f", a); } c = d; 4. A continue statement in a complete nested loop example: The following example shows a continue statement in a nested loop. When the inner loop encounters a number in the array strings, that iteration of the loop ends. Processing continues with the third expression of the inner loop. The inner loop ends when the '\0' escape sequence is encountered. /** ** This program counts the characters in strings that are part ** of an array of pointers to characters. The count excludes ** the digits 0 through 9. **/ #include #define SIZE 3 int main(void) { static char *strings[SIZE] = { "ab", "c5d", "e5" }; int i; int letter_count = 0; char *pointer; for (i = 0; i = '0' && *pointer <= '9') continue; letter_count++; } printf("letter count="%d\n"," letter_count); } The program produces the following output: letter count = 5 The break Statement We have already met break in the discussion of the switch statement. It is used to exit from a loop or a switch, control passing to the first statement beyond the loop or a switch. With loops, break can be used to force an early exit from the loop, or to implement a loop with a test to exit in the middle of the loop body. A break within a loop should always be protected within an if statement, this provides the test to control the loop exit condition. C Examples Using the break Statement The following example shows a break statement in the action part of a for statement. If the ith element of the array string is equal to '\0', the break statement causes the for statement to end. 1. A break statement in for loop example segment: for (i = 0; i < 5; i++) { if (string[i] == '\0') break; length++; } The following is an equivalent for statement, if string does not contain any embedded null characters: for (i = 0; (i < 5)&& (string[i] != '\0'); i++) { length++; } The following example shows a break statement in a nested iterative statement. The outer loop goes through an array of pointers to strings. The inner loop examines each character of the string. When the break statement is processed, the inner loop ends and control returns to the outer loop. 2. A break statement in a complete nested for loop example: /** ** This program counts the characters in the strings that are ** part of an array of pointers to characters. The count stops ** when one of the digits 0 through 9 is encountered ** and resumes at the beginning of the next string. **/ #include #define SIZE 3 int main(void) { static char *strings[SIZE] = { "ab", "c5d", "e5" }; int i; int letter_count = 0; char *pointer; for (i = 0; i ='0' && *pointer <= '9' ) break; letter_count++; } printf("letter count="%d\n"," letter_count); } The program produces the following output: letter count = 4 3. A break statement in a selective statement block example: The following example is a switch statement that contains several break statements. Each break statement indicates the end of a specific clause and ends the switch statement. #include enum {morning, afternoon, evening} timeofday = morning; int main(void) { switch (timeofday) { case (morning): printf("Good Morning\n"); break; case (evening): printf("Good Evening\n"); break; default: printf("Good Day, eh\n"); } } The goto Statement C has a goto statement which permits unstructured jumps to be made. Thougu it sometimes can be very powerful, it is not often recommended for lack of better control. The following is the syntax of goto statement and an c example: goto name; . . . name: statement The goto keyword transfers control directly to the statement specified by the label name. Example In this example, a goto statement transfers control to the point labeled stop when i equals 5. // Example of the goto statement void main() { int i, j; for ( i = 0; i < 10; i++ ) { printf( "Outer loop executing. i = %d\n", i ); for ( j = 0; j < 3; j++ ) { printf( " Inner loop executing. j = %d\n", j ); if ( i == 5 ) goto stop; } } /* This message does not print: */ printf( "Loop exited. i = %d\n", i ); stop: printf( "Jumped to stop. i = %d\n", i ); } GoTo Statement Description Branches unconditionally to a specified line within a procedure. Syntax GoTo line The required line argument can be any line label or line number. Remarks GoTo can branch only to lines within the procedure where it appears. Note Too many GoTo statements can make code difficult to read and debug. Use structured control statements (Do...Loop, For...Next, If...Then...Else, Select Case) whenever possible. See Also Do...Loop statement, For...Next statement, GoSub...Return statement, If...Then...Else statement, Select Case statement. GOTO Statement The GOTO statement: is a powerful but undisciplined branching statement; can be used to create jumps to almost anywhere in a program unit; can be dangerous; can lead to unstructured code (logical spaghetti). can be very useful! The basic syntax is GOTO numeric-label The label must exist, be in the same scoping unit as the statement and be executable. 2.5.8 The goto statement The goto statement causes control to be transferred to the statement after a specified label. A goto can not branch into a statement. A goto must be within the same 'block' of code as the target label. Should be no need to use a goto statement - don't! Recursion Recursive Functions A function which calls itself is described as recursive. This is another complicated idea which you are unlikely to meet frequently. We shall provide some examples to illustrate recursive functions. Recursive functions are useful in evaluating certain types of mathematical function. You may also encounter certain dynamic data structures such as linked lists or binary trees. Recursion is a very useful way of creating and accessing these structures. There is one extra requirement when writing a recursive function. At some point, it has better stop recursion or it will have the same effects as an infinite loop-at least, until run out of stack space. To make sure that the recursion always stops, you must fill two requirements. First, there must be some path through the function that returns without making any recursive call. The conditions that invoke this path are called termination condition. The second requirements for guaranteeing that the recursion will stop is that you should be getting closer, somehow, to the termination conditions on each recursion. As long as there is some way that the function stops recursion and that every recursion moves you closer to the termination conditions, then there is no risk that recursion will go on infinitely. Indirect Recursion Indirect recursion is where a function does not actually call itself, but it calls a different function that may then call the first function. Example for Indirect Recursion A recursive function is likely to run slower than its nonrecursive (or iterative) counterpart because of the overhead associated with the invocation of a function. The recursive function, however, is likely to be smaller and more easily understood. C Examples of Recursive Functions: 1. A Non-recursive Factorial Function int fact(int n) { int k, prod; prod = 1; for(k=1; k<=n; ++k) { prod = prod * k; } return prod; } 2. The Recursive Factorial Function int fact(int n) { if (n <= 1) return 1; else return n*fact(n-1); } 3. A Recursive Fibonacci Function int fib(num) int num; /* Fibonacci value of a number */ { switch(num) { case 0: return(0); break; case 1: return(1); break; default: return(fib(num - 1) + fib(num - 2)); break; } } 4. A Recursive Power Function double power(val, pow) double val; unsigned pow; { if(pow == 0) return(1.0); else return(power(val, pow - 1) * val); } Notice that each of these definitions incorporate a test. Where an input value gives a trivial result, then it is returned directly, otherwise the function calls itself, passing a changed version of the input values. The definition of fib is interesting, because it calls itself twice when recursion is used. Consider the effect on program performance of such a function calculating the fibonacci function of a moderate size number. If such a function is to be called many times, it is likely to have an adverse effect on program performance. Don't be frightened by the apparent complexity of recursion. Recursive definitions of functions are sometimes the simplest answer to a calculation. However there is always an alternative non-recursive solution available too. This will normally involve the use of a loop, and may lack the elegance of the recursive solution. Tips and Points: A recursive function is a function that invokes itself. To write a recursive function, one needs to think how to break a larger problem into smaller problems of the same kind. The conditions that stop a recursion. C++ examples for recursion Example 1 #include long fib(long n) { if (n <= 2) return 1; else return fib (n-1) + fib (n-2); } int main ( ) { long N; cout << "Which Fibonacci number do you want?" << endl; cin >> N; cout << "Fibonacci ( " << N >> ) is " << fib (N) << '\n\n"; return 0; } Example 2 The following function rgcd ( ) is a recursive function: int rgcd( int v1, int v2 ) { if ( v2 != 0 ) return rgcd( v2, v1%v2 ); return v1, } Example for Indirect Recursion class Directory : public File { public: Directory (const string & name) : File (name) {} -Directory ( ) ; virtual void Display (ostream & os, int level = 1, const string & prefix = ""); void DisplayChildren (ostream & os, int level, const string & prefix); void AddFile (File * fp) {m_FileList.push_back(fp) ;} private: list m_FileList; typedef list::iterator FileIter; }; // To display a Directory, output name and newline, then // Display all of my contained Files using recursive call void Directory :: Display(ostream & os, int level, const string & prefix) { File::Display (os, level, prefix); string newPrefix = prefix + getName ( ) + ":"; DisplayChildren (os, level, newPrefix); } void Directory::DisplayChildren(ostream & os, int level, const string & prefix) { for (FileIter iter = m_FileList.begin ( ) ; iter != m_FileList.end ( ); iter++) ( *iter) ->Display (os, level + 1, prefix); C++ bad example 1 A goto statement may not jump forward over a declaration statement that is not enclosed within a statement block. The following, for example, results in a compiletime error: int oops_in_error () { // mumble... goto end; // error: goto over declaration statement int ix = 10; // ... code using ix end: ; } The correct implementation places the declaration statement and any statements making use of that declaration within a statement block. For example: C++ example bad 2 int ok_its_fixed () { // mumble... goto end; { // ok: declaration statement within statement block int ix = 10; // ... code using ix } end: ; } A backward jump over an initialized object definition, however, is not illegal. Why? Jumping over the initialization of an object is a programming error; initializing an object multiple times, although inefficient, is still correct. For example: bad example in C++ // backward jump over declaration statement ok void mumble ( int max_size ) { begin: int sz = get_size ( ) ; if ( sz <= 0 ) { // issue warning ... goto end; } else if (sz > max_size ) // get a new size value goto bagin; { // ok: entire block jumped over int *ia = new int[sz ] ; doit (ia, sz ); // whatever that is... delete [ ] ia; } end: ; }