In this project, we’re going to pretend that vectors DO NOT EXIST. Instead, you will
build a limited version of the vector template class. Yours will NOT be a template that
deals with arbitrary types (Chapter 16), only a normal class that can handle a collection of
integers, but it will have to handle arrays of an arbitrarily large size.
To ensure consistency, I’ve already provided basic files for you (implementation file
IntVector.cpp, declaration file IntVector.h). The constructor will accept no
parameters, but will simply perform initialization necessary for an empty vector.
Remember to assign initial values to all member variables. The public functions (besides
the constructor and destructor) are outlined as follows: CMPSC 122
Return Type | Public Member Function | Parameters | Comments |
int & | operator[]() | index | Return a reference to pdata[index] (or whatever you call your private member variable where you point to your data). Use assert() to insure that index is valid. |
void | clear() | (none) | Delete any existing data, reset to initial state. |
bool | empty() | (none) | Return true if no elements are in use, false otherwise. |
void | pop_back() | (none) | Remove the last element from the array, but do not return it. Shrink the dynamic memory when possible. |
void | push_back() | value | Add the specified value to the end of the vector, grow the dynamic memory if needed. |
int | size() | (none) | Return the number of elements in use. |
void | stats() | (none) | Display statistics: current number used, max number available, number of times resizing has occurred. |
ostream | operator<<() | strm, obj | Display the contents of the array, the same way you did in Exercise 3. |
Although stats() is not a member function that would normally exist in a generalpurpose class, and the existing vector class does not have a << operator, they are
useful for testing and development purposes. Note that those functions which return a
value currently return fixed ‘dummy’ values (i.e. empty() returns true), so that the
source code files will compile when you receive them. Do NOT try using
operator[]() as it is: it returns a reference to a local dummy variable, so that the
project compiles. Note that as-is, it compiles successfully (with a warning, but causes an
error if it is executed.
You are going to need to add several private member variables to implement the class,
and at least one private member function, let’s call it adjust() (since I’ve already
included this in the starter files). The point of using vectors, rather than just normal
arrays, is that you do not have an arbitrary, compile-time upper limit on how much data
your program can handle. Instead, your new IntVector class will maintain an array
which is dynamically allocated with new. Whenever this array proves to be of
insufficient size (or much larger than necessary), a replacement array is dynamically
allocated (again, via new) of a more appropriate size, the contents of the old array are
copied to the replacement array, and the space occupied by the old array is deallocated
with delete.
What do you need to keep track of in these private member variables? Well a pointer
should be obvious, since you must maintain a pointer to the dynamic memory area. For
the others, think about what you have to keep track of. Looking at the stats()
member function description might help also.
1. A pointer to dynamic memory where the array is stored.
2. The current number of elements in use. This should be equal to the number of
times that push_back() has been called, minus the number of times that
pop_back() has been called. Unless clear() has been called, that is.
3. The maximum size of the dynamic memory currently allocated. This will often
be larger than the actual number in use (see below).
4. The number of times resizing has occurred. This is only used for testing
purposes, so you can keep track of what has happened when you call stats().
Your adjust() function (or one with a similar name, if you wish to rename it) will
handle the tasks of growing and shrinking the dynamic memory. You will probably wish
to pass it the desired ‘adjusted’ size of the new array. Alternatively, you could pass it a
value indicating whether you wish to grow or shrink the dynamic memory, and let
adjust() figure out the new size.
The public member functions push_back() and pop_back() will need to call
adjust() whenever they detect that the array size needs to be changed (and perhaps
the clear() member function will call adjust() as well, depending on how you
write it). The algorithm which you will use for adjusting vector size can be summed up
as follows:
1) Start with room for 0 elements.
2) If you need more room, double the current size (minimum new size 1).
3) If you are utilizing LESS THAN HALF of the allocated space, reduce the
allocated space by half (minimum new size 0).
The goal here is to attempt to balance two different costs: the amount of time spent
copying current contents vs. the amount of wasted space. If you always increase the size
by 1 (and there is a large amount of data), you spend too much time recopying data you
just copied; if you increase the size by too much, you waste too much space.
The operator<<() function is intended to help with debugging, by displaying the
contents of the dynamic memory in a useful format. Display the contents the same way
that you did in Exercise 3, with [ ] around the values, and one space between each
value.
The clear() member function should basically reset the IntVector to its initial
state. If everything else is implemented and working, it should release the dynamic
memory, and set the member variables to meaningful values (probably the same values
used by the constructor).
NOTE: Make sure that Project1.cpp contains nothing critical to your IntVector
class; I may replace this file with one of my own for testing purposes.
NOTE 2: You MAY NOT change the public interface of the IntVector class, except
to add comments (which is a good idea if you want to receive the maximum points). You
MUST change the private section (to add member variables). You may change the name
of the adjust() function, or change what adjust() accepts as a parameter, or add a
return type to it. You may also add additional private member functions if you need.
You MUST have a function that does the job described above for adjust(): do NOT
have push_back() do all the work of growing the array and pop_back() do all the
work of shrinking the array, because you will end up duplicating critical code.
Tiered grading:
55% Can only handle fixed-size dynamic memory. Your constructor will
allocate an array of dynamic memory of size 100 for testing purposes (and
use a named constant for 100). The constructor works, and member
functions operator[]() and operator<<() work. Handles out-ofrange calls to operator[]() by using assert() if the subscript is
invalid (outside the range 0 through 99).
65% Still maintains a fixed-size block, but uses member variable(s) to keep
track of how many are valid. push_back() places a value in the fixedsize array, and size() will return how many (of the 100 allocated
indices) are valid. operator[]() only allows operations on valid
indices, and operator<<() only displays valid elements. The
destructor de-allocates the dynamic memory. The empty() member
function works, returning true if there are no elements in use and
false otherwise.
75% Can handle arbitrarily large vectors, resizing as needed (using the
algorithm given above), using dynamic memory. The constructor properly
initializes all member variables. The member functions push_back(),
and size() work. The dynamically allocated space is always deleted via
the destructor. The earlier member functions, operator[]() and
operator<<(), only operate on valid indices. The member function
empty()works properly, based on the current number in use.
85% Reduces allocated space as possible when elements are removed
(according to the algorithm given above). The member functions
clear(), pop_back(), and stats() work. Dynamically allocated
space is always deleted.
Up to 15% will be awarded for good programming practices, broken down as follows:
2% Meaningful identifiers for variables and named constants (a full working
version should not need any named constants, but the 55 and 65% tiers
should have one).
5% Proper formatting, indenting, and use of blank lines.
7% Meaningful comments. Add a block comment at the start of the file, and
comment each section of code. Add a block comment for each function,
describing its purpose. Your comments should be in proper English. I am
not going to nickel and dime you over every miniscule spelling error (the
compiler has no spelling checker), but your comments should be
understandable and (mostly) grammatically correct. Do NOT use IMspeak, such as “These variables r 4 the inputs”.
1% No compiler warnings. This should not be an issue on this project, but if
you have trouble with any, let me know and I will help you clean them up.
NOTE: The only member functions which should be sending output to cout are
operator<<() and stats(); any other output should be done via your main()
program.
You should add more code to main() to test your class and verify that it is working.
Grow and shrink the array, display the contents and statistics. Think of test cases: there is
a potential problem that can occur that I have not outlined above, related to
push_back() and pop_back(); think about an empty vector.
Make sure that your program compiles; programs which do not compile may receive a 0.
With the tiered grading system, most of you should have a good idea of approximately
how many points you are going to receive. Add a comment to the text-box of your
submission stating where you developed your program.
When you are done, place your three source code files in a zip file as described in the
submission document (IntVector.h, IntVector.cpp, Project1.cpp) in the
Project 1 Drop Box. They must be received by the due date to receive full credit. Other
than comments and formatting, the contents of Project1.cpp are not being graded.
However, the completeness of your testing will very likely be a determining factor in
your score on other functions, and I do want to see what tests you added.
One final note: you MUST NOT #include <vector> or base your code off of the
vectors that come with the compiler, you must code them yourself.