A better array
As we discussed in class, it is very useful to create abstractions that contain data and allow us to access and manipulate it in different ways. In this lab, you are going to create a List class that holds lists of numbers and does useful things with them.
In lab, we'll walk through using SVN to submit your work. This is the URL for the repository (repo) we'll be using today (where username is your utrgv username without the @utrgv.edu part)
https://cssvn.utrgv.edu/svn_etomai/201720_2380/lab01_classes/username
When you're done working for the day, commit your changes! You get participation credit for today by committing the work you got done in lab. Only commit the main.cpp file! We don't need or want all the other stuff, as we can easily create a new project whenever we need it.
We already have a perfectly good way to store a list of numbers: an array. But arrays are very low-level, meaning they give you control and power but lots of details to keep straight. We want a higher level abstraction that supports more convenient features like keeping track of it's own length, automatically resizing and functionality like searching.
For any class we make, there is the public interface (the constructors and methods) and the private implementation (the data members and private methods). When using a class, we don't want to care or think about the private implementation, just what it does for us. For your List class, the private internal implementation is going to be an array of integers. That's the only way at the moment that you know how to store a list of numbers.
Below is a starting point for the class definition, and testing code in main.
The testing code is important because it completely specifies everything in the public interface. But trying to make it all work at once is foolish. Always keep the code working! Don't have a big pile of stuff that doesn't compile, that's a horrible strategy.
How do you resize an array? You can't. That's why your List class is going to be better than using an array. With dynamic memory allocation, you can create a new, bigger array and copy the data over, then discard the old one. This all happens in the private, internal space, so the user doesn't even worry about it.
Reallocating and copying is expensive, so you don't want to resize one step bigger at a time. Instead, increase by the initial capacity again. So in the example below, when we add a 6th item, we resize our List to hold 10. Then 15. Then 20 and so on.
#include <iostream>
#include <cassert>
using namespace std;
class List
{
private:
// data members here, starting with a pointer for the internal array
public:
// public interface here, starting with the constructor that takes an initial capacity
};
int main()
{
// Part I: Tests for Basic Usage
List ages( 5 ); // create a list that can hold up to 5 integers
ages.Add( 17 );
ages.Add( 43 );
ages.Add( 71 );
// this should print "List length: 3"
cout << "List length: " << ages.Length() << endl;
// this should print "List items: [ 17, 43, 71 ]"
cout << "List items: " << ages.toString() << endl;
ages.Remove(1);
// this should print "List length: 2"
cout << "List length: " << ages.Length() << endl;
// this should print "List items: [ 17, 71 ]"
cout << "List items: " << ages.toString() << endl;
// Part II: Tests for Resizing
ages.Add( 2 )
ages.Add( 30 )
ages.Add( 51 )
ages.Add( 15 ) // the list needs to resize here!
// this should print "List length: 6"
cout << "List length: " << ages.Length() << endl;
// this should print "List items: [ 17, 71, 2, 30, 51, 15 ]"
cout << "List items: " << ages.toString() << endl;
// Part III: Additional Functionality
// this should print "Max item: 71"
cout << "Max item: " << ages.Max() << endl;
// testing the find method (four cases: first, middle, last, not found)
assert( ages.Find(17) == 0 );
assert( ages.Find(30) == 3 );
assert( ages.Find(15) == 5 );
assert( ages.Find(1000) == -1 );
return 0;
}