|
|||||
CS201
Introduction to Programming
Lecture
Handout
Introduction
to Programming
Lecture
No. 12
Reading
Material
Deitel
& Deitel - C++ How to
Program
chapter
4
4.4,
4.5, 4.6, 4.8,
4.9
Summary
·
Character
Arrays
·
Initialization
Of Character Arrays
·
Arrays
Comparison
·
Sorting
Arrays
·
Searching
arrays
·
Functions
And arrays
·
Example
1
·
Multidimensional
Arrays
·
Example
2
·
Tips
Page
116
CS201
Introduction to Programming
Character
Arrays
While
dealing with words and
sentences, we actually make
use of character arrays. Up
to
now, we
were dealing with integer arrays
and storing integer values. Here we
have to see
what
needs to be done for storing a
name. A simple variable can't be
used to store a name
(which is
a string of characters) as a variable stores
only a single character. We need
a
character
array to grab a name. A
character array is not
different from an integer
array.
To
declare a character array, we
will write as under:
char
name [100] ;
In this
way, we declare a string or character
array. There are some
special properties of
character
arrays. Suppose that we
declare an array of 100
characters. We enter a
name
with
15-20 characters. These
characters in the array occupy
15-20 character spaces.
Now
we have
to see what has happened to
the remaining character spaces in
the array.
Similarly,
a question arises, will an
array displayed on the screen,
show 100 characters
with a
name in 15-20 spaces and
blanks for the remaining. Here C
has a character
handling
capability i.e. the notion of
strings. When we place a string in a
character array,
the
computer keeps a mark to identify
that the array was of this
size while the string
stored in
it is of the other size. That marker is a
special character, called null
character.
The
ASCII code of null
character
is all zeros. In C language, we
represent the null
character
as "\0". C uses
this character to terminate a string. All
strings are terminated
with
the null
character.
Now, we
will see how the
character arrays are stored
in memory. While declaring a
character
array, we normally declare
its size larger than the
required one. By using
a
character
array, it becomes easy to
store a string. We declare a character
array as under.
char
name [100] ;
Now we
can store a string in this
array simply by using the
cin
statement
in the following
way.
cin
>> name ;
In the
above statement, there is an
array on right hand side of
cin
instead
of a simple
variable.
The cin
stream
has a built-in intelligence
that allows the compiler
(program) to
read
whole string at a time rather
than a single character as in case of
simple variable of
type
char. The
compiler determines that the
name
is
not a simple variable. Rather it is
a
string or
character array. Thus cin
reads a
character array until the
user presses the
enter
key. When
enter key is pressed, cin
takes
the whole input (i.e. string)
and stores it into
the
array
name. The C
language, by itself, attaches a
null
character
at the end of the string.
In
this
way, the total number of
spaces occupied in the array
by the string is the number
of
characters
entered by the user plus 1
(this one character is the
null
character
inserted at
the
end of the string by C automatically).
The null
character
is used to determine where
the
populated area of the array
has ended. If we put a string
larger than the size of
the
array in
absence of a null
character
in it, then it is not
possible to determine where a
string is
terminated in the memory.
This can cause severe
logical error. So, one
should be
careful
while declaring a character array.
The size of array should be
one more than the
number of
characters you want to
store.
Page
117
CS201
Introduction to Programming
Initialization
Of Character Arrays
Now we
will look into integer
array initialization process
that can provide a list of
integer
values
separated by commas and
enclosed in curly braces.
Following is the
statement
through
which we initialize an integer
array.
int
age [5] = {12, 13,
16, 13, 14};
If we
don't mention the size of
the array and assign a
list of values to the array,
the
compiler
itself generates an array of
the size according the
number of values in the
list.
Thus,
the statement int age
[] = {14, 15, 13}; will
allocate a memory to the
array of size
3
integers. These things also apply to
character arrays as well. We
can initialize an
array
by giving
a list of characters of the string,
the way we assign integer
values in integer
array. We
write the characters of this
string one by one in single quotes
(as we write a
single
character in single quotes), separated by
commas and enclosed in curly
braces. So
the
initialization line will be as
under
char
name [100] = {`i', `m',
`r', `a', `n'};
we can
also write the string on
right hand side in double
quotes as
char
name [100] = "imran"
;
The
easy way to initialize a
character array is to assign it a string
in double quotes. We
can
skip the size of the array
in the square brackets. We
know that the compiler
allocates
the
memory at the declaration
time, which is used during
the execution of the program. In
this
case, the compiler will
allocate the memory to the
array of size equal to the
number
of
characters in the provided string plus 1 (1 is
for the null
character
that is inserted at
the
end of
string). Thus it is a better to
initialize an array in the
following way.
char
name [] = "Hello World"
;
In the
above statement, a memory of 12
characters will be allocated to
the array name
as
there
are 11 characters in double
quotes (space character
after Hello is also
considered
and
counted) while the twelfth
is the null character
inserted automatically at the
end of
the
string.
We can do
many interesting things with arrays.
Let's start with reading a
string (for
example
your name) from keyboard
and displaying it on the
screen. For this purpose,
we
can
write the following code
segment
char
name [100] ;
cout
<< "Please enter your
name : " ;
cin
>> name ;
In the
cin
statement,
when the user presses
the enter key the
previous characters
entered,
that is a
string will be stored in the
array name. Now we
have a string in the array
name.
We can
display it with cout
statement.
To display the string, we have stored in
name.
We
can
write as under
cout
<< name ;
This
will display the string. Alternatively,
we can use a loop to display
the string. As the
string is an
array of characters, we can
display these characters one
by one in a 'for
loop'.
We can
write a loop as under
for ( i =
0 ; i < 100 ; i ++ )
cout
<< name [ i ] ;
Page
118
CS201
Introduction to Programming
Thus
this loop will display the
characters in the array one
by one in each iteration. First,
it
will
display the character at name
[0], followed by that at
name [1] and so on. Here
we
know
that the string in the array
is terminated by a null
character
and after this null
character,
there are random values
that may not be characters
(some garbage data) in
the
array. We
don't want to display the
garbage data that is in the
array after this null
character.
While using the statement
cout
<< name; the
cout
stream
takes the characters
of the
array name
up to
the null
character
and the remaining part of
the array is ignored.
When we
are displaying the
characters one by one, it is
necessary to stop the
displaying
process
at the end of a string (which
means when null character is
reached). For this
purpose,
we may put a condition in
the loop to terminate the
loop when the null
character
is
reached. So we can use if
statement
in the loop to check the
null
character.
We can
modify
the above for
loop so
that it could terminate when null
character
reaches in the
array.
for ( i =
0 ; i < 100 ; i ++ )
{ if
(name [ i ] == `\0')
break
;
cout
<< name [ i ] ;
}
Here a
while loop can also be
used instead of a 'for
loop'.
Arrays
Comparison
We can
use this character-by-character
manipulation of the array to
compare the
characters
of two arrays of the same
size. Two arrays can be
equal only when first of
all
their
sizes are equal. Afterwards,
we compare the values of the
two arrays with one to
one
correspondence.
If all the values in the
first array are equal to
the corresponding values
of
the
second array, then both
the arrays will be equal.
Suppose, we have two integer
arrays
num1
and
num2
of
size 100 each and want to
find whether both arrays are
equal. For this
purpose,
we will declare a flag and
set it to zero, that means
that arrays are not
equal this
time.
For this flag, we write
int
equals = 0 ;
To
compare the values of the
arrays one by one, we write
a for loop i.e. for
( i = 0 ; i <
100
; i ++ ). In the body
of the for
loop,
we use an if
statement
to check the values. In
the
if
statement,
we use the not equal
operator ( != ). The advantage of
using not-equal
operator
is that in case if the
values at some position are
not equal to each other,
then we
need
not to compare the remaining
values. We terminate the loop
here and say that
the
arrays
are not equal. If the values
at a position are equal, we continue to
compare the next
values.
If all the values are found
same, we set the flag
equal
to 1
and display the
results
that
both the arrays are
identical. The same
criterion applies to character
arrays. The
comparison
of character arrays is very
common. While finding a name
in a database, we
will
compare two character arrays
(strings). The comparison of two
strings is so common
in
programming that C has a
function in its library to manipulate
it. We will discuss
it
later in
the lecture on string handling. For
the time being, we will
write our own
function
to find
the equality of two
strings.
Page
119
CS201
Introduction to Programming
Following
is the code of a program, which
takes two arrays of 5
numbers from the
user
and
compares them for equality.
// This
program takes two arrays of
5 integers from user
//displays them
and after comparing them displays the
result
# include
<iostream.h>
main (
)
{
int num1
[5], num2 [5], i, equals = 0
;
// input
of 5 integers of first
array
cout
<< "Please enter five
integers for the first
array" << endl ;
for ( i =
0 ; i < 5 ; i ++)
cin
>> num1 [ i ] ;
// input
of 5 integers of 2nd
array
cout
<< "Please enter five
integers for the second
array" << endl ;
for ( i =
0 ; i < 5 ; i ++)
cin
>> num2 [ i ] ;
//display
the elements of two
arrays
cout
<< "\n The values in
the first array are : "
;
for ( i =
0 ; i < 5 ; i ++)
cout
<< "\t" << num1 [ i ] ;
cout
<< "\n The values in
the second array are : "
;
for ( i =
0 ; i < 5 ; i ++)
cout
<< "\t" << num2 [ i ];
//
compare the two
arrays
for ( i =
0 ; i < 5 ; i ++ )
{
if ( num1 [ i ] !=
num2 [ i ] )
{
cout
<< "\n The arrays are
not equal " ;
equals =
0 ; //set the flag to
false
break
;
}
equals =
1;
//set
flag to true
}
if
(equals)
cout
<< "\n Both arrays are
equal" ;
}
Page
120
CS201
Introduction to Programming
Similarly,
we can write a program that
compares two strings
(character arrays) of
the
same
size. While comparing strings, a point to
remember is that C language is
case-
sensitive.
In C-language `A' is not equal to
`a'. Similarly, the string "AZMAT" is
not
equal to
the string "azmat" or
"Azmat".
A sample
out-put of the program is given
below.
Please
enter five integers for
the first array
1
3
5
7
9
Please
enter five integers for
the second array
1
3
4
5
6
The
values in the first array
are : 1
3
5
7
9
The
values in the first array
are : 1
3
4
5
6
The
arrays are not
equal
Sorting
We want
to sort an array in ascending
order. There may be many
ways to sort an
array.
Suppose
we have an array of 100
numbers. To sort it in ascending
order, we start from
the
first number (number at zero
index ) and find the
smallest number in the
array.
Suppose,
we find it at sixteenth position (index
15). If we assign this
number directly to
the
first position, the number
already placed at first
position will be over
written. But we
want
that number should exist in
the array. For this
purpose, we use a technique
called
swapping. In this
technique, we swap two values
with each other. For
this purpose, we
declare a
variable and assign the
value of first variable to this variable
before assigning
the
second number (i.e. to be swapped) to
the first variable. Then we
assign the value of
second
variable to the first variable.
Afterwards, the number,
which we have stored in
a
separate
third variable (that is actually
the value of first variable) is
assigned to the
second
variable. In arrays, the single element
of an array is treated as a single variable
so
we can
swap two numbers of an array
with each other with
this technique.
In our
sorting process, we declare a variable x
and
assign it the number at the
first
position.
Then assign the number at
sixteenth position to the first position.
After this, we
Page
121
CS201
Introduction to Programming
assign
the number in x
(that is
actually the number that was
at first position in the
array)
to the
sixteenth position. In programming, this can be
done in the following
fashion.
x = num
[0] ;
// assign
number at first position to
x
num
[0] = num [15] ;
// assign
number at sixteenth position to
first
position
num
[15] = x ;
// assign
number in x to sixteenth position
We have
the smallest number at the
first position. Now we start
reading the array
from
second
position (index 1) and find
the smallest number. We swap
this number with
the
second
position before starting from
index 2. The same process
can be repeated later.
We
continue
this process of finding smallest
number and swapping it till we
reach the last
number of
the array. The sorting of
array in this way is a brute
force and a very
tedious
work.
The computer will do fine
with small arrays. The
large arrays may slow it
down.
Searching
The
same applies to the search
algorithms. For finding out a particular
number in an
array, we
can use technique of linear
search. In this technique,
there may be as many
comparisons
as numbers in the array. We
make comparison of the number to be
found
with
each number in the array
and find it out if it
matches any number in the
array.
However,
we can perform even better
by using a binary search
algorithm.
Binary
Search Algorithm
In binary
search algorithm, the
`divide and conquer' strategy is
applied. This
algorithm
applies
only to sorted arrays in
ascending or descending order.
Suppose that we want
to
search a
number in an ascending array.
For this purpose, we divide
the array into
two
parts
(say left and right). We
compare the target value
with the value at middle
location
of the
array. If it does not match, we
see whether it is greater or less
than the middle
value. If
it is greater than the
middle value, we discard the
left part of the array.
Being an
ascending
array, the left part
contains the smaller numbers
than the middle. Our
target
number is
greater than the middle
number. Therefore, it will be in
the right part of
the
array.
Now we have a sub-array,
which is the half of the
actual array (right side
portion of
main
array). Now we divide this
array into two parts
and check the target
value. If target
value is
not found, we discard a portion of
the array according to the
result whether target
value is
greater or less than the
middle value. In each iteration of
testing the target
value,
we get an
array that is half of the
previous array. Thus, we
find the target
value.
The
binary search is more efficient than
the linear search. In binary
search, each iteration
reduces
the search by a factor of two
(as we reduce to half array
in each iteration). For
example, if we
have an array of 1000
elements, the linear search
could require 1000
iterations.
The binary search would not
require more than 10. If an
array has elements 2n,
Page
122
CS201
Introduction to Programming
then
the maximum number of iterations
required by binary search will be
n. If
there are
1000
elements (i.e. 210,
actually it will 1024), the
number of iterations would not be
more
than
10.
Functions
and Arrays
In C
language, the default mechanism of
calling a function is `call by
value'. When we
call a
function, say fn, and
pass it a parameter x
(argument
value) by writing statement
fn(x),
the calling mechanism puts
the value of x
at
some other place. Then calls
the
function
and gives this value to
it. This means a copy of the
value is sent to the
program.
The
original x
remains
untouched and unchanged at
its place. The function
uses the
passed
value (that has placed at
some other place) and
manipulates it in its own
way.
When the
control goes back to the
calling program, the value of
original x
is
found intact.
This is
the call by value
mechanism.
Now
let's see what happens
when we pass an array to a
function. To pass an array to
a
function,
we will tell the function
two things about the array
i.e. the name of the array
and
the size.
The size of the array is
necessary to pass to the
function. As the array is
declared
in the
calling function, it is visible
there. The calling function
knows its size but
the
function
being called does not know
the size of the array. So it is
necessary to pass the
size of
the array along with
its name. Suppose we have
declared a character array in
the
program
by the following
statement:
char
name[50] ;
We have a
function (say reverse,
you
should write it as an exercise)
that reverses the
array
elements and displays them.
Firstly,
we need to write the prototype of
the function reverse. We say
that this function
returns
nothing so we use the keyword
void
in
its return type. Secondly, we
have to write
the
parameters this function
will get. We write these
parameters with their
type.
Now
the prototype of this function
will be written as
void
reverse ( char [], int )
;
In the
above statement, the
brackets [] are necessary.
These brackets indicate that an
array
of type
char will be passed to the
function. If we skip these
brackets and simply
write
char,
it
will mean that a single
character will be passed to
the function. In addition,
the
second
parameter i.e. of type int, is of
array's size. Note that in
the prototype of the
function
we have not written the
names of the parameters. It is
not necessary to write
the
names of
the parameters in function prototype.
However, if we write the
names, it is not
an error.
The compiler will simply
ignore these names.
Now we
will define the function
reverse. In the function's definition, we
will use the
array
and variable names. These
names are local to this
function so we can give
these
variables
a name other than the
one used in declaration in
the calling program. We
write
this as
below.
void
reverse ( char characters
[], int arraySize )
{
// The
body of the function.
}
Page
123
CS201
Introduction to Programming
Here, the
body of the function is left
over for an exercise.
Let's
say we have a character
array name
and a
name `adnan' is stored in
it. We call the
reverse
function by passing the
array name
to
it. For this we write
reverse
( name, 100 );
In this
function call, we are
sending the name of the
array to the function i.e.
name
and
the size
of the array that is 100.
When this call of the
function is executed the
control
goes to
the function reverse. The
statements in this function
are executed which
reverses
the
array and displays it. After
this, the control comes back
to the main function to
the
statement
next to the function call
statement. The return type
of the function is void
so
it
does
not return any thing.
Now in the main, we write
the statement cout
<< name;
What
will be
displayed by this statement? Whether it
will be the original name
`adnan' or
something
else. It will display the
reversed array. In this
instance, we see that
whatever
the
function reverse
did to
the array ( that was passed
to it) is appearing in the
calling
function.
It means that the original
array in the calling program
has been changed.
Here
we change
(reverse) the order of the
characters of array in the
function and find that
the
characters
of the array in the calling
function are reversed. This
means that the called
function
has not a copy of the array
but has the original
array itself. Whereas in
case of
simple
variables, a called function uses a copy
of variables passed to it in a 'call
by value'
mechanism,
which is by default in case of simple
variables. In arrays, the by
default
mechanism is
`call
by reference'. While
passing arrays to a function, we
don't need to
use &
and * operators, as we use
for variables in call
by reference mechanism.
Thus if
we pass an array to a function,
the array itself is passed
to the function. This
is
due to
the fact that when we
declare an array, the name
of the array has the
address of the
memory
location from where the
array starts. In other
words, it is the address of
the first
element
of the array. Thus the
name of the array actually
represents the address of
the
first
location of the array.
Passing the name of array to
a function means the passing
of
the
address of the array which
is exactly the same as we do in
call
by reference.
So
whatever
the function does to the
array, it is happening in the
same memory locations
where the
array originally resides. In
this way, any modifications
that the function does
to
the
contents of the array are
taking place in the contents
of the original array too.
This
means
that any change to the
array made by the function
will be reflected in the
calling
program.
Thus an important point to
remember is that whenever we
pass simple variables
to a
function, the default mechanism is call
by value and
whenever we pass an array to
a
function,
the default mechanism is call
by reference. We know
that when we talk about
a
single
element of an array like x
[3] (which means the
fourth element of the array
x), it is
treated
as simple variable. So if we pass a single
element of an array to a function
(let's
say
like fn ( x [3] ); ), it is just
like a simple variable whose copy is
passed to the
function
(as it is
a call by value). The original
value of the element in the
array remains the
same.
So be careful
while passing arrays and a
single element of array to functions.
This can be
well
understood from the
following examples.
Example
1
Suppose
we declare an array in the
main program and pass this
array to a function,
which
populates
it with values. After the
function call, we display the
elements of the array
and
Page
124
CS201
Introduction to Programming
see
that it contains the values
that were given in the function
call. This demonstrates
that
the
called function changes the
original array passed to
it.
Following
is the code of the
program.
//This
program demonstrates that
when an array is passed to a
function then it is a call
by
//reference
and the changes made by
the function effects the
original array
# include
<iostream.h>
void
getvalues( int [], int)
;
main (
)
{
int
num [10], i ;
getvalues
( num, 10) ; //function
call, passing array
num
//display
the values of the
array
cout
<< "\n The array is
populated with values \n"
;
for ( i =
0 ; i < 10 ; i ++)
cout
<< " num[" << i << "] = " <<
num[i]<< endl ;
}
void
getvalues ( int num[], int
arraysize)
{
int i
;
for ( i =
0 ; i < arraysize ; i ++)
num[i] =
i ;
}
Here in
the function getvalues, we can
get the values of the
array from user by using
the
cin
statement.
Following
is the output of the execution of
the program.
The
array is populated with
values
num[0] =
0
num[1] =
1
num[2] =
2
num[3] =
3
num[4] =
4
num[5] =
5
num[6] =
6
num[7] =
7
num[8] =
8
num[9] =
9
Page
125
CS201
Introduction to Programming
Multidimensional
Arrays
There
may be many applications of arrays in
daily life. In mathematics, there
are many
applications of
arrays. Let's talk about
vectors. A vector is a set of values
which have
independent
coordinates. There may be
two-dimensional vector or three-dimensional
vector.
There are dot and
cross products of vectors
besides many other manipulations.
We do all
the manipulations using arrays. We
manipulate the arrays with
loops. Then
there is
a mathematical structure matrix, which is
in rows and columns. These
rows and
columns
are manipulated in two-dimensional
arrays. To work with rows
and columns, C
provides
a structure i.e. a two-dimensional array.
A two dimensional array can
be
declared
by putting two sets of
brackets [] with the name of
array. The first
bracket
represents
the number of rows while
the second one depicts
the number of columns. So
we can
declare an array numbers
of
two rows and three columns
as follows.
int
numbers [2] [3] ;
Using
two-dimensional arrays, we can do
the addition, multiplication and
other
manipulations of
matrices. A value in a two-dimensional
array is accessed by using
the
row
number and column number. To
put values in a two-dimensional
array is different
from
the one-dimensional array. In one-dimensional
array, we use a single 'for
loop'
to
populate
the array while nested
loops are used to populate
the two-dimensional
array.
We can do
addition, multiplication and other
manipulations of two-dimensional arrays.
In
C
language, we can declare
arrays of any number of dimensions (i.e.
1, 2, 3 ... n ). We
declare a
n-dimensional array by putting n pair of
brackets [] after the name
of the array.
So a three-dimensional
array with values of dimensions 3, 5
and 7 respectively, will be
declared
as int num [3] [5]
[7] ;
Example
2
Let's
have a matrix (two-dimensional
array) of two rows and
three columns. We want to
fill it
with values from the
user and to display them in
two rows and three
columns.
Solution
To solve
this problem, we use a two-dimensional
array of two rows and
three columns.
First, we
will declare the array by
writing
int
matrix [2] [3] ;
We
declare different variables in
our program. To put the
values in the array, we use
two
nested
for
loops,
which can be written as
under.
for (
row = 0 ; row < maxrows ;
row ++ )
{
for (
col = 0 ; col < maxcols ;
col ++)
{
cout
<< "Please enter a value
for position [" << row << ",
" << col << "]" ;
cin
>> matrix [row] [col]
;
}
Page
126
CS201
Introduction to Programming
}
The inner
for
loop
totals the elements of the
array one row at a time. It
fills all the
columns of a
row. The outer for
loop increments the row
after each iteration. In the
above
code
segment, the inner loop
executes for each iteration of
the outer loop. Thus, when
the
outer
loop starts with the
value of row
0,
the inner loop is executed
for a number of
iterations
equal to the number of columns i.e. 3 in
our program. Thus the
first row is
completed
for the three columns with
positions [0,0], [0,1] and
[0,2]. Then the outer
loop
increments
the row
variable to 1
and the inner loop is again
executed which
completes
the
second row (i.e. the positions
[1,0], [1,1] and [1,2] ).
All the values of matrix
having
two
rows and three columns are
found.
Similarly,
to display these values one
by one, we again use nested
loops.
Following
is the code of the
program.
//This
program takes values from
user to fill a two-dimensional
array (matrix) having
two
//rows
and three columns. And then
displays these values in row
column format.
# include
<iostream.h>
main (
)
{
int
matrix [2] [3], row,
col, maxrows = 2, maxcols = 3
;
// get
values for the
matrix
for (
row = 0 ; row < maxrows ;
row ++)
{
for
(col = 0 ; col < maxcols ;
col ++)
{
cout
<< "Please enter a value for
position [" << row << ", " <<
col << "] " ;
cin
>> matrix [row] [col]
;
}
}
//
Display the values of
matrix
cout
<< "The values entered
for the matrix are "
<< endl ;
for (
row = 0 ; row < maxrows ;
row ++)
{
for
(col = 0 ; col < maxcols ;
col ++)
{
cout
<< "\t" << matrix [row]
[col] ;
}
cout
<< endl ; //to start a
new line for the
next row
}
}
A sample
output of the program is given
below.
Page
127
CS201
Introduction to Programming
Please
enter a value for position
[0,0]
1
Please
enter a value for position
[0,1]
2
Please
enter a value for position
[0,2]
3
Please
enter a value for position
[1,0]
4
Please
enter a value for position
[1,1]
5
Please
enter a value for position
[1,2]
6
The
values entered for the
matrix are
1
2
3
4
5
6
Tips
· A
character array can be
initialized using a string
literal
· Individual
characters in a string stored in an array
can be accessed
directly
using
array subscript
· Arrays
are passed to functions by
reference
· To
pass an array to a function,
the name of the
array(without any
brackets)
is passed
along with its size
· To
receive an array, the
function's parameter list must specify
that an
array
will be received
· Including
variable names in function prototype is
unnecessary. The
compiler
ignores these names.
Page
128
Table of Contents:
|
|||||