7.4. Examples Using Arrays
This section presents many examples
that demonstrate how to declare arrays, how to initialize arrays and how to
perform common array manipulations.
7.4.1. Declaring an Array and Using
a Loop to Initialize the Array's Elements
The program in Fig. 7.3 declares 10-element integer
array n (line 12). Lines 15–16 use a for statement to initialize the array elements to zeros. Like
other automatic variables, automatic arrays are not implicitly initialized to
zero although static arrays are. The
first output statement (line 18) displays the column headings for the columns
printed in the subsequent for statement (lines
21–22), which prints the array in tabular format. Remember that setw specifies the field width in which only the next value is to be output.
Fig. 7.3. Initializing an array's elements to zeros and
printing the array.
1 // Fig. 7.3: fig07_03.cpp
2 // Initializing an array.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 #include <iomanip>
8 using std::setw;
9
10 int main()
11 {
12 int n[ 10 ]; // n is an array of 10 integers
13
14 // initialize elements of array n to 0
15 for ( int i = 0; i < 10; i++ )
16 n[ i ] = 0; // set element at location i to 0
17
18 cout << "Element" << setw( 13 ) << "Value" << endl;
19
20 // output each array element's value
21 for ( int j = 0; j < 10; j++ )
22 cout << setw( 7 ) << j << setw( 13 ) << n[ j ] << endl;
23
24 return 0; // indicates successful termination
25 } // end main
|
Element Value
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
|
7.4.2. Initializing an Array in a
Declaration with an Initializer List
The elements of
an array also can be initialized in the array declaration by following the array
name with an equals sign and a brace-delimited comma-separated list of initializers. The program in Fig. 7.4 uses an initializer list to
initialize an integer array with 10 values (line 13) and prints the array in
tabular format (lines 15–19).
Fig. 7.4. Initializing the
elements of an array in its declaration.
1 // Fig. 7.4: fig07_04.cpp
2 // Initializing an array in a declaration.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 #include <iomanip>
8 using std::setw;
9
10 int main()
11 {
12 // use initializer list to initialize array n
13 int n[ 10 ] = { 32, 27, 64, 18, 95, 14, 90, 70, 60, 37 };
14
15 cout << "Element" << setw( 13 ) << "Value" << endl;
16
17 // output each array element's value
18 for ( int i = 0; i < 10; i++ )
19 cout << setw( 7 ) << i << setw( 13 ) << n[ i ] << endl;
20
21 return 0; // indicates successful termination
22 } // end main
|
Element Value
0 32
1 27
2 64
3 18
4 95
5 14
6 90
7 70
8 60
9 37
|
If there are fewer initializers
than elements in the array, the remaining array elements are initialized to
zero. For example, the elements of array n in Fig. 7.3 could have been initialized to zero with the
declaration
int n[ 10 ] = {}; // initialize elements of array n to 0
The declaration implicitly
initializes the elements to zero, because there are fewer initializers (none in
this case) than elements in the array. This technique can be used only in the
array's declaration, whereas the initialization technique shown in Fig. 7.3 can be used repeatedly during program execution to
"reinitialize" an array's elements.
If the array size is omitted from a
declaration with an initializer list, the compiler determines the number of
elements in the array by counting the number of elements in the initializer
list. For example,
int n[] = { 1, 2, 3, 4, 5 };
creates a five-element array.
If the array size and an initializer list
are specified in an array declaration, the number of initializers must be less
than or equal to the array size. The array declaration
int n[ 5 ] = { 32, 27, 64, 18, 95, 14 };
causes a compilation error,
because there are six initializers and only five array elements.
Common Programming Error 7.2
|
Providing more initializers in an array
initializer list than there are elements in the array is a compilation
error. |
Common Programming Error 7.3
|
Forgetting to
initialize the elements of an array whose elements should be initialized is a
logic error. |
7.4.3. Specifying an Array's Size
with a Constant Variable and Setting Array Elements with Calculations
Figure
7.5 sets the elements of a 10-element array
s to the even integers 2, 4,
6, . . ., 20 (lines 17–18) and prints
the array in tabular format (lines 20–24). These numbers are generated (line 18)
by multiplying each successive value of the loop counter by 2 and
adding 2.
Fig. 7.5. Generating values to be
placed into elements of an array.
1 // Fig. 7.5: fig07_05.cpp
2 // Set array s to the even integers from 2 to 20.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 #include <iomanip>
8 using std::setw;
9
10 int main()
11 {
12 // constant variable can be used to specify array size
13 const int arraySize = 10;
14
15 int s[ arraySize ]; // array s has 10 elements
16
17 for ( int i = 0; i < arraySize; i++ ) // set the values
18 s[ i ] = 2 + 2 * i;
19
20 cout << "Element" << setw( 13 ) << "Value" << endl;
21
22 // output contents of array s in tabular format
23 for ( int j = 0; j < arraySize; j++ )
24 cout << setw( 7 ) << j << setw( 13 ) << s[ j ] << endl;
25
26 return 0; // indicates successful termination
27 } // end main
|
Element Value
0 2
1 4
2 6
3 8
4 10
5 12
6 14
7 16
8 18
9 20
|
Line 13 uses the const qualifier to declare a so-called constant variable arraySize with the
value 10. Constant variables must be
initialized with a constant expression when they are declared and cannot be
modified thereafter (as shown in Fig. 7.6 and Fig. 7.7). Constant variables are
also called named constants or read-only variables.
Fig. 7.6. Initializing and using a constant
variable.
1 // Fig. 7.6: fig07_06.cpp
2 // Using a properly initialized constant variable.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 int main()
8 {
9 const int x = 7; // initialized constant variable
10
11 cout << "The value of constant variable x is: " << x << endl;
12
13 return 0; // indicates successful termination
14 } // end main
|
The value of constant variable x is: 7
|
Fig. 7.7. const variables must be
initialized.
1 // Fig. 7.7: fig07_07.cpp
2 // A const variable must be initialized.
3
4 int main()
5 {
6 const int x; // Error: x must be initialized
7
8 x = 7; // Error: cannot modify a const variable
9
10 return 0; // indicates successful termination
11 } // end main
|
| Borland C++ command-line compiler
error message: |
Error E2304 fig07_07.cpp 6: Constant variable 'x' must be initialized
in function main()
Error E2024 fig07_07.cpp 8: Cannot modify a const object in function main()
|
| Microsoft Visual C++ compiler
error message: |
C:\cppfp_examples\ch07\fig07_07.cpp(6) : error C2734: 'x' : const object
must be initialized if not extern
C:\cppfp_examples\ch07\fig07_07.cpp(8) : error C3892: 'x' : you cannot
assign to a variable that is const
|
| GNU C++ compiler error
message: |
fig07_07.cpp:6: error: uninitialized const 'x'
fig07_07.cpp:8: error: assignment of read-only variable 'x'
|
Common Programming Error 7.4
|
Not assigning
a value to a constant variable when it is declared is a compilation
error. |
Common Programming Error 7.5
|
Assigning a value to a constant variable in an executable
statement is a compilation
error. |
In Fig.
7.7, note that the compilation errors produced
by Borland C++ and Microsoft Visual C++ refer to the int variable
x as a "const object." The
ISO/IEC C++ standard defines an "object" as any "region of storage." Like
objects of classes, fundamental-type variables also occupy space in memory, so
they are often referred to as "objects."
Constant variables can be
placed anywhere a constant expression is expected. In Fig. 7.5, constant variable
arraySize specifies the size of array s
in line 15.
Common Programming Error 7.6
|
Only constants
can be used to declare the size of automatic and static arrays. Not using a
constant for this purpose is a compilation
error. |
Using constant variables to specify
array sizes makes programs more scalable.
In Fig. 7.5, the
first for statement could fill a 1000-element array by
simply changing the value of arraySize in its declaration from
10 to 1000. If the constant variable arraySize had not been used, we would have to change lines 15, 17 and
23 of the program to scale the program to handle 1000 array elements. As
programs get larger, this technique becomes more useful for writing clearer,
easier-to-modify programs.
Software Engineering Observation 7.1
|
Defining the
size of each array as a constant variable instead of a literal constant can make
programs more scalable. |
Good Programming Practice 7.2
|
Defining the
size of an array as a constant variable instead of a literal constant makes
programs clearer. This technique eliminates so-called magic numbers. For
example, repeatedly mentioning the size 10 in array-processing code for a
10-element array gives the number 10 an artificial significance and can be
confusing when the program includes other 10s that have nothing to do with the
array size. |
7.4.4. Summing the Elements of an
Array
Often, the elements of an array represent a
series of values to be used in a calculation. For example, if the elements of an
array represent exam grades, a professor may wish to total the elements
of the array and use that sum to calculate the class average for the exam. The
examples using class GradeBook later in the chapter,
namely Figs.
7.16–7.17
and Figs.
7.23–7.24,
use this technique.
The program in Fig. 7.8
sums the values contained in the 10-element integer array a. The program declares, creates and initializes the array
in line 10. The for statement (lines 14–15)
performs the calculations. The values being supplied as initializers for array
a also could be read into the program from the
user at the keyboard, or from a file on disk (see Chapter
17, File Processing). For example, the for statement
Fig. 7.8. Computing the sum of
the elements of an array.
1 // Fig. 7.8: fig07_08.cpp
2 // Compute the sum of the elements of the array.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 int main()
8 {
9 const int arraySize = 10; // constant variable indicating size of array
10 int a[ arraySize ] = { 87, 68, 94, 100, 83, 78, 85, 91, 76, 87 };
11 int total = 0;
12
13 // sum contents of array a
14 for ( int i = 0; i < arraySize; i++ )
15 total += a[ i ];
16
17 cout << "Total of array elements: " << total << endl;
18
19 return 0; // indicates successful termination
20 } // end main
|
Total of array elements: 849
|
for ( int j = 0; j < arraySize; j++ )
cin >> a[ j ];
reads one value at a time from the
keyboard and stores the value in element a[ j ].
7.4.5. Using Bar Charts to Display
Array Data Graphically
Many programs present data to
users in a graphical manner. For example, numeric values are often displayed as
bars in a bar chart. In such a chart, longer bars represent proportionally
larger numeric values. One simple way to display numeric data graphically is
with a bar chart that shows each numeric value as a bar of asterisks
(*).
Professors often like to examine
the distribution of grades on an exam. A professor might graph the number of
grades in each of several categories to visualize the grade distribution.
Suppose the grades were 87, 68, 94, 100, 83, 78, 85, 91, 76 and 87. Note that
there was one grade of 100, two grades in the 90s, four grades in the 80s, two
grades in the 70s, one grade in the 60s and no grades below 60. Our next program
(Fig. 7.9) stores this grade distribution data in an array
of 11 elements, each corresponding to a category of grades. For example, n[0]
indicates the number of grades in the range 0–9, n[7] indicates the number of grades in the range 70–79 and
n[ 10 ] indicates the number of grades of 100. The two versions of class GradeBook later in
the chapter (Figs.
7.16–7.17
and Figs.
7.23–7.24) contain code that calculates these grade frequencies based
on a set of grades. For now, we manually create the array by looking at the set
of grades.
Fig. 7.9. Bar chart printing program.
1 // Fig. 7.9: fig07_09.cpp
2 // Bar chart printing program.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 #include <iomanip>
8 using std::setw;
9
10 int main()
11 {
12 const int arraySize = 11;
13 int n[ arraySize ] = { 0, 0, 0, 0, 0, 0, 1, 2, 4, 2, 1 };
14
15 cout << "Grade distribution:" << endl;
16
17 // for each element of array n, output a bar of the chart
18 for ( int i = 0; i < arraySize; i++ )
19 {
20 // output bar labels ("0-9:", ..., "90-99:", "100:" )
21 if ( i == 0 )
22 cout << " 0-9: ";
23 else if ( i == 10 )
24 cout << " 100: ";
25 else
26 cout << i * 10 << "-" << ( i * 10 ) + 9 << ": ";
27
28 // print bar of asterisks
29 for ( int stars = 0; stars < n[ i ]; stars++ )
30 cout << '*';
31
32 cout << endl; // start a new line of output
33 } // end outer for
34
35 return 0; // indicates successful termination
36 } // end main
|
Grade distribution:
0-9:
10-19:
20-29:
30-39:
40-49:
50-59:
60-69: *
70-79: **
80-89: ****
90-99: **
100: *
|
The program reads the numbers from the
array and graphs the information as a bar chart, displaying each grade range
followed by a bar of asterisks indicating the number of grades in that range. To
label each bar, lines 21–26 output a grade range (e.g., "70-79: ") based on the current value of counter variable i.
The nested for statement (lines 29–30) outputs the bars. Note the
loop-continuation condition in line 29 (stars < n[ i ]). Each time
the program reaches the inner for, the loop counts from 0 up
to n[ i ], thus using a value in array n to determine the
number of asterisks to display. In this example, n[ 0 ]–n[5] contain zeros because no students received a grade
below 60. Thus, the program displays no asterisks next to the first six grade
ranges.
Common Programming Error
7.7
|
Although it
is possible to use the same control variable in a for statement and in a second for statement nested inside, this is confusing and can lead to
logic errors. |
7.4.6. Using the Elements of an
Array as Counters
Sometimes, programs use counter
variables to summarize data, such as the results of a survey. In Fig.
6.8, we used separate counters in our die-rolling
program to track the number of occurrences of each side of a die as the program
rolled the die 6,000,000 times. An array version of this program is shown in Fig. 7.10.
Fig. 7.10. Die-rolling program using an array instead of
switch.
1 // Fig. 7.10: fig07_10.cpp
2 // Roll a six-sided die 6,000,000 times.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 #include <iomanip>
8 using std::setw;
9
10 #include <cstdlib>
11 using std::rand;
12 using std::srand;
13
14 #include <ctime>
15 using std::time;
16
17 int main()
18 {
19 const int arraySize = 7; // ignore element zero
20 int frequency[ arraySize ] = {}; // initialize elements to 0
21
22 srand( time( 0 ) ); // seed random number generator
23
24 // roll die 6,000,000 times; use die value as frequency index
25 for ( int roll = 1; roll <= 6000000; roll++ )
26 frequency[ 1 + rand() % 6 ]++;
27
28 cout << "Face" << setw( 13 ) << "Frequency" << endl;
29
30 // output each array element's value
31 for ( int face = 1; face < arraySize; face++ )
32 cout << setw( 4 ) << face << setw( 13 ) << frequency[ face ]
33 << endl;
34
35 return 0; // indicates successful termination
36 } // end main
|
Face Frequency
1 1000167
2 1000149
3 1000152
4 998748
5 999626
6 1001158
|
Figure
7.10 uses the array frequency (line 20) to
count the occurrences of each side of the die. The single statement in line 26 of this program replaces the
switch statement in lines 30–52 of Fig.
6.8. Line 26 uses a random value to determine which
frequency element to increment during each
iteration of the loop. The calculation in line 26 produces a random subscript
from 1 to 6, so array frequency must be large
enough to store six counters. However, we use a seven-element array in which we
ignore frequency[ 0 ]—it is more logical to have
the die face value 1 increment frequency[ 1 ] than frequency[ 0
]. Thus, each face value is used as a subscript for
array frequency. We also replace lines
56–61 of Fig.
6.8 by looping through array frequency to
output the results (lines 31–33).
7.4.7. Using Arrays to Summarize
Survey Results
Our next example
(Fig. 7.11) uses arrays to summarize the results of data collected in
a survey. Consider the following problem statement:
Forty students
were asked to rate the quality of the food in the student cafeteria on a scale
of 1 to 10 (1 meaning awful and 10 meaning excellent). Place the 40 responses in
an integer array and summarize the results of the
poll.
Fig. 7.11. Poll analysis program.
1 // Fig. 7.11: fig07_11.cpp
2 // Student poll program.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 #include <iomanip>
8 using std::setw;
9
10 int main()
11 {
12 // define array sizes
13 const int responseSize = 40; // size of array responses
14 const int frequencySize = 11; // size of array frequency
15
16 // place survey responses in array responses
17 const int responses[ responseSize ] = { 1, 2, 6, 4, 8, 5, 9, 7, 8,
18 10, 1, 6, 3, 8, 6, 10, 3, 8, 2, 7, 6, 5, 7, 6, 8, 6, 7,
19 5, 6, 6, 5, 6, 7, 5, 6, 4, 8, 6, 8, 10 };
20
21 // initialize frequency counters to 0
22 int frequency[ frequencySize ] = {};
23
24 // for each answer, select responses element and use that value
25 // as frequency subscript to determine element to increment
26 for ( int answer = 0; answer < responseSize; answer++ )
27 frequency[ responses[ answer ] ]++;
28
29 cout << "Rating" << setw( 17 ) << "Frequency" << endl;
30
31 // output each array element's value
32 for ( int rating = 1; rating < frequencySize; rating++ )
33 cout << setw( 6 ) << rating << setw( 17 ) << frequency[ rating ]
34 << endl;
35
36 return 0; // indicates successful termination
37 } // end main
|
Rating Frequency
1 2
2 2
3 2
4 2
5 5
6 11
7 5
8 7
9 1
10 3
|
This is a typical array-processing
application. We wish to summarize the number of responses of each type (i.e., 1
through 10). The array responses (lines 17–19)
is a 40-element integer array of the students' responses to the survey. Note
that array responses is declared
const, as its values do not (and should not)
change. We use an 11-element array frequency
(line 22) to count the number of occurrences of each response. Each element of
the array is used as a counter for one of the survey responses and is
initialized to zero. As in Fig. 7.10, we ignore frequency[ 0
].
Software Engineering
Observation 7.2
|
The const qualifier should be used to enforce the principle of least
privilege. Using the principle of least privilege to properly design software
can greatly reduce debugging time and improper side effects and can make a
program easier to modify and
maintain. |
The first for statement (lines
26–27) takes the responses one at a time from the array responses and increments one of the 10 counters in the frequency
array (frequency[ 1 ] to frequency[
10 ]). The key statement in the loop is line 27,
which increments the appropriate frequency counter, depending on the
value of responses[ answer ].
Let's consider several iterations of the for loop.
When control variable answer is 0, the value of responses[
answer ] is the value of responses[ 0 ] (i.e., 1 in line
17), so the program interprets frequency[ responses[ answer ] ]++
as
which increments the value in array
element 1. To evaluate the expression, start with the value in the innermost set
of square brackets (answer). Once you know
answer's value (which is the value of the loop
control variable in line 26), plug it into the expression and evaluate the next
outer set of square brackets (i.e., responses[ answer ], which is a value selected from the
responses array in lines 17–19). Then use the
resulting value as the subscript for the frequency array to specify which counter to increment.
When answer is 1, responses[ answer
] is the value of responses[ 1 ], which is 2, so the
program interprets frequency[ responses[ answer ] ]++ as
which increments array element 2.
When answer is 2, responses[ answer
] is the value of responses[ 2 ], which is 6, so the
program interprets frequency[ responses[ answer ] ]++ as
which increments array element 6,
and so on. Regardless of the number of responses processed in the survey, the
program requires only an 11-element array (ignoring element zero) to summarize
the results, because all the response values are between 1 and 10 and the
subscript values for an 11-element array are 0 through 10.
If the data in the responses
array had contained an invalid value, such as 13, the program would have
attempted to add 1 to frequency[ 13 ],
which is outside the bounds of the array. C++ has no array bounds checking to prevent the computer
from referring to an element that does not exist. Thus, an executing program can "walk off" either end of
an array without warning. You should ensure that all array references remain
within the bounds of the array.
Common Programming Error 7.8
|
Referring
to an element outside the array bounds is an execution-time logic error. It is
not a syntax error. |
Error-Prevention Tip 7.1
|
When looping
through an array, the array subscript should never go below 0 and should always
be less than the total number of elements in the array (one less than the size
of the array). Make sure that the loop-termination condition prevents accessing
elements outside this
range. |
Portability Tip 7.1
|
The
(normally serious) effects of referencing elements outside the array bounds are
system dependent. Often this results in changes to the value of an unrelated
variable or a fatal error that terminates program
execution. |
C++ is an extensible language. Section
7.11 presents C++ Standard Library class
template vector, which enables programmers
to perform many operations that are not available for C++'s built-in arrays. For
example, we'll be able to compare vectors directly and assign one
vector to another. In Chapter
11, we extend C++ further by implementing an array as a
user-defined class of our own. This new array definition will enable us to input
and output entire arrays with cin and cout, initialize arrays when they are created, prevent access
to out-of-range array elements and change the range of subscripts (and even
their subscript type) so that the first element of an array is not required to
be element 0. We'll even be able to use noninteger subscripts.
Error-Prevention Tip 7.2
|
In Chapter
11, we'll see how to develop a class representing a
"smart array," which checks that all subscript references are in bounds at
runtime. Using such smart data types helps eliminate
bugs. |
7.4.8. Using Character Arrays to
Store and Manipulate Strings
To this point, we have discussed only
integer arrays. However, arrays may be of any type. We now introduce storing
character strings in character arrays. Recall that, starting in Chapter
3, we have been using string objects to store character strings, such as the
course name in our GradeBook class. A string such
as "hello" is actually an array of characters.
While string objects are convenient to
use and reduce the potential for errors, character arrays that represent strings
have several unique features, which we discuss in this section. As you continue
your study of C++, you may encounter C++ capabilities that require you to use
character arrays in preference to string
objects. You may also be asked to update existing code using character
arrays.
A character array can be
initialized using a string literal. For example, the declaration
char string1[] = "first";
initializes the elements of array string1 to the
individual characters in the string literal "first". The size of array
string1 in the preceding declaration is determined
by the compiler based on the length of the string. It is important to note that
the string "first" contains five characters
plus a special
string-termination character called the null
character. Thus, array string1
actually contains six elements. The character-constant that represents the null
character is '\0' (backslash followed by
zero). All strings represented by character arrays end with this character. A
character array representing a string should always be declared large enough to
hold the number of characters in the string and the terminating null
character.
Character arrays also can be initialized
with individual character constants in an initializer list. The preceding
declaration is equivalent to the more tedious form
char string1[] = { 'f', 'i', 'r', 's', 't', '\0' };
Note the use of single quotes to
delineate each character constant. Also, note that we explicitly provided the
terminating null character as the last initializer value. Without it, this array
would simply represent an array of characters, not a string. As we discuss in Chapter
8, not providing a terminating null character for a
string can cause logic errors.
Because a string
is an array of characters, we can access individual characters in a string
directly with array subscript notation. For example, string1[ 0 ] is
the character 'f', string1[ 3 ] is the character 's'
and string1[ 5 ] is the null character.
We can input a string directly into a
character array from the keyboard using cin and
>>. For example, the declaration
creates a character array capable
of storing a string of up to 19 characters and a terminating null character. The
statement
reads a string from the keyboard into
string2 and appends the null character to the
end of the string input by the user. Note that the preceding statement provides
only the name of the array and no information about the size of the array. It is
your responsibility to ensure that the array into which the string is read is
capable of holding any string the user types at the keyboard. By default,
cin reads characters from the keyboard until
the first white-space character is encountered—regardless of the array size.
Thus, inputting data with cin and >> can insert data
beyond the end of the array (see Section
8.13 for information on preventing insertion beyond the end of a char
array).
Common Programming Error 7.9
|
Not providing cin >> with a character array large enough to store a string typed
at the keyboard can result in loss of data in a program and other serious
runtime errors. |
A character array representing a
null-terminated string can be output with cout and <<.
The statement
prints the array string2. Note that cout
<<, like cin >>, does not care
how large the character array is. The characters of the string are output until
a terminating null character is encountered; the null character is not printed.
[Note: cin and cout assume that character arrays should be processed as strings
terminated by null characters; cin and cout do not provide similar input and output processing
capabilities for other array types.]
Figure
7.12 demonstrates initializing a character
array with a string literal, reading a string into a character array, printing a
character array as a string and accessing individual characters of a
string.
Fig. 7.12. Character arrays
processed as strings.
1 // Fig. 7.12: fig07_12.cpp
2 // Treating character arrays as strings.
3 #include <iostream>
4 using std::cout;
5 using std::cin;
6 using std::endl;
7
8 int main()
9 {
10 char string1[ 20 ]; // reserves 20 characters
11 char string2[] = "string literal"; // reserves 15 characters
12
13 // read string from user into array string1
14 cout << "Enter the string \"hello there\": ";
15 cin >> string1; // reads "hello" [space terminates input]
16
17 // output strings
18 cout << "string1 is: " << string1 << "\nstring2 is: " << string2;
19
20 cout << "\nstring1 with spaces between characters is:\n";
21
22 // output characters until null character is reached
23 for ( int i = 0; string1[ i ] != '\0'; i++ )
24 cout << string1[ i ] << ' ';
25
26 cin >> string1; // reads "there"
27 cout << "\nstring1 is: " << string1 << endl;
28
29 return 0; // indicates successful termination
30 } // end main
|
Enter the string "hello there": hello there
string1 is: hello
string2 is: string literal
string1 with spaces between characters is:
h e l l o
string1 is: there
|
Lines 23–24 of Fig. 7.12 use a for statement to loop through the string1 array and print its characters separated by spaces. The condition
in the for statement, string1[ i ] != '\0', is true until the loop encounters the terminating
null character of the string.
7.4.9. Static Local Arrays and
Automatic Local Arrays
Chapter
6 discussed the storage-class specifier static. A static local variable in a function definition exists
for the program's duration but is visible only in the function's body.
Performance Tip 7.1
|
We can apply static to a local array declaration so that the array is not
created and initialized each time the program calls the function and is not
destroyed each time the function terminates in the program. This can improve
performance, especially when using large
arrays. |
A program initializes static local arrays when their declarations are first
encountered. If a static array is
not initialized explicitly by you, each element of that array is initialized to
zero by the compiler when the array is created. Recall that C++ does not perform
such default initialization for automatic variables.
Figure
7.13 demonstrates function staticArrayInit (lines 25–41) with a
static local array (line 28) and function
automaticArrayInit (lines 44–60) with an
automatic local array (line 47).
Fig. 7.13. static array initialization and
automatic array initialization.
1 // Fig. 7.13: fig07_13.cpp
2 // Static arrays are initialized to zero.
3 #include <iostream>
4 using std::cout;
5 using std::endl;
6
7 void staticArrayInit( void ); // function prototype
8 void automaticArrayInit( void ); // function prototype
9
10 int main()
11 {
12 cout << "First call to each function:\n";
13 staticArrayInit();
14 automaticArrayInit();
15
16 cout << "\n\nSecond call to each function:\n";
17 staticArrayInit();
18 automaticArrayInit();
19 cout << endl;
20
21 return 0; // indicates successful termination
22 } // end main
23
24 // function to demonstrate a static local array
25 void staticArrayInit( void )
26 {
27 // initializes elements to 0 first time function is called
28 static int array1[ 3 ]; // static local array
29
30 cout << "\nValues on entering staticArrayInit:\n";
31
32 // output contents of array1
33 for ( int i = 0; i < 3; i++ )
34 cout << "array1[" << i << "] = " << array1[ i ] << " ";
35
36 cout << "\nValues on exiting staticArrayInit:\n";
37
38 // modify and output contents of array1
39 for ( int j = 0; j < 3; j++ )
40 cout << "array1[" << j << "] = " << ( array1[ j ] += 5 ) << " ";
41 } // end function staticArrayInit
42
43 // function to demonstrate an automatic local array
44 void automaticArrayInit( void )
45 {
46 // initializes elements each time function is called
47 int array2[ 3 ] = { 1, 2, 3 }; // automatic local array
48
49 cout << "\n\nValues on entering automaticArrayInit:\n";
50
51 // output contents of array2
52 for ( int i = 0; i < 3; i++ )
53 cout << "array2[" << i << "] = " << array2[ i ] << " ";
54
55 cout << "\nValues on exiting automaticArrayInit:\n";
56
57 // modify and output contents of array2
58 for ( int j = 0; j < 3; j++ )
59 cout << "array2[" << j << "] = " << ( array2[ j ] += 5 ) << " ";
60 } // end function automaticArrayInit
|
First call to each function:
Values on entering staticArrayInit:
array1[0] = 0 array1[1] = 0 array1[2] = 0
Values on exiting staticArrayInit:
array1[0] = 5 array1[1] = 5 array1[2] = 5
Values on entering automaticArrayInit:
array2[0] = 1 array2[1] = 2 array2[2] = 3
Values on exiting automaticArrayInit:
array2[0] = 6 array2[1] = 7 array2[2] = 8
Second call to each function:
Values on entering staticArrayInit:
array1[0] = 5 array1[1] = 5 array1[2] = 5
Values on exiting staticArrayInit:
array1[0] = 10 array1[1] = 10 array1[2] = 10
Values on entering automaticArrayInit:
array2[0] = 1 array2[1] = 2 array2[2] = 3
Values on exiting automaticArrayInit:
array2[0] = 6 array2[1] = 7 array2[2] = 8
|
Function staticArrayInit is
called twice (lines 13 and 17). The static
local array is initialized to zero by the compiler the first time the function
is called. The function prints the array, adds 5 to each element and prints the
array again. The second time the function is called, the static array contains the modified values stored during the first
function call. Function automaticArrayInit also is
called twice (lines 14 and 18). The elements of the automatic local array are
initialized (line 47) with the values 1, 2 and 3. The function prints the array,
adds 5 to each element and prints the array again. The second time the function
is called, the array elements are reinitialized to 1, 2 and 3. The array has
automatic storage class, so the array is recreated and reinitialized during each
call to automaticArrayInit.
Common Programming Error 7.10
|
Assuming that elements of a function's
local static array are initialized every time the
function is called can lead to logic errors in a
program. |