As you know, when compilers
first became available, the only way to use them was from the command line.
This makes sense considering the fact that graphical user interfaces didn't
make their way to forefront until the early 80's. IDEs (like Borland
C++) are more than just an editor, compiler, and linker rolled into one
package, and in this lab we will begin to see what other tools are available
to us. Certainly IDEs are around for some reason or another - this
lab will help you get a glimpse of what they can do.
This lab is important for
you even if you don't plan on using Borland C++ after this semester, or
are using a different environment at home. For example, at some point
in your life, you've probably used some popular word processor like Microsoft
Word. Now, assuming you got fairly proficient at using it, you would
then be able to pull up pretty much any word processor and still be productive.
IDEs are similar: once you get good at using one graphical debugger,
for example, you will be able to pick up any other one with much less effort.
So, what is a debugger
and why do we need it? When you type in your C++ program and compile
it, you sometimes get errors. These are called syntax errors and
indicate that there is something wrong with the physical structure of your
C++ code. Hopefully the message given by the compiler will help you to
fix the mistakes and thus eliminate the errors (with some help from your
textbook and notes). Take note, compiler error messages are helpful
about 50% of the time, if you're lucky! If the compiler tells
you that you are missing a semi-colon, for example, and you can't determine
where one is missing in less than 2 seconds, then you should ignore the
error message and look for the real cause of the problem. Adding
semi-colons everywhere they will fit (something some people actually do!)
will only prolong your frustration. The compiler does its best at
categorizing your errors, just don't assume anything about its accuracy.
Unfortunately, especially
in large programs, most of the problems are not of the syntax variety,
but rather lie in the logic of the program (or maybe we should say
"illogic" of the program). In other words, the program is structured in
a legal way as far as the compiler is concerned, yet it does not accomplish
what was intended. These logic errors are what are commonly referred to
as bugs. Logic errors are often quite difficult to detect in programs,
since the programmer needs to know what the program is expected to do in
order to determine that something is wrong. Even after detection, logic
errors are difficult to locate and eliminate since in large programs it
can be extremely difficult to determine exactly where and how the logic
error was made.
The debugger can be very
helpful in locating and correcting logic errors, by allowing the programmer
to check variable values, stop execution at certain points, and step through
the program a single instruction at a time. You will next try some of these
debugging features in the Borland C++ environment.
Finally, it should be noted
that the better you plan and organize your program, the less
you will need a debugger. It's just like building anything else:
the better your car was built and maintained, the less trouble you'll have
later; same thing for houses, clothes, etc.
|
Take note: you will
be running the debugger while simultaneously, the program will be running
in its own window. You'll have to go back and forth between these
two windows. One way to do this is to click on the appropriate button
on the task bar (at the bottom of your screen), or you can use the key
combination ALT-TAB, which lets you rotate through the various running
tasks. Your TA can help you figure this part out if you have trouble.
Stepping through a program
The debugger can show you
exactly what lines of code are executed and in what order. In addition,
you can control when the program advances to the next statement.
-
Go ahead and start up Borland
C++ V5.02 and create a new project called euclid.ide. You
should refer to Lab 0 to remind yourself how to create projects.
-
Click on the euclid.cpp
node in the project window and enter the following C++ program (don't worry
if you don't understand some of it - we haven't covered loops yet, for
example):
// euclid.cpp
// <your name>
// Euclid's GCD algorithm
#include <iostream>
#include <string>
#include <conio>
// gives access to getch()
using namespace std;
int main() {
cout << "Enter two integers (separated
by a space) and I will compute their" << endl;
cout << "Greatest Common Divisor : ";
int m,n,r;
cin >> m >> n;
cout << "\nGCD(" << m <<
"," << n << ") = " ;
while (n != 0) {
r = m % n;
m = n;
n = r;
}
cout << m << endl;
cout << "press any key...";
getch();
// waits for a character to be entered
// it holds the window open
return 0;
} |
-
Try using the "lightening bolt"
button (if you haven't used it before) to run the program a few times with
varying input. Get a feel for the program's behavior.
-
When pointing into the program
window, click the right mouse button and select the Statement Step Over
option from the menu. Notice that this menu option has a shortcut key <F8>.
-
Step through the execution of
your program by using the <F8> key. Enter the input into the execution
window when prompted. Note that each line of the program is highlighted
as it is about to be executed and you can’t step over a line that requests
input until that input is provided. This requires you to move from one
window to another. When the execution is finished, the output window for
the program will go away. This occurs after the getch() function has gotten
a character from the user.
-
For programs with separate functions
(which we have not yet discussed), the <F7> key can be used to "Trace
Into" function calls as they are made. You will be able to try this once
we use functions in our programs. For the euclid.cpp program, <F7> will
be no different than <F8>.
-
When you are finished stepping
or want to start stepping again from the beginning, you must first terminate
the current process. You can do this by selecting the Terminate Process
option from the Debug menu.
Monitoring an expression
or variable during execution
You can keep track of a variable
(and watch its value change as the program runs) by watching it.
This is especially useful because you usually have an idea of what a variable
should have in it, so this will show you what actually happens to that
variable.
-
Choose Add Watch from
the Debug menu (or CTRL-F5).
-
On the "Expression" line type
n
and then click on "OK". A window should appear with n in it.
-
To add another watch click on
n
in the "Watch" window to highlight it, then single click the right mouse
button to get another menu.
-
Click on Add Watch, but
this time enter m for the "Expression".
-
Do this again and add the variable
r.
-
All three watch values should
now indicate <Undefined Symbol> since the program is not being
executed yet.
-
You may want to rearrange and/or
resize the windows so you can see both the source file and the watch window.
This is important, so if you can't figure this out, ask the TA.
-
Step through the program as
you did in the previous section, but this time watch the "Watch" window
as you do so (it is appropriately named!). Note that initially the values
for n and m and r are totally bogus -- they have not been initialized.
See how the values change as the program execution progresses. Very
cool.
-
Close the watch window when
you're done.
Selecting points at
which to pause execution
Usually you will have some
idea where the program is screwing up, and since there is no need to step
through the entire program every time, you can tell it where to begin waiting
for you to single step. These are called breakpoints.
-
Click the cursor on the line
in the program where you wish to begin single-step mode and press F5 (or
left click the left border next to the line where you want your breakpoint
to be set). This line will now be highlighted, indicating the presence
of a breakpoint. A good line to choose is the second output statement.
-
To execute to this breakpoint,
hit CTRL-F9 (or "Run" from the Debug menu).
-
Use <F8> to step through
the code after you hit the breakpoint (go for about 4 or 5 steps).
Note: you'll be giving input for the running program in the meantime.
-
Set another breakpoint on the
line n = r at the bottom of the loop body.
-
To "run" to the next breakpoint,
use CTRL-F9 again. Do this a couple of times.
-
If your program is not complete
yet, remove all breakpoints in the program you just set and hit CTRL-F9
again. To remove breakpoints, just click on that line and hit F5
again. You are toggling the breakpoint.
Breakpoints will be very helpful
in debugging large programs, where much of the program is known to be correct
and thus can be executed normally. A breakpoint can then be placed at a
point where execution becomes questionable, and the program can be traced
in single step mode from there.
Printing your source code
Choose Print from
the File menu and print a copy of euclid.cpp. Make
sure you have put your name in the header comment. You'll be turning
this in with your worksheet.
Passing information through
command-line parameters
This program will show you
how to supply the input from the command-line.
-
Close euclid.ide and
create a new project called euclid2.ide (make sure you don't miss
any steps!).
-
Enter the following code into
euclid2.cpp.
Again, do not worry if you don't understand some of the details (we will
cover functions and arrays later, which is what you need to know about
to completely follow this).
// euclid2.cpp -- Euclid's GCD algorithm
// <your name>
// This version includes command line parameters
#include <iostream>
#include <string>
#include <conio>
// gives access to getch()
using namespace std;
int main(int argc, char *argv[]){
int m,n,r;
m = atoi(argv[1]); // get m,n
from the command line
n = atoi(argv[2]);
cout << "\nGCD(" << m <<
"," << n << ") = " ;
while (n != 0) {
r = m % n;
m = n;
n = r;
}
cout << m << endl;
getch();
return 0;
} |
-
Compile your program (but don't
run it) by pullin down the Project menu and selecting Make All.
Just ignore the warnings.
-
We'll run it twice. The
first time, start up a command window, cd to the "users" directory, use
dir
to look for your executable file, then run it with the command:
c:\users>euclid2
36 180
-
Now we'll see how to provide
command line parameters from within Borland. Select Debug-->Load
and then in the Arguments box enter the two integers separated by
a space.
-
After clicking on OK,
if a CPU window opens, just close it by clicking on the X in the upper
right corner.
-
Select Debug/Run and
the arguments will be passed into the variables m and n inside the program.
|