Introduction to Computer Science by Huong Nguyen - HTML preview

PLEASE NOTE: This is an HTML preview only and some elements such as links or page numbers may be incorrect.
Download the book in PDF, ePub, Kindle for a complete version.

least to the uninitiated, somewhat harder to understand.

Declarations and Usage of Arrays

The definition of an array determines its name, the type of its elements, and the number of

elements in the array. The general syntax for declaring a single-dimensional array is

type name[ number_of_elements ];

The number of elements, between square brackets ([ ]), must be an integer expression whose value

is greater than zero.

For example, the declaration,

int a[10];

defines an array of size 10, that is, a block of 10 consecutive objects named a[0], a[1], ...,a[9].

char buffer[4*512];

defines an array with the name buffer, which consists of 2,048 elements of type char.

The lower bound of an array is set at 0. C++ does not allow you to override or alter this lower

bound

Declaring a C++ array entails specifying the number of members. The number of member is

equal to the upper bound plus one

The valid range of indices extends between 0 and number_of_elements -1.

Multidimensional Arrays

A multidimensional array in C is merely an array whose elements are themselves arrays. The

elements of an n-dimensional array are (n-1)-dimensional arrays. For example, each element of a

two-dimensional array is a one-dimensional array. The elements of a one-dimensional array, of

course, do not have an array type.

A multidimensional array declaration has a pair of brackets for each dimension:

char screen[10][40][80]; // A three-dimensional array.

The array screen consists of the 10 elements screen[0] to screen[9]. Each of these elements is a

two-dimensional array, consisting in turn of 40 one-dimensional arrays of 80 characters each. All

in all, the array screen contains 32,000 elements with the type char.

Two-dimensional arrays are also called matrices. Because they are so frequently used, they merit

a closer look. It is often helpful to think of the elements of a matrix as being arranged in rows and columns. Thus the matrix mat in the following definition has three rows and five columns:

float mat[3][5];

The three elements mat[0], mat[1], and mat[2] are the rows of the matrix mat. Each of these rows

is an array of five float elements. Thus the matrix contains a total of 3 x 5 = 15 float elements, as the following diagram illustrates:

Table 2.21.

0

1

2

3

4

index-132_1.jpg

mat[0] 0.0 0.1 0.2 0.3 0.4

mat[1] 1.0 1.1 1.2 1.3 1.4

mat[2] 2.0 2.1 2.2 2.3 2.4

Accessing Array Elements

The subscript operator [ ] provides an easy way to address the individual elements of an array by

index. If myArray is the name of an one dimensional array and i is an integer, then the expression

myArray[i] designates the array element with the index i. Array elements are indexed beginning

with 0. Thus, if len is the number of elements in an array, the last element of the array has the

index len-1.

The following code fragment defines the array myArray and assigns a value to each element.

#define A_SIZE 4

long myarray[A_SIZE];

for (int i = 0; i < A_SIZE; ++i)

myarray[i] = 2 * i;

The diagram in Figure 2.16 illustrates the result of this assignment loop.

Figure 2.16.

Values assigned to elements by index

To access a char element in the three-dimensional array screen, you must specify three indices.

For example, the following statement writes the character Z in a char element of the array:

screen[9][39][79] = 'Z';

Initializing Arrays

If you do not explicitly initialize an array variable, the usual rules apply: if the array has

automatic storage duration, then its elements have undefined values. Otherwise, all elements are

initialized by default to the value 0.

You cannot include an initialization in the definition of a variable-length array.

If the array has static storage duration, then the array initializers must be constant expressions.

If the array has automatic storage duration, then you can use variables in its initializers.

You may omit the length of the array in its definition if you supply an initialization list. The

array's length is then determined by the index of the last array element for which the list

contains an initializer. For example, the definition of the array a in the previous example is

equivalent to this:

int a[ ] = { 1, 2, 4, 8 }; // An array with four elements.

If the definition of an array contains both a length specification and an initialization list, then

the length is that specified by the expression between the square brackets. Any elements for

which there is no initializer in the list are initialized to zero (or NULL, for pointers). If the list contains more initializers than the array has elements, the superfluous initializers are simply

ignored.

A superfluous comma after the last initializer is also ignored.

As a result of these rules, all of the following definitions are equivalent:

int a[4] = {1, 2};

int a[ ] = {1, 2, 0, 0};

int a[ ] = {1, 2, 0, 0, };

int a[4] = {1, 2, 0, 0, 5};

Operations on arrays

Read the elements of a 1-dimensional array:

float a[10]; // declare a float array of size 10

int i;

// read the second element of the array : a[1]

scanf(“%f”,&a[1]);

// Assign an expression to the third element of the array

a[2] = a[1] + 5;

