apvector, apstring, etc:
Frequently Asked Questions
Description of the C++ classes defined for use in the Advanced Placement*
Computer Science courses and inclusion of the link to the College Board web page
does not constitute endorsement of the other material in this document by the
College Board, Educational Testing Service, or the AP* Computer Science
Development Committee. The description of the C++ classes defined for use in
the AP Computer Science courses included in this document were accurate as of
9/01/98. Revisions to the classes may have been made since that time.
How to set up include paths and projects:
specific instructions for your compiler.
Please e-mail other questions to
support@skylit.com
Q: What are
the AP classes?
A: In C++ and a few other programming
languages, a class is an entity that combines data elements and functions
that operate on them. A class may implement a particular type of an object or a
functional module. The College Board's Ad Hoc Development Committee on C++
defined five classes, apvector, apmatrix,
apstring, apstack and apqueue to be used
in the Advanced Placement program and exams. The A-level
exam requires only the apvector, apmatrix and
apstring classes; the AB-level exam requires all five classes.
The apvector, apmatrix and apstring
classes implement "safe" one- and two-dimensional arrays and character strings,
respectively. The apstack and apqueue classes
implement the stack and queue ADTs.
Q: Are the AP classes part of the C++
standard?
A: No, they are not included in standard
C++. The AP classes are separate modules, developed by the College Board, that
provide additional functionality. The apstring class is a subset of
a typical string class that handles character strings -- different versions of
such classes are included in different class libraries. The other four classes
are loosely based on similar classes from the STL -- Standard Template
Library.
Q: Why do we need the AP classes?
A: The question whether the AP classes
are helpful in the AP curriculum has been discussed at length on the
ap-compsci listserve. The Development Committee felt
that standard arrays in C++ -- the Committee refers to them as "C-style arrays"
-- are "unsafe." Indeed, in C and C++ an array is treated pretty much as a
pointer to its first element and neither the compiler, nor the executable
program checks that a subscript refers to an element inside the array.
Therefore, a bug in the program can easily cause overwriting a memory location
outside an array, and such program may hang. The "C-style" null-terminated
strings are unsafe, too. The library functions that handle them, such as
strcpy(...) for copying and strcat() for
concatenation, assume that the array that receives the result has enough space
to accommodate the resulting string. If the programmer is not careful, these
functions may overwrite vital segments of the program's or system's memory.
The apstack and apqueue classes provide
implementations of stacks and queues. The Committee defined these classes so
that they could be shared by everyone involved in the AP program and used in the
AP exam questions and solutions.
Q: Where can I get the AP classes?
A: You can download the AP classes from
the College Board's AP CS web page. A slightly
edited version of the AP classes is also included on the C++ for You++
Teacher's Disk.
Q: I can display apvector.h,
apvector.cpp etc. in my web browser, but how do I "download" them?
A: Once you display a file in your
browser, click on the File menu and choose Save As.... Navigate to the folder on your disk where you want to save the file, and click
OK.
Q: Why do we have two files, a
.h and a
.cpp file (e.g. apvector.h and
apvector.cpp), for each of the classes?
A: This is an important question.
Strictly speaking we need two separate files, apstring.h and
apstring.cpp, only for the apstring class. A
.h file only would suffice for the other four classes. The best
thing to do is to pretend that apvector.cpp,
apmatrix.cpp, apstack.cpp, and
apqueue.cpp do not exist, at least until you are ready to find out
how these classes are implemented.
A full explanation of this requires some understanding of C++ modules, header
files, and templates (See, for example, C++ for You++,
Chapter 14).
A C++ module (e.g. a class) is usually implemented as a header file,
something.h, and a source file something.cpp.
The source file contains the actual code for the functions. The header file
contains only structure/class definitions and function prototypes and serves as
an interface between the module and a client program that uses it.
something.h is included into both something.cpp and
into the client program using the #include directive. A source file
can be compiled separately, then linked with other modules to form one
executable program.
That is how apstring.h and apstring.cpp are used.
The situation is different for the other four classes, because they are
templated classes, that is classes that work with elements of different
data types. Such classes cannot be compiled separately because the compiler
needs to see first which data type they are used with. It is customary to place
all the definitions and code for such classes into one header file,
something.h. The Development Committee decided to split each of
these four classes into a "header" (.h) and an "implementation"
(.cpp) file. But in this case the .cpp file serves
simply as the continuation of the respective .h file. For example,
apvector.h has the directive
#include "apvector.cpp"
at the end of the file, which has the same effect as if the text of
apvector.cpp were pasted at the end of apvector.h.
apvector.cpp cannot be compiled separately. In this sense,
the .cpp extension, usually reserved for valid C++ source modules,
is misleading here.
Q: What do I have to do to use
the apvector class?
A: Add the line
#include "apvector.h"
at the top of your program.
Q: I have downloaded the
apvector.h and apvector.cpp files, and added
#include "apvector.h", but I am getting an error message:
Error ...: Unable to open include file 'APVECTOR.H'
(or something to that effect, depending on the compiler) followed by a list of
other errors. How can I help my compiler find apvector.h?
A: There are three ways of doing it: an
"ugly" way, an "expedient" way, and a "correct" way.
The "ugly" way is to include the complete pathname for the folder where
apvector.h resides. For example:
#include "c:\apclass\apvector.h"
It works, but no self-respecting programmer would do that (because you would
need to edit and rebuild all your programs if the location of your AP classes
changes).
The "expedient" way is to copy all the AP classes into your compiler's
"include" folder, that is the folder that contains iostream.h and
other standard header files. For example, if you have Borland C++ 5.0 installed
in c:\bc5, you can copy apvector.h,
apvector.cpp, etc. into the c:\bc5\include folder.
This works, but you "contaminate" your compiler installation with "foreign
matter." If you have to reinstall your compiler or install a new version of the
compiler, or if the new version of the AP classes arrives, you have to remember
to copy them again into the compiler's include folder.
The "correct" way (i.e. the way we recommend) is to put all the AP classes
into a separate folder (for example, c:\apclass) and to add that
folder to the list of the "include paths" searched by your compiler. Follow the
appropriate link for your compiler to learn the
specific steps needed for using apvector, apstring, and the other AP classes.
Q: I am getting an error
Error ...: Variable bool initialized more than once
(or other errors that refer to the keyword bool). What's wrong?
A: The data type bool was
added to the C++ standard fairly recently and older compilers do not
understand it. To get around this problem, the Development Committee (and book
authors) use a special header file bool.h. It contains the code
that redefines the bool type as int and defines the
constants false and true:
typedef int bool;
const int false = 0;
const int true = 1;
This file may be included at the top of a module that uses the
bool data type:
#include "bool.h"
In particular apstring.h, apstack.h, and
apqueue.h have this line.
This directive may be enabled or commented out depending on whether your
compiler recognizes the bool type. The problems begin when you use
bool.h with compilers that have the built-in bool type
(e.g. Visual C++ 6.0, Borland's 5.0, Borland's Builder, CodeWarrior) or forget to include it with compilers that do not understand bool (e.g.
Borland's 4.5 or older). For example, the error message above comes from Turbo
C++ 4.5 when you try to declare a bool variable but forgot to include or enable
bool.h. Another message --
'bool' redefinition; different basic type.
-- comes from VC++ 6.0 if you forget to disable bool.h.
We recommend the following method of dealing with bool:
- leave all
#include "bool.h" directives active (i.e. do
not comment them out) in all programs, in particular, in
apstring.h, apstack.h and apqueue.h;
- If your compiler has the built-in
bool type, comment out the
definitions inside bool.h:
// typedef int bool;
// const int false = 0;
// const int true = 1;
This will make your programs portable between compilers: all you have to do
is to use the appropriate (active or inactive) version of bool.h.
(In a more recent version of bool.h, the definitions inside bool.h
are automatically disabled for Visual C++ because they are placed inside the
conditional compilation directive #ifndef _MSC_VER.)
Q: I am getting an error message:
...APVECTOR.CPP ...: Templates must be classes or functions
What have I done wrong?
A: You are trying to compile
apvector.h or apvector.cpp. As explained
above,
neither of these files can be compiled separately and should never be added as
an item to projects.
Q: What do I have to do to use
the apstring class in my program?
A: You need to do two things:
- Add the line
#include "apstring.h"
at the top of your program.
- Set up a project with two items: your program
and
apstring.cpp. Follow the
appropriate link for your compiler to learn the
specific steps needed for using the apstring class.
Q: I have included
apstring.h into my program but I am still getting a long list of
errors:
Linker error: Undefined symbol apstring::~apstring() in module ...
etc. What is missing?
A: Your program compiled correctly, but
it failed at the linking stage because the code for the apstring
functions is missing. apstring.h contains only function prototypes
for the apstring functions, but not their code.
There are three ways to take care of this problem: the "ugly," the
"expedient" and the "correct" way. The "ugly" way is to add all the source code
for the apstring class to your program using
#include "apstring.cpp" instead of (or in addition to)
#include "apstring.h". A more subtle way of achieving the same
result is to leave #include "apstring.h" in your program, but add
#include "apstring.cpp" at the bottom of
apstring.h. This will work for a while -- as long as you use
single-module projects -- but it will fail when you start using multiple modules
(e.g. the Marine Biology case study).
Then the linker will complain that the
apstring functions are defined more than once.
The "expedient" way is to add the compiled apstring module to
the standard compiler libraries.
The "correct" way (i.e. the one we recommend) is to
set up a project that includes your program and
apstring.cpp.
Q: What is the difference between the
"capacity" and the "length" of a vector?
A: The implementation of the
apvector class is such that there is no explicit distinction
between the length of the vector (meaning the number of elements
currently stored in the vector) and its capacity (meaning the number of
elements that can fit in its currently allocated array). These two notions are
somewhat confused. For example, the apvector class definition contains the line:
int length( ) const; // capacity of vector
There are two points of view on how vectors should be used. One approach is
that the actual length of the vector may be smaller than its capacity. In this
approach your program has to maintain the length of the vector in a separate
variable. If you pass a vector to a function, you have to also pass its length.
For example:
int AddElements(const apvector &v, int len)
{
int i;
for (i = 0; i < len; i++)...
}
In this approach it makes sense to say that the length() member
function returns the capacity of the vector, and therefore it is not very
useful. The subscript checking functionality will be limited: the
apvector class will check that a subscript falls within the
capacity of the vector, but not that it actually refers to a valid element.
Another advantage of the apvector class -- the capability of
allocating exactly the required amount of space -- will not be always utilized.
This approach is closer to the way built-in arrays are used.
The second approach (the one we recommend) is to make sure that the capacity
of the vector and the length of the vector are almost always the same. There may
be a need to sometimes resize a vector to achieve that (using the
resize(...) member function). In this approach, the
length() function returns the length of the vector. There is
no need to maintain the length of the vector in a separate variable and pass it
to functions: it can be obtained inside a function by calling
length(). For example:
int AddElements(const apvector &v)
{
int i, len = v.length();
for (i = 0; i < len; i++)...
}
In the latter approach, the apvector class checks that all
subscripts refer to valid elements of the array.
Past AP exam materials seem to lean toward the second approach,
but AP students will be safer if they are familiar with both approaches and
understand the difference between them.
Q: I wrote a simple program:
#include
#include "apvector.h"
int main()
{
apvector x;
int i;
cout << "Enter 5 integers: ";
for (i = 0; i < 5; i++)
cin << x[i];
...
}
When I run it I get a message: "Illegal vector index: 0 max index = -1" and
the program is aborted. What is the meaning of this message?
A: The declaration
apvector x;
constructs an empty vector because you have not specified its size. The run-
time message is a service of the apvector class: it indicates that
a subscript (index) is out of bounds. The apvector class calculates
the maximum allowed index as size - 1, and in this case the size is
0, so it reports "max index = -1."
Q: I am trying to use the
apvector class in a simple program:
#include
#include "apvector.h"
int main()
{
apvector a[3];
int sum;
a[0] = 1;
a[1] = 2;
a[2] = 3;
sum = a[0] + a[1] + a[2]; // Line 11
cout << sum << endl;
return 0;
}
The compiler gives me an error message "Illegal structure operation" for line
11. Why?
A: You used brackets instead of
parentheses in the declaration
apvector a[3];
It should be
apvector a(3);
Brackets are used with built-in arrays. Your declaration, while syntactically
valid, declares an array of three empty vectors instead of one vector with three
elements.
The compiler detects a problem only when you try to add
a[0] + a[1] + a[2]: each addend here is an
apvector, and there is no valid addition operator for
apvector variables.
Skylight Publishing Home Page
Skylight Publishing
support@skylit.com
|