Sie sind auf Seite 1von 7

C++ Vectors

Arrays are a programming tool that provide a mechanism to store a group of values under a
single name. The values can be any available data type (e.g., int, double, string, etc.). In C+
+, we talk about vectors, rather than arrays.

Vectors are declared with the following syntax:

vector<type> variable_name (number_of_elements);

Type refers to the data type of the elements of the array; variable_name is the name that we
assign to the array, and the optional number_of_elements may be provided to indicate how
many elements the array will contain.

Examples of vector declarations are the following:

vector<int> values (5); // declares a vector of 5 integers


vector<double> marks (20); // declares a vector of 20 doubles

When we use vectors in our programs, we must provide, at the top of the file, the line:

#include <vector>

After a vector has been declared specifying a certain number of elements, we can refer to
individual elements in the vector using square brackets to provide a subscript or an index.

In the following example, the program asks the user for the marks for a group of 20 students
and stores them in a vector:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
vector<double> student_marks (20);

for (int i = 0; i < 20; i++)


{
cout << "Enter marks for student #" << i+1 << ": ";
cin >> student_marks[i];
}

return 0;
}

The first statement (right after main) declares a vector called student_marks with capacity to
hold 20 values of type double. These values can be accessed individually as student_marks[0]
to student_marks[19]. The for loop has the counter i go from 0 to 19, allowing access to each
individual element in a sequential manner, starting at 0 and going through each value from 0
to 19, inclusively.

Vectors have one important advantage with respect to arrays in C, C++ and in other
languages: vectors can be resized during the execution of the program to accommodate extra
elements as needed. Many other programming languages suffer the limitation of fixed-size
arrays; that is, once the arrays are declared with a size, they can not be resized later in the
program.
In the example above, if we don't know in advance that there are 20 students, we could ask
the user how many students are there, and resize the vector accordingly.

This is shown in the example below:

#include <iostream>
#include <vector>
using namespace std;

int main()
{
vector<double> student_marks; // no size specified: vector contains
// zero elements

int num_students;

cout << "Number of students in this group: ";


cin >> num_students;

student_marks.resize (num_students);

for (int i = 0; i < num_students; i++)


{
cout << "Enter marks for student #" << i+1 << ": ";
cin >> student_marks[i];
}

return 0;
}

Notice that the valid subscripts for a vector with num_students elements are 0 to
num_students-1. For that reason, the for loop goes from 0, while i is less than num_elements.

It's always a better idea to control for loops using the size() method of vector. That way, we
make sure that we loop only through the right subscript values, and we avoid the risk of
accidentally exceeding the limits of the vector:

for (int i = 0; i < student_marks.size(); i++)

The difference in this case seems insignificant, and it almost sounds unnecessary to use the
size() method; but again, it's always a good idea to stick to good programming practices that
may be very convenient in larger or more complex programs.

In some situations, we can't determine the number of elements before reading them. That is,
we may have to read numbers and store them in an array to then determine when to stop
reading values. In such situations, the trick of resizing the vector is not an option.

Vectors provide a convenient way of handling this type of situation. We can use the
push_back() method to append one element at the end of the array. The operation includes
resizing to one more element to accommodate for the extra element, and storing the given
value at the end of the array.

The example below shows how to use the push_back() method to accept numbers from the
user and store them in a vector, until the user indicates that there are no more numbers.
After all the numbers were entered, we use a for loop to print them in the order that they were
entered (this is just for illustrations purpose -- it's not particularly useful to do that!):

#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<double> student_marks;
int number;
char answer;

cout << "Do you want to enter numbers (y/n)? ";


cin >> answer;

while (answer == 'y')


{
cout << "Enter value: ";
cin >> number;

// Now that we have the number from the user,


// append it at the end of the vector

student_marks.push_back(number);

cout << "Do you want to enter more numbers (y/n)? ";
cin >> answer;
}

// Now print all the values; notice that we didn't need to


// count how many elements were entered: we can always use
// the size() method to ask student_marks how many are there!

for (int i = 0; i < student_marks.size(); i++)


{
cout << "Student #" << i+1 << '\t' << student_marks[i];
}
// '\t' is the code for the TAB character

return 0;
}

Iterators: an alternative way of accessing the elements

Iterators provide an arguably more flexible way of accessing elements in a vector. They allow
you to refer directly to the elements of the vector and iterate over the entire vector.

To work with iterators, we first declare a variable of type iterator. When declaring the iterator,
we have to specify that it is an iterator for a vector of the given type, as shown in the example
below:

vector<int>::iterator i;

This statement declares an iterator to (not surprisingly) iterate over the elements of a vector
of ints.

The iterator variable (in the above example, i) allows us to access a particular element, and to
move to the next element (those two operations are clearly necessary if we want to iterator
over all the elements of the vector).

To access the element "pointed to" by the iterator, we place a * operator in front. To advance
to the next element, we use the ++ operator (either pre-increment or post-increment,
although with iterators, it is slightly more efficient to use the pre-increment form).
So, the following fragment of code prints an element and moves the itertator to the next
element:

cout << *i << endl;


++i;