To read the value for each element of an array, you should use for statement. For example,

int b[10];

int i;

// Read the value for each element of the array

for(i = 0; i < 10; i++)

{

printf(“\n Enter the value of b[%d]”, i);

scanf(“%d”,&b[i]);

}

In case you do not now the exact number of elements, declare the maximum number of elements

and use a variable to store the actual size of the array

int a[100]; // Declare the array with the number of elements not greater than 100

int n; // n is the actual size of the array

int i;

printf(“\n Enter the number of elements: “);

scanf(“%d”,&n);

for(i = 0; i < n; i++)

{

printf("\n a[%d] = ", i);

scanf("%d",&a[i]);

}

C allow you to associate initializers with specific elements . To specify a certain element to

initialize, place its index in square brackets. In other words, the general form of an element

designator for array elements is:

int a[4] = {4, 9, 22, 16};

float b[3] = {40.5, 20.1, 100};

char c[5] = {‘h’, ‘e’, ‘l’, ‘l’, ‘o’};

The first statement is equivalent to four assign statements

a[0] = 4; a[1] = 9; a[2] = 22; a[3] = 16;

Printing array elements

printf function are used to print the element of an array. In the following example, we print the

element of array a in different ways

#include <stdio.h>

#include <conio.h>

void main()

{

int a[5];

int i, k;

// Read the elements of the array

for(i = 0; i < 5; i++)

{

printf(“\n a[%d] = “, i);

scanf(“%d”, &a[i]);

}

// print the value of element a[3]

printf(“\n a[3] = %d”, a[3]);

// Display all the elements of array a, each element in a line.

for(i = 0; i < 5; i++)

printf(“\n%d”, a[i]);

// Display all the elements of array a in a line

printf(“\n”); // change to a new line

for(i = 0; i < 5; i++)

printf(“%d “, a[i]);

// Display all the elements of array a, k elements in a line

printf(“\n Enter the value of k = “);

scanf(“%d”,&k);

for(i = 0; i < 5; i++)

{

printf(“%d “,a[i]);

if((i+1)%k == 0) // change to a new line after printing k

//elements

printf(“\n”);

}

getch();

}

here is the sample session with the above program

a[0] = 6

a[1] = 14

a[2] = 23

a[3] = 37

a[4] = 9

a[3] = 37

6

14

23

37

9

6 14 23 37 9

Input the value of k = 2

6 14

23 37

9

Find the maximum value stored in the array.

The purpose of this function is to find the maximum value stored in the array

Set up a trial minimum value. The function begins by declaring a variable named min and

initializing that variable with a trial minimum value – value of the first element .

Then the function uses a while loop to:

Fetch the value stored in each element in the array

Compare each of those values with the current value stored in the variable named max

Possibly replace if the value fetched from an element is algebraically greater than the current

value stored in max:

The value fetched from the element is stored in the variable named max

Replacing the value that was previously stored in the variable named max by the new value

from the element.

When all of the array elements have been examined and processed in this manner, the variable

named max will contain the maximum value of all the values stored in the array.

int a[100];

int i, n;

int max;

printf("\n Enter the size of the array: ");

scanf("%d",&n);

// Read the number of elements of the array

for(i = 0; i < n; i++)

{

printf("\n a[%d] = ",i);

scanf("%d",&a[i]);

}

// Find the maximum element

max = a[0]; // max is initialized by a[0]

// compare max to other elements

for(i = 1; i < n; i++)

if(max < a[i]) //meet an element greater than max

max = a[i]; // replace max by the new value from the elements.

printf("\n The maximum element of the array is: %d", max);

Searching

The simplest type of searching process is the sequential search. In the sequential search, each

element of the array is compared to the key, in the order it appears in the array, until the first

element matching the key is found. If you are looking for an element that is near the front of the

array, the sequential search will find it quickly. The more data that must be searched, the longer it will take to find the data that matches the key using this process.

here is the sample session with the above program

#include <stdio.h>

#include <conio.h>

void main()

