CSCI 1300 - Exercise 3
Loops and BGI Graphics

What You'll Get from This Exercise

This exercise is to supplement your reading on loops. It also introduces you to the BGI collection of graphics functions that we'll use to draw objects from within a C++ program.

Getting the Demonstration Programs

Start this exercise by opening a cs1300 command-line window. Create a directory to work in (I would suggest moving over to the D: drive and moving down to your own directory, as you did last week), then copy these files to your working directory:

You can right click on the names above to download them.

The Purpose of loops.cxx

  • The purpose of loops.cxx is to let you step through a couple different kinds of loops. Apart from that, the program doesn’t really do anything useful. Anyway, go ahead and start emacs with the loops.cxx file. You can look through the code to get an idea of what the program is doing. Compile the program. Then run the program once and give the W response, and run it a second time with the F response. Running the program in this way won’t be particularly enlightening, but using the debugger you can get more out of the program.
Putting some breakpoints in the program

  • The loops program will be most useful if you use the debugger to run the program with two breakpoints. Remember from Exercise 2 that a breakpoint is a statement in your program where you want the program to stop so you can examine the state of affairs more closely. To set the first breakpoint, move down through the file until the cursor reaches the line in the main program which calls a function named savings_time. It looks like this in the main program:
    	case 'W': case 'w': // Call savings_time
    	    many_years = savings_time(50, 100, 0.10);
    
    Put the cursor on the "many_years..." line shown above, which is the line that calls the savings_time function. We will put a breakpoint at this line, so that when the program executes, it will stop here to let you examine matters. To set the breakpoint, open a second window, start gdb in that window, move the cursor back to the line where you want a breakpoint, and press Ctrl-x Spacebar.

    Next, move down to the line that calls the second function, called future_balance. The line looks like this:

    	case 'F': case 'f': // Call future_balance
                final_balance = future_balance(50, 0.10, 5);
    
    Set a second breakpoint on this "final_balance..." line.

Running the Program up to the Breakpoint

  • With the two breakpoints in place, you can run the program in the usual way. When you are asked which kind of loop to see, respond with W. The program will then run until it reaches the breakpoint at the statement "many_years = savings_time(50, 100, 0.10);". This line calls the savings_time function to determine how many years are required to increase a balance of $50 to a goal of $100 with an annual interest rate of 10%. We want to step into this function and watch the lines execute one at a time to see how a while-loop works. When you are executing a program, the command to step into a function and see the lines execute one at a time is the s key followed by the return key. Give the s command now, and the program Steps to the start of the savings_time function. (Note that s is slightly different that the n command. The n command executes an entire line without stepping through any functions line-by-line.)

Setting Watches

  • In a moment you will step through the savings_time function, one line at a time. But first, let’s set things up to watch the values of a few variables. Put watches on the local variables balance, goal and years.

    You should now continue executing the savings_time function. In order to execute the lines of the function one at a time, give the n command. The function’s first statement, years=0, is now highlighted and ready to execute. Press n and the statement will execute, setting the value of years to zero in the Watch window. The highlighted line moves down to the first line of the while-loop:

        while (balance < goal)
    

Seeing the While-loop in Action

  • The loop that we are about the execute will calculate how many years are required to increase the balance ($50.00) to the goal ($100.00) at the stated interest rate (10%). At the start of the loop’s execution, the highlighted line is the while-statement:
        while (balance < goal)
    
    This is the statement that controls the while-loop. The statement indicates that the loop should continue as long as balance is less than goal. At the moment, balance ($50) is less than goal ($100), so the loop will continue executing. To continue this execution, press n again (or just press the return key, which repeats the previous command). The highlight moves to the first assignment statement in the body of the loop (balance = ...). At this point, you should execute the two lines of the loop’s body by giving two n commands. These statements will increase balance to $55, and increase years to 1. The highlight will once again be at the first line of the while-loop:
        while (balance < goal)
    
    The balance ($55) is still less than the goal ($100), so the loop continues. Execute three more lines, and once more you are back at the top of the loop. This is what a while-loop does: It goes around and around, always controlled by the expression at the top of the loop. The current balance ($60.5) is still less than the goal ($100), so the loop continues. again. Keep executing, keeping an eye on the value of the balance. Stop when you notice that the balance is greater than or equal to 100. At this point, the balance should be 107.1794, and years is 7.

    The program is still executing inside the loop. The highlighted statement:

        years = years + 1;
    
    is about to be executed. Now, at this point, balance is bigger than goal--so you might be thinking that the loop should stop. But it won’t--not quite yet. The loop must always continue until it reaches the controlling statement at the top. At that point, the loop uses the control statement to determine whether to continue.

    For our example, execute one more line. The value of years increases to 8, and we are back at the top of the loop. Now, balance is no longer less than goal, so the loop will end. To see this, execute one more line and the highlighted statement moves after the loop to: return years; This is the function’s return statement, which returns 8 (the current value of years). In other words, it took 8 years to increase $50 to at least $100 at a 10% interest rate.

    You can continue pressing return to complete the execution of the program. When the execution completes, the arrow will be on the last closing bracket of the main program.

Running to the Second Breakpoint

  • You can now run the program a second time. This time you should answer F when you are asked what kind of loop you want to see. The program will run to line that calls the future_balance function:
        final_balance = future_balance(50, 0.10, 5);
    

Stepping into the future_balance Function

  • This function call computes how much money will be in an account that starts with a balance of $50 and earns 10% annual interest for 5 years. To step into this function, give the s command once. The compiler jumps to the first line of future_balance, displaying the values of the arguments and local variables.

