CS1440-Lab 11 (More on Arrays)

In this lab we will learn about

Getting Ready

Before you start the lab, create directory lab11 and complete your work in that directory.

Arrays in Structs

In the previous lab, you learned to create one dimensional (1-D) arrays to store numbers (float, integers, ...) and characters.  A 1-D array is like a pill container with only one column of cells.  Each cell holds one pill only and all pills that are held by a container are the same.  We store the pills in the container in some order.  Some of these containers have days of the week written on the side.  So one knows where to get the pill for a particular day.  The name written on the side corresponds to the address of the cell in the container.  Also, the physical location of each cell can be used as a reference to the cell.  Suppose the bottom cell is for Sunday, then the cell with address 0 corresponds to Sunday, 1 marks Monday, 2 marks Tuesday, ..., 6 marks Saturday.  That makes cells 0-6 mark 7 days of the week.  If we look at this like an array, we could define it as:      pill_container[7];
If we wanted to use a similar container to hold 10 integers, then we would use    int container[10];      right?

You also learned to access individual members of each array using their indexes.  You can combine the power of arrays with classes and structures to create much better programs.  Suppose you want to write a program that keeps track of practice times for various running distances.  If you define an struct called Data as shown below, then you can use it in a program to keep track of the 5 best times.

struct  Data
    double  time[5];
    int distance;

Data my_best;

Please pay attention to the way time is defined.  We have defined the structure this way so you can save up to 5 times for a distance.  These 5 times represent the 5 best times you have had in running the recorded distance.  So, you could say:

my_best.distance = 200;    // What are we doing here?

cout << "Enter five times (in seconds): \n";
for(i = 0; i < 5; i++)
   cin >> my_best.time[i];

What did we do in the last three lines of this code segment?

Now, we will use this struct in a program.


struct Data
   double time[5];     //   to store times in seconds
   int distance;          //   distance in meters

Data my_best;

int main( )
   int i;

   cout << "Enter a distance for which you want to record ";
   cout << "the running times : ";
   cin >> my_best.distance;

   cout << "\nEnter 5 of your best running times for this distance\n";
   for(i = 0;  i < 5; i++)
        cout << "Enter a time \n";
        cin >> my_best.time[i];

   cout << "Here are your best 5 times for ";
   cout << my_best.distance << " meters\n";

   for(i = 0;  i < 5; i++)
        cout << my_best.time[i] << endl;

   return 0;

Copy program P11_1.C into your lab11 directory and try it for several cases.  Make sure you read through the program to understand how things are set up.  Modify the above program, calling the new program ex11_1.C, so that it reads, stores in an array, then displays the best 5 running times for each one of the distances 100m, 150m, 200m, 400m, 800m, and 1600m in the same program.  For now, you can read/store/display times for one distance at a time, then replace the values in the time array when you read the times for a next distance. This way, you will only use one array for the times.

Two-Dimensional arrays
Two dimensional arrays are defined in a similar way as the 1-D arrays.  You can imagine the container that we used for pills to have two columns of cells.  My grandmother used to have one of those.  She had to take two pills a day.  So, we would load the container for her every Sunday night and she was good to go for the rest of the week.  She only had to know where the cells for each day were and which one of the cells was for day and which was for night. We would tell her that the left ones were for the morning and the right ones for the nights.  The container had 7 rows (for the 7 days of the week) and two columns (one for the morning and the other for the night). If we view the container as an array, we can define it as  pill_container[7][2].  Here we use two pairs of brackets, one for the number of rows and the other for the number of columns.  Similarly, a 2-D array of integers with 3 rows and 4 columns is defined as:
      int x[3][4];

Now, let me ask you a question.  Suppose we used the container with 7 rows and 2 columns to keep the pills and assumed the bottom cell to be Sunday.  Can you tell me, in terms of rows and columns, where do I get the pill for Tuesday night? 
Row: ______   Column:______  container[___][___]?

Now let's write a program that uses a 2-D arrays.

//P11_2.C - This program will ask for the fastest 5 times
//          for 6 different distances and will display them.
//          It uses a 2-D array. 

const int N_DISTANCES = 6;
const int N_TIMES     = 5;

#include <iostream> 
#include <cstdlib>

int Find_distance(int j);      // returns the jth distance

