An array is a
collection of variables of the same type that are referenced by a common name.
Specific elements or variables in the array are accessed by means of an index
into the array.
In C all arrays
consist of contiguous memory locations. The lowest address corresponds to the
first element in the array while the largest address corresponds to the last
element in the array.
C supports both
single and multi-dimensional arrays.
Syntax : type var_name[ size ] ;
where type is the
type of each element in the array, var_name is any valid C identifier, and size
is the number of elements in the array which has to be a constant value.
NB : In C all arrays use zero as the index to the first element in
the array.
For Example :-
int array[ 5 ] ;
which we might
illustrate as follows for a 32-bit system where each int requires 4 bytes.
array[0]
|
12
|
locn 1000
|
array[1]
|
-345
|
locn 1004
|
array[2]
|
342
|
locn 1008
|
array[3]
|
-30000
|
locn 1012
|
array[4]
|
23455
|
locn 1016
|
NB : The valid indices for array above
are 0 .. 4, i.e. 0 .. number of elements - 1
For Example :- To
load an array with values 0 .. 99
int x[100] ;
int i ;
for ( i = 0; i
< 100; i++ )
x[i] = i ;
Arrays should be
viewed as just collections of variables so we can treat the individual elements
in the same way as any other variables. For example we can obtain the address
of each one as follows to read values into the array
for
( i = 0; i < 100; i++ ) {
printf(
"Enter element %d", i + 1 ) ;
scanf( "%d\n",
&x[i] ) ;
}
NB : Note the use of the printf
statement here. As arrays are normally viewed as starting with index 1 the user
will feel happier using this so it is good policy to use it in “public”.
To determine to size
of an array at run time the sizeof operator is used. This returns the size in
bytes of its argument. The name of the array is given as the operand
size_of_array =
sizeof ( array_name ) ;
NB : C carries out no boundary checking on array
access so the programmer has to ensure he/she is within the bounds of the array
when accessing it. If the program tries to access an array element outside of
the bounds of the array C will try and accommodate the operation. For example
if a program tries to access element array[5] above which does not exist the
system will give access to the location where element array[5] should be i.e. 5
x 4 bytes from the beginning of the array.
array[0]
|
12
|
locn 1000
|
array[1]
|
-345
|
locn 1004
|
array[2]
|
342
|
locn 1008
|
array[3]
|
-30000
|
locn 1012
|
array[4]
|
23455
|
locn 1016
|
array[5]
|
123
|
locn 1020
|
This piece of memory
does not belong to the array and is likely to be in use by some other variable
in the program. If we are just reading a value from this location the situation
isn’t so drastic our logic just goes haywire. However if we are writing to this
memory location we will be changing values belonging to another section of the
program which can be catastrophic.
Initialising Arrays
Arrays can be
initialised at time of declaration in the following manner.
type array[ size ] = {
value list };
For Example :-
int i[5] = {1,
2, 3, 4, 5 } ;
i[0] = 1, i[1] = 2, etc.
The size
specification in the declaration may be omitted which causes the compiler to
count the number of elements in the value list and allocate appropriate
storage.
For Example :- int i[ ]
= { 1, 2, 3, 4, 5 } ;
In C a string is
defined as a character array which is terminated by a special character, the
null character '\0', as there is no string type as such in C.
Thus the string or
character array must always be defined to be one character longer than is
needed in order to cater for the '\0'.
For Example :- string
to hold 5 characters
char s[6] ;
A string constant is
simply a list of characters within double quotes e.g. "Hello" with
the '\0' character being automatically appended at the end by the compiler.
A string may be
initialised as simply as follows
char s[6] = "Hello" ;
as opposed to
char s[6] = { 'H', 'e', 'l', 'l', 'o', '\0' }
;
Again the size
specification may be omitted allowing the compiler to determine the size
required.
Manipulating Strings
We can print out the
contents of a string using printf() as we have seen already or by using puts().
printf(
"%s", s ) ;
puts( s ) ;
Strings can be read
in using scanf()
scanf(
"%s", s ) ;
where we do not
require the familiar & as the name
of an array without any index or square braces is also the address of the array.
A string can also be
read in using gets()
gets ( s ) ;
There is also a wide
range of string manipulation functions included in the C Standard Library which
are prototyped in <string.h> which
you should familiarise yourself with.
For Example :-
char s1[20] = “String1”,
s2[20] = “String2” ;
int i ;
strcpy( s1, s2 ) ; /* copies s2 into s1. */
i = strcmp( s1,s2 ) ; /*
compares s1 and s2. It returns zero if
s1 same as
s2,-1 if s1 < s2, and +1 if s1 > s2 */
i = strlen( s1 ) ; /*
returns the length of s1 */
strcat ( s1, s2 ) ; /*
Concatenates s2 onto end of s1 */
Multidimensional
arrays of any dimension are possible in C but in practice only two or three
dimensional arrays are workable. The most common multidimensional array is a
two dimensional array for example the computer display, board games, a
mathematical matrix etc.
Syntax : type name [ rows ] [ columns ] ;
For Example :- 2D
array of dimension 2 X 3.
int d[ 2 ] [ 3 ] ;
d[0][0]
|
d[0][1]
|
d[0][2]
|
d[1][0]
|
d[1][1]
|
d[1][2]
|
A two dimensional
array is actually an array of arrays, in the above case an array of two integer
arrays (the rows) each with three elements, and is stored row-wise in memory.
For Example :-
Program to fill in a 2D array with numbers 1 to 6 and to print it out row-wise.
#include
<stdio.h>
void main( )
{
int i, j,
num[2][3] ;
for ( i = 0; i
< 2; i++ )
for ( j =
0; j < 3; j ++ )
num[i][j]
= i * 3 + j + 1 ;
for ( i = 0; i
< 2; i++ )
{
for ( j =
0; j < 3; j ++ )
printf("%d
",num[i][j] ) ;
printf("\n"
);
}
}
For Example :-
Program to tabulate sin(x) from x = 0 to 10 radians in steps of 0.1 radians.
#include
<stdio.h>
#include
<math.h>
void main()
{
int i
;
double x ;
double table[100][2] ;// we will need 100
data points for
// the above range and step size and
// will store both x and f(x)
for ( x = 0.0, i = 0; x < 10.0; x += 0.1,
i++ ) {
table[i][0]
= x ;
table[i][1]
= sin( x ) ;
printf(“\n Sin( %lf ) = %lf”, table[i][0], table[i][1] );
}
}
To initialise a
multidimensional array all but the leftmost index must be specified so that the
compiler can index the array properly.
For Example :-
int d[ ] [ 3 ] =
{ 1, 2, 3, 4, 5, 6 } ;
However it is more useful
to enclose the individual row values in curly braces for clarity as follows.
int d[ ] [ 3 ] = { {1, 2, 3}, {4,
5, 6} } ;
An array of strings
is in fact a two dimensional array of characters but it is more useful to view
this as an array of individual single dimension character arrays or strings.
For Example :-
char str_array[ 10 ] [ 30 ] ;
where the row index
is used to access the individual row strings and where the column index is the
size of each string, thus str_array is an array of 10 strings each with a
maximum size of 29 characters leaving
one extra for the terminating null character.
For Example :-
Program to read strings into str_array and print them out character by
character.
#include <stdio.h>
char str_array[10][30] ;
void main()
{
int i, j ;
puts("Enter ten strings\n") ;
for ( i = 0 ; i < 10; i++ ) // read in as strings so a single
for
// loop suffices
{
printf( " %d : ", i + 1) ;
gets( str_array[i] ) ;
}
for ( i = 0; i < 10; i++ )//printed out as individual chars
so a
{ // nested for loop structure is required
for ( j=0;
str_array[i][j] != '\0' ; j++ )
putchar (
str_array[i][j] ) ;
putchar( '\n' ) ;
}
}
In C it is impossible
to pass an entire array as an argument to a function -- instead the address of
the array is passed as a parameter to the function. (In time we will regard
this as a pointer).
The name of an array
without any index is the address of the first element of the array and hence of
the whole array as it is stored contiguously. However we need to know the size
of the array in the function - either by passing an extra parameter or by using
the sizeof operator..
For Example :-
void main()
{
int array[20] ;
func1( array ) ;/* passes pointer to array to
func1 */
}
Since we are passing
the address of the array the function will be able to manipulate the actual
data of the array in main(). This is call by reference as we are not making a
copy of the data but are instead passing its address to the function. Thus the
called function is manipulating the same data space as the calling function.
In the function
receiving the array the formal parameters can be declared in one of three
almost equivalent ways as follows :-
·
As a sized array :
func1 ( int
x[10] ) {
...
}
·
As an unsized array :
func1 ( int x[ ]
) {
...
}
·
As an actual pointer
func1 ( int *x )
{
...
}
All three methods are
identical because each tells us that in this case the address of an array of
integers is to be expected.
Note however that in
cases 2 and 3 above where we specify the formal parameter as an unsized array
or simply as a pointer we cannot determine the size of the array passed in
using the sizeof operator as the compiler does not know what dimensions the
array has at this point. Instead sizeof returns the size of the pointer itself,
two in the case of near pointers in a 16-bit system but four in 32-bit systems.
For Example :-
Program to calculate the average value of an array of doubles.
#include
<stdio.h>
void read_array(
double array[ ], int size ) ;
double mean( double
array[ ], int size ) ;
void main()
{
double data[ 100 ] ;
double average ;
read_array( data, 100
) ;
average = mean( data,
100 ) ;
}
void read_array( double
array[ ], int size )
{
int i ;
for ( i = 0; i<100;
i++ ) {
printf( “\nEnter
data value %d : i + 1 );
scanf( “%lf”,
&array[i] ;
_flushall() ;
}
}
double mean( double
array[ ], int size )
{
double total = 0.0 ;
int count = size ;
while ( count-- ) // size is a local variable which we can
// use at will
total += array[
count ] ;
return ( total / size
) ;
}
For Example :-
Program to test if a user input string is a palindrome or not.
#include <stdio.h>
int palin( char array[ ] ) ;
/* Function to determine if array
is a palindrome returns 1 if it is a
palindrome, 0 otherwise */
void main( )
{
char str[100] ;
puts( "Enter test string" ) ;
gets( str ) ;
if ( palin( str ) )
printf( "%s is a
palindrome\n", str ) ;
else
printf( "%s is not a palindrome\n")
;
}
int palin ( char array[ ] )
{
int i = 0, j = 0 ;
while ( array[j++] ) ; /* get length of string i.e. increment j while array[j] != '\0' */
j -= 2 ; /*
move back two -- gone one beyond '\0' */
for ( ; i < j ; i++, j-- )
if ( array[ i ]
!= array[ j ]
return 0 ; /* return value 0 if not a palindrome
*/
return 1 ; /* otherwise it is a palindrome */
}
An alternative way of
writing the palin() function might be as follows using string manipulation
functions ( must add #include <string.h> to top of file in this case).
int palin( char array[
] )
{
char temp[30] ;
strcpy( temp, array )
;/* make a working copy of string */
strrev( temp ) ; /* reverse string */
if ( ! strcmp( temp,
array ) ) /* compare strings –
if same
strcmp returns 0 */
return 1 ;
else
return 0 ;
}
Function calls with
multi-dimensional arrays will be the same as with single dimension arrays as we
will still only pass the address of the first element of the array.
However to declare
the formal parameters to the function we need to specify all but one of the
dimensions of the array so that it may be indexed properly in the function.
For Example :-
2D
array of doubles :- double x[10][20] ;
Call
func1 with x a parameter :- func1( x ) ;
Declaration
in func1 :- func1( double y[ ][20] ) {
...
}
The compiler must at
least be informed how many columns the matrix has to index it correctly. For
example to access element y[5][3] of the array in memory the compiler might do
the following
element No =
5 * 20 + 3 = 103.
NB : Multi-dimensional arrays are stored
row-wise so y[5][3] is the 4th element in the 6th row.
Since we are dealing
with an array of doubles this means it must access the memory location
103 X 8 bytes from
the beginning of the array.
Thus the compiler
needs to know how many elements are in each row of the 2D array above. In
general the compiler needs to know all dimensions except the leftmost at the
very least.
For Example :-
Program to add two 2 x 2 matrices.
#include < stdio.h>
void mat_read( int mat[2][2] ) ; //
Write these two functions for
//yourselves
void mat_print( int mat[2][2] ) ;
void mat_add( int mat1[ ][2], int mat2[ ][2], int mat3[ ][2] ) ;
void main()
{
int mat_a[2][2], mat_b[2][2], mat_res[2][2] ;
puts( “Enter Matrix a row-wise :-\n” );
mat_read( mat_a ) ;
puts( “\nMatrix a is :-\n” ) ;
mat_print( mat_a ) ;
puts( “Enter Matrix b row-wise” );
mat_read( mat_b ) ;
puts( “\nMatrix b is :-\n” ) ;
mat_print( mat_b ) ;
mat_add( mat_a, mat_b, mat_res ) ;
puts( “The resultant matrix is\n” ) ;
mat_print( mat_res ) ;
}
void mat_add( int mat1[ ][2], int mat2[ ][2], int mat3[ ][2] )
{
int j, k ;
for ( j = 0; j < 2; j++ )
for ( k = 0; k < 2;
k++ )
mat_res[j][k] =
mat1[j][k] + mat2[j][k] ;
}
1. Write a program that allows the user
to read a user specified number of double precision floating point numbers from
the keyboard, storing them in an array of maximum size 100 say. Your program
should then calculate the sum and the average of the numbers input.
2. Modify your program in exercise 1 so
that the maximum and minimum values in the data are found and are ignored when
calculating the average value.
3. Write a program that allows the elements of a user input array of
doubles to be reversed so that first becomes last etc. Use a separate swap
function to carry out the switching of elements.
4. Write a program that reads an array
of up to 20 integers from the keyboard and produces a histogram of the values
as indicated below.
|
|
|
|
|
*
|
|
|
|
|
|
|
|
*
|
*
|
|
|
|
|
|
|
|
*
|
*
|
|
|
|
|
|
|
*
|
*
|
*
|
*
|
|
|
|
*
|
|
*
|
*
|
*
|
*
|
|
*
|
|
*
|
*
|
*
|
*
|
*
|
*
|
|
*
|
*
|
*
|
*
|
*
|
*
|
*
|
*
|
*
|
*
|
1
|
3
|
2
|
4
|
6
|
7
|
4
|
1
|
3
|
A two dimensional
array of characters should be used to produce the histogram, filling it with
asterisks appropriate to the data values and then just printing out the array.
Some scaling will be required if the values are allowed to exceed the number of
asterisks that can fit on the screen vertically.
5. Write a program to accept two strings
from the keyboard, compare them and then print out whether or not they are the
same.
6(a). Write a function to test whether
or not a word is a palindrome e.g. MADAM.
(b).
Modify the function in 2(a) so that white space characters are ignored i.e. so
that
MADAM IM ADAM for example is deemed a palindrome.
7.
Write and test a function that inserts a character anywhere in a string.
The function should take the general form
strins( char *string,
char character, int position )
Notes :-
1. Recall Microsoft C supports a broad range of string handling
functions such as strlen(), strcpy(), etc.
2. Your function should provide sufficient
error checking to prevent erroneous operation e.g. your function should check
that the desired position actually exists.
3. Your function need not consider
memory / space requirements placing the onus on the user to make sure
sufficient space is available in the operands.
Modify the strins( )
function written above so that it allows a string of characters rather than an
individual character to be inserted at the designated position.
8. Write a program that multiplies two 2 X
2 matrices and prints out the resultant
matrix. The program should read in the
individual matrices and display them in standard format for the user to check them. The user should
be allowed to correct/alter any one element of the matrix at a time and check
the revised matrix until satisfied. The results of the operation should be
displayed along with the two component matrices.
Recall that
9.
A real polynomial p(x) of degree n is given by
where the
coefficients an are real numbers.
Write a function
double eval ( double p[], double x, int n );
which calculates the
value of a polynomial of degree n at a value x using the coefficients in the
array p[]. Your program should read in
the values of the coefficients an and store them in an array and present the results of the calculation.
(a)
Use straightforward calculations
to compute the value.
(b)
Employ Horner's Rule to calculate the value.
Recall Horner's Rule for a three degree polynomial
for example is
p(x) =
a0 + x( a1 +
x( a2 + x(
a3 )))
Compare the efficiency obtained using both methods.
10. Programming Assignment :
Tic-Tac-Toe
Write a C program
which allows the user to play the computer in a game of tic--tac--toe (noughts
and crosses ).
The program should
use a two dimensional array to represent the 3x3 board matrix and allow the
various positions on the board to be referenced as co-ordinates such as (0,0)
for the upper--left corner and (2,2) for
the lower--right corner.
Your program might
include functions to do the following :-
1.
Initialise the playing area appropriately.
2.
Display the current state of the game.
3.
Get the player's move.
4.
Get the computer's move.
5.
Check if there is a winner.
The character 'O'
should be used to indicate a computer occupied position and the character 'X'
to indicate that of a player. The space character might be used to indicate an
unoccupied location. In displaying the current state of the board simple
formatted text output will suffice (
clearing the screen between move updates etc.) as opposed to providing DOS
graphics support.
The tic tac toe program should
incorporate the following three user specified options in a single package.
Option 1: The computer will be limited to playing a
very simple dull game. When it is the computer's turn to move it simply scans
the board matrix and fills the first unoccupied position encountered. If it
cannot find an unoccupied location it reports a drawn game.
Option 2: The computer plays a full game ie. it
checks first if it can win the game with its current move. This failing it
checks if it can prevent the player from
winning with his/her next move. Otherwise it fills the first available
unoccupied position.
Option 3: The program allows two players to play
each other (without any help or hints!).
The program should
run continuously allowing the player to exit using a special
"hot-key" during
a game and
should allow the player to choose who moves first.