int
s, double
s, string
s,
etc. already. We could choose something more exotic, like
ofstream
s, even! For example, imagine a situation
where we'd like a program that reads a list of file names from the
user, creates those files, and then takes a sentence he types and
writes it to each of those files. Can we do this? Well, let's
try the following strategy:
// Get number of files, call it N int N; cout << "Enter number of files: "; cin >> N; // Create an array of N ofstreams ofstream *FILE = new ofstream[N];Now we have a problem,
FILE
points to M
objects of type ofstream
, but how do we tell each
ofstream
object what file they should point to?
I mean usually we tell the object what file it should point to at
the same time it is created, as in:
ofstream OUT("temp.txt");When we create arrays of objects using
new
, those
objects are uninitialized, so we have to go through and initialize
each one individually. In this case, that means opening a file
for each ofstream
object. To do this, we need to use
.open()
to attach a stream to a file. For example,
we can create OUT as above in this way:
ofstream OUT; OUT.open("temp.txt");In the case of our array, we can read in names and initialize this way:
cout << "Please enter " << N << " filenames: "; for(int j = 0; j < N; j++) { string s; cin >> s; FILE[j].open(s.c_str()); }Having done this, we can write whatever we want to all the files, like this:
for(int k = 0; k < N; k++) FILE[k] << "Hello file number " << k << "!!!" << endl;You can take a look at this complete program that writes a sentence to a whole list of files.
int
s, of course! So, each object in my array of
students is itself an array of int
s, i.e. each
object is an int*
. Remember, we create an array of
10
objects of type T
like this:
T* array = new T[10]So, if the type of object that gets stored in the array is
int*
, we create our array like this:
int** array = new int*[10];Now, having done that, we have an array full of uninitialized pointers, in otherwords we have an array of pointers that don't yet point to anything! Thus, for each of these 10 pointers we must allocate an array for them to point to! Remember,
array[i]
is an object of type
int*
. So wherever you see
array[i]
just think of it as being a normal old
pointer:
int** array = new int*[10]; for(int i = 0; i < 10; i++) array[i] = new int[10];What gets created and how you index elements in it are depicted in this diagram:
This is how you can create "multi-dimensional" arrays in C++. You just have arrays of arrays! Okay, now let's read the grade information and store it in our 2-dimensional array:
ifstream IN("grades.txt"); for(int s = 0; s < 10; s++) for(int g = 0; g < 10; g++) IN >> array[s][g];With this, I can get the grade for student
stu
on homework assignment hwa
as
array[stu][hwa]
. This
program is a simple one that reads the grade info and allows
the user to ask questions about grades.
This version makes nice use of functions,
and gives you an idea of how we pass multi-dimensional arrays
around for this sort of thing.
Here are three extensions
of the functionality of this program you might like to consider:
new
live on until the end of your program, or until deleted with the
delete []
command. With mutli-dimensional arrays,
you have to remember to delete each array you created. That
means, if we refer back to the grades problem from above, that all
of the arrays pointed to by the elements of the array
grade
must be deleted before we can delete the array
grade
itself.
for(int k = 0; k < 10; k++) delete [] grade[k]; delete [] grade;
rand()
Functioncstdlib
contains a function rand()
that
you can use. It returns a random int
in the range
0,....,RAND_MAX, where RAND_MAX is a variable defined in
cstdlib
. So, if you need to print out 10 random
numbers in the range [0,1], you could do the following:
for(int i = 0; i < 10; i++) cout << double(rand())/RAND_MAX << " "; cout << endl;If I run this, I get:
0.513871 0.175726 0.308634 0.534532 0.94763 0.171728 0.702231 0.226417 0.494766 0.124699Unfortunately, if I run it again, I get the same sequence of numbers! As a matter of fact, every time I run it, I get the same 10 "random" numbers! The problem is this, the computer doesn't generate random numbers. Instead, it has a long sequence of numbers that it generates, which looks more or less random - i.e. there is no discernable pattern. But every time I run my program, I just start over again with that same sequence. To combat this, you can call
srand()
, which
seeds the random number generator. Essentially, when
you give srand
a seed, it uses the seed to pick a
starting point in this sequence of "random" numbers. With
different starting points each time you run the program, you
appear to be getting different sequences of random numbers.
Typically, you use the time()
function from
ctime
to seed your random number generator. Since
the time changes each time you run the program, you should get
different sequences of "random" numbers. The following program
shows how this all works:
#include <cstdlib> #include <ctime> #include <iostream> using namespace std; int main() { // Seed the random number generator based on the time srand(time(0)); // Print out 10 random numbers in the range [0,1] for(int i = 0; i < 10; i++) cout << double(rand())/RAND_MAX << " "; cout << endl; return 0; }
~/$ ./ex1 There are 24 people. How many teams would you like? (make it evenly divide n) 3 Team 0: Mike Dan Chris Joni Christy Seung-Geol Cathy Susan Team 1: Gavin Nate Paul Adina Jeff Carl Karen Eric Team 2: Phong Betty Madeline Marianne Don Shirley Tim Steve