Deep C Dives: The Brilliant But Evil for |
Written by Mike James | |||||
Tuesday, 19 November 2024 | |||||
Page 3 of 4
Break and ContinueWhat about loops that have their exit point not at the end and not at the beginning? Before languages like C, loops could exit from any point in their body simply by using a jmp instruction to outside the loop. This was not a good idea because it relied on the programmer to keep things simple and clear. For a long time it was asserted that you only needed a for loop, a while loop and an until loop – and this is true. Any program that can be written, can be written using just these loops. This is the original premise of “structured programming”, the first attempt to make programming better. Today we tend not to be as hardline and the break and continue statements were introduced in C90. The break statement is equivalent to a goto that jumps out of the loop, i.e. to the first instruction following the loop. The continue statement is equivalent to a goto that jumps to the start of the loop, i.e. it skips any remaining statements in the body of the loop. Both constructs let you construct loops that complete a fractional number of repeats. For example: for(i = 0; i < 10; i++){ print(“before\n”); if(i == 5) break: printf("after\n", i); } This loop executes the before 5 times, but the after 4 times and you can see that there is a sense in which it repeats the loop body four and a half times. You can write a completely general loop with any number of exit points anywhere in the loop using: for(;;){ first part of loop if(condition) break; second part of loop if(condition) break; third part of loop and so on } Find It and Fix ItIf you are wondering what the break and continue statements are for, you have never encountered, or never thought about, the find it or fix it algorithms. The find it algorithm is simply having to scan through an array to find a specified value. Many attempt to implement this as an enumeration loop because you know the length of the array n: for(i = 0; i < n; i++){ if(array[i] == target) hit = i; } printf(“%d\n”,hit); The problem is that the loop repeats n times, even if the target is in the first element. You can fix this inefficiency using the break statement: for(i = 0; i < n; i++){ if(array[i] == target) break; } printf(“%d\n”,i); This brings the loop to an end when the target is found but notice that it relies on the value of i not changing due to the operation of the break. This is the case unless you use the C99 idiom of declaring the index in the for statement: for(int i = 0; i < n; i++){ if(array[i] == target) break; } printf(“%d\n”,i); This doesn’t work because i no longer exists at the end of the loop. It is also worth reminding the reader that a for loop is a block and as such variables declared within it only live for as long as the for loop is executing, see Dive 8. In this case, however, the use of an enumeration loop isn’t really justified. For a true enumeration loop you have to know the number of repeats before the loop begins. In this case we only know the maximum number of repeats is the number of elements in the array – the loop may finish earlier if the target is found. This is not an enumeration loop. It is a conditional loop where we know the maximum number of repeats and it can be written more expressively as: i = 0; while(array[i]! = target && i<n ){ i++; } You can even write this loop as a C for loop: for(i = 0; array[i]! = target && i<n; i++){ } printf(“%d\n”,i); However, many programmers think that having a compound condition to keep a loop running is less clear than a misuse of a for loop at the cost of a break. Finally what is the continue for? The continue is for the “fix it” loop. If you need to scan through an array and pick out elements that need to be “fixed” or processed in some way you might use: for(i = 0; i < n; i++){ if(array[i]! = fixFlag) continue; fix(array[i]; } If the array element needs fixing then it is fixed, otherwise the continue skips the fix and moves the loop on to the next element of the array. This is an enumeration loop proper, as we know the number of repeats before the loop begins. However, we don’t really need the continue and can write instead: for(i = 0; i < n; i++){ if(array[i] == fixFlag) fix(array[i]; } The continue just gives you a way of skipping the last part of a loop and you can always do this with an if statement. |
|||||
Last Updated ( Wednesday, 20 November 2024 ) |