Part V
Arrays and Pointers
Introducing Array s
This chapter discusses different types of arrays. You are already familiar with character arrays, which are the only method for storing character strings in the C++ language. A character array isn’t the only kind of array you can use, however. There is an array for every data type in C++. By learning how to process arrays, you greatly improve the power and efficiency of your programs.
This chapter introduces
-
Array basics of names, data types, and subscripts
-
Initializing an array at declaration time
-
Initializing an array during program execution
-
Selecting elements from arrays
The sample programs in these next few chapters are the most advanced that you have seen in this book. Arrays are not difficult to use, but their power makes them well-suited to more advanced programming.
Chapter 23 ♦Introducing Arrays
An array is a list of more than one
Array Basic s
Although you have seen arrays used as character strings, you still must have a review of arrays in general. An array is a list of more
variable having the
same name.
than one variable having the same name. Not all lists of variables are arrays. The following list of four variables, for example, does not qualify as an array.
sal es bonus_92 f i r st _i ni t i al ct r
This is a list of variables (four of them), but it isn’t an array because each variable has a different name. You might wonder how more than one variable can have the same name; this seems to violate the rules for variables. If two variables have the same name, how can C++ determine which you are referring to when you use that name? Array variables, or array elements, are differentiated by a subscript, which is a number inside brackets. Suppose you want to store a person’s name in a character array called name. You can do
this with
char name[ ] = “ Ray Kr ebbs” ;
or
char name[ 11] = “ Ray Kr ebbs” ;
Because C++ reserves an extra element for the null zero at the end of every string, you don’t have to specify the 11 as long as you initialize the array with a value. The variable name is an array because brackets follow its name. The array has a single name, name, and it contains 11 elements. The array is stored in memory, as shown in Figure 23.1. Each element is a character.
You can manipulate individual elements in the array by refer- encing their subscripts. For instance, the following cout prints Ray’s initials.
Print the first and fifth elements of the array called name*.*
cout << name[ 0] << “ “ << name[ 4];
EXAMPLE
Figure 23.1. Storing the name character array in memory.
You can define an array as any data type in C++. You can have integer arrays, long integer arrays, double floating-point arrays, short integer arrays, and so on. C++ recognizes that the brackets [] following the array name signify that you are defining an array, and not a single nonarray variable.
The following line defines an array called ages , consisting of five integers:
i nt ages[ 5];
The first element in the ages array is ages[ 0] . The second element is ages[ 1] , and the last one is ages[ 4] . This declaration of ages does not assign values to the elements, so you don’t know what is in ages and your program does not automatically zero ages for you.
Here are some more array definitions:
i nt wei ght s[ 25] , si zes[ 100] ; / / Decl ar e t wo i nt eger arr ays. f l oat sal ar i es[ 8] ; / / Decl ar e a f l oat i ng- poi nt arr ay. doubl e t emps[ 50] ; / / Decl ar e a doubl e f l oat i ng- poi nt
/ / arr ay.
char l ett er s[ 15] ; / / Decl ar e an arr ay of char act er s.
When you declare an array, you instruct C++ to reserve a specific number of memory locations for that array. C++ protects
Chapter 23 ♦Introducing Arrays
those elements. In the previous lines of code, if you assign a value to l ett er s[ 2] you don’t overwrite any data in wei ght s , si zes , sal ar i es , or t emps . Also, if you assign a value to si zes[ 94] , you don’t overwrite data stored in wei ght s , sal ar i es , t emps , or l ett er s .
Each element in an array occupies the same amount of storage as a nonarray variable of the same data type. In other words, each element in a character array occupies one byte. Each element in an integer array occupies two or more bytes of memory—depending on the computer’s internal architecture. The same is true for every other data type.
Your program can reference elements by using formulas for subscripts. As long as the subscript can evaluate to an integer, you can use a literal, a variable, or an expression for the subscript. All the following are references to individual array elements:
Array elements follow each other in memory, with nothing between them.
ar a[ 4]
sal es[ ct r+1] bonus[ mont h]
sal ary[ mont h[ i ] * 2]
All array elements are stored in a contiguous, back-to-back fashion. This is important to remember, especially as you write more advanced programs. You can always count on an array’s first element preceding the second. The second element is always placed immediately before the third, and so on. Memory is not “padded”; meaning that C++ guarantees there is no extra space between array elements. This is true for character arrays, integer arrays, floating- point arrays, and every other type of array. If a floating-point value occupies four bytes of memory on your computer, the next element in a floating-point array always begins exactly four bytes after the previous element.
EXAMPLE
C++ protects only as many array elements as you specify.
You must never go out-of-bounds of any array. For example, suppose you want to keep track of the exemptions and salary codes of five employees. You can reserve two arrays to hold such data, like this:
i nt exempt i ons[ 5] ; / / Hol ds up t o f i ve empl oyee exempt i ons. char sal _codes[ 5] ; / / Hol ds up t o f i ve empl oyee codes.
Figure 23.2 shows how C++ reserves memory for these arrays. The figure assumes a two-byte integer size, although this might differ on some computers. Notice that C++ reserves five elements for exempt i ons from the array declaration. C++ starts reserving memory for sal _codes after it reserves all five elements for exempt i ons . If you declare several more variables—either locally or globally— after these two lines, C++ always protects these reserved five elements for exempt i ons and sal _codes .
Because C++ does its part to protect data in the array, so must you. If you reserve five elements for exempt i ons , you have five inte- ger array elements referred to as exempt i ons[ 0] , exempt i ons[ 1] , exempt i ons[ 2] , exempt i ons[ 3] , and exempt i ons[ 4] . C++ does not protect
Chapter 23 ♦Introducing Arrays
more than five elements for exempt i ons ! Suppose you put a value in an exempt i ons element you did not reserve:
exempt i ons[ 6] = 4; / / Assi gn a val ue t o an
/ / out - of -r ange el ement.
Figure 23.2. Locating two arrays in memory.
C++ enables you to do this—but the results are damaging! C++ overwrites other data (in this case, sal _codes[ 2] and sal _codes[ 3] because they are reserved in the location of the seventh element of exempt i ons ). Figure 23.3 shows the damaging results of assigning a value to an out-of-range element.
Figure 23.3. The arrays in memory after overwriting part of sal _codes .
Although you can define an array of any data type, you cannot declare an array of strings. A string is not a C++ variable data type. You learn how to hold multiple strings in an array-like structure in Chapter 27, “Pointers and Arrays.”
EXAMPLE
Initializing Array s
You must assign values to array elements before using them.
Here are the two ways to initialize elements in an array:
-
Initialize the elements at declaration time
-
Initialize
the elements in the program
Initializing Element s at Declaration Tim e
You already know how to initialize character arrays that hold strings when you define the arrays: You simply assign them a string. For example, the following declaration reserves six elements in a character array called ci t y :
char ci t y[ 6] ; / / Reser ve space f or ci t y.
If you want also to initialize ci t y with a value, you can do it like
this:
char ci t y[ 6] = “ Tul sa” ; / / Reser ve space and
/ / i ni t i ali ze ci t y.
Chapter 23 ♦Introducing Arrays
The 6 is optional because C++ counts the elements needed to hold Tul sa , plus an extra element for the null zero at the end of the quoted string.
You also can reserve a character array and initialize it — a single character at a time—by placing braces around the character data. The following line of code declares an array called i ni t i al s and initializes it with eight characters:
char i ni t i al s[ 8] = { ‘ Q’ , ‘ K’ , ‘ P’ , ‘ G’ , ‘ V’ , ‘ M’ , ‘ U’ , ‘ S’ } ;
The array i ni t i al s is not a string! Its data does not end in a null zero. There is nothing wrong with defining an array of characters such as this one, but you must remember that you cannot treat the array as if it were a string. Do not use string functions with it, or attempt to print the array with cout .
By using brackets, you can initialize any type of array. For example, if you want to initialize an integer array that holds your five children’s ages, you can do it with the following declaration:
i nt chil d_ages[ 5] = { 2, 5, 6, 8, 12} ; / / Decl ar e and
/ / i ni t i ali ze arr ay.
In another example, if you want to keep track of the previous three years’ total sales, you can declare an array and initialize it at the same time with the following:
doubl e sal es[ ] = { 454323. 43, 122355. 32, 343324. 96} ;
As with character arrays, you do not have to state explicitly the array size when you declare and initialize an array of any type. C++ determines, in this case, to reserve three double floating-point array elements for sal es . Figure 23.4 shows the representation of chi l d_ages and sal es in memory.
EXAMPLE
chi l d–ages
Integers
sal es
Floating-points
Figure 23.4. In-memory representation of two different types of arrays.
C++ assigns zero nulls to all array values that you do not define explicitly at declaration time.
Although C++ does not automatically initialize the array ele- ments, if you initialize some but not all the elements when you declare the array, C++ finishes the job for you by assigning the remainder to zero.
For instance, suppose you have to reserve array storage for profit figures of the three previous months as well as the three months to follow. You must reserve six elements of storage, but you know values for only the first three. You can initialize the array as follows:
doubl e pr of i t[ 6] = { 67654. 43, 46472. 34, 63451. 93} ;
Because you explicitly initialized three of the elements, C++ initializes the rest to zero. If you use cout to print the entire array, one element per line, you receive:
67654. 43
46472. 34
63451. 93
00000. 00
00000. 00
00000. 00
Chapter 23 ♦Introducing Arrays
Examples
- Suppose
you want to track the stock market averages for the previous 90 days. Instead of storing them in 90 different variables, it is much easier to store them in an array. You can declare the array like this:
f l oat st ock[ 90];
The remainder of the program can assign values to the averages.
- Suppose
you just finished taking classes at a local university and want to average your six class scores. The following program initializes one array for the school name and an- other for the six classes. The body of the program averages the six scores.
/ / Fil ename: C23ARA1. CPP
/ / Aver ages si x t est scor es. #i ncl ude <i ost r eam. h>
#i ncl ude <i omani p. h> voi d mai n()
EXAMPLE
{
char s_name[ ] = “ Tr i St ar Uni ver si t y” ;
f l oat scor es[ 6] = { 88. 7, 90. 4, 76. 0, 97. 0, 100. 0, 86. 7} ;
f l oat aver age=0. 0; i nt ct r ;
/ / Comput es t ot al of scor es. f or ( ct r =0; ct r <6; ct r ++)
{ aver age += scor es[ ct r ] ; }
/ / Comput es t he aver age. aver age / = f l oat ( 6) ;
cout << “ At “ << s_name << “ , your cl ass aver age i s “
<< set pr eci si on( 2) << aver age << “ \ n” ; r et ur n;
}
The output follows:
At Tr i St ar Uni ver si t y, your cl ass aver age i s 89. 8.
Notice that using arrays makes processing lists of informa- tion much easier. Instead of averaging six differently named variables, you can use a f or loop to step through each array element. If you had to average 1000 numbers, you can still do so with a simple f or loop, as in this example. If the 1000 variables were not in an array, but were individually named, you would have to write a considerable amount of code just to add them.
- The following program is an expanded version of the previ- ous one.
It prints the six scores before computing the aver- age. Notice that you must print array elements individually; you cannot print an entire array in a single cout . (You can print an entire character array with cout , but only if it holds a null-terminated string of characters.)
/ / Fil ename: C23ARA2. CPP
/ / Pr i nt s and aver ages si x t est scor es. #i ncl ude <i ost r eam. h>
#i ncl ude <i omani p. h>
voi d pr _scor es( f l oat scor es[] ) ; / / Pr ot ot ype
Chapter 23 ♦Introducing Arrays
voi d mai n()
{
char s_name[ ] = “ Tr i St ar Uni ver si t y” ;
f l oat scor es[ 6] = { 88. 7, 90. 4, 76. 0, 97. 0, 100. 0, 86. 7} ;
f l oat aver age=0. 0; i nt ct r ;
/ / Call f unct i on t o pr i nt scor es. pr _scor es( scor es) ;
/ / Comput es t ot al of scor es. f or ( ct r =0; ct r <6; ct r ++)
{ aver age += scor es[ ct r ] ; }
/ / Comput es t he aver age. aver age / = f l oat ( 6) ;
cout << “ At “ << s_name << “ , your cl ass aver age i s “
<< set pr eci si on( 2) << aver age; r et ur n;
}
voi d pr _scor es( f l oat scor es[ 6] )
{
/ / Pr i nt s t he si x scor es. i nt ct r ;
cout << “ Her e ar e your scor es:\ n” ; / / Ti t l e f or ( ct r =0; ct r <6; ct r ++)
cout << set pr eci si on( 2) << scor es[ ct r ] << “ \ n” ; r et ur n;
}
To pass an array to a function, you must specify its name only. In the receiving function’s parameter list, you must state the array type and include its brackets, which tell the function that it is an array. (You do not explicitly have to state the array size in the receiving parameter list, as shown in the prototype.)
EXAMPLE
- To
improve the maintainability of your programs, define all array sizes with the const instruction. What if you took four classes next semester but still wanted to use the same pro- gram? You can modify it by changing all the 6s to 4s, but if you had defined the array size with a constant, you have to change only one line to change the program’s subscript limits. Notice how the following program uses a constant for the number of classes.
/ / Fil ename: C23ARA3. CPP
/ / Pr i nt s and aver ages si x t est scor es. #i ncl ude <i ost r eam. h>
#i ncl ude <i omani p. h>
voi d pr _scor es( f l oat scor es[] ) ;
const i nt CLASS_NUM = 6; / / Const ant hol ds arr ay si ze.
voi d mai n()
{
char s_name[ ] = “ Tr i St ar Uni ver si t y” ;
f l oat scor es[ CLASS_NUM] = { 88. 7, 90. 4, 76. 0, 97. 0,
100. 0, 86. 7} ;
f l oat aver age=0. 0; i nt ct r ;
/ / Call s f unct i on t o pr i nt scor es. pr _scor es( scor es) ;
/ / Comput es t ot al of scor es.
f or ( ct r =0; ct r <CLASS_NUM; ct r ++)
{ aver age += scor es[ ct r ] ; }
/ / Comput es t he aver age. aver age / = f l oat ( CLASS_NUM) ;
cout << “ At “ << s_name << “ , your cl ass aver age i s “
<< set pr eci si on( 2) << aver age; r et ur n;
}
voi d pr _scor es( f l oat scor es[ CLASS_NUM] )
Chapter 23 ♦Introducing Arrays
{
/ / Pr i nt s t he si x scor es. i nt ct r ;
cout << “ Her e ar e your scor es:\ n” ; / / Ti t l e f or ( ct r =0; ct r <CLASS_NUM; ct r ++)
cout << set pr eci si on( 2) << scor es[ ct r ] << “ \ n” ; r et ur n;
}
For such a simple example, using a constant for the maxi- mum subscript might not seem like a big advantage. If you were writing a larger program that processed several arrays, however, changing the constant at the top of the program would be much easier than searching the program for each occurrence of that array reference.
Using constants for array sizes has the added advantage of protecting you from going out of the subscript bounds. You do not have to remember the subscript when looping through arrays; you can use the constant instead.
Initializing Elements in th e Program
Rarely do you know the contents of arrays when you declare them. Usually, you fill an array with user input or a disk file’s data. The f or loop is a perfect tool for looping through arrays when you fill them with values.
You cannot assign one array to another. Suppose you want to copy an array called t ot al _sal es to a second array called saved_sal es . You cannot do so with the following assignment statement:
saved_sal es = t ot al _sal es; / / I nvali d!
EXAMPLE
Rather, you have to copy the arrays one element at a time, using a loop, such as the following section of code does:
You want to copy one array to another. You have to do so one element at a time, so you need a counter. Initialize a variable called ct r to 0*; the value of* ct r *represents a position in the array.*
-
*Assign the element that occupies the position in the first array
represented by the value of* ct r *to the same position in the second array.*
-
*If the counter is less than the size of the array, add one to the
counter. Repeat step one.*
f or ( ct r =0; ct r <ARRAY_SI ZE; ct r ++)
{ saved_sal es[ ct r ] = t ot al _sal es[ ct r ] ; }
The following examples illustrate methods for initializing ar- rays in a program. After learning about disk processing later in the book, you learn to read array values from a disk file.
Examples
- The
following program uses the assignment operator to assign 10 temperatures to an array.
/ / Fil ename: C23ARA4. CPP
/ / Fill s an arr ay wi t h 10 t emper at ur e val ues. #i ncl ude <i ost r eam. h>
#i ncl ude <i omani p. h>
const i nt NUM_TEMPS = 10; voi d mai n()
{
f l oat t emps[ NUM_TEMPS]; i nt ct r ;
t emps[ 0] = 78. 6; / / Subscr i pt s al ways begi n at 0. t emps[ 1] = 82. 1;
t emps[ 2] = 79. 5;
t emps[ 3] = 75. 0;
t emps[ 4] = 75. 4;
Chapter 23 ♦Introducing Arrays
t emps[ 5] = 71. 8;
t emps[ 6] = 73. 3;
t emps[ 7] = 69. 5;
t emps[ 8] = 74. 1;
t emps[ 9] = 75. 7;
/ / Pr i nt t he t emps.
cout << “ Dail y t emper at ur es f or t he l ast “ << NUM_TEMPS << “ days:\ n” ;
f or ( ct r =0; ct r <NUM_TEMPS; ct r ++)
{ cout << set pr eci si on( 1) << t emps[ ct r ] << “ \ n” ; }
r et ur n;
}
- The following program uses a f or loop and ci n to assign eight
integers entered individually by the user. The program then prints a total of the numbers.
/ / Fil ename: C23TOT. CPP
/ / Tot al s ei ght i nput val ues f r om t he user . #i ncl ude <i ost r eam. h>
const i nt NUM = 8; voi d mai n()
{
i nt nums[ NUM];
i nt t ot al = 0; / / Hol ds t ot al of user ’ s ei ght number s. i nt ct r ;
f or ( ct r =0; ct r <NUM; ct r ++)
{ cout << “ Pl ease ent er t he next number ... ” ; ci n >> nums[ ct r ];
t ot al += nums[ ct r ] ; }
cout << “ The t ot al of t he number s i s “ << t ot al << “ \ n” ; r et ur n;
}
- You don’t have to access an array in the same order as you
initialized it. Chapter 24, “Array Processing,” shows you how to change the order of an array. You also can use the subscript to select items from an array of values.
EXAMPLE
The following program requests sales data for the preceding 12 months. Users can then type a month they want to see.
That month’s sales figure is then printed, without figures from other months getting in the way. This is how you begin to build a search program to find requested data: You store the data in an array (or in a disk file that can be read into an array, as you learn later), then wait for a user’s request to see specific pieces of the data.
/ / Fil ename: C23SAL. CPP
/ / St or es t wel ve mont hs of sal es and
/ / pr i nt s sel ect ed ones. #i ncl ude <i ost r eam. h>
#i ncl ude <ct ype. h> #i ncl ude <coni o. h>
#i ncl ude <i omani p. h> const i nt NUM = 12; voi d mai n()
{
f l oat sal es[ NUM]; i nt ct r , ans;
i nt r eq_mont h; / / Hol ds user ’ s r equest.
/ / Fill t he arr ay.
cout << “ Pl ease ent er t he t wel ve mont hl y sal es val ues\ n” ; f or ( ct r =0; ct r <NUM; ct r ++)
{ cout << “ What ar e sal es f or mont h number “
<< ct r +1 << “ ? \ n” ; ci n >> sal es[ ct r ] ; }
/ / Wai t f or a r equest ed mont h. f or ( ct r =0; ct r <25; ct r ++)
{ cout << “ \ n” ; } / / Cl ear s t he scr een.
cout << “ *** Sal es Pr i nt i ng Pr ogr am *** \ n” ;
cout << “ Pr i nt s any sal es f r om t he l ast “ << NUM
<< “ mont hs\ n\ n” ;
do
{ cout << “ For what mont h ( 1-” << NUM << “) do you want “
<< “ t o see a sal es val ue? “ ; ci n >> r eq_mont h;
Chapter 23 ♦Introducing Arrays
/ / Adj ust f or zer o- based subscr i pt. cout << “ \ nMont h “ << r eq_mont h <<
“ ‘ s sal es ar e “ << set pr eci si on( 2) << sal es[ r eq_mont h- 1];
cout << “ \ nDo you want t o see anot her ( Y/ N) ? “ ; ans=get ch() ;
ans=t oupper( ans) ;
} whil e ( ans == ‘ Y’ ) ; r et ur n;
}
Notice the helpful screen-clearing routine that prints 23 newline characters. This routine scrolls the screen until it is blank. (Most compilers come with a better built-in screen- clearing function, but the AT&T C++ standard does not offer one because the compiler is too closely linked with specific hardware.)
The following is the second screen from this program. After the 12 sales values are entered in the array, any or all can be requested, one at a time, simply by supplying the month’s number (the number of the subscript).
*** Sal es Pr i nt i ng Pr ogr am ***
Pr i nt s any sal es f r om t he l ast 12 mont hs
For what mont h ( 1- 12) do you want t o see a sal es val ue? 2 Mont h 2’ s sal es ar e 433. 22
Do you want t o see anot her ( Y/ N) ?
For what mont h ( 1- 12) do you want t o see a sal es val ue? 5
Mont h 5’ s sal es ar e 123. 45
Do you want t o see anot her ( Y/ N) ?
EXAMPLE
Review Question s
Answers to the review questions are in Appendix B.
-
True
or false: A single array can hold several values of different data types.
-
How do C++ programs tell one array element from another if all
elements have identical names?
-
Why
must you initialize an array before using it?
-
Given the following definition of an array, called wei ght s , what
is the value of wei ght s[ 5] ?
i nt wei ght s[ 10] = { 5, 2, 4} ;
-
If
you pass an integer array to a function and change it, does the array change also in the calling function? (Hint: Remem- ber how character arrays are passed to functions.)
-
How does C++ initialize global array elements?
Review Exercise s
-
Write
a program to store the ages of six of your friends in a single array. Store each of the six ages using the assignment operator. Print the ages on-screen.
-
Modify the program in Exercise 1 to print the ages in reverse order.
-
Write
a simple data program to track a radio station’s ratings (1, 2, 3, 4, or 5) for the previous 18 months. Use ci n to initial- ize the array with the ratings. Print the ratings on-screen with an appropriate title.
-
Write a program to store the numbers from 1 to 100 in an array of
100 integer elements. (Hint: The subscripts should begin at 0 and end at 99.)
Chapter 23 ♦Introducing Arrays
- Write
a program a small business owner can use to track customers. Assign each customer a number (starting at 0). Whenever a customer purchases something, record the sale in the element that matches the customer’s number (that is, the next unused array element). When the store owner signals the end of the day, print a report consisting of each customer number with its matching sales, a total sales figure, and an average sales figure per customer.
Summary
You now know how to declare and initialize arrays consisting of various data types. You can initialize an array either when you declare it or in the body of your program. Array elements are much easier to process than other variables because each has a different name.
C++ has powerful sorting and searching techniques that make your programs even more serviceable. The next chapter introduces these techniques and shows you still other ways to access array elements.