{

int m[100], idx[100];

int n; // n is the actual size of the array

int i, k, test;

clrscr(); // clear screen

// Read array m

// Read the actual size of m

printf(“ Enter the number of elements

scanf(“%d”,&n);

// Read array’s elements

for(i = 0;i<n;i++)

{

int temp;

printf(“\n Enter the value of m[%d] = “,i);

scanf(“%d”,&temp);

m[i] = temp;

}

// Read the searching key k

printf(“\n Enter the value you want to search : “);

scanf(“%d”,&k);

// Begin searching

test = 0;

// Scan all the elements

for(i = 0;i<n;i++)

if(m[i] = = k)//Compare the current element with the

//searching key k

{

// save the index of the current element

idx[test] = i;

test ++;

}

// Conclusion

if(test > 0)

{

printf(“\n there are %d elements which has the value of %d”,test,k);

printf(“\n Indexes of those elements: “);

for(i = 0;i < test;i++)

printf(“%3d”,idx[i]);

}

else

printf(“\n No element has the value %d”,k);

getch(); // Wait until the user press any key

}

Sorting

Selection sort is a sorting algorithm, specifically an in-place comparison sort. Selection sort is

noted for its simplicity, and also has performance advantages over more complicated algorithms

in certain situations. It works as follows:

Find the minimum value in the list

Swap it with the value in the first position

Repeat the steps above for remainder of the list (starting at the second position)

Effectively, we divide the list into two parts: the sublist of items already sorted, which we build

up from left to right and is found at the beginning, and the sublist of items remaining to be sorted, occupying the remainder of the array.

Here is an example of this sort algorithm sorting five elements:

31 25 12 22 11

11 25 12 22 31

11 12 25 22 31

11 12 22 25 31

#include <stdio.h>

#include <conio.h>

void main()

{

int m[100];//100 is the maximum size for array m

int n; // n is the number of elements int i, j, k;

clrscr(); // clear screen

// Read the elements of array m

// Read the actual size of the array

printf(“ Enter the number of elements: “);

scanf(“%d”,&n);

// Read array elements

for(i = 0;i<n;i++)

{

int temp;

printf(“\n Enter the value of m[%d] = “,i);

scanf(“%d”,&temp);

m[i] = temp;

}

// Print the array

printf(“\n The array before sorting: “);

for(i=0;i<n;i++)

printf(“%3d”,m[i]);

// Begin to sort

for(i = 0; i<n-1;i++)

{

// Put the minimum value in the list of n-i elements

//to the ith position

for(j = i+1;j<n;j++)

{

// compare m[i] with other element of the sublist

// and swap m[i] and m[j] if m[j] < m[i].

if(m[j]<m[i])

{

int temp;

temp = m[j]; m[j] = m[i]; m[i] = temp;

}

}

// Print the array after the i+1 th step of sorting process

printf(“\n The array after step %d”,i+1);

for(k = 0;k < n ;k++)

printf(“%3d”,m[k]);

}

getch(); // Wait until the user press any key.

}

here is the sample session with the above program

Enter the number of elements: : 5

Enter the value of m[0]: 34

Enter the value of m[1]: 20

Enter the value of m[2]: 17

Enter the value of m[3]: 65

Enter the value of m[4]: 21

The array before sorting: 34 20 17 65 21

The array after step 1: 17 34 20 65 21

The array after step 2: 17 20 34 65 21

The array after step 3: 17 20 21 65 34

The array after step 4: 17 20 21 34 65

Pointers vs Arrays

Pointers occur in many C programs as references to arrays , and also as elements of arrays. A

pointer to an array type is called an array pointer for short, and an array whose elements are

pointers is called a pointer array.

Array Pointers

For the sake of example, the following description deals with an array of int. The same principles

apply for any other array type, including multidimensional arrays.

To declare a pointer to an array type, you must use parentheses, as the following example

illustrates:

int (* arrPtr)[10] = NULL; // A pointer to an array of

// ten elements with type int.

Without the parentheses, the declaration int * arrPtr[10]; would define arrPtr as an array of 10

pointers to int. Arrays of pointers are described in the next section.

In the example, the pointer to an array of 10 int elements is initialized with NULL. However, if we

assign it the address of an appropriate array, then the expression *arrPtr yields the array, and

(*arrPtr)[i] yields the array element with the index i. According to the rules for the subscript

operator, the expression (*arrPtr)[i] is equivalent to *((*arrPtr)+i). Hence **arrPtr yields the first element of the array, with the index 0.

In order to demonstrate a few operations with the array pointer arrPtr, the following example uses

it to address some elements of a two-dimensional array that is, some rows of a matrix:

int matrix[3][10]; // Array of three rows, each with 10 columns.

// The array name is a pointer to the first

// element; i.e., the first row.

arrPtr = matrix; // Let arrPtr point to the first row of

// the matrix.

(*arrPtr)[0] = 5; // Assign the value 5 to the first element of the

// first row.

//

arrPtr[2][9] = 6; // Assign the value 6 to the last element of the

// last row.

//

++arrPtr; // Advance the pointer to the next row.

(*arrPtr)[0] = 7; // Assign the value 7 to the first element of the

// second row.

After the initial assignment, arrPtr points to the first row of the matrix, just as the array name

matrix does. At this point you can use arrPtr in the same way as matrix to access the elements. For

example, the assignment (*arrPtr)[0] = 5 is equivalent to arrPtr[0][0] = 5 or matrix[0][0] = 5.

However, unlike the array name matrix, the pointer name arrPtr does not represent a constant

address, as the operation ++arrPtr shows. The increment operation increases the address stored in

an array pointer by the size of one array in this case, one row of the matrix, or ten times the

number of bytes in an int element.

If you want to pass a multidimensional array to a function, you must declare the corresponding

function parameter as a pointer to an array type.

One more word of caution: if a is an array of ten int elements, then you cannot make the pointer

from the previous example, arrPtr, point to the array a by this assignment:

arrPtr = a; // Error: mismatched pointer types.

The reason is that an array name, such as a, is implicitly converted into a pointer to the array's

first element, not a pointer to the whole array. The pointer to int is not implicitly converted into a pointer to an array of int. The assignment in the example requires an explicit type conversion,

specifying the target type int (*)[10] in the cast operator:

arrPtr = (int (*)[10])a; // OK

You can derive this notation for the array pointer type from the declaration of arrPtr by removing

the identifier. However, for more readable and more flexible code, it is a good idea to define a

simpler name for the type using typedef:

typedef int ARRAY_t[10]; // A type name for "array of ten int elements".

ARRAY_t a, // An array of this type,

*arrPtr; // and a pointer to this array type.

arrPtr = (ARRAY_t *)a; // Let arrPtr point to a.

Pointer Arrays

Pointer arrays that is, arrays whose elements have a pointer type are often a handy alternative to

two-dimensional arrays. Usually the pointers in such an array point to dynamically allocated

memory blocks.

For example, if you need to process strings, you could store them in a two-dimensional array

whose row size is large enough to hold the longest string that can occur:

#define ARRAY_LEN 100

#define STRLEN_MAX 256

char myStrings[ARRAY_LEN][STRLEN_MAX] =

{ // Several corollaries of Murphy's Law:

"If anything can go wrong, it will.",

"Nothing is foolproof, because fools are so ingenious.",

"Every solution breeds new problems."

};

However, this technique wastes memory, as only a small fraction of the 25,600 bytes devoted to

the array is actually used. For one thing, a short string leaves most of a row empty; for another,

memory is reserved for whole rows that may never be used. A simple solution in such cases is to

use an array of pointers that reference the objects in this case, the strings and to allocate memory only for the pointer array and for objects that actually exist. Unused array elements are null

pointers.

#define ARRAY_LEN 100

char *myStrPtr[ARRAY_LEN] = // Array of pointers to char

{ // Several corollaries of Murphy's Law:

"If anything can go wrong, it will.",

"Nothing is foolproof, because fools are so ingenious.",

"Every solution breeds new problems."

index-143_1.jpg

};

Figure 2.17.

Pointer array

The diagram in illustrates how the objects are stored in memory. The pointers not yet used can be

made to point to other strings at runtime. The necessary storage can be reserved dynamically in

the usual way. The memory can also be released when it is no longer needed.

2.5. Functions*

Basic of C functions

Functions break large computing tasks into smaller ones, and enable people to build on what

others have done instead of starting over from scratch. Appropriate functions hide details of

operation from parts of the program that don't need to know about them, thus clarifying the whole,

and easing the pain of making changes.

C has been designed to make functions efficient and easy to use; C programs generally consist of

many small functions rather than a few big ones. A program may reside in one or more source

files. Source files may be compiled separately and loaded together, along with previously

compiled functions from libraries. We will not go into that process here, however, since the

details vary from system to system.

Function declaration and definition is the area where the ANSI standard has made the most

changes to C. It is now possible to declare the type of arguments when a function is declared. The

syntax of function declaration also changes, so that declarations and definitions match. This

makes it possible for a compiler to detect many more errors than it could before. Furthermore,

when arguments are properly declared, appropriate type coercions are performed automatically.

Every function is defined exactly once. A program can declare and call a function as many times

as necessary.

Declaration and Usage of Function

Function Declarations

The definition of a function consists of a function head (or the declarator) and a function block .

The function head specifies the name of the function, the type of its return value, and the types

and names of its parameters, if any. The statements in the function block specify what the function

does. The general form of a function definition is as follows:

//function head

type function-name(parameter declarations)

//function block

{

declarations and statements

}

In the function head, name is the function's name, while type (return-type) consists of at least one type specifier, which defines the type of the function's return value. The return type may be void

or any object type, except array types. Furthermore, type may include the function specifier inline, and/or one of the storage class specifiers extern and static.

A function cannot return a function or an array. However, you can define a function that returns a

pointer to a function or a pointer to an array.

The parameterdeclarations are contained in a comma-separated list of declarations of the

function's parameters. If the function has no parameters, this list is either empty or contains

merely the word void.