Chapter 4 (v2) - Array and String
Chapter 4 (v2) - Array and String
CHAPTER FOUR
Array and Strings
4.1 Introduction
As discussed so far variables in a program have values associated with them. During program
execution these values are accessed by using the identifier associated with the variable in
expressions. All the variables we have used so far have a common characteristic: Each variable
can be used to store only a single value at a time. For example, although the variables key, count,
and grade declared in the statements as follow are of different data types, each variable can store
only one value of the declared data type.
char key;
int count;
double grade;
These types of variables are called atomic variables (also referred to as scalar variables), which
means their values can’t be further subdivided or separated into a legitimate data type.
Thus even though programs have been written that could handle large lists of data values it has
not been necessary to use a separate identifier for each data value in the list. This is because in all
these programs it has never been necessary to keep a note of each value individually for later
processing. For example in summing the numbers in a list only one variable was used to hold the
current entered number which was added to the accumulated sum and was then overwritten by
the next number entered. If that value were required again later in the program there would be no
way of accessing it because the value has now been overwritten by the later input.
If only a few values were involved a different identifier could be declared for each variable, but
now a loop could not be used to enter the values. Using a loop and assuming that after a value
has been entered and used no further use will be made of it allows the following code to be
written. This code enters six numbers and outputs their sum:
Float x, sum = 0.0;
for (i = 0; i < 6; i++)
{
cin >> x;
sum += x;
}
float a, b, c, d, e, f;
which is obviously a very tedious way to program. To extend this solution so that it would work
with more than six values then more declarations would have to be added, extra assignment
statements added and the program re-compiled. If there were 10000 values imagine the tedium of
typing the program (and making up variable names and remembering which is which)!
To get round this difficulty all high-level programming languages use the concept of a data
structure called an Array. So that for example if you want to find the average of the marks for a
class of 30 students, you certainly do not want to create 30 variables: mark1, mark2, ... , mark30.
Instead, you could use a single variable, called an array, with 30 elements.
An array can be thought of as a collection of numbered boxes each containing one data item. The
number associated with the box is the index of the item. To access a particular item the index of
the box associated with the item is used to access the appropriate box. The index must be an
integer (literal, expression or constant) and indicates the position of the element in the array.
Thus the elements of an array are ordered by the index.
Declaration of Arrays
Arrays occupy space in memory. Defining the name and type of an array and setting the number
of elements in an array is called dimensioning the array. The array must be declared before one
uses in like other variables. In the array declaration one must define and specify:
• The type of the array (i.e. integer, floating point, char etc.)
• Size of the array:- The total number of memory locations to be allocated or the number of
elements in the array
So the general syntax to specify the type of the elements and the number of elements required by
an array use a declaration of the form:
For example average temperature data over the year in Ethiopia for each of the last 100 years
could be stored in an array declared as follows:
float annual_temp[100];
This declaration will cause the compiler to allocate enough space for 100 consecutive float
variables in memory.
Note:
The arraySize must be an integer constant or integer expression greater than zero and cannot be
a variable whose value is set while the program is running. If a program uses an expression as a
subscript, then the program evaluates the expression to determine the subscript. For example, if
we assume that variable a is equal to 5 and that variable b is equal to 6, then the statement
annual_temp [ a + b ] += 2;
then if more records come to light it is easy to amend the program to cope with more values by
changing the value of NE or SIZE. This works because the compiler knows the value of the
constant NE or SIZE at compile time and can allocate an appropriate amount of space for the
array. It would not work if an ordinary variable was used for the size in the array declaration
since at compile time the compiler would not know a value for it.
Note: It is recommendable using a plural name for array, e.g., marks, rows, numbers.
Initializing Arrays
In C++, the values of the elements are undefined after declaration. When declaring an array of
local scope (within a function), if we do not specify the array variable the array will not be
initialized, so its content is undetermined value until we store some values in it. But if we declare
a global array (outside any function) its content will be initialized with all its elements filled with
zeros for numerical data types and empty for character types.
Thus, if in the global scope we declare array as int day[5]; every element of day will be set
initially to 0:
But Array elements can be initialized in their declaration statements in the same manner as scalar
variables, except the initializing elements must be included in braces, as shown in the following
examples:
int day [5] = { 16, 2, 77, 40, 12071 };
Initializations are applied in the order they are written, with the first value used to initialize
element 0, the second value used to initialize element 1, and so on, until all values have been
used. For example:
Because white space is ignored in C++, initializations can be continued across multiple
lines. For example, the following declaration uses four lines to initialize all the array elements:
int gallons[20] = {19, 16, 14, 19, 20, 18, // initializing values
12, 10, 22, 15, 18, 17, // can extend across
16, 14, 23, 19, 15, 18, // multiple lines
21, 5};
Note: The number of elements in the array that we initialized within curly brackets { } must be
equal or less than the length in elements that we declared for the array enclosed within square
brackets [ ]. When initializing an array, we can provide fewer values than the array elements. If
we have less number of items for the initialization, the rest will be filled with zero. For example,
in the declaration
only length[0], length[1], length[2], and length[3] are initialized with the listed values. The
other array elements are initialized to 0 automatically. Unfortunately, there’s no method of
indicating repetition of an initialization value or of initializing later array elements without first
specifying values for earlier elements.
A unique feature of array initialization is that the array size can be omitted when initializing
values are included in the declaration statement. Because specifying the size of array can be
considered as useless repetition, C++ allows the possibility of leaving empty the brackets [ ],
where the number of items in the initialization bracket will be counted to set the size of the array.
For example, the following declaration reserves enough storage room for five elements:
You can use the initialization form only when defining the array. You cannot use it later, and
cannot assign one array to another once; i.e.
Array_Name [ index ]
In C++ the first element has an index of 0 and the last element has an index, which is one less the
size of the array (i.e. arraysize-1). Let us consider the day array defined as: int day [5];
▪ Thus, from this declaration we can understand, day[0] is the first element and day[4] is the
last element.
▪ Following the above examples where day has 5 elements and each element is of type int,
the name, which we can use to refer to each element, is the following one:
▪ For example, to store the value 75 in the third element of the array variable day a suitable
sentence would be:
▪ And, for example, to pass the value of the third element of the array variable day to the
variable myNumber , we could write:
myNumbe = day[2];
Therefore, for all the effects, the expression day[2] is like any variable of type int with the same
properties. Thus an array declaration enables us to create a lot of variables of the same type with
a single declaration and we can use an index to identify individual elements.
In C++ it is perfectly valid to exceed the valid range of indices for an Array, which can cause
certain detectable problems, since they do not cause compilation errors but they can cause
unexpected results or serious errors during execution. The reason why this is allowed will be
seen ahead when we begin to use pointers.
Note: At this point it is important to be able to clearly distinguish between the two uses the
square brackets [ ] have for arrays.
▪ The other is to specify indices for a specific array element when accessing the elements of
the array
We must take care of not confusing these two possible uses of brackets [ ] with arrays: For
example:
Arrays Example Program which display the sum of the numbers in the array
#include <iostream.h>
int day [ ] = {16, 2, 77, 40, 12071};
int n, result=0;
void main () {
for ( n=0 ; n<5 ; n++ ) {
result += day[n]; }
cout << result;
getch();
}
Copying Arrays
Only individual elements can be assigned to using the index operator, e.g., x[1] = y[2];
But to make all elements in 'x' the same as those in 'y' (equivalent to assignment), a loop has to
be used.
// Loop to do copying, one element at a time
for (int i = 0 ; i < SIZE; i++)
x[i] = y[i];
This code will copy the elements of array y into x, overwriting the original contents of x. A loop
like this has to be written whenever an array assignment is needed.
Notice the use of a constant to store the array size. This avoids the literal constant '10' appearing
a number of times in the code. If the code need to be edited to use different sized arrays, only the
constant value is need to be changed. If the constant is not used, all the '10's would have to be
changed individually - it is easy to miss one out.
Arrays can have any number of dimensions, although most of the arrays that you create will
likely be of one or two dimensions. A chess board is a good example of a two-dimensional array.
One dimension represents the eight rows, the other dimension represents the eight columns.
This array consists of three rows and five columns. To reserve storage for this array, both the
number of rows and columns must be included in the array’s declaration.
So the general syntax to specify the type of the elements and the number of elements required by
two dimensional array use a declaration of the form:
For example the above matrix which represents a bi-dimensional array of 3 per 5 values of type
int would be declared as follow:
int matrix[3][5];
Multidimensional arrays are not limited to two indices (two dimensions). They can contain so
many indices as needed, although it is rare to have to represent more than 3 dimensions. Just
consider the amount of memory that an array with many indices may need.
Here assigns a char for each second contained in century variable, that allows you to store more
than 3 billion chars! What would consume about 3000 megabytes of RAM memory if we could
declare it?
To initialize multidimensional arrays, you must assign the list of values to array elements in
order, with last array subscript changing while the first subscript holds steady. Therefore, if the
program has an array int theArray[5][3], the first three elements go int theArray[0]; the next
three into theArray[1]; and so forth. Thus the program initializes this array by writing
int theArray[5][3] ={ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15};
But for the sake of clarity, additionally, braces can be used to separate rows and the program
could group the initializations with braces, as shown below.
int theArray[5][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9},
{10, 11, 12}, {13, 14,15} };
The compiler ignores the inner braces, which clarify how the numbers are distributed. Generally,
each value should be separated by comma, regardless of whither inner braces are include. The
entire initialization must set must appear within braces, and it must end with a semicolon.
If a one-dimensional array is initialized, the size can be omitted as it can be found from the
number of initializing elements:
In C++ declaration of multidimensional array must have bounds for all dimensions except the
first. So that the above declaration must be written as follow:
To access individual elements or locate each element in a two-dimensional array, we use its
position in the array. For example, the way to reference the second element vertically and fourth
horizontally of matrix array the following expression would be used:
matrix[1][3]
int sumRow0 = matrix [0][0] + matrix [0][1] + matrix [0][2] + matrix [0][3];
The last statement causes the values of the four elements in row 0 to be added and the
sum to be stored in the scalar variable sumRow0.
In the first statement, a single value is read and stored in the variable temp[0]. The
second statement causes three values to be read and stored in the variables temp[1],
temp[2], and temp[3]. Finally, the last cin statement is used to read values into the
variables temp[4] and volts[6].
Alternatively, for loop can be used to cycle through the array for interactive data input. For
example, the following code prompts the user for five temperatures:
During output, an array element can be displayed by using a cout statement, or complete sections
of the array can be displayed by including a cout statement in a for loop. Examples of all
methods are shown below:
The first statement displays the value of the subscripted variable volts[6]. The second statement
displays the values of subscript i and of temp[i]. Before this statement can be executed, i must
have an assigned value. Finally, the last example includes a cout statement in a for loop that
displays both the value of the index and the value of elements 5 to 20.
int a2[SIZE] = {21, 22, 23, 24, 25}; // All elements initialized
for (int i = 0; i < SIZE; ++i)
cout << a2[i] << " ";
cout << endl; // 21 22 23 24 25
int a3[] = {31, 32, 33, 34, 35}; // Size deduced from init values
int a3Size = sizeof(a3)/sizeof(int);
cout << "Size is " << a3Size << endl; // 5
for (int i = 0; i < a3Size; ++i)
cout << a3[i] << " ";
cout << endl; // 31 32 33 34 35
#define MAX_ROWS 10
#define MAX_COLS 10
int main()
{
int mat1[MAX_ROWS][MAX_COLS];
int mat2[MAX_ROWS][MAX_COLS];
int res_mat[MAX_ROWS][MAX_COLS];
int i,j, rows, cols;
cout<<"Enter 1st Matrix: \n "Enter [Link] rows: ";
cin>>rows;
cout<<"Enter no. of cols: ";
cin>>cols;
for(i=0;i<rows;i++)
{
for(j=0;j<cols;j++)
{
//user input element of row x col
cout<<"Enter value for ROW "<<i<<" , "<<"COL "<<j<<" : ";
cin>>mat1[i][j];
}
}
for(i=0;i<rows;i++)
{
for(j=0;j<cols;j++)
{
//user input element of row x col
cout<<"\nEnter value for ROW"<<i<<","<<"COL"<<j<<":";
cin>>mat2[i][j];
}
}
return 0;
}
4.3 Strings
In all programs and concepts we have seen so far, we have used only numerical variables, used
to express numbers exclusively. But in addition to numerical variables there also exist strings of
characters that allow us to represent successive characters, like words, sentences, names, texts,
etc. Until now we have only used them as constants, but we have never considered variables able
to contain them.
In C++ there is no specific elementary variable type to store string of characters. In order to
fulfill this feature we can use arrays of type char, which are successions of char elements.
Remember that this data type (char) is the one used to store a single character, for that reason
arrays of them are generally used to make strings of single characters.
For example, the following array (or string of characters) can store a string up to 20 characters
long. You may imagine it thus:
This maximum size of 20 characters is not required to be always fully used. For example, name
could store at some moment in a program either the string of characters "Hello" or the string
"studying C++”. Therefore, since the array of characters can store shorter strings than its total
length, there has been reached a convention to end the valid content of a string with a null
character, whose constant can be written as '\0’. The last character '\0’ is called the null-
terminating character. For this reason, a string is said to be null-terminated.
We could represent name (an array of 20 elements of type char) storing the strings of characters
"Hello" and "Studying C++" in the following way:
H e l l o \o
S t u d y i n g C + + \o
Notice how after the valid content it is included a null character ('\0') in order to indicate the end
of string. The empty cells (elements) represent indeterminate values.
In this case we would have declared one-dimensional string of characters (array) of 6 elements of
type char initialized with the characters that compose Hello plus a null character '\0'. Also we
declared a two-dimensional string of characters of 2 x 6.
Nevertheless, string of characters has an additional way to initialize its values using constant
strings (string literals) which are specified enclosed between double quotes ( “ “ ). For example:
"the result is:” ------- is a string literal that we have probably used in some occasion.
Unlike single quotes ( ' ) which allow to specify single character constants, double quotes
( " ) are constants that specify a succession of characters. These strings enclosed between
double quotes have always a null character ( '\0' ) automatically appended at the end.
Therefore we could initialize the string of characters for example called mystring with values by
any of these two ways:
char mystring [] = { 'H', 'e', 'l', 'l', 'o', '\0' };
char mystring [] = "Hello"; // also {“Hello”} is valid
char mystring [][6] = {“TESTS”, “FINAL”}
In the first two cases the Array or string of characters mystring is declared with a size of 6
characters (elements of type char ): the 5 characters that compose Hello plus a final null
character ( '\0' ) which specifies the end of the string and that, in the second case, when using
double quotes ( " ) it is automatically appended. In the last the Array is declared as 2x6 two-
dimensional and assigned initial values the same as one-dimensional.
Note that before going further, you should note that the assignation of multiple constants like
double-quoted constants ( " ) to arrays are only valid when initializing the array, that is, at the
moment when declared.
The following expressions within a code are not valid for arrays:
char mystring[6];
mystring="Hello"; // not allowed
mystring[] = "Hello"; //illegal
mystring = { 'H', 'e', 'l', 'l', 'o', '\0' }; // neither would be valid
mystring=”Hello”;
This is allowed only during initialization. Therefore, since the lvalue of an assignation
can only be an element of an array and not the entire array, what would be valid is to
assign a string of characters to an array of char using a loop statements or method like
the following:
mystring[0] = 'H';
mystring[1] = 'e';
mystring[2] = 'l';
mystring[3] = 'l';
mystring[4] = 'o';
mystring[5] = '\0';
#include <iostream.h>
void main()
{
char name[10], dest[10];
cout<< “\n enter your name : ”;
cin>>name;
int c = 0;
while(source[c] != ‘\0’) {
dest[c] = source[c];
c++;
}
dest[c] = ‘\0’;
cout<< “\n your name after copying : ”<<dest;
}
Another frequently used method to assign values to an array is by using directly the input
stream (cin). In this case the value of the string is assigned by the user during program
execution. When cin is used with strings of characters it is usually used with its getline
method, which can be called following this prototype:
[Link] ( char buffer [], int length , char delimiter = ' \n');
where buffer is the address where to store the input (like an array, for example), length is
the maximum length of the buffer (the size of the array) and delimiter is the character
used to determine the end of the user input, which by default - if we do not include that
parameter - will be the newline character ('\n'). The following example repeats whatever
you type on your keyboard. It is quite simple but serves as example on how you can use
[Link] with strings:
return 0;
}
Notice how in both calls to [Link] we used the same string identifier ( mybuffer ). What the
program does in the second call is simply step on the previous content of buffer by the new one
that is introduced.
But this would work, but this method has the following limitations that [Link] has not:
▪ It can only receive single words (no complete sentences) since this method uses as
delimiter any occurrence of a blank character, including spaces, tabulators, newlines and
carriage returns.
▪ It is not allowed to specify a size for the buffer. This makes your program unstable in
case that the user input is longer than the array that will host it.
For these reasons it is recommendable that whenever you require strings of characters coming
from cin you use [Link] instead of cin >> .
All of these functions admit one parameter and return a value of the requested type ( int , long or
float). These functions combined with getline method of cin are a more reliable way to get the
user input when requesting a number than the classic cin>> method:
// cin and ato* functions cout << "Enter quantity: ";
#include <iostream.h> [Link] (mybuffer,100);
#include <stdlib.h> quantity = atoi (mybuffer);
int main() { cout<<"\nafter conversion :\n";
char mybuffer[100]; cout<<"\nprice is : "<<price;
float price; int quantity; cout<<"\nquantity is : "<<quantity;
cout << "Enter price: "; cout << "\nTotal price: " << price*quantity;
[Link] (mybuffer,100); return 0;
price = atof (mybuffer); }
The strings that you can use in your program may be defined in various libraries depending on
your compiler but most of the time, they are available once you include the string library that is
defined in the std namespace. For example, the strings that are part of the (C++) Standard
Template Library (STL) are defined in the string class of the std namespace. Based on this, most
compilers make all these functions accessible once you include the string library (string.h) which
defines many functions to perform some manipulation operations and the std namespace in your
program.
The functions used for this purpose are numerous and here you have a brief with the most usual
what they are used for.
a) String length
In many operations, you will want to know how many characters a string consists of. To find the
number of characters of a string, use the strlen() function.
The strlen() function takes one argument, which is the string you are considering and returns the
number of characters of the string (length of a string) not including the null character (\0).
Here is an example:
#include <iostream>
using namespace std;
int main(){
char *School = "Manchester United";
int Length = strlen(School);
cout << "The length of \"" << School << "\" is " << Length << " characters\n\n";
return 0;
}
If you have two strings, to append one to another, use the strcat() or strncat() function. These
two functions append source string at the end of destination string.
The strcat() function appends the whole content of the source string to the destination string
while strncat() function will append only specified part of the source string to the destination. Its
syntax is:
strcat (char* dest , const char* src ); //appending the whole content of the source
strncat (char* dest , const char* src, int size ); //appending part of the source
Here is an example:
#include <iostream>
using namespace std;
int main()
{
char *Make = "Ford ";
char *Model = "Explorer";
cout << "Originally, Make = " <<Make;
strcat(Make, Model);
cout << "\n\nAfter concatenating, Make = " << Make << endl;
c) String Copy:
The strcpy() and strncpy() function is used to copy one string into another string. In English, it
is used to replace one string with another. Overwrite the content of the destination string by the
source strings. Both return destination string.
strcpy (char* dest , const char* src ); // Copy the whole content of the source
strncpy (char* dest , const char* src, int size ); //appending part of the source
The first argument of these two functions is the string that you are trying to replace while the
second argument is the new string that you want to replace. The third argument of the strncpy()
function specify the number of characters that the compiler would copy from the source string.
There are two main scenarios suitable for the strcpy() function: To replace an existing string or
to initialize a string.
char CarName[20];
strcpy(CarName, "Toyota Camry");
cout << "Car Name: " << CarName;
If you have two strings and copy one into another, both strings would hold the same value.
Here is an example:
#include <iostream>
using namespace std;
int main(){
char carName1[] = "Ford Escort";
char carName2[] = "Toyota 4-Runner";
cout << "The String Copy Operation";
cout << "\nFirst Car: " << carName1;
cout << "\nSecond Car: " << carName2;
strcpy(carName2, carName1);
cout << "\n\nAfter using strcpy()...";
cout << "\nFirst Car: " << carName1;
cout << "\nSecond Car: " << carName2 << endl;
strncpy(CarName2, CarName1, 8);
cout << "\n\nAfter using strncpy() for 8 characters";
cout << "\nFirst Car: " << CarName1;
cout << "\nSecond Car: " << CarName2 << endl;
return 0;
}
d) String Compare:
Various routines are available for strings comparison. The C++ string library is equipped with
functions that perform the comparisons by characters. Alternatively, some compilers like
Borland C++ Buider ships with additional multiple functions to perform these comparisons on
null-terminated strings.
The strcmp(), strncmp(),stricmp(), strnicmp() functions are used to compare two strings
string1 and string2.
▪ The strcmp() and stricmp() function compare the whole content of the two strings with
and without regard to their case respectively.
▪ Where the strncmp() and strnicmp() function compare two strings using a specified
number of characters (only part of the two strings) with and without regard to their case
respectively.
int main(){
char *FirstName1 = "Andy";
char *FirstName2 = "Charles";
char *LastName1 = "Stanley";
char *LastName2 = "Stanley";
int Value1 = strcmp(FirstName1, FirstName2);
int Value2 = strcmp(FirstName2, FirstName1);
int Value3 = strcmp(LastName1, LastName2);
cout << "The result of comparing " << FirstName1
<< " and " << FirstName2 << " is\t" << Value1 << endl;
cout << "The result of comparing " << FirstName2
<< " and " << FirstName1 << " is\t" << Value2 << endl;
cout << "The result of comparing " << LastName1
<< " and " << LastName2 << " is\t" << Value3;
return 0;
}
o Examines a string starting at the end (right side) of the string and looks for the
first occurrence of a certain character.
o The function will scan the string S from right to left. Once it finds the first
appearance of the character c in the string, it would return a new string whose
value starts at that first occurrence. If the character c does not appear in the string
S, then the function would return NULL.
▪ strstr() function
o Looks for the first occurrence of a sub-string in another string and returns a new
string as the remaining string.
o The first argument of the function is the main string that would be examined.
o The function would look for the second argument, the Sub string appearance in
the main string. If the Sub string is part of the Main string, then the function
would return a string whose value starts at the first appearance of Sub and make it
a new string. If Sub is not part of the Main string, the function would return a
NULL value
o Its syntax is: strlwr(const char *S); and strupr(const char *S);
o This means any symbol that is not a readable character would not be converted.
2. Forgetting to declare the array. This error results in a compiler error message such as
“invalid indirection” each time a subscripted variable is encountered in a program.
3. Using a subscript that references a non-existent array element (element outside the array
bounds), such as declaring the array as size 20 and using a subscript value of 25. Most C++
compilers don’t detect this error. However, it results in a runtime error that causes a
program crash or results in a value with no relation to the intended element being accessed
from memory. In either case, this error is usually difficult to locate. The only solution is to
make sure, by specific programming statements or by careful coding, that each subscript
references a valid array element. Generally, when looping through an array, the index
should never go below 0 and should always be
less than the total number of array elements (one less than the size of the array). Make
sure that the loop-termination condition prevents accessing elements outside this range.
4. Not using a large enough counter value in a for loop counter to cycle through all the
array elements. This error usually occurs when an array is initially specified as size n and
there’s a for loop in the program of the form for(i = 0; i < n; i++). The array size is then
expanded, but the programmer forgets to change the interior for loop parameters. Declaring
an array’s size with a named constant and consistently using the named constant throughout
the function in place of the variable n eliminates this problem.
5. Forgetting to initialize the array. Although many compilers set all elements of integer
and real value arrays to 0 automatically, and all elements of character arrays to blanks, it’s
up to the programmer to make sure each array is initialized correctly before processing of
array elements begins.