We need to do this in a loop, which means that we need to make our iterator start at the
beginning of our vector, and loop while it still is within the vector's elements. To do this, we
use the .begin() and .end() methods of vector. These methods give us iterators positioned at
the beginning and at the end of the vector (more specifically, .end() will give us an iterator
positioned at one-past-the-last element, such that we can use it to control the loop).

The following fragment of code illustrates the use of iterators to print all the elements of a
vector:

// values has been declared as: vector<int> values;


for (vector<int>::iterator i = values.begin(); i != values.end(); ++i)
{
cout << *i << endl;
}

Notice that, because values.end()is an iterator placed at one-past-the-last element, when i is


equal to that value, then we exit the loop, since that means that we are now outside the range
of the vector's elements.

If we have a vector of strings and want to print the elements (the strings) and their lengths,
we could do the following:

// names has been declared as: vector<string> names;


for (vector<string>::iterator i = names.begin(); i != names.end(); ++i)
{
cout << "Name: " << *i << "\tLength: " << (*i).length() << endl;
}

Instead of writing (*i).length() (we need the parenthesis, because the dot operator has higher
precedence than the unary * operator), we could simply write i->length(), as shown in the
fragment below, which is exactly equivalent to the above:

for (vector<string>::iterator i = names.begin(); i != names.end(); ++i)


{
cout << "Name: " << *i << "\tLength: " << i->length() << endl;
}

A Few Algorithms from the Standard Library

One of the additional benefits of using iterators is that the Standard Library algorithms are
compatible with this idiom. In other words, Standard Library algorithms work with iterators,
rather than directly with vectors (for a more advanced discussion on the benefits of this
approach, you may take a look at my STL Tutorial -- that tutorial, however, requires a
relatively advanced knowledge of C++ features, including templates, classes and object
oriented; use it at your own risk :-)).

The Standard Library algorithms deal with "sequences" rather than with containers (e.g.,
vectors). A sequence is specified by a pair of iterators that indicate the beginning of the
sequence and the end (given by an iterator to one-past-the-last element of the sequence).

So, for example, the algorithm sort may be used to sort the elements of a vector. We would
use .begin() and .end() to obtain the sequence of elements that sort expects. The line below
shows an example of sorting the values of a vector:
sort (values.begin(), values.end());

This is just one of the many available algorithms from the Standard Library. I will mention
only a few of the simple ones (some algorithms require knowledge of more advanced
techniques to work with them -- again, you may check the STL Tutorial if you want to learn
more and have familiarity with those advanced issues).

The following sample program illustrates several useful algorithms -- notice that we include
both <algorithm> and <numeric> (the <numeric> part is for the accumulate algorithm):
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <numeric>
using namespace std;

int main()
{
vector<string> student_names;
vector<double> student_marks;

do
{
string name;
cout << "Enter student name (Enter to finish): ";
getline (cin, name);

// Now that we have the name from the user,


// append it at the end of the vector if valid
if (name != "")
{
student_names.push_back (name);
}

}
while (name != "");

// sort them alphabetically


sort (student_names.begin(), student_names.end());

// Now enter grades for each student

student_marks.resize (student_names.size());

vector<string>::iterator s;
vector<double>::iterator m;

for (s = student_names.begin(), m = student_marks.begin();


s != student_names.end();
++s, ++m)
{
do
{
cout << "Enter marks (0 to 100) for " << *s << ": ";
cin >> *m;

if (*m < 0 || *m > 100)


{
cout << "Error: marks must be between 0 and 100" << endl;
}
}
while (*m < 0 || *m > 100);
}

if (! students_marks.empty()) // equivalent to student_marks.size() != 0


{
cout << "There are " << count (student_marks.begin(), student_marks.end(), 100)
<< " students that got highest mark!" << endl;

cout << "Lowest mark: "


<< *min_element (student_marks.begin(), student_marks.end())
<< "\nHighest mark: "
<< *max_element (student_marks.begin(), student_marks.end()) << endl;

cout << "Average: "


<< accumulate (student_marks.begin(), student_marks.end(), 0) /
student_marks.size() << endl;
}

return 0;
}

Some other useful algorithms (not shown in the above demo) are:

Algorithm

Description and Example of use

find

Finds the first occurence of a given value, and returns an iterator to it. If the value is
not found in the sequence, it returns end.

if (find (marks.begin(), marks.end(), 0) == marks.end())


{
// 0 is not found in the sequence
}

replace

Replaces all the occurences of a given value with another one.

replace (names.begin(), names.end(), "", "not valid");

reverse

Reverses the order of the elements in the sequence.

sort (values.begin(), values.end());


reverse (values.begin(), values.end());
// the sequence is now sorted in descendant order

random_shuffle

Reorders the sequence randomly, such that every possible permutation is equally probable.

random_shuffle (cards.begin(), cards.end());


An important detail to notice: these algorithms may be used with strings, to iterate over the
characters of the string. For instance, if you want to replace all of the spaces with
underscores, you could simply do:

replace (str.begin(), str.end(), ' ', '_');

In some cases, however, it may be better to use the built-in string facilities (for instance, why
using the find algorithm with strings, if we have the find method as part of the string
manipulation facilities?)

http://www.mochima.com/tutorials/vectors.html

Das könnte Ihnen auch gefallen