int main( ) 
   int    i, j; 
   int    distance[N_DISTANCES]; 
   double data[N_DISTANCES][N_TIMES];  //keeps N_DISTANCES * N_TIMES
                                       // values in N_DISTANCES rows
                                       // of N_TIMES columns 
   for(j = 0; j < N_DISTANCES; j++)  {
       distance[j] = Find_distance(j); 
       cout << "\nEnter "  << N_TIMES 
            << " of your best running times for "
            <<  distance[j] << " meters\n"; 
       for(i = 0;  i < N_TIMES; i++)    { 
         cout << "Time " << i+1 << " is: ";
         cin  >> data[j][i]; 
   for(j = 0;  j < N_DISTANCES; j++) 	{
         cout << "\nYour best times at " << distance[j]
              << " meters \n"; 
         for(i = 0; i < N_TIMES; i++)    { 
             cout << "\t" << data[j][i];
         cout << endl; 
   return 0; 

int Find_distance(int j) 
       switch (j) 
               case 0:  return 100; 
               case 1:  return 150; 
               case 2:  return 200; 
               case 3:  return 400; 
               case 4:  return 800; 
               case 5:  return 1600; 
		    cout << "Find_distance only knows about"
		         << " distances 0-5. You asked for "
		         << j
		         << endl;

First copy the program P11_2.C into your directory and make sure it runs.  Go through the program and make sure you understand the program very well.  Modify the program to unclude a 7th distance, 3000 meters, and call your new program ex11_2.C.

Class with arrays
You can use arrays with classes. You create an array of objects of some class in the same way as you create an array of things of some other type.

Use the following class definition and the functions, to re-write program P11_2.C with a class Data. Your program should have a N_DISTANCES array of objects of type Data. Each element of the array is an object that records a distance and five (actually, N_TIMES) times for that distance. Your main program will loop through the array. It will use the member functions of the object to record values and to display information.

const int N_TIMES = 5;

class Data 
     void Set_a_distance(int d); 
     void Set_a_time(int i, double t); 
     void Display(); 

     double time[N_TIMES];  //time in seconds
     int distance;          //distance in meters

And the functions are defined as:

void Data::Set_a_distance(int d) 
        distance = d; 

void Data::Set_a_time(int i, double t) 
        if(0 <= i && i < N_TIMES)  time[i] = t; 

void Data::Display() 
   int i; 
   cout << "Here are your best " << N_TIMES
        << " times for "
        << distance << " meters:\n"; 

   for(i = 0;  i < N_TIMES; i++) { 
        cout << "\t" << time[i];
        cout << endl; 

As we discussed before, we can create arrays of characters to hold what we usually refer to as "C-style strings".  Recall that the array that holds a C-style string has one element for each character of the string followed by an element containing the ASCII NUL character. In programs we often use '\0' to represent that marker character, and in English text we sometimes spell the name of the character as "null". Note that the character array has at least one more element than there are characters in the string. There are some library functions that we can use to process strings.  I am sure that, by now, you can tell me what this line of code will do:

char what[11] = {"Do Be Do"};

If you said that we have initialized the array of characters, what, with Do Be Do (8 characters) and placed the null, \0, at the end, you were right.  I am sure, you all did that.

How about this one?
char what[ ] = {"Do Be Do"};

if you said that this one does the same thing as the one before but the size will be set to 9 (one more than the number of characters in between "  ", you are right. What is the extra cell for?  the null.

Okay, so you know that the above two methods of initialization are almost the same.  (But the first declaration sets aside more storage space -- 11 characters worth instead of 9.) Let's see if you know the following.  How about?
char what[ ] = {"Do Be Do"};
char what[ ] = {'D', 'o', ' ', 'B', 'e', ' ', 'D', 'o'};

Well, the second one will initialize the array in the same way as it was done in the first one up to the last 'o', but will not put the null, \0, at the end.  In that case, the array doesn't contain a C-style string -- the terminating ASCII NUL is missing, and if you try to use it with the C-string library functions, you will overrun the array. That's a nasty thing to do. Which one do you prefer to use?

To can that last style of initialization to get a properly formed C-style string, but you need to write:
char what[ ] = {'D', 'o', ' ', 'B', 'e', ' ', 'D', 'o', '\0'};

Now we learned these few differences, let talk about some of the Cstring functions. The table below lists some of the functions in the cstring library. The text's Appendix 4 lists more of them (see page 920). Note that with the functions listed below it is the responsibility of the caller to assure that no array (buffer) will be overrun.

Here is an example in which we have used the Cstring functions.

// P11_3.C - This program is to demonstrate the function string_copy - from the textbook
#include <iostream>
#include <cstring>
void string_copy(char target[ ], const char source[ ], int target_size);
//Precondition: target_size is the declared size of the cstring variable target.
//The array source contains a cstring value terminated with \0.
//Postcondition: The value of target has been set to the cstring value in source,
//provided the declared size of target is large enough. If target is not large
//enough to hold the entire cstring, a cstring equal to as much of the value of
//source as will fit is stored in target.

int main( )

    char short_string[11]; //Can hold cstrings of up to 10 characters.
    string_copy(short_string, "Hello", 11);
    cout << short_string << "STRING ENDS HERE.\n";

    char long_string[ ] = "This is rather long.";
    string_copy(short_string, long_string, 11);
    cout << short_string << "STRING ENDS HERE.\n";
    return 0;

//Uses header file cstring:
void string_copy(char target[ ], const char source[ ], int target_size)
 using namespace std;
    int new_length = strlen(source);
    int index;
    if (new_length > (target_size - 1))
        new_length = target_size - 1; //That is all that will fit.
    for (index = 0; index < new_length; index++)
        target[index] = source[index];
    target[index] = '\0';

Copy the program P11_3.C into your lab directory and run it.  Replace the calls made to string_copy with strcpy.  Don't forget your responsibilities. Here is an example:
string_copy(short_string, "Hello", 11);

will be replaced with:
strcpy(short_string, "Hello");

Call your new program ex11_4.C. Run it and confirm that you produce the same result.
Note that you no longer need the function string_copy.

Modify program P11_3.C to ask for two words and put them together in two different ways:
    1) First word, then second
    2) Second word, then first.

First word:  race        Second word:    car

First method results:               racecar
Second method results:          carrace

Please note that you have to create an array (using strcat) that contains the combined words in it.  Don't just use the cout to display them together.
Note: you may want to create a duplicate of the first and the second word (using strcpy) and work on them instead of the original arrays. This way,  your original words will stay the same.

Reread the description of strcmp function. (There's one above. There are descriptions in the text. If you're logged on to CS you can type the command: man   3   strcmp)   Use the strcmp function to compare the resulting two arrays and display an statement to tell you whether the resulting words were the same or different.

Test your program. Test it with the two words cat and rat where the words are different and with the two words cat and cat, where both the first and the second words are the same.

Post Lab
Write a program using C-style strings that asks users to input a word and display a message on whether or not the word is a Palindrome.  Such words will become the same when you write them backward.  For example:  racecar  .... in backward is  ... racecar.  So racecar is a palindrome.  Here is what your program will do:

1) prompts the user to enter a word
2) display how long the word was
3) display whether it is a palindrome or not.