Seeing the For-loop in Action

  • We haven't talked about for-loops yet, but you can get an idea for this kind of loop by seeing the statements of the function’s for loop executed one at a time. Give the n command once, and the highlighted line jumps into the function’s body. Here’s what you see on the screen:
        for (i=0;
            i<years;
            i++
            )
    
    These four lines combined are actually the control statement of a for-loop. Normally the control statement would be written on a single line, like this: for (i=0; i<years; i++)—but we have broken it into separate lines so that the debugger can show precisely how the different parts of the control statement are executed. In order to see this execution more clearly, put a watch on the local variable i, and then move to the next step of this exercise.

The Initialization Clause of the For-Loop

  • The control statement of every for-loop has three parts, separated by semi-colons. The first part is the initialization clause. For our example, the initialization clause is the highlighted statement i=0; The initialization clause is always executed once when the for-loop begins. For our example, execute one line now; the assignment i=0 will be executed, and i changes to zero in the watch window. The highlight moves to the second clause in the for-loop’s control statement. (Note: This doesn't seem to work for all versions of gdb. It might go straight into the body of the loop.)

The Repetition Test Condition

  • The second part of a for-loop’s control statement is the repetition test condition. This is a test, such as our test i<years. The test is executed each time before the body of the loop is about to begin. If the test is true, then the loop continues. If the test fails, then the loop stops. In our example, the test i<years is true. So, press n to execute this test, and the debugger will move the highlighted statement to the inside of the loop’s body.

Executing the Body of the For Loop, and the Update Clause

  • The body of our for-loop is now ready to be executed. This body consists of two assignment statements, so you should press n twice to execute these statements. After the second assignment statement, the debugger will move the highlight to the third clause in the for-loop’s control statement. This clause, which is written i++ in our example, is the update clause. The update clause is executed each time the body of the loop finishes. In our example, the update clause i++ adds one to the value of i. Press n to execute the update clause, and the highlight moves back to the repetition test condition. You have now seen the complete cycle of a for-loop, which looks like this in a diagram:

Execute the For-loop to Completion

  • At this point you can use the n key to execute our for-loop to completion. As you are executing the loop, pause for a moment whenever the repetition test condition is highlighted. This condition, i<years, determines whether the loop should continue. When the condition becomes false, the loop will end. When the loop ends, you can continue executing the program to completion.

Introduction to BGI

  • There's one more brief task before the end of this exercise. The task introduces you to the graphics library that we'll use throughout the semester. From your working directory, compile the program bgidemo0.cxx bgi++ -Wall -g bgidemo0.cxx -o bgidemo0 The bgi++ command is a lot like g++, except that it allows you to use certain graphical functions in your program. After running the command, you should end with an executable file called bgidemo0.exe.

Run the Demonstration Program

  • From the command line, run the demonstration program by typing its name (bgidemo0).
  • Press any key to step through the program. Keep going until it ends. The last screen contains the message
    "That's all, folks!"
A Simpler Graphics Program for You To Modify

  • Whenever you run a BGI program, you'll have to compile and run it as you did with the bgidemo program (using the bgi++ command). Writing a BGI program also requires some techniques that are more easily illustrated with the small graphics program, bgismall.cxx. Compile and run this file now. Then bring up the source code in emacs and notice these things:
    1. In order to use any BGI graphics, you must always compile with bgi++ rather than g++.
    2. To access the BGI library, the program includes the graphics.h header file with the directive
      #include <graphics.h>

    3. When a program begins execution, it opens a graphics window where the drawing will occur. Text input and output may still go through the original text window (using cin or cout), or it may go to the graphics window using other commands.

    4. The program needs to call the initwindow(...) function to initialize the graphics screen and begin graphics mode. In bgismall.cxx, the main program calls initwindow(450, 300), which creates a graphics window that is 450 pixels wide and 300 pixels high.

    5. The graphics screen consists of a grid of pixels which can be thought of as points of light on the screen. For smaller monitors, the grid usually has a maximum of 640 pixels in the horizontal direction ( numbered 0 to 639 from left to right ) and 480 pixels in the vertical direction ( numbered 0 to 479 from top to bottom). If we take x to be our name for the coordinate in the horizontal direction and y for the vertical direction, then the origin ( x = 0, y = 0 ) of the numbered grid is in the upper left corner of the screen. The x-coordinate increases as one moves to the right. The y-coordinate increases as one moves down the screen. The direction for increasing y is opposite to our usual practice, and will probably cause much hardship until everyone becomes used to it.

      In general, the code that you write should not depend on a particular screen size. Instead, you should call the BGI functions getmaxx() and getmaxy() to get the maximum x and y pixel numbers.

    6. Once the program in in graphics mode, there are nearly 100 different BGI functions that can be used. The bgismall program uses these functions:
      • putpixel(x, y, color) -- draws a pixel in a particular color at a given x and y location.
      • setcolor(color) -- determines the color for subsequent drawing functions such as line and circle.
      • line(x1, y1, x2, y2) -- draws a line from (x1,y1) to (x2,y2).
      • circle(x, y, radius) -- draws a circle with center (x,y) and the specified radius.
      These graphics functions may also be called from within other functions (such as within the triangle function that is part of bgismall.cxx).

    7. When the program is finished drawing it should call the function getch(). This pauses for the user to press the return key (with the mouse focus in the graphics window). Then call closegraph() to close the graphics window.

More BGI Functions

  • Play around with the bgismall.cxx program a little bit, making it draw some new lines or use new colors. A complete list of the BGI functions is available at www.cs.colorado.edu/~main/cs1300/doc/bgi/index.html).

    You may have noticed that any program that's compiled with g++ or bgi++ will always open a DOS command window when the program is run. If you want to stop this window from opening, then add the option -mwindows to the compile line (just after g++ or bgi++).