0% found this document useful (0 votes)
5 views256 pages

Book 1

This book aims to provide a comprehensive foundation in Advanced Level Computer Science 795, emphasizing the importance of actively solving problems rather than just reading solutions. It covers various topics including programming fundamentals, data structures, algorithms, and relational databases, structured in a clear and systematic manner. The document outlines the program development life cycle and problem-solving techniques, encouraging readers to engage with the material for effective learning.

Uploaded by

julienezeti
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views256 pages

Book 1

This book aims to provide a comprehensive foundation in Advanced Level Computer Science 795, emphasizing the importance of actively solving problems rather than just reading solutions. It covers various topics including programming fundamentals, data structures, algorithms, and relational databases, structured in a clear and systematic manner. The document outlines the program development life cycle and problem-solving techniques, encouraging readers to engage with the material for effective learning.

Uploaded by

julienezeti
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 256

HOW TO USE THIS BOOK

The main objective of this book is to provide a solid foundation in the practical aspects of Advanced Level
Computer Science 795. To properly use this book, ensure attempting your own solutions to problems presented
throughout the book. Attempting to just read solutions for every problem presented without first trying to solve
the problem, won’t help you develop into a skillful problem solver.

NEBONGO D. MOSAKA
671166171
[email protected]

1
Table of Contents
1 DATA STRUCTURES, ALGORITHMS AND PROGRAMMING ................................................................................... 5
1.1 Programming Fundamentals ........................................................................................................................... 5
1.1.1 Program Development Life Cycle ............................................................................................................ 5
1.1.2 Problem Formulation and Problem Solving ........................................................................................... 6
1.1.3 Algorithm ................................................................................................................................................... 6
1.1.4 General Structure of An Algorithm .......................................................................................................... 8
1.1.5 Data Types, Variables and Constants....................................................................................................... 9
1.1.6 Escape Sequences. ................................................................................................................................... 10
1.1.7 Format Specifiers .................................................................................................................................... 11
1.1.8 Operators and Expressions .................................................................................................................... 12
1.1.9 Type Conversion and Typecasting ......................................................................................................... 14
1.1.10 Managing Input and Output Operations................................................................................................ 14
1.1.11 Flow Control Statements ........................................................................................................................ 15
1.2 Arrays ............................................................................................................................................................... 22
1.2.1 Introduction............................................................................................................................................. 22
1.2.2 Application of Arrays .............................................................................................................................. 22
1.2.3 Declaration (i.e. creation) of array ........................................................................................................ 22
1.2.4 One-dimensional Arrays ......................................................................................................................... 22
1.2.5 Insertion and Deletion of elements from a 1-D Array .......................................................................... 23
1.2.6 Array of Arrays (Multi-dimensional Arrays) ........................................................................................ 25
1.2.7 Algorithm and Programming Examples ................................................................................................ 27
1.3 Subroutines, Local and Global Variables ....................................................................................................... 37
1.3.1 Introduction............................................................................................................................................. 37
1.3.2 Procedures ............................................................................................................................................... 38
1.3.3 Functions ................................................................................................................................................. 38
1.3.4 A Multi-Function Program...................................................................................................................... 38
1.3.5 Library Functions .................................................................................................................................... 39
1.3.6 User-defined Functions (programmer-defined functions) ................................................................. 41
1.3.7 Function Declaration .............................................................................................................................. 41
1.3.8 Function Definition ................................................................................................................................. 41
1.3.9 Function Calls .......................................................................................................................................... 42
1.3.10 The Scope, Visibility and Lifetime of Variables..................................................................................... 43
1.3.11 Recursion ................................................................................................................................................. 45
1.3.12 Random-Number Generation: Simulation and Game Playing. ............................................................ 46
1.3.13 A Common Technique: The Flag Principle ............................................................................................ 46
1.3.14 Algorithm and Programming Examples ................................................................................................ 47
2
1.4 Structures ........................................................................................................................................................ 58
1.4.1 Defining a Structure ................................................................................................................................ 58
1.4.2 Declaring Structure Variables ................................................................................................................ 58
1.4.3 Typedef DECLARATIONS ........................................................................................................................ 59
1.4.4 Operations on Structures ....................................................................................................................... 60
1.4.5 Aggregate Operations ............................................................................................................................. 60
1.4.6 Arrays of Structures ................................................................................................................................ 60
1.4.7 Arrays Within Structures........................................................................................................................ 61
1.4.8 Structures Within Structures ................................................................................................................. 61
1.4.9 Structures and Functions ....................................................................................................................... 62
1.4.10 Unions and Structures ............................................................................................................................ 62
1.5 Strings .............................................................................................................................................................. 63
1.5.1 String Library Functions ......................................................................................................................... 63
1.5.2 Declaring and Initializing String Variable ............................................................................................. 63
1.5.3 Reading Strings From Terminal ............................................................................................................. 63
1.5.4 Displaying Strings ................................................................................................................................... 64
1.5.5 Arithmetic Operations on Characters .................................................................................................... 64
1.5.6 List of Strings ........................................................................................................................................... 64
1.6 Sorting and Searching ..................................................................................................................................... 66
1.6.1 Sorting ...................................................................................................................................................... 66
1.6.2 Searching ................................................................................................................................................. 85
1.7 Pointers ............................................................................................................................................................ 91
1.7.1 Introduction............................................................................................................................................. 91
1.7.2 Declaration and Manipulation of a Pointer ........................................................................................... 92
1.7.3 Pointer arithmetic ................................................................................................................................... 93
1.7.4 Illegal Pointer Operations ...................................................................................................................... 93
1.7.5 Initializing a pointer................................................................................................................................ 94
1.7.6 Dynamic Memory Allocation .................................................................................................................. 94
1.7.7 Application of pointers. .......................................................................................................................... 96
1.8 STACKS and QUEUES .................................................................................................................................... 101
1.8.1 Stacks ..................................................................................................................................................... 101
1.8.2 Queues.................................................................................................................................................... 104
1.9 Case Studies ................................................................................................................................................... 105
2 RELATIONAL DATABASES ................................................................................................................................... 190
2.1 Introduction................................................................................................................................................... 190
2.2 Characteristics of a Relational Table ........................................................................................................... 190
2.3 Relational Database Keys ............................................................................................................................. 190
3
2.4 Selecting Primary Keys ................................................................................................................................. 190
2.5 Integrity Rules ............................................................................................................................................... 191
2.6 Entity Relationship (ER) Modeling .............................................................................................................. 192
2.6.1 Entities ................................................................................................................................................... 192
2.6.2 Attributes ............................................................................................................................................... 192
2.6.3 Identifiers (Primary Keys) ................................................................................................................... 193
2.6.4 Relationships ......................................................................................................................................... 193
2.6.5 Developing an ER Diagram ................................................................................................................... 194
2.6.6 Conversion of an Entity-Relationship Diagram (ERD) to a Relational Database Model ................. 194
2.6.7 Associative Table................................................................................................................................... 195
2.7 Database Normalization ............................................................................................................................... 195
2.7.1 The Normalization Process .................................................................................................................. 195
2.7.2 Dependencies ........................................................................................................................................ 196
2.7.3 Conversion to First Normal Form (1NF)............................................................................................. 196
2.7.4 Conversion to Second Normal Form (2NF) ........................................................................................ 197
2.7.5 Conversion to Third Normal Form (3NF) ........................................................................................... 197
2.8 Structured Query Language (SQL) .............................................................................................................. 203
2.8.1 Data Definition Language (DDL). [CREATE TABLE, ALTER TABLE, DROP TABLE] ........................ 203
2.8.2 Data Types ............................................................................................................................................. 205
2.8.3 Data Manipulation Language (DML). [INSERT, UPDATE, DELETE, SELECT]................................... 206
2.8.4 Common SQL Text Manipulation Functions Along With Their Syntax And Examples .................... 208
2.8.5 Common SQL Date & Time Manipulation Functions Along With Their Syntax And Examples ...... 209
2.8.6 Subquery ................................................................................................................................................ 212
2.8.7 Wildcard Characters ............................................................................................................................. 212
2.8.8 LIKE, IN, BETWEEN, DISTINCT & EXIST ............................................................................................. 213
2.8.9 SQL Aggregate Functions Along with Their Syntax and Example Code............................................ 217
2.8.10 The roles of GROUP BY, ORDER BY and HAVING clauses in SQL select query with aggregate functions ..... 218
2.8.11 Calculated Fields ................................................................................................................................... 219
2.9 Case Studies ................................................................................................................................................... 222

4
1 DATA STRUCTURES, ALGORITHMS AND PROGRAMMING
1.1 Programming Fundamentals
A computer can perform both simple and complex tasks with very high speed and accuracy. However, a computer
cannot perform any task—simple or complex, on its own. Computers need to be instructed about “how” the task
is to be performed.
The set of instructions that instruct the computer about the way the task is to be performed is called a program.
A program is required for processing all kind of tasks—simple tasks like addition of two numbers, and complex
tasks like gaming etc.
1.1.1 Program Development Life Cycle
The instructions in a program have three essential parts:
1. Instructions to accept the input data that needs to be processed,
2. Instructions that will act upon the input data and process it, and
3. Instructions to provide the output to user
The instructions in a program are defined in a specific order.
The steps that are followed by the programmer for writing a program are:
1. Problem Analysis—The programmer first understands the problem to be solved. The programmer determines
the various ways in which the problem can be solved, and decides upon a single solution which will be followed
to solve the problem.
2. Program Design—The selected solution is represented in a form, so that it can be coded.
This requires two steps:
a. A flowchart is drawn, which is a diagrammatic representation of the solution. The solution is represented
diagrammatically, for easy understanding and clarity.
b. A pseudo code is written for the selected solution. Pseudo code uses the structured programming
constructs. The pseudo code becomes an input to the next phase.
3. Program Development
a. The pseudo code is coded using a suitable programming language.
b. The coded pseudo code or program is compiled for any syntax errors. During compilation, the syntax
errors, if any, are removed.
c. The successfully compiled program is now ready for execution.
d. The executed program generates the output result, which may be correct or incorrect.
e. The program is tested with various inputs, to see that it generates the desired results. If incorrect results
are displayed, then the program has semantic error. The semantic errors are removed from the program
to get the correct results.
f. The successfully tested program is ready for use and is installed on the user’s machine.
4. Program Documentation and Maintenance—The program is properly documented, so that later on, anyone can
use it and understand its working. Any changes made to the program, after installation, forms part of the
maintenance of the program. The program may require updating, fixing of errors etc. during the maintenance
phase. Table below summarizes the steps of the program development cycle.

5
Stage Tasks
Problem Analysis Understand the problem
Have multiple solutions
Select the most efficient solution
Program Design Draw the flowchart
Write the Pseudocode
Program Choose the most appropriate programming language
Development Write the program by converting the pseudocode using the chosen
programming language
Compile the program and remove syntax errors, if any.
Execute the program
Test the program. Check the output results with different inputs. If the output
is incorrect, modify the program to get correct results
Install the tested program on the user’s computer
Program Document the program for later use
Documentation Maintain the program for updating, removing errors, changing requirements
and Maintenance etc.

1.1.2 Problem Formulation and Problem Solving


a. Problem Solving
Problem solving is an innovative process for finding solutions to problems. The process involves the following
sequence of steps to be followed:
1. Identify the problem
2. Collect information to improve the understanding about the problem
3. Chart down the set of solutions
4. Select the best solution
5. Implement the best solution
6. Assess the results
7. If the results are satisfactory, stop else investigate the alternative solutions
The commonly used problem-solving tools are flowcharts and pseudo code.
b. Problem Formulation
Problem formulation is the methodology of describing the problem and the results by stating the requirements
and the objectives. The objectives are defined in terms of:
1. Input and its characteristics
2. Expected Output and its characteristics
3. Relationship between the input & the desired output
Example: Problem formulation to find the largest of three numbers
− Requirement: To find and print the largest of three numbers
− Input: Three numbers
− Characteristics of input: Numbers
− Output: One of the three input that is large
− Characteristics of output: Number
− Relationship between Input and Output: Output will be one of the three numbers given as input.

1.1.3 Algorithm
An Algorithm is an ordered sequence of finite, well defined, unambiguous instructions for solving a problem.
a. Different Ways of Expressing Algorithms
Algorithms may be represented in various ways. The two common ways of representing algorithms are as follows:
▪ Pseudo-code
6

Flowchart
i) Flowchart
A flowchart is a diagrammatic (or symbolic) representation of an algorithm. A flowchart is drawn using different
shapes with lines connecting them to show the flow of control. In a flowchart, the different shapes represent
operations and the arrows linking them represent the order of execution of instructions (also called flow of
control). The purpose of drawing a flowchart is to make the logic of the program clearer in a visual form.

Symbol Meaning
Terminal: Used to show the beginning and end of the algorithm

Process: Used to represent any type of internal operation e.g. set sum
to A plus B, add number to total or increment counter by one
Predefined Process: Used to indicate any process not specially
defined in the flowchart

Decision/Branch: Evaluates a condition or statement and branches


depending on whether the evaluation is true or false. E.g.
− If A is less than B then
− While counter is less than or equal to N do

Input/Output: Input or output of data E.g.


− Get a number A
− Print Average
Flow Lines: Indicate the direction of the progression of the algorithm

On-page Connector: Connects sections of the flowchart on the same


page so that the diagram can maintain a smooth, linear flow

Document: Used when input comes from a document and output goes
to a document.

Off-page Connector: Used to connect parts of a flowchart continued


to separate pages

ii. Pseudocode
A Pseudocode is a description of an algorithm using a combination of a formally-styled natural
language (such English language) with some rules of structure rather than in a programming
language
− Difference between Algorithm, Flowchart, and Pseudo Code
An algorithm is a sequence of instructions used to solve a particular problem. Flowchart and Pseudo code are
tools to document and represent the algorithm. In other words, an algorithm can be represented using a flowchart
or a pseudo code. Flowchart is a graphical representation of the algorithm. Pseudocode is a readable, formally
styled English like language representation of the algorithm. Both flowchart and pseudo code use structured
constructs of the programming language for representation. The user does not require the knowledge of a
programming language to write or understand a flowchart or a pseudo code.

7
1.1.4 General Structure of An Algorithm

Structure of Algorithm using Pseudocode Structure of a Program in the C language


1. Algorithm Algo_Name Documentation Section
2. /* Objective:. . . .*/ Link Section
Definition Section
3. /* Input :. . . .*/ Global Declaration Section
4. /* Output : . . . */ Main () Function Section
5. /*Declaration Part */ {
6. Constant: . . . . . .
7. Type: . . . . . . Declaration Part
8. Variable: . . . . . . Execution Part
9. /*Execution Part */ }
10. Start Subprogram Section
11. Instruction 1
12. Instruction 2 Function/Procedure 1
13. ....... Function/Procedure 2 (User Defined
……………………………….
14. Instruction n Functions)
Function/Procedure n
15. Stop
16. /*Subprogram Part */
17. .......

− Documentation Section
The documentation section consists of a set of comment lines giving the name of the program, the author and
other details, which the programmer would like to use later. Comments are not processed by the compiler. There
are two types of comments:
1. Single-line comment
2. Multi-line comment
− Single-line Comment
A single-line comment starts with two forward slashes (i.e. //) and is automatically terminated with the end of
line.
− Multi-line Comment
A multi-line comment starts with /* and terminates with */. A multi-line comment is used when multiple lines of
text are to be commented.
− Link Section
The link section provides instructions to the compiler to link functions from the system library. The libraries are
included using # followed by include, then the name of the library within angular brackets or within double
quotations for Self-created or user-defined header files. Examples include #include<stdio.h>,
#include<string.h>, #include<math.h>, #include<time.h> etc.
− Definition Section
The definition section defines all symbolic constants. For example, #define N 5
− Declaration Section
There are some variables that are used in more than one function. Such variables are called global variables and
are declared in the global declaration section that is outside of all the functions. This section can also be used to
declare all the user-defined functions.

8
− Main() Function Section
Every C program must have one main() function section. This section contains two parts, declaration part and
executable part. The declaration part declares all the variables used in the executable part. There is at least one
statement in the executable part. These two parts must appear between the opening and the closing braces. The
program execution begins at the opening brace and ends at the closing brace. The closing brace of the main
function section is the logical end of the program. All statements in the declaration and executable parts end with
a semicolon(;).
− Subprogram Section
The subprogram section contains all the user-defined functions that are called in the main function. User-defined
functions are generally placed immediately after the main function, although they may appear before the main
under the declaration section.
All sections, except the main function section may be absent when they are not required

1.1.5 Data Types, Variables and Constants


a) Identifiers and Keywords
− Identifiers
An identifier refers to the name of an object. It can be a variable name, a label name, a function name, a typedef
name, a macro name or a macro parameter, a tag or a member of a structure, a union or an enumeration.
Keywords or reserved words cannot form a valid identifier name.

It is always advisable to create meaningful identifier names. Meaningful identifier names are easier to read and
i increase the maintainability of a program. For example, it is better to create an identifier name as student_name
i instead of snam.
i
i − Keywords
Keyword is a reserved word that has a particular meaning in the programming language. The meaning of a
keyword is predefined. A keyword cannot be used as an identifier name in C language. There are 32 keywords
available in C
List of keywords in C

𝐍𝐨 Keyword 𝐍𝐨 Keyword 𝐍𝐨 Keyword 𝐍𝐨 Keyword


1 auto 9 double 17 int 25 struct
2 break 10 else 18 long 26 switch
3 case 11 enum 19 register 27 typedef
4 char 12 extern 20 return 28 union
5 const 13 float 21 short 29 unsigned
6 continue 14 for 22 signed 30 void
7 default 15 goto 23 sizeof 31 volatile
8 do 16 if 24 static 32 while

− Declaration Statement
Every identifier (except label name) needs to be declared before it is used. An identifier can be declared by making
use of the declaration statement. The role of a declaration statement is to introduce the name of an identifier along
with its data type (or just type) to the compiler before its use. The general form of a declaration statement is:
[storage_class_specifier][type_qualifier|type_modifier] type identifier [=value[,...]];
Keywords or reserved words cannot form a valid identifier name.

9
The terms enclosed within square brackets (i.e. []) are optional and might not be present in a declaration
i statement. The type, identifier and the terminating semicolon (shown in bold) are the mandatory parts of a
i declaration statement.

i
i − Data Types
Data type or just type is one of the most important attributes of an identifier. It determines the possible values
that an identifier can have and the valid operations that can be applied on it. In C language, data types are broadly
classified as:
1. Basic data types (primitive data types)
2. Derived data types
3. User-defined data types
− Basic/Primitive Data Types
The five basic data types and their corresponding keywords available in C are:
1. Character (char)
2. Integer (int)
3. Single-precision floating point (float)
4. Double-precision floating point (double)
5. No value available (void)
− Type Modifiers
A type modifier modifies the base type to yield a new type. It modifies the range and the arithmetic properties of
the base type. The type modifiers and the corresponding keywords available in C are:
1. signed (e.g. signed int, signed char)
2. unsigned (e.g. unsigned int, unsigned char)
3. short (e.g. short int)
4. long (e.g. long int, long float, long double)
− Variables and Constants
A variable is a name assigned to a location in memory used to store information. In C, a variable must be defined
before it can be used. A variable definition informs the compiler of the variable’s name and the type of information
the variable is to hold. By using a variable’s name in your program, you are, in effect, referring to the data stored
there.
A constant has a fixed value that can’t change while a variable has a value that can change during program
execution.
A variable declaration has the following form: typename varname(s);. typename specifies the variable type and
varname is the variable name. Example int i, j, k;
The line int i, j, k; both declares and defines the variables i, j and k;
There are two simple ways in C to define constants:
− Using #define preprocessor.
#define identifier value Example #define WIDTH 5
− Using const keyword.
You can use const prefix to declare constants with a specific type as follows:
const type variable = value; Example const int WIDTH = 5;
1.1.6 Escape Sequences.
An escape sequence consists of a backward slash (i.e. \) followed by a character and both enclosed within single
quotes. An escape sequence is treated as a single character. A list of the escape sequences available in C is given
in the Table below

10
Escape Sequences
𝐨
𝐍 Escape Character value Action on output device
sequence
1 \’ Single quotation mark Prints ‘
2 \” Double quotation Prints “
mark (“)
3 \? Question mark (?) Prints ?
4 \\ Backslash character Prints \
(\)
5 \a Alert Alerts by generating a beep
6 \b Backspace Moves the cursor one position to the left of its
current position
7 \f Form feed Moves the cursor to the beginning of next page
8 \n New line Moves the cursor to the beginning of the next line
9 \r Carriage return Moves the cursor to the beginning of the current
line
10 \t Horizontal tab Moves the cursor to the next horizontal tab stop
11 \v Vertical tab Vertical tab
12 \0 Null character Prints nothing

1.1.7 Format Specifiers


The format specifier is used during input and output. It is a way to tell the compiler what type of data is in a
variable during taking input using scanf() or printing using printf(). There is a different format specifier for each
data type. Format specifier is written as %x, where x is a character code listed in the table below.
Format specifiers in C language
𝐍 𝐎 Data Type x Format Specifier Remark
1 char c %c Single character
2 int i %i Signed integer
3 int d %d Signed integer in decimal number system
4 unsigned int o %o Unsigned integer in octal number system
5 unsigned int u %u Unsigned integer in decimal number system
6 unsigned int x %x Unsigned integer in hexadecimal number system
7 unsigned int X %X Unsigned integer in hexadecimal number system
8 long int ld %ld Signed long
9 short int hd %hd Signed short
10 unsigned lu %lu Unsigned long
long
11 unsigned hu %hu Unsigned short
short
12 float f %f Signed single precision float in form of [-]dddd.dddd e.g.
22.25, −12.34
13 float e %e Singed single precision float in form of [-]d.dddde[+/-
]ddd e.g. −2.3e4, 2.25e−2
14 float E %E Same as %e, with E for exponent
15 float g %g Singed value in either e or f form, based on given value
and precision
16 float G %G Same as %g, with E for exponent if e format is used
17 double lf %lf Signed double-precision float
18 String type s %s String
19 Pointer type p %p Pointer

11
1.1.8 Operators and Expressions
An operator is a symbol that specifies the mathematical, logical, or relational operation to be performed.
Operators are used in programs to manipulate data in variables. They usually form a part of the mathematical or
logical expressions. C operators can be classified into a number of categories. They include:
Arithmetic operators, Relational operators, Logical operators, Assignment operators, Increment and decrement
operators, Conditional operators, Bitwise operators and Special operators.
− ARITHMETIC OPERATORS
They are used to perform arithmetic operations
Operator in Pseudocode Operator in C Meaning
+ + Addition or unary plus
− − Subtraction or unary minus
× * Multiplication
Div / Division (Integer Division)
/ Division (Real Division)
Mod % Modulo arithmetic

In C programming:
− Integer division truncates any fractional part e.g. 5/2=2.
− The modulo division operation produces the remainder of an integer division e.g. 7%2=1, 4%9=4
− The modulo division operator % cannot be used on floating point data.
− When one of the operands is real and the other is integer, the expression is called a mixed-mode arithmetic
expression. If either operand is of the real type, then only the real operation is performed and the result
is always a real number. Thus 15/10.0 = 1.5 whereas 15/10 = 1

− RELATIONAL OPERATORS
We often compare two quantities and depending on their relation, take certain decisions. For example, we may
compare the age of two persons, or the price of two items, and so on. These comparisons can be done with the
help of relational operators
Operator in Pseudocode Operator in C Meaning
< < is less than
≤ <= is less than or equal to
> > is greater than
≥ >= is greater than or equal to
= == is equal to
≠ or <> != is not equal to

− LOGICAL OPERATORS
They are used to combine logical values. The logical operators && and || are used when we want to test more than
one condition and make decisions.
Operator in Pseudocode Operator in C Meaning
NOT ! Logical NOT
OR || Logical OR
AND && Logical AND

Relational Operator Complement


Operator Complement
> <=
< >=
== !=
For example, !(a<b) is equivalent to a>=b

12
For example, !(a>=b) is equivalent to a<b.

In mathematics, 3 < j < 5 indicates that the variable j has the property of being greater than 3 and less than 5. In C,
the correct way to write an expression for testing both 3 < j and j < 5 is 3 < j && j < 5. This is equivalent to (3 < j)
&& (j < 5) and, this expression is true if and only if both operands of the && expression are true.

EXAMPLES
Given the following declarations and initializations: int a=3, b=-5, c=0; Determine the result of the following
Expression Result
a>0 && c>0 0(false)
a>=0 && c>=0 1(true)
a || c 1(true)
5 && !c 1(true)

− INCREMENT AND DECREMENT OPERATORS


They are used to increment or decrement by 1 the variable they act on.
Operator in Pseudocode Operator in C Meaning
++ ++ Increment
−− −− Decrement

− ASSIGNMENT OPERATORS
Assignment operators are used to assign the result of an expression to a variable.
Operator in Pseudocode Operator in C Meaning
← = Assignment

− CONDITIONAL OPERATOR
A ternary operator pair “? :” is available in C to construct conditional expressions of the form
exp1 ? exp2 : exp3;
where exp1, exp2, and exp3 are expressions.
The operator ? : works as follows: exp1 is evaluated first. If it is nonzero (true), then the expression exp2 is
evaluated and becomes the value of the expression. If exp1 is false, exp3 is evaluated and its value becomes the
value of the expression.
− BITWISE OPERATORS
C has a distinction of supporting special operators known as bitwise operators for manipulation of data at bit
level. These operators are used for testing the bits, or shifting them right or left. Bitwise operators may not be
applied to float or double.
Operator Meaning
& bitwise AND
| bitwise OR
^ bitwise exclusive OR
<< shift left
>> shift right

− SPECIAL OPERATORS
C supports some special operators of interest such as comma operator, sizeof operator, pointer operators (& and *) and
member selection operators (. and –> ).
− The Comma Operator
The comma operator can be used to link the related expressions together. A comma-linked list of expressions are
evaluated left to right and the value of right-most expression is the value of the combined expression. For example,
the statement
value = (x = 10, y = 5, x+y);
first assigns the value 10 to x, then assigns 5 to y, and finally assigns 15 (i.e. 10 + 5) to value

13
− The sizeof Operator
The sizeof () is a compile time operator and, when used with an operand, it returns the number of bytes the
operand occupies. The operand may be a variable, a constant or a data type qualifier.
1.1.9 Type Conversion and Typecasting
Type conversion or typecasting of variables refers to changing a variable of one data type into another
− Typecasting
Typecasting is also known as forced conversion. It is done when the value of one data type has to be converted
into the value of another data type. The code to perform typecasting can be given as:
float salary = 10000.00;
int sal;
sal = (int) salary;
When floating point numbers are converted to integers, the digits after the decimal are truncated. Explicit casting
can be carried out by means of a cast operator which has the following syntax
(type) expression;
1.1.10 Managing Input and Output Operations
The most fundamental operation in a C program is to accept input values from a standard input device and output
the data produced by the program to a standard output device.

A program that uses standard input/output functions must contain the following statement at the beginning of
i the program: #include <stdio.h>
i
i
i − Input Operations
Pseudocode C Language
READ, GET, INPUT scanf(), gets(), getchar()
▪ scanf()
The scanf()function is used to read formatted data from the keyboard. The syntax of the scanf() function can be
given as,
scanf ("control string", arg1, arg2, arg3 ...argn);
The control string specifies the type and format of the data that has to be obtained from the keyboard and stored
in the memory locations pointed by the arguments, arg1, arg2, ...,argn. The prototype of the control string can be
given as,
%[*][width][modifier]type
− * is an optional argument that suppresses assignment of the input field. That is, it indicates that data
should be read from the stream but ignored (not stored in the memory location).
− width is an optional argument that specifies the maximum number of characters to be read. However, if
the scanf function encounters a white space or an unconvertible character, input is terminated.
− modifier is an optional argument (h, l, or L) , which modifies the type specifier. Modifier h is used for short
int or unsigned short int, l is used for long int, unsigned long int, or double values. Finally, L is used for
long double data values.
− type specifies the type of data that has to be read. It also indicates how this data is expected to be read
from the user.
− The address of the variable is denoted by an & sign followed by the name of the variable. For example
scanf(“%d”,&number)
In case of reading strings, we do not use the & sign in the scanf function.

14
− Output Operations
Pseudocode C Language
WRITE, PRINT, DISPLAY, OUTPUT printf(), puts(), putchar()
▪ printf()
The printf function is used to display information required by the user and also prints the values of the variables.
Its syntax can be given as:
printf ("control string", arg1,arg2,arg3,...,argn);
After the control string, the function can have as many arguments as specified in the control string. The control
string contains format specifiers which are arranged in the order so that they correspond with the arguments in
the variable list. It may also contain text to be printed such as instructions to the user, identifier names, or any
other text to make the text readable.
The prototype of the control string can be given as below:
%[flags][width][.precision][modifier]type
Each control string must begin with a % sign.
− flags is an optional argument, which specifies output justification like decimal point, numerical sign,
trailing zeros or octadecimal or hexadecimal prefixes.
− width is an optional argument which specifies the minimum number of positions that the output
characters will occupy. If the number of output characters is smaller than the specified width, then the
output would be right justified with blank spaces to the left. However, if the number of characters is
greater than the specified width, then all the characters would be printed.
− precision is an optional argument which specifies the number of digits to print after the decimal point or
the number of characters to print from a string.
− modifier field is same as given for scanf() function.
− type is used to define the type and the interpretation of the value of the corresponding argument
Example printf(The area of the circle with radius %f is %f”, Area, Radius);
1.1.11 Flow Control Statements
By default, statements in a C program are executed in a sequential order. The order in which the program
statements are executed is known as ‘flow of program control’ or just ‘flow of control’. By default, the program
control flows sequentially from top to bottom. The default flow of control can be altered by using flow control
statements. Flow control statements are of two types:
1. Branching statements
▪ Selection statements
▪ Jump statements
2. Iteration statements
Branching Statements
Branching statements are used to transfer the program control from one point to another. They are categorized
as:
1. Conditional branching: In conditional branching, also known as selection, program control is transferred from
one point to another based upon the outcome of a certain condition. Selection statements select a statement to be
executed among a set of various statements. The following selection statements are available in C: if statement,
if-else statement and switch statement.
2. Unconditional branching: In unconditional branching, also known as jumping, program control is transferred
from one point to another without checking any condition. The following jump statements are available in C: goto
statement, break statement, continue statement and return statement

15
Selection Statements

If Statement

Pseudocode Flowchart C-Syntax


IF (Test Expression) THEN if (test expression)
Statement Block 1 {
ENDIF statement 1;
Statement x ...........
statement n;
}
statement x;

Remark:
The test expression is any valid C language expression that evaluates to either true or false. In addition to simple
relational expressions, we can also use compound expressions formed using logical operators. The if block may
include 1 statement or n statements enclosed within curly brackets. First the test expression is evaluated. If the
test expression is true, the statements of the if block are executed, otherwise these statements will be skipped and
the execution will jump to statement x.
if–else Statement
Pseudocode Flowchart C-Syntax
IF (Test Expression) THEN if (test expression)
Statement Block 1 {
ELSE statement block 1;
Statement Block 2 }
ENDIF else
Statement x {
statement block 2;
}
statement x;

Remark: In the if–else construct, first the test expression is evaluated. If the expression is true, statement block 1
is executed and statement block 2 is skipped. Otherwise, if the expression is false, statement block 2 is executed
and statement block 1 is ignored. In any case after the statement block 1 or 2 gets executed, the control will pass
to statement x. Therefore, statement x is executed in every case.

16
if–else–if Statement

Pseudocode Flowchart C-Syntax


IF (Test Expression 1) THEN if (test expression 1)
Statement Block 1 {
ELSE IF (Test Expression 2) statement block 1;
Statement Block 2 }
ELSE else if (test expression 2)
Statement Block x {
ENDIF statement block 2;
Statement y }
...........................
else
{
statement block x;
}
statement y;

switch Statement
SWITCH statements are mostly used in two situations:
▪ When there is only one variable to evaluate in the expression
▪ When many conditions are being tested for
The switch case statement compares the value of the variable given in the switch statement with the value of each
case statement that follows. When the value of the switch and the case statement matches, the statement block of
that particular case is executed. Default is the case that is executed when the value of the variable does not match
with any of the values of the case statements. That is, default case is executed when no match is found between
the values of switch and case statements and thus there are no statements to be executed.
Flowchart C-Syntax
switch (variable)
{
case value 1:
statement block 1;
break;
case value 2:
statement block 2;
break;
...................
case value N:
statement block N;
break;
default:
statement block D;
break;
}
statement X;

Jump Statements
A jump statement transfers the control from one point to another without checking any condition, i.e.
unconditionally.
17
The following jump statements are present in C language:
▪ Goto statement
▪ Break statement
▪ Continue statement
▪ Return statement
Break Statement
The syntactic form of a break statement is: break;
A break statement can appear only inside, or as a body of, a switch statement or a loop.
▪ When the break statement present inside a loop is executed, it terminates the loop and the program
control is transferred to the statement present next to the loop.
▪ When the break statement present inside a nested loop is executed, it only terminates the execution of the
nearest enclosing loop. The execution resumes with the statement present next to the terminated loop.
continue Statement
The syntactic form of a continue statement is: continue;
A continue statement can appear only inside, or as the body of, a loop.
▪ A continue statement terminates the current iteration of the loop.
▪ When a continue statement present inside a nested loop is executed, it only terminates the
current iteration of the nearest enclosing loop.
▪ On the execution of a continue statement, the program control is immediately transferred
to the header of the loop
return Statement
The general forms of a return statement are: return; //Form 1 or return expression; //Form 2
The important points about a return statement are as follows:
▪ A return statement without an expression (i.e. Form 1) can appear only in a function whose return type
is void.
▪ A return statement with an expression (i.e. Form 2) should not appear in a function whose return type is
void.
▪ A return statement terminates the execution of a function and returns the control to the calling function.

Iteration Statements
Iterative statements are used to repeat the execution of a sequence of statements until the specified expression
becomes false. C supports three types of iterative statements also known as looping statements. They are
▪ while loop
▪ do–while loop
▪ for loop
In general, loops are classified as:
▪ Counter-controlled loops
▪ Sentinel-controlled loops
Counter-Controlled Loops
Counter-controlled looping is a form of looping in which the number of iterations to be performed is known in
advance. Counter-controlled loops are so named because they use a control variable, known as the loop counter,
to keep a track of loop iterations. The counter-controlled loop starts with the initial value of the loop counter and
terminates when the final value of the loop counter is reached. Since the counter-controlled loops iterate a fixed
number of times, which is known in advance, they are also known as definite repetition loops. There are three
main ingredients of counter-controlled looping:
▪ Initialization of the loop counter.
▪ An expression (specifically a condition) determining whether the loop body should be executed or not.
▪ An expression that manipulates the value of the loop counter so that the condition above eventually
becomes false and the loop terminates
Sentinel-Controlled Loops
In sentinel-controlled looping, the number of times the iteration is to be performed is not known beforehand. The
execution or termination of the loop depends upon a special value called the sentinel value. If the sentinel value
is true, the loop body will be executed, otherwise it will not
18
for Statement: pre-test loop

Flowchart Pseudocode C-Syntax


FOR(i← Initial value TO Final Value) DO for (initialization; condition; increment/decrement)
Statement block {
ENDFOR statement block;
Statement y }
statement y;
In general, a for loop can be written as an In general, how many times does the body
equivalent while loop and vice versa. The (statement block) of a for() loop execute?
for loop (a) The following loop is executed (n-m)+1 times.
for(initialization; TestExpr; updating) for(i=m; i<=n; i++)
{ ...
stmT; (b) The following loop is executed (n-m) times.
} for(i=m; i<n; i++)
is equivalent to the following while ...
construct: (c) The following loop is executed ⌈(𝐧 − 𝐦)/𝐱 ⌉
initialization; times.
while (TestExpr) for(i=m; i<n; i=x+i)
{ ...
stmT;
updating;
}

The for statement is executed as follows:


a. Initialization section is executed only once at the start of the loop. The loop variable is given an initial
value
b. The expression present in the condition section is evaluated.
i. If it evaluates to true, the body of the loop is executed.
ii. If it evaluates to false, the loop terminates and the program control is transferred to the statement
present next to the for statement.
c. After the execution of the body of the loop, the loop variable is updated i.e. incremented or decremented
d. These three steps represent the first iteration of the for loop. For the next iterations, Steps b and c are
repeated until the expression in Step b evaluates to false.
while Statement: pre-test loop

Flowchart Pseudocode C-Syntax


Statement x statement x;
WHILE (CONDITION) DO while (condition)
Statement block {
ENDWHILE statement block;
Statement y }
statement y;

The while statement is executed as follows:


❖ The while controlling expression is evaluated.
o If it evaluates to true, the body of the loop is executed.
o If it evaluates to false, the program control is transferred to the statement present next to the
while statement.
❖ After executing the while body, the program control returns back to the while header.
❖ Steps above are repeated until the while controlling expression in the Step above evaluates to false.
19
do-while Statement: post-test loop

Flowchart Pseudocode C-Syntax


Statement x statement x;
DO do
Statement block {
WHILE (Condition) statement block;
ENDDOWHILE } while (condition);
Statement y statement y;

The do-while statement is executed as follows:


a. The statement, i.e. body of do-while statement, is executed.
b. After the execution of a do-while body, the do-while controlling expression is evaluated.
a. If it evaluates to true, the statement, i.e. do-while body is executed again and Step above is
repeated.
b. If it evaluates to false, the program control is transferred to the statement present next to the do-
while statement

Nested Loops
If the body of a loop is, or contains another iteration statement, then we say that the loops are nested. In nested
loops, the inside loop (or loops) executes completely before the outside loop’s next iteration.
− Which loop structure to use?
If you know how many times around the loop you need to go when the program execution gets to the loop statements,
use a count-controlled loop (Preferably use a for loop). If the termination of the loop depends on some condition
determined by what happens within the loop, then use a conditional loop (Preferably use a while loop or do while).

Specifying Test Condition For Selection and Iteration


A test condition used for selection and iteration is expressed as a test expression. Test expression is a Boolean
expression that is either true or false.
If an expression evaluates to true, it is given the value of 1. If a test expression evaluates to false, it is given the
value of 0. Similarly, if a numeric expression is used to form a test expression, any non-zero value (including
negative) will be considered as true, while a zero value will be considered as false.
It is formed in terms of relational expression or logical expression or both.
In addition to using simple relational expressions as conditions, compound conditions can be formed using
the logical operators.
Relational operators are used to specify individual test expression. More than one test expression can be
connected through the logical operator.
❖ Writing Test Expression
Relational expression can be formed using relational operators. A relational operator takes two operands and
compares them to each other, resulting in a value of true (1) or false (0). The syntax for relational expression is
as follows:

20
Simple Test Condition

𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒 𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒
/ /
𝐸𝑥𝑝𝑟𝑒𝑠𝑠𝑖𝑜𝑛 Relational_Operator 𝐸𝑥𝑝𝑟𝑒𝑠𝑠𝑖𝑜𝑛
/ /
{ 𝐶𝑜𝑛𝑠𝑡𝑎𝑛𝑡 } { 𝐶𝑜𝑛𝑠𝑡𝑎𝑛𝑡 }

Compound Test Condition

𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒 𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒 𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒 𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒


/ / / /
( 𝐸𝑥𝑝𝑟𝑒𝑠𝑠𝑖𝑜𝑛 Relational_Operator 𝐸𝑥𝑝𝑟𝑒𝑠𝑠𝑖𝑜𝑛 )Logical Operator ( 𝐸𝑥𝑝𝑟𝑒𝑠𝑠𝑖𝑜𝑛 Relational_Operator 𝐸𝑥𝑝𝑟𝑒𝑠𝑠𝑖𝑜𝑛 )
/ / / /
{ 𝐶𝑜𝑛𝑠𝑡𝑎𝑛𝑡 } { 𝐶𝑜𝑛𝑠𝑡𝑎𝑛𝑡 } { 𝐶𝑜𝑛𝑠𝑡𝑎𝑛𝑡 } { 𝐶𝑜𝑛𝑠𝑡𝑎𝑛𝑡 }

21
1.2 Arrays
1.2.1 Introduction
An array is a data structure that is used for the storage of homogeneous data, i.e. data of the same type. In its
simplest form, an array can be used to represent a list of numbers, or a list of names.
The group of array elements is referred with a common name called array name. Access to individual array
elements is provided with the help of an index identifier. In C language, array index starts with 0. For example,
list[5] refers to the 6th element of the array ‘list’.

Array index: row or column number of an individual array element


i Upper bound: the highest number index of an array dimension
i Lower bound: the smallest number index of an array dimension
i
i 1.2.2 Application of Arrays
Arrays are particularly used in programs that require storing large collection of similar type data elements. Some
examples where the concept of an array can be used include:
Storing the list of temperatures recorded every hour in a day, storing the list of names of employees in an organization,
storing test scores of a class of students etc.
Examples
Data to be stored Pseudocode C - Syntax
Test scores of a class of 50 students. Score : ARRAY[50] of Reals float scores[50];
Heights of students in a class of 60 Height : ARRAY[60] of Reals float height[60];
Ages of students in a class of 70 Age : ARRAY[70] of Integers int age[70];
The name of a single student that Name : ARRAY[11] of Characters char name[11];
has 10 letters
The surname of 30 students in a Names : ARRAY[30][13] of Characters char names[30][13];
classroom where each name has a
maximum of 12 letters

1.2.3 Declaration (i.e. creation) of array


An array must be declared before being used. Declaring an array means specifying the following:
▪ Data type: The kind of values it can store, for example, int, char, float, double.
▪ Name: To identify the array.
▪ Size: The maximum number of values that the array can hold.
Arrays are declared using the following syntax:
data_type name[size];
The data type can be either int, float, double, char, or any other valid data type. The number within brackets
indicates the size of the array, i.e., the maximum number of elements that can be stored in the array. In general,
arrays are classified as:
o One-dimensional arrays
o Multi-dimensional arrays
1.2.4 One-dimensional Arrays
A One-dimensional array consists of a fixed number of elements of the same data type organized as a simple linear
sequence and is declared using a single index.
▪ Declaration (i.e. Creation) of a Single-dimensional Array
Arrays are declared using the following syntax: Data_type name[size];
For example, int marks[10]; This statement declares marks to be an array containing 10 integers.

22
▪ Storing and Displaying Elements of a One-dimensional Array
An iteration statement (i.e. loop) is used for storing and reading the elements of a one-dimensional Array
− Storing Elements into a 1-D array
Reading N Elements into an Array, Elements
Pseudocode C Language
Write (“Enter the elements”) int elements[20], N, i;
FOR (i←0 TO N-1) DO printf(“Enter the elements:\n”);
Read(Elements[i]) for(i=0;i<N; i++)
ENDFOR {
scanf(“%d”, &elements[i]);
}

− Displaying Elements stored in a 1-D array

Displaying N Elements stored in an Array, Elements


Pseudocode C Language
Write (“Display of the elements”) int i;
FOR (i←0 TO N-1) DO printf(“Display of the elements:\n”);
Write(Elements[i]) for(i=0;i<N; i++)
ENDFOR {
printf(“%d”, elements[i]);
}

1.2.5 Insertion and Deletion of elements from a 1-D Array


− Insertion
Insertion is the task of adding an element into an existing array. The point of insertion that is the position where
an element is to be inserted holds vital importance.
If an element is to be inserted at the end of the array, then it can be simply achieved by storing the new element
one position to the right of the last element. However, the array must have vacant positions at the end for this to
be feasible.
Alternatively, if an element is required to be inserted at the middle, then this will require all the subsequent
elements to be moved one place to the right. Figure below depicts the insertion of an element into an array.

Figure: Insertion

23
Insertion of an element P at index location k in the array A[N], where k<N.
Pseudocode C Language
Algorithm Insert_NUMBER #include <stdio.h>
Variables int main()
A: ARRAY[10] of Integers {
i, N, num, P, K: Integers int i, N, num, P, K;
Start int A[10]= {-1, 3, 5, 22, 77};
A[10] ←{-1,3,5,22,77} N=5;
N← 5 printf("\n Enter the number to be inserted : ");
Write(Enter the number to be inserted : ) scanf("%d", &P);
Read(P) printf("\n Enter the position at which the number has to be added : ");
Write(Enter the position at which the number has to be added) scanf("%d", &K);
Read(K) for(i=N–1; i>=K; i––)
FOR (i ← 𝑁 − 1 (-1) K) DO {
A[i+1] ← A[i]; A[i+1] = A[i];
ENDFOR }
A[K] ← P; A[K] = P;
N← N+1; N = N+1;
Write("The array after insertion of is : ", P); printf("\n The array after insertion of %d is : ", P);
FOR (i←0 TO N-1) DO for(i=0;i<N;i++)
Write(A[i]:) {
ENDFOR printf("\n A[%d] = %d", i, A[i]);
Stop }
return 0;
}

− Program analysis
Key Statement Purpose
int A[10]= {-1, 3, 5, 22, 77}; Declares and initializes the array A with 5 elements
for(i=N–1; i>=K; i––) All The existing array elements need to be moved to make space for the new element.
{ This loop shuffles the array elements to the right to create space for inserting a new
arr[i+1] = arr[i]; element. It starts by shifting the last element (element at index N-1) of the array. It
} continues shifting up to at the element in the desired position
A[k] = P; Inserts a new element at the point of insertion.
N = N + 1; Increments the total number of array elements by 1.

− Deletion
The deletion of elements follows a similar procedure as insertion. The deletion of element from the end is quite simple and
can be achieved by mere updating of index identifier. However, to remove an element from the middle, one must move all
the elements present to the right of the point of deletion, one position to the left. Figure below depicts the deletion of an
element from an array.

Figure: Deletion
24
Deletion of an element at index location k in the array A[N], where k<N.
Pseudocode C Language
Algorithm Insert_NUMBER #include <stdio.h>
Variables int main()
A: ARRAY[10] of Integers {
i, N, num, D, K: Integers int i, N, num, D, K;
Start int A[10]= {-1, 3, 5, 22, 77};
A[10] ←{-1,3,5,22,77} N=5;
N← 5 printf("\n Enter the position at which the number has to be deleted : ");
Write(Enter the position at which the number has to be deleted) scanf("%d", &K);
Read(K) D = A[K];
D← 𝐴[𝐾] for(i=K; i<N–1;i++)
FOR (i ← 𝐾 𝑇𝑂 𝑛 − 2 ) DO {
A[i] ← A[i+1]; A[i] = A[i+1];
ENDFOR }
N← N-1; N = N-1;
Write("The array after deletion of is : "D); printf("\n The array after deletion of %d is : ",D);
FOR (i←0 TO N-1) DO for(i=0;i<N;i++)
Write(A[i]:) {
ENDFOR printf("\n A[%d] = %d", i, A[i]);
Stop }
return 0;
}

− Program analysis

Key Statement Purpose


int A[10]= {-1, 3, 5, 22, 77}; Declares and initializes the array A with 5 elements
for(i=K; i<N–1;i++) The existing array elements need to be moved to fill the vacant space
{ created by the deleted element.
A[i] = A[i+1]; The loop shifts the array elements to the left to fill the vacant space
} created after deleting the array element. The element just after the
element to be deleted takes the place of the deleted element
D = A[k]; Retrieves the element value that is to be deleted.
N = N - 1; Decrements the total number of array elements by 1.

1.2.6 Array of Arrays (Multi-dimensional Arrays)


A 2-D array is an array of 1-D (i.e. single dimensional) arrays and can be visualized as a plane that has rows and
columns. Each row is a single-dimensional array. A 3-D array is an array of 2-D arrays and can be visualized as a
cube that has planes. Each plane is a 2-D array
▪ Two-dimensional Arrays
A two-dimensional array has its elements arranged in a rectangular grid of rows and columns. The elements of a
two-dimensional array can be accessed by using a row subscript (i.e. row number) and a column subscript (i.e.
column number). Both the row subscript and the column subscript are required to select an element of a two-
dimensional array
▪ Declaration (i.e. Creation) of a Two-dimensional Array
A two-dimensional array is declared as:
data_type array_name[row_size][column_size];
Therefore, a two-dimensional m x n array is an array that contains m x n data elements and each element is
accessed using two subscripts, i and j, where i <= m-1 (0 ≤ 𝑖 ≤ 𝑚 − 1) and j <= n-1 (0 ≤ 𝑗 ≤ 𝑛 − 1).
For example, if we want to store the marks [All the marks are assumed to be whole numbers for this example]
obtained by three students in five different subjects, we can declare a two-dimensional array as:
int marks[3][5];
In the above statement, a two-dimensional array called marks has been declared that has m(3) rows and n(5)
columns. The first element of the array is denoted by marks[0][0], the second element as marks[0][1], and so on.

25
Here, marks[0][0] stores the marks obtained by the first student in the first subject, marks[1][0] stores the marks
obtained by the second student in the first subject. The pictorial form of a two-dimensional array is shown

Hence, we see that a 2D array is treated as a collection of 1D arrays. Each row of a 2D array corresponds to a 1D
array consisting of n elements, where n is the number of columns. To understand this, we can also see the
representation of a two-dimensional array as shown below

▪ Storing and Displaying elements of a 2-D array


The elements can be stored in a 2-D array by making use of nested loops
− Reading Elements into a 2-D array
Reading Elements into a 2-D Array, Matrix
Pseudocode C Language
Write(“Enter the row size of the matrix”) int matrix[10][10];
Read(M) int i, j, N, M;
Write(“Enter the column size of the matrix”) printf(“Enter the row size of the matrix \t”);
Read(N)
scanf(“%d”, &M);
Write(“Enter the elements of the matrix:”)
FOR (i←0 TO M-1) DO printf(“Enter the column size of the matrix \t”);
FOR (j←0 TO N-1) DO scanf(“%d”, &N);
Read(Matrix[i][j]) printf(“Enter the elements of the matrix:\n”);
ENDFOR for(i=0;i<M; i++)
ENDFOR {
for(j=0;j<N; j++)
{
scanf(“%d”,&matrix[i][j]);
}
}

− Displaying Elements stored in 2-D array

Displaying N Elements stored in an Array, Elements


Pseudocode C Language
Write(“Displaying the elements of the matrix:”) printf(“Displaying the elements of the matrix:\n”);
FOR (i←0 TO M-1) DO for(i=0;i<M; i++)
FOR (j←0 TO N-1) DO {
Write(Matrix[i][j])
for(j=0;j<N; j++)
ENDFOR
ENDFOR {
printf(“%d ”, matrix[i][j]);
}
}

26
1.2.7 Algorithm and Programming Examples
Program 1: Maximum-Minimum: Finding the maximum and minimum element in a set of n elements
Algorithm:
Step 1: Start
Step 2: Read the n items into the array. The number of elements n must be less than or equal to the size of
the array.
Step 3: Assign the first array element to two different variables (i.e. max and min) that will hold the maximum
and minimum value
Step 4: Loop through the remaining elements, starting from the second element. When a value larger than the
present maximum value is found, it becomes the new maximum. Similarly, when a value smaller than the
present minimum value is found, it becomes the new minimum
Step 5: After the termination of the loop, print the maximum and minimum values
Step 6: Stop

Pseudocode C-Code
Algorithm Min_Max #include<stdio.h>
Variables: int main()
Elements : ARRAY[20] of Integers {
Num, i, Max, Min : Integers int elements[20], num, i, max, min;
printf(“Enter the number of elements in the set (max. 20)\t”);
Start
scanf(“%d”,&num);
Write(“Enter the number of elements in the set (max. 20)”) printf(“Enter the elements:\n”);
Read (Num) for(i=0;i<num;i++)
Write (“Enter the elements”) {
FOR (i←0 TO Num-1) DO scanf(“%d”,&elements[i]);
Read(Elements[i]) }
ENDFOR max=elements[0];
Min←Elements[0] min=elements[0];
for(i=1;i<num;i++)
Max←Elements[0]
{
FOR (i← 1 TO Num-1) DO if(elements[i]>max)
IF(Elements[i]>max) THEN {
max← 𝐸lements[i]; max=elements[i];
ELSE IF (Elements[i]<min) THEN }
min← 𝐸lements[i]; else if(elements[i]<min)
ENDIF {
ENDFOR min=elements[i];
}
Write (“Maximum element in the set is ”, Max)
}
Write (“Minimum element in the set is ”, Min) printf(“Maximum element in the set is %d\n”,max);
Stop printf(“Minimum element in the set is %d\n”,min);
return 0;
}

Program 2: Calculation of arithmetic mean, variance and standard deviation of n elements


In statistics, standard deviation is used to measure deviation of data from its mean.
Algorithm:
The algorithm for calculating the standard deviation is as follows:
1. Read n numbers into an array.
2. Calculate sum and mean of the n numbers
3. Calculate variance.
4. Calculate standard deviation
∑𝑛
𝑖=1 𝑥𝑖
Arithmetic mean is given as: 𝑥̅ = 𝑛
∑𝑛
𝑖=1(𝑥𝑖 −𝑥̅ )
2
Variance is given as: 𝜎𝑥 = 𝑛
Standard deviation is given as √𝜎𝑥

27
Pseudocode C-Code
Algorithm Mean_Variance_SD #include<stdio.h>
Variables: #include<math.h>
Elements : ARRAY[20] of Reals int main()
Sum, Mean, Var, SD : Real {
Num, i : Integers float elements[20], sum=0.0, mean, var, sd;
Start int num, i;
Sum ← 0.0 printf(“Enter the number of elements (max. 20)\t”);
Write(“Enter the number of elements (max. 20)”) scanf(“%d”,&num);
Read (num) printf(“Enter the elements:\n”);
Write (“Enter the elements”) for(i=0;i<num;i++)
FOR (i←0 TO Num-1) DO {
Read(Elements[i]) scanf(“%f”,&elements[i]);
ENDFOR }
FOR (i← 0 TO Num-1) DO for(i=0;i<num;i++)
Sum←Sum+Elements[i]; {
ENDFOR sum=sum+elements[i];
Mean←Sum/Num }
Sum ← 0.0 mean=sum/num;
FOR (i← 0 TO Num-1) DO sum=0.0;
Sum← 𝑆um+(Elements[i]-Mean)*(Elements[i]-Mean); for(i=0;i<num;i++)
ENDFOR {
Var←Sum/Num sum=sum+(elements[i]-mean)*(elements[i]-mean);
SD←Sum sqrt(var); }
Write(“Arithmetic mean ”,Mean) var=sum/num;
Write(“Variance is ”,Var) sd=sqrt(var);
Write(“Standard deviation is ”,SD) printf(“Arithmetic mean is %f\n”,mean);
Stop printf(“Variance is %f\n”,var);
printf(“Standard deviation is %f\n”,sd);
return 0;
}

Program 3. Evaluating an MCQ Test


A test consisting of 25 multiple-choice items is administered to a batch of 3 students. Correct answers and student
responses are tabulated as shown below:
Items
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

Correct
Answers
Student 1
11
Student 2

Student 3

Algorithm
The algorithm for evaluating the answers of students is as follows:
1. Read correct answers into an array.
2. Read the responses of a student and count the correct ones.
3. Repeat step-2 for each student.
4. Print the results.
A program to implement this algorithm uses the following arrays:
key[i] - To store correct answers of items
response[i] - To store responses of students
correct[i] - To identify items that are answered correctly.

28
Pseudocode C-Code
Algorithm MCQ_EVALUATION #include <stdio.h>
Constants: #define STUDENTS 3
ITEMS=25 #define ITEMS 25
int main( )
STUDENTS=3
{
Variables: char key[ITEMS+1],response[ITEMS+1];
Key : ARRAY[ITEMS+1] of Characters int count, i, student, n, correct[ITEMS+1];
Response : ARRAY[ITEMS +1] of Characters printf(“Enter the correct answers\n”);
Correct : ARRAY[ITEMS+1] of Integers for(i=0; i < ITEMS; i++)
Count, i, student, n: Integers {
Start scanf(“%c”,&key[i]);
Write(“Enter the correct answers”) }
key[i] = ‘\0’;
FOR (i←0 TO ITEMS-1) DO
printf(“Enter answers of all students starting with student 1\n”);
Read(Key[i]) for(student = 1; student <= STUDENTS ; student++)
ENDFOR {
Key[i] ←‘\0’; count = 0;
Write (“Enter answers of all students starting with student 1) printf(“\n”);
FOR (student ← 1 TO STUDENTS) DO printf(“Input responses of student-%d\n”,student);
Count ← 0 for(i=0; i < ITEMS ; i++)
Write(“Input responses of ”,student); {
FOR (i← 0 TO ITEMS-1) DO scanf(“%c”,&response[i]);
}
Read(Response[i])
response[i] = ‘\0’;
ENDFOR for(i=0; i < ITEMS; i++)
Response[i] ←‘\0’; {
FOR (i← 0 TO ITEMS-1) DO correct[i] = 0;
Correct[i] ← 0; }
ENDFOR for(i=0; i < ITEMS ; i++)
FOR (i← 0 TO ITEMS-1) DO {
IF(Response[i] = Key[i]) THEN if(response[i] == key[i])
count ←count +1 ; {
count = count +1 ;
correct[i] ←1 ;
correct[i] = 1 ;
ENDIF
}
ENDFOR }
Write(“Student--”, student) printf(“\n”);
Write(“Score is out of ”,count, ITEMS) printf(“Student-%d\n”, student);
Write(“Response to the items below are wrong”) printf(“Score is %d out of %d\n”,count, ITEMS);
n ←0 printf(“Response to the items below are wrong\n”);
FOR (i← 0 TO ITEMS-1) DO n = 0;
IF(Correct[i] = 0) THEN for(i=0; i < ITEMS ; i++)
Write(“i+1 “) {
n ←n+1 if(correct[i] == 0)
ENDIF {
ENDFOR printf(“%d “,i+1);
IF(n= 0) THEN n = n+1;
Write(“NIL “) }
ENDIF }
ENDFOR if(n == 0)
Stop {
printf(“NIL\n”);
}
printf(“\n”);
}
return 0;
}

Program 4. Determining the second largest of a list of n numbers that represent ages of students in a class.
Approach:
The approach is to traverse the array twice. In the first traversal, find the maximum element.
In the second traversal, find the greatest element in the remaining excluding the previous greatest.
The program to accomplish this task will use a one-dimensional array to store the ages of the students.

29
Pseudocode C-Code
Algorithm AGES #include <stdio.h>
Variables int main()
Arr : ARRAY[70] of Integers {
int i, n, arr[70], large, second_large;
Large, i, n, Second_large; Integers
printf("\n Enter the number of ages to be registered: ");
Start scanf("%d", &n);
Write(“Enter the number of ages to be registered:”) printf("\n Enter the ages");
Read(n) for(i=0;i<n;i++)
Write(“Enter the ages:”) {
FOR (i←0 TO n-1) DO scanf("%d",&arr[i]);
Read(Arr[i]) }
ENDFOR large = arr[0];
for(i=1;i<n;i++)
Large ← 𝐴𝑟𝑟[0]
{
FOR (i ← 1 TO n-1) DO if(arr[i]>large)
IF(Arr[i] >Large) THEN {
Large ← 𝐴𝑟𝑟[𝑖] large = arr[i];
ENDIF }
ENDFOR }
Second_large ← Arr[1] second_large = arr[1];
FOR (i← 0 TO n-1) DO for(i=0;i<n;i++)
IF(Arr[i] ≠Large) THEN {
IF(Arr[i] >Second_large) THEN if(arr[i] != large)
Second_large← 𝐴𝑟𝑟[𝑖] {
ENDIF if(arr[i]>second_large)
ENDIF {
ENDFOR second_large = arr[i];
Write (The ages you entered are:) }
}
FOR (i← 0 TO n-1) DO
}
Write (Arr[i]) printf("\n The ages you entered are : ");
ENDFOR for(i=0;i<n;i++)
Write(“The largest of these is”, Large) {
Write(“The second largest of these is”, Second_large) printf("\t %d", arr[i]);
Stop }
printf("\n The largest of these is : %d",large);
printf("\n The second largest of these is : %d",second_large);
return 0;
}

Program 4. Same Age.


This program records ages of students in a classroom and determines if there are students with the same age
Approach
Store the ages in an array
Duplicate elements can be found using two loops. The outer loop will iterate through the array from 0 to length
of the array. The outer loop will select an element. The inner loop will be used to compare the selected element
with the rest of the elements of the array.
If a match is found, it means some students have the same ages. Display the ages.
The flag principle will be used to indicate when a match is found. A flag is a Boolean variable whose value
changes when an event takes place.

30
Pseudocode C-Code
Algorithm DUPLICATE_AGES #include <stdio.h>
Variables int main()
Array : ARRAY[70] of Integers {
Large, i, n, Second_large: Integers int array[10], i, n, j, flag =0;
Flag : Boolean printf("\n Enter the number of ages to be registered: ");
Start scanf("%d", &n);
Flag ←0 print(“\nEnter the ages:”)
Write(“Enter the number of ages to be registered:”) for(i=0;i<n;i++)
Read(n) {
Write(“Enter the ages:”) printf("\n array[%d] = ", i);
FOR (i←0 TO n-1) DO scanf("%d", &array[i]);
Write(Array[i]:) }
Read(Array[i]) for(i=0;i<n;i++)
ENDFOR {
FOR (i ← 0 TO n-1) DO for(j=i+1;j<n;j++)
FOR (j← 𝑖 + 1 TO n-1) DO {
IF(Array[i] =Array[j] AND i≠ 𝑗) THEN if(array[i] == array[j] && i!=j)
Flag ← 1 {
Write(“The duplicate ages are:” Array[i],Array[j]) flag =1;
ENDIF printf("\n Same ages are %d and %d", array[i], array[j]);
ENDFOR }
ENDFOR }
IF(Flag=0) THEN }
Write (“No Duplicates”) if(flag==0)
ENDIF {
Stop printf("\n No Duplicates Found");
}
return 0;
}

Program 5: Insertion of a number at a given location in an array.


Approach: There two cases:
Case 1: Element to be inserted at the end of the existing array with available space. Here, we just have to add
1 to the upper_bound and assign the value.
Case 2 : Element to be added anywhere else within the array. Here, we first find the location where the new
element will be inserted and then move all the elements one position to the right so that space can be created
to store the new value

Pseudocode C-Code
Algorithm ADD_NUMBER #include <stdio.h>
Variables int main()
Arr : ARRAY[70] of Integers {
Pos, i, n, Num: Integers int i, n, num, pos, arr[70];
Start printf("\n Enter the number of elements in the array : ");
Write(“Enter the number of elements in the array:”) scanf("%d", &n);
Read(n) for(i=0;i<n;i++)
Write(“Enter the ages:”) {
FOR (i←0 TO n-1) DO printf("\n arr[%d] = ", i);
Write(Arr[i]:) scanf("%d", &arr[i]);
Read(Arr[i]) }
ENDFOR printf("\n Enter the number to be inserted : ");
Write(Enter the number to be inserted : ) scanf("%d", &num);
Read(Num) printf("\n Enter the position at which the number has to be added : ");
Write(Enter the position at which the number has to be added) scanf("%d", &pos);
Read(Pos) for(i=n–1;i>=pos;i––)
FOR (i ← 𝑛 − 1 (-1) pos) DO {
Arr[i+1] ← Arr[i]; arr[i+1] = arr[i];
ENDFOR }
Arr[pos] ← Num; arr[pos] = num;
n← n+1; n = n+1;
Write("The array after insertion of is : ", num); printf("\n The array after insertion of %d is : ", num);
FOR (i←0 TO n-1) DO for(i=0;i<n;i++)
Write(Arr[i]:) {
ENDFOR printf("\n arr[%d] = %d", i, arr[i]);
Stop }
return 0;
}

31
Program 6: Deletion of a number from a given location in an array.
To do this, we must first find the location from where the element has to be deleted and then move all the elements
one position towards left so that the space vacated by the deleted element can be occupied by rest of the elements.

Pseudocode C-Code
Algorithm Del_NUMBER #include <stdio.h>
Variables int main()
Arr : ARRAY[70] of Integers {
Pos, i, n: Integers int i, n, pos, arr[70];
Start printf("\n Enter the number of elements in the array : ");
Write(“Enter the number of elements in the array:”) scanf("%d", &n);
Read(n) for(i=0;i<n;i++)
FOR (i←0 TO n-1) DO {
Write(Arr[i]:) printf("\n arr[%d] = ", i);
Read(Arr[i]) scanf("%d", &arr[i]);
ENDFOR }
Write(Enter the position from which the number has to be deleted) printf("\nEnter the position from which the number has to be deleted : ");
Read(Pos) scanf("%d", &pos);
FOR (i ← 𝑃𝑜𝑠 𝑇𝑂 𝑛 − 2 ) DO for(i=pos; i<n–1;i++)
Arr[i] ← Arr[i+1]; {
ENDFOR arr[i] = arr[i+1];
n← n-1; }
Write("The array after deletion is: "); n––;
FOR (i←0 TO n-1) DO printf("\n The array after deletion is : ");
Write(Arr[i]) for(i=0;i<n;i++)
ENDFOR {
Stop printf("\n arr[%d] = %d", i, arr[i]);
}
return 0;
}

Program 7 Upper triangular matrix: Extract the upper triangular matrix from a square matrix
A square matrix in which all the elements below the main (i.e. principal) diagonal are zero is known as upper
triangular matrix and a square matrix in which all the elements above the main diagonal are zero is known as
lower triangular matrix.
Upper triangular matrix can be extracted from a square matrix by extracting the elements of principle diagonal
and the elements that lie above it. Consider the following 3 x 3 Matrix
𝑎00 𝑎01 𝑎02
A= (𝑎10 𝑎11 𝑎12 )
𝑎20 𝑎21 𝑎22
We notice the following:
Along the main (i.e. principal) diagonal, the row and column number are equal. That is i=j where i represents
row and j column for all elements on the principal diagonal
Above the principal diagonal, i<j, that’s the row number is less than the column number
Below the principal diagonal, i>j, that’s the row number is greater than the column number

32
Pseudocode C-Code
Algorithm U_Triangular #include<stdio.h>
Variables int main()
Matrix : ARRAY[10][10] of Integers {
UT_Matrix : ARRAY[10][10] of Integers
int matrix[10][10], ut_matrix[10][10];
Order, i, j: Integers
Start int i, j, order;
Write(“Enter the order of the square matrix(max. 10 by 10):”) printf(“Enter the order of the square matrix(max. 10 by 10)\t”);
Read(Order) scanf(“%d”,&order);
Write(“Enter the elements of the matrix:”) printf(“Enter the elements of the matrix:\n”);
FOR (i←0 TO Order-1) DO for(i=0;i<order;i++)
FOR (j←0 TO Order-1) DO {
Read(Matrix[i][j]) for(j=0;j<order;j++)
ENDFOR
scanf(“%d”,&matrix[i][j]);
ENDFOR
FOR (i←0 TO Order-1) DO }
FOR (j←0 TO Order-1) DO for(i=0;i<order;i++)
IF(i≤j) THEN for(j=0;j<order;j++)
UT_Matrix[i][j] ← Matrix[i][j]; if(i<=j)
ELSE ut_matrix[i][j]=matrix[i][j];
UT_Matrix[i][j] ← 0 else
ENDIF ut_matrix[i][j]=0;
ENDFOR printf(“Upper Triangular matrix is:\n”);
ENDFOR for(i=0;i<order;i++)
{
Write(Upper Triangular matrix is) for(j=0;j<order;j++)
FOR (i←0 TO Order-1) DO printf(“%d\t “,ut_matrix[i][j]);
FOR (j←0 TO Order-1) DO printf(“\n”);
Write(Matrix[i][j])
}
ENDFOR
ENDFOR return 0;
}
Stop

Program 8 Strictly upper triangular matrix: Check whether a given matrix is strictly upper triangular or not
An upper triangular matrix is strictly upper triangular if the elements of the principal diagonal are zero.

Pseudocode C-Code
Algorithm SU_Triangular_Test #include<stdio.h>
Variables int main()
Matrix : ARRAY[10][10] of Integers {
Notzero, Order, i, j: Integers
int matrix[10][10], notzero=0;
Start
int i,j,order;
Notzero←0;
Write(“Enter the order of the square matrix(max. 10 by 10):”) printf(“Enter the order of the square matrix(max. 10 by 10)\t”);
Read(Order) scanf(“%d”,&order);
Write(“Enter the elements of the matrix:”) printf(“Enter the elements of the matrix:\n”);
FOR (i←0 TO Order-1) DO for(i=0;i<order;i++)
FOR (j←0 TO Order-1) DO {
Read(Matrix[i][j]) for(j=0;j<order;j++)
ENDFOR scanf(“%d”,&matrix[i][j]);
ENDFOR
}
FOR (i←0 TO Order-1) DO
FOR (j←0 TO Order-1) DO for(i=0;i<order;i++)
IF(i≥j) THEN {
IF(Matrix[i][j]≠ 0) THEN for(j=0;j<order;j++)
Notzero ← 1 if(i>=j)
Break if(matrix[i][j]!=0)
ENDIF {
ENDIF notzero=1;
ENDFOR break;
IF(Notzero=1) THEN }
Break if(notzero==1)
ENDIF break;
ENDFOR }
IF(Notzero=1) THEN if(notzero==1)
Write(The matrix is not strictly upper triangular) printf(“The given matrix is not strictly upper triangular\n”);
ELSE else
Write(The matrix is strictly upper triangular) printf(“The given matrix is strictly upper triangular\n”);

33
ENDIF return 0;
Stop }

Program 9 Sum of principal diagonal elements of a square matrix


The set of elements extending from the upper-left-most corner to the lower-right-most corner in a square
matrix are known as principal diagonal elements.
An element Aij of a square matrix is principle diagonal element if and only if i=j.
Pseudocode C-Code
Algorithm SUM_DIAGONAL #include<stdio.h>
Variables int main()
Matrix : ARRAY[10][10] of Integers {
Sum, Order, i, j: Integers
int matrix[10][10];
Start
int order, sum=0, i, j;
Sum←0;
Write(“Enter the order of the square matrix(max. 10 by 10):”) printf(“Enter the order of the square matrix(max. 10)\t”);
Read(Order) scanf(“%d”,&order);
Write(“Enter the elements of the matrix:”) printf(“Enter the elements of matrix:\n”);
FOR (i←0 TO Order-1) DO for(i=0;i<order;i++)
FOR (j←0 TO Order-1) DO {
Read(Matrix[i][j]) for(j=0;j<order;j++)
ENDFOR scanf(“%d”,&matrix[i][j]);
ENDFOR
}
FOR (i←0 TO Order-1) DO
Sum←Sum+ Matrix[i][i] for(i=0;i<order;i++)
ENDFOR sum=sum+matrix[i][i];
Write(The sum of the elements is:Sum) printf(“Sum of elements of principal diagonal is %d”,sum);
Stop return 0;
}

Program 10 Matrix transpose: Find the transpose of a given matrix


The transpose of the matrix A is another matrix 𝐴𝑇 , which can be found by any one of the following actions:
1. Writing the rows of A as the columns of 𝐴𝑇 ,
2. Writing the columns of A as the rows of 𝐴𝑇 ,
3. Reflect A about its main diagonal to obtain 𝐴𝑇 , (only possible in case of square matrix).
The transpose of an m×n matrix A with elements Aij is an n×m matrix 𝑨𝑻 =Aji, 1≤i≤n and 1≤j≤m.

Pseudocode C-Code
Algorithm MATRIX_TRANSPOSE #include<stdio.h>
Variables int main()
Matrix : ARRAY[10][10] of Integers {
Matrix_Transpose : ARRAY[10][10] of Integers
int matrix[10][10], matrix_transpose[10][10];
m, n , i, j: Integers
Start int m, n, i, j;
Write(“Enter the order of the matrix(max. 10 by 10):”) printf(“Enter the order of the matrix(max. 10 by 10)\t”);
Read(m, n) scanf(“%d %d”, &m, &n);
Write(“Enter the elements of the matrix:”) printf(“Enter the elements of the matrix:\n”);
FOR (i←0 TO m-1) DO for(i=0;i<m; i++)
FOR (j←0 TO n-1) DO {
Read(Matrix[i][j]) for(j=0;j<n;j++)
ENDFOR
scanf(“%d”,&matrix[i][j]);
ENDFOR
FOR (i←0 TO n-1) DO }
FOR (j←0 TO m-1) DO for(i=0;i<n; i++)
Matrix_Transpose[i][j] ←Matrix[j][i]; for(j=0;j<m; j++)
ENDFOR matrix_transpose[i][j]=matrix[j][i];
ENDFOR printf(“Transpose of the matrix is:\n”);
Write(Transpose of the matrix is:) for(i=0;i<n; i++)
FOR (i←0 TO m-1) DO {
FOR (j←0 TO n-1) DO for(j=0;j<m; j++)
Write(Transpose_Matrix[i][j]) printf(“%d \t“,matrix_transpose[i][j]);
ENDFOR
printf(“\n”);
ENDFOR
Stop }
return 0;
}

34
Program 11 Check whether a given square matrix is symmetric or not

A square matrix A is symmetric if A=𝐴𝑇 (i.e. the matrix is equal to its transpose).

Pseudocode C-Code
Algorithm SYMMETRIC #include<stdio.h>
Variables int main()
Matrix : ARRAY[10][10] of Integers {
Matrix_Transpose : ARRAY[10][10] of Integers int matrix[10][10], matrix_transpose[10][10], unequal=0;
Order, Unequal , i, j: Integers int i, j, order;
Start printf(“Enter the order of the square matrix(max. 10 by 10)\t”);
Unequal ←0 scanf(“%d”,&order);
Write(“Enter the order of the matrix(max. 10 by 10):”) printf(“Enter the elements of the matrix:\n”);
Read(Order) for(i=0;i<order;i++)
Write(“Enter the elements of the matrix:”) {
FOR (i←0 TO m-1) DO for(j=0;j<order;j++)
FOR (j←0 TO n-1) DO scanf(“%d”,&matrix[i][j]);
Read(Matrix[i][j]) }
ENDFOR for(i=0;i<order;i++)
ENDFOR for(j=0;j<order;j++)
FOR (i←0 TO Order-1) DO matrix_transpose[i][j]=matrix[j][i];
FOR (j←0 TO Order-1) DO for(i=0;i<order;i++)
Matrix_Transpose[i][j] ←Matrix[j][i]; {
ENDFOR for(j=0;j<order;j++)
ENDFOR if(matrix[i][j]!=matrix_transpose[i][j])
FOR (i←0 TO Order-1) DO {
FOR (j←0 TO Order-1) DO unequal=1;
IF(Matrix[i][j]≠ 𝑀atrix_Transpose[i][j]) THEN break;
Unequal ← 1 }
Break if(unequal==1)
ENDIF break;
ENDFOR }
IF(Unequal=1) THEN if(unequal==0)
Break printf(“The matrix is symmetric\n”);
ENDIF else
ENDFOR printf(“The matrix is not symmetric\n”);
IF(Unequal=0) THEN return 0;
Write(The matrix is symmetric:) }
ELSE
Write(The matrix is symmetric:)
ENDIF
Stop

Program 12 Matrix multiplication: Multiply two matrices


Two matrices can be multiplied with each other if the number of columns in the first matrix is equal to the number
of rows in the second matrix. Therefore, m x n matrix A can be multiplied with a p x q matrix B if n=p. The
dimension of the product matrix is m x q. The elements of two matrices can be multiplied by writing:
𝐶𝑖,𝑗 = ∑ 𝐴𝑖,𝑘 𝐵𝑘,𝑗 𝑓𝑜𝑟 𝑘 = 1 𝑡𝑜 𝑛

Given two matrices A and B


𝐴 𝐴12 𝐵 𝐵12 𝐵13
A = ( 11 ) and B = ( 11 )
𝐴21 𝐴22 𝐵21 𝐵22 𝐵23
The result of the matrix multiplication is given as:
𝐴 𝐵 + 𝐴12 𝐵21 𝐴11 𝐵12 + 𝐴12 𝐵22 𝐴11 𝐵13 + 𝐴12 𝐵23
𝐶2𝑥3 = 𝐴2𝑥2 𝐵2𝑥3 = ( 11 11 )
𝐴21 𝐵11 + 𝐴22 𝐵21 𝐴21 𝐵12 + 𝐴22 𝐵22 𝐴21 𝐵13 + 𝐴22 𝐵23

35
Pseudocode C-Code
Algorithm PRODUCT #include<stdio.h>
Variables #include<stdlib.h>
Mat1 : ARRAY[10][10] of Integers int main()
Mat2 : ARRAY[10][10] of Integers
{
Res : ARRAY[10][10] of Integers
m1, n1, m2, n2 , i, j, k: Integers int mat1[10][10], mat2[10][10], resultant[10][10]={0};
Start int m1, n1, m2, n2, i, j, k;
Write(“Enter the order of the matrix 1(max. 10 by 10):”) printf(“Enter the order of matrix-1 (max. 10 by 10)\t”);
Read(m1, n1) scanf(“%d %d”,&m1, &n1);
Write(“Enter the elements of the matrix:”) printf(“Enter the elements of matrix-1:\n”);
FOR (i←0 TO m1-1) DO for(i=0;i<m1;i++)
FOR (j←0 TO n1-1) DO {
Read(Mat1[i][j])
for(j=0;j<n1;j++)
ENDFOR
ENDFOR {
Write(“Enter the order of the matrix 2(max. 10 by 10):”) scanf(“%d”,&mat1[i][j]);
Read(m2, n2) }
Write(“Enter the elements of the matrix:”) }
FOR (i←0 TO m2-1) DO printf(“Enter the order of matrix-2 (max. 10 by 10)\t”);
FOR (j←0 TO n2-1) DO scanf(“%d %d”,&m2, &n2);
Read(Mat2[i][j]) printf(“Enter the elements of matrix-2:\n”);
ENDFOR
for(i=0;i<m2;i++)
ENDFOR
IF(n1≠m2) THEN {
Write(Matrices are incompatible for multiplication) for(j=0;j<n2;j++)
Exit(1) {
ELSE scanf(“%d”,&mat2[i][j]);
FOR (i←0 TO m1-1) DO }
FOR (j←0 TO n2-1) DO }
FOR (k←0 TO n1-1) DO if(n1!=m2)
Res[i][j] ←Res[i][j]+Mat1[i][k]*Mat2[k][j]; {
ENDFOR printf(“Matrices are not compatible for multiplication\n”);
ENDFOR
exit(1);
ENDFOR
ENDIF }
Write(The result of matrix multiplication is:) else
FOR (i←0 TO m1-1) DO {
FOR (j←0 TO n2-1) DO for(i=0;i<m1;i++)
Write(Res[i][j]) {
ENDFOR for(j=0;j<n2;j++)
ENDFOR {
Stop for(k=0;k<n1;k++)
{
resultant[i][j]=resultant[i][j]+mat1[i][k]*mat2[k][j];
}
}
}
}
printf(“The result of matrix multiplication is:\n”);
for(i=0;i<m1;i++)
{
for(j=0;j<n2;j++)
{
printf(“%d\t”, resultant[i][j]);
}
printf(“\n”);
}
return 0;
}

36
1.3 Subroutines, Local and Global Variables
1.3.1 Introduction
Some tasks within your program are complex and involve many lines of code, but in the end these lines of code
are intended to carry out a specific task. Including all those lines of complex code in the middle of your program
will probably make it harder to understand, so instead you could put the code in a subroutine and put the
subroutine itself somewhere else in the program, away from the main body of the program.
This also means that if you want to alter the subroutine it is easier to find. It also makes the main body of the code
easier to work through.
If you have to carry out the same task in lots of different places in the program, then instead of having to rewrite
the same code over and over again, you would create the code once as a subroutine and call it from the various
places through the program

In programming a subroutine is a named block of programming code that performs a specific task within
i
a program. Subroutines are also called subprograms.
i
Alliprograms therefore are made up of a number of subroutines. Subroutines use variables that can either be local
or iglobal. Local variables are those that can only be used within that subroutine whereas global variables are
accessible throughout the program
− Subroutines must be given unique identifiers or names, which means that once they have been written
they can be called using their name at any time while the program is being run
The advantages of breaking down a program into subprogram include:
− it reduces duplicate code within a program, thereby reducing the size of the program
− it enables reuse of code in a program or across programs
− it makes it easier to maintain a program
− it helps to divide a large programming task amongst various programmers, which saves time and
increases quality
▪ Parameters and Arguments
In order for a subroutine to operate efficiently you need a way to control the data that it takes in. This is usually
done by using parameters and arguments. A parameter works like a variable in that it identifies the data that you
want a subroutine to take in and use. The argument is the actual value being passed to the subroutine.
▪ Local and Global Variables
The value of a variable is constantly changing throughout the program and values may be passed around between
subroutines. If the subroutine changes the value stored in the variable, this may be passed back to the original
subroutine or on to another subroutine.
− An important aspect of programming is keeping track of the state of variables and one of the main causes
of program errors is when the value of a variable is changed within one subroutine, that then has an impact
on another subroutine. This is known as a side effect.
It is good practice to use local variables wherever possible and using them has a number of advantages:
− You cannot inadvertently change the value being stored somewhere else in the program.
− You could use the same variable name in different sections, and each could be treated as a separate
variable.
− You free up memory as each time a local variable is finished with, it is removed from memory.
You should only use a global variable where it needs to be available throughout the whole program. For example,
you might store the password to a program as a global variable if you wanted to make a password accessible to
different sections of your code.
Most high-level programming languages support two types of subroutines: Function and Procedure

37
1.3.2 Procedures
A procedure is a subroutine that does not return a value.
They are usually called to perform a specific task using the following format

Format to Use When Calling A Procedure


Pseudocode C Syntax
𝑞𝑢𝑎𝑑𝑠(𝑥) quads(x);
− 𝑞𝑢𝑎𝑑𝑠(𝑥)is the name of a procedure − 𝑞𝑢𝑎𝑑𝑠(𝑥)is the name of a procedure
− x is the value it receives as argument − x is the value it receives as argument
− It doesn’t return a value hence needless for the − It doesn’t return a value hence needless for the
assignment statement assignment statement

1.3.3 Functions
A function is a subroutine that returns a value.
They are usually called to perform a specific task using the following format
Format to Use When Calling A Function
Pseudocode C Syntax
𝐴 ← 𝑟𝑜𝑜𝑡𝑠(𝑥) A=roots(x);
− roots() is the name of a function − roots() is the name of a function
− x is the value it receives as argument − x is the value it receives as argument
− The value returned by the function is stored in − The value returned by the function is stored in the
the variable A and can be used in the calling variable A and can be used in the calling function
function

1.3.4 A Multi-Function Program


Every program must contain a main function. The program execution always begins with the main function. In
addition to the main function, a program can be further divided into a number of functions (for example Function
A, B and C), each performing a specific task. These functions are called in the main.

38
The figure below shows the interaction between the main function and a couple of other functions.

In the figure, the main() calls a function named func1() to perform a task. Therefore, main() is known as the
calling function and func1() is known as the called function. The moment the compiler encounters a function
call, the control jumps to the statements that are a part of the called function.
− After the called function is executed, the control is returned to the calling program.
− The main() function can call as many functions as it wants and as many times as it wants. For example, a
function call placed within a for loop, while loop, or do–while loop may call the same function multiple
times.
− Not only main(), any function can call any other function. For example, in the figure above, one function
calls another, and the other function in turn calling some other function.
Based upon who develops the function, functions are classified as:
User-defined functions
Library functions
1.3.5 Library Functions
Library functions or pre-defined functions are the functions whose functionality has already been developed by
someone and are available to the user for use . For example, printf and scanf are library functions. There are
two aspects of working with library functions:
❖ Declaration of library functions
❖ Use of library functions
1. Declaration of Library Functions/Role of Header Files
To use a library function such as printf or sqrt, its corresponding header file is added at the top of the program as
follows: #include <name_of_header_file.h> e.g. #include <math.h>, #include<string.h>, etc.
The header file contains the declarations of library functions, including these header files make these declarations
accessible in your program.
2. Use of Library Functions
The role and usage of some of the common library functions are listed below
❖ Library of Standard Input/ Output Functions: #include <stdio.h>
The functionality of standard input and output operations is provided by this library. The declarations of these
functions are available in the header file stdio.h. The common standard input/output functions are printf, scanf,
gets, puts, getch, getchar, putch, putchar, etc.
❖ Library of String Processing Functions #include <string.h>
This library consists of functions that are used for string processing. The common string library functions are
strcpy, strrev, strcat, strcmp, strcmpi, etc. The declarations of these functions are available in the header file
string.h.
❖ Library of Date time functions #include<time.h>
The time.h header defines four variable types, two macro and various functions for manipulating date and time.
Examples include time(), setdate() etc.
❖ Library of Mathematical Functions
The mathematical library defines some of the common mathematical functions. The declarations
of these mathematical functions are available in the header file math.h

39
#include<math.h>
Function Role Example
sqrt(x) square root of x sqrt(4.0) is 2.0, sqrt(10.0) is 3.162278
exp(x) exponential (ex) exp(1.0) is 2.718282
log(x) natural logarithm of x (base e) log(2.0) is 0.693147
log10(x) logarithm of x (base 10 log10(10.0) is 1.0
fabs(x) absolute value of x fabs(-2.0) is 2.0
ceil(x) rounds x to smallest integer not less than x ceil(9.2) is 10.0, ceil(-9.2) is -9.0
floor(x) rounds x to largest integer not greater than x floor(9.2) is 9.0, floor(-9.2) is -10.0
pow(x,y) x raised to power y (𝑥 𝑦 ) pow(2,2) is 4.0
fmod(x,y) remainder of x/y as floating-point number fmod(13.657, 2.333) is 1.992
sin(x) sine of x (x in radian) sin(0.0) is 0.0
cos(x) cosine of x (x in radian) cos(0.0) is 1.0
tan(x) tangent of x (x in radian) tan(0.0) is 0.0

Others include acos, asin, atan, cosh, sinh, and tanh

i The return type of every math library function is double.


i
i ❖ Library of Standard Utility functions
Stdlib.h is a header file that declares a variety of utility functions for type conversions, memory allocation, process
i
control, random number generator and other similar tasks. This library contains functions such as atoi, rand, abs,
srand etc.
#include<stdlib.h>
Function Role
abs(i) Return the absolute value of i. e.g. abs(-4)=4
atof(s) Convert string s to a double-precision quantity.
atoi(s) Convert string s to an integer.
atol(s) Convert string s to a long integer.
calloc(u1,u2) Allocate memory for an array having u1 elements, each of length u2 bytes.
Return a pointer to the beginning of the allocated space.
exit(u) Close all fi les and buffers, and terminate the program. (Value of u is assigned by the
function, to indicate termination status).
free(p) Free a block of allocated memory whose beginning is indicated by p.
malloc(u) Allocate u bytes of memory. Return a pointer to the beginning of the allocated space.
rand(void) Return a random positive integer.
realloc(p, u) Allocate u bytes of new memory to the pointer variable p. Return a pointer to the
beginning of the new memory space.
srand(u) Initialize the random number generator.
system(s) Pass command string s to the operating system. Return 0 if the command is successfully
executed; otherwise, return a nonzero value typically –1.

❖ Library of Character testing and conversion functions


#include<ctype.h>
Function Role
islower(c) Determine if argument is lowercase. Return nonzero value if true; 0 otherwise.
isalpha(c) Determine if argument is alphabetic. Return nonzero value if true; 0 otherwise.
iscntrl(c) Determine if argument is a control character or not. Return nonzero value if true; 0 otherwise.
islower(c) Determine if argument is lowercase. Return nonzero value if true; 0 otherwise.
isupper(c) Determine if argument is uppercase. Return nonzero value if true; 0 otherwise.
toascii(c) Convert value of argument to ASCII.
tolower(c) Convert letter to lowercase.
toupper(c) Convert letter to uppercase.

40
1.3.6 User-defined Functions (programmer-defined functions)
User-defined functions are the functions that are defined (i.e. developed) by the user at the time of writing a program.
The user develops the functionality by writing the body of the function. There are three aspects of working with user-
defined functions:
1. Function declaration, also known as function prototype
2. Function definition
3. Function use, also known as function call or function invocation
1.3.7 Function Declaration
All the functions need to be declared or defined before they are used (i.e. called). The general form of a function
declaration is: [return_type] function_name([parameter_list or parameter_type_list]);
The terms enclosed within the square brackets are optional and might not be present in a function declaration
statement. The terms shown in bold are the mandatory parts of a function declaration
1.3.8 Function Definition
Function definition, also known as function implementation, means composing a function. Every function definition
consists of two parts:
1. Header of the function
2. Body of the function
Thus, defining a function involves composing its header and the body
Header of a Function
The general form of header of a function is: [return_type] function_name([parameter_list])
The terms enclosed within the square brackets are optional and might not be present in a function header. The
specification of the return type is optional. If specified, the return type of a function can be any type (e.g. char, int,
float, int*, int**, void, etc.) except array type and function type.
The return type of a function can be:
An integer
A character
A real number (float)
A record (structure)
A pointer
BUT IT CANNOT BE
An array
Other functions

Body of a Function
The body of a function consists of a set of statements enclosed within braces. A function can have special executable
statement known as the return statement. The return statement is used to return the result of the computations done
in the called function and/or to return the program control back to the calling function.
Function Definition: Header and Body are shown below

STUCTURE OF A FUNCTION
Pseudocode C-Code
return_data_type FUNCTION function_name return_data_type function_name (data_type variable1,
([data_type variable1, data_type variable2,…… ]) data_type variable,……)
Start {
//Declaration of local variables //Declaration of local variables first
Variable: //Execution part of the function
//Execution part of the function Instruction 1
Instruction 1 Instruction 2. ...
Instruction 2. ... Instruction n
Instruction n return result;
Return result
}
Stop

41
STUCTURE OF A PROCEDURE
Pseudocode C-Code
PROCEDURE Procedure_name ([data_type variable1, void procedure_name (data_type variable1,
data_type variable2,…… ]) data_type variable,……)
{
Start
//Declaration of local variables
//Declaration of local variables
//Execution part of the function
Variable:
Instruction 1
//Execution part of the function
Instruction 2. ...
Instruction 1
Instruction n
Instruction 2. ...
return; // This can be omitted since no value is returned
Instruction n
Return; // This can be omitted since no value is returned }
Stop

(data_type variable1, data_type variable,……) are called formal parameters.

return Statement
The return statement is used to return the result of the computations performed in the called function and/or to
transfer the program control back to the calling function. There are two forms of the return statement:
return; This form of the return statement is used when a subroutine does not return any value (i.e. inside void
procedures).
return expression; for example, return 3.1428*radius*radius; return n*fact(n-1);
Although, a number of return statements can be placed inside the body of a function, only one of them that appears
first in the logical flow of control gets executed.

It is not possible to return more than one value (without making the use of structures) by making use of the return
i statement. However, it is possible to indirectly return more than one value to the calling function using pointers.
i
i▪ Subroutines can be used in a program in various ways:
i o Functions can perform operations on their parameters and return a value.
o Functions can manipulate information on their parameters and return a value that simply indicates
the success or failure of that manipulation.
o Procedures can have no return type.

1.3.9 Function Calls


A function can be called by simply using the function name followed by a list of actual parameters (or arguments),
if any, enclosed in parentheses.
The general form of the function/procedure call statement (or construct) is
− procedure_name(variable1, variable2,…);
or
− Variable_Name = function_name(variable1, variable2,…);
If there are no arguments to be passed in the function, i.e., the argument is void, then the calling statement would
be
− procedure_name();
or
− Variable_Name = function_name();
42
− Example:

main( )
{
int y;
y = mul(10,5); /* Function call */
printf(“%d\n”, y);
}

When the compiler encounters a function call, the control is transferred to the function mul(). This function is
then executed line by line as described and a value is returned when a return statement is encountered. This
value is assigned to y. This is illustrated below:

The function call sends two integer values 10 and 5 to the function. int mul(int x, int y) which are assigned to x
and y respectively. The function computes the product x and y, assigns the result to the local variable p, and then
returns the value 50 to the main where it is assigned to y again.
Remark:
If mul() was a procedure (a subroutine with no return value) there will be no need for the variable y in the main.
1.3.10 The Scope, Visibility and Lifetime of Variables
The scope of variable determines over what region of the program a variable is actually available for use (‘active’).
Longevity refers to the period during which a variable retains a given value during execution of a program (‘alive’).
So, longevity has a direct effect on the utility of a given variable. The visibility refers to the accessibility of a
variable from the memory.
Automatic Variables or Local Variables or Internal Variables.
Automatic variables are declared inside a function in which they are to be utilized. They are created when the
function is called and destroyed automatically when the function is exited, hence the name automatic. Automatic
variables are therefore private (or local) to the function in which they are declared.
External Variables or Global Variables.
Variables that are both alive and active throughout the entire program are known as external variables. Unlike
local variables, global variables can be accessed by any function defined in the program i.e. a global variable is
available for use throughout your entire program after its declaration. External variables are declared outside a
function.
PARAMETERS
The expressions that appear within the parentheses of a function call are known as arguments(or actual
parameters), and the variables declared in the parameter list in the function header are known as formal
parameters.

43
main()
{
………………
𝒂𝒄𝒕𝒖𝒂𝒍 𝒑𝒂𝒓𝒂𝒎𝒆𝒕𝒆𝒓𝒔 𝒐𝒓 𝒂𝒓𝒈𝒖𝒎𝒆𝒏𝒕𝒔
Function
⏞ 𝒂𝟐, 𝒂𝟑, . . . . . . . . . . . . . . . . . . . 𝒂𝒎)
Function 1 (𝒂𝟏,
Call
………………
}
Called
Function 1 (𝒇𝟏,
⏟ 𝒇𝟐, 𝒇𝟑, … … … … … … … . . 𝒇𝒏)
Function 𝒇𝒐𝒓𝒎𝒂𝒍 𝒑𝒂𝒓𝒂𝒎𝒆𝒕𝒆𝒓𝒔
{
……….……..
………………
}

Arguments matching between the function call and the called function

Depending upon whether the values or addresses (i.e. pointers) are passed as arguments to a function, the
argument passing methods in C language are classified as:
1. Pass by value
2. Pass by address
Passing Arguments by Value or Call by Value
In this method, the values of actual arguments are copied to the formal parameters of the function. If the arguments are
passed by value, the changes made in the values of formal parameters inside the called function are not reflected back
to the calling function
Passing Arguments by Address/Reference or call by address or call by reference.
In this method, the addresses of the actual arguments are passed to the formal parameters of the function. If the
arguments are passed by reference, the changes made in the values pointed to by the formal parameters in the called
function are reflected back to the calling function.
Passing One-dimensional Arrays to Functions
The syntactic rules to pass one-dimensional arrays to a function are as follows:
1. The actual argument in the function call should only be the name of the array without any subscript.
For example find_max_min(arr, nele); arr is the array
2. The corresponding formal parameter in the function definition must be of array type or pointer type (i.e. pointer to
the first element of the array). If a formal parameter is of array type, it will be implicitly converted to pointer type.
For example void find_max_min(int arr[], int nele) arr is the array
3. The corresponding parameter type in the function declaration should be of array type or pointer type.
Passing Two-dimensional Arrays to Functions
The syntactic rules to pass two-dimensional arrays to a function are as follows:
1. The actual argument in the function call should be the name of an array.
For example largest_ele(arr, rows, cols); arr is the array
2. The corresponding formal parameter in the function definition must be of array type or pointer type (i.e. pointer to
the first element of the array).
a. If the formal parameter is of array type, it is mandatory to specify the column specifier.
b. If the formal parameter is of pointer type, it must be a pointer to an element of the two-dimensional array (i.e. one-
dimensional array having the number of columns same as the number of columns specified for the two-dimensional
array).
For example void largest_ele (int arr[][10],int rows, int cols) arr is a 2D array

44
1.3.11 Recursion
In recursive programming, a function calls itself. A function that calls itself is known as a recursive function, and the
phenomenon is known as recursion. Every recursive solution has two major cases. They are:
Base case, in which the problem is simple enough to be solved directly without making any further calls to the same
function. Every recursive algorithm requires at least one base case in order to be valid.
General (Recursive) case, in which first the problem at hand is divided into simpler sub-parts. Second the function calls
itself but with sub-parts of the problem obtained in the first step. Third, the result is obtained by combining the
solutions of simpler sub-parts

A recursive function is one that calls itself directly or indirectly to solve a smaller version of its task until a final
i call which does not require a self-call.
i
i
i
Structure of a recursive function
Pseudocode C-Code
return_data_type FUNCTION function_name return_data_type function_name (data_type variable1,
([data_type variable1, data_type variable2,…… ]) data_type variable,……)
Start {
//Declaration of local variables //Declaration of local variables
Variable: //Execution part of the function
//Execution part of the function if(Base_Case_Condition)
IF(Base_Case_Condition) THEN {
Base_Case_Instruction Base_Case_Instruction;
ELSE }
Return function_name (PARAMETER_CHANGES) else
ENDIF {
Stop return function_name (PARAMETER_CHANGES);
}

Example
FIBONACCI SEQUENCE Pseudocode
The Fibonacci series is a series in which each number is the Integer: FUNCTION fib (Integer n)
sum of the two previous numbers in the series. The first nine Begin
terms of the series are 0, 1, 1, 2, 3, 5, 8, 13, and 21. IF (n=0) THEN
The Fibonacci series is defined as follows Return 0
F(0) = 0 ELSE
F(1) = 1 IF (n=1) THEN
F(n) = F(n-1) + F(n-2), n≥ 𝟐 Return 1
F(0) and F(1) are the base cases ELSE
Input to the function: integer n>=0 Return (fib (n-1) + fib (n-2))
Output: nth Fibonacci number. ENDIF
ENDIF
End

45
1.3.12 Random-Number Generation: Simulation and Game Playing.
Pseudocode Implementation in C
To generate random numbers in pseudocode we use the We use the rand() function from the stdlib.h library. The
Random() function. This function generates random whole rand() function generates an integer between 0 and
numbers in the interval [0;+∞[ RAND_MAX. RAND_MAX is equal to 32,767 in some systems
For example the instruction n←Random(); assigns a and has a higher value in some other systems.
random whole number in the interval [0;+∞[ to the The values generated by rand are always in the range:
variable n. 0 ≤ rand() ≤ RAND_MAX
Task: Generate random numbers within an arbitrarily To generate random numbers within the interval [a; 𝑏], we
interval [a; 𝑏] use a + rand() % (b-a+1);
To do this, we need a: To generate random numbers within the interval ]𝑎; 𝑏[, we
❖ Shifting value (which is equal to the first number in the use a+1 + rand() % (b-a-1);
desired range of consecutive integers) For example the statement int face = 1 + rand() % 6;
❖ Scaling factor (which is equal to the width of the simulates rolling a six-sided die as it randomly generates the
desired range of consecutive integers). The width is the following numbers 1, 2, 3, 4, 5 and 6 and assigns them to the
number of consecutive integers in the range. variable face.
To generate random numbers with a given shifting value The sequence of random whole numbers generated repeats
and a scaling factor we simply, itself each time the program is executed.
n ← shifting value + Random() MOD scaling factor; To produce a different sequence of random numbers for each
To generate random numbers within the interval execution is accomplished with the standard library function
[a; 𝑏], srand. Function srand takes an int argument and seeds
Scaling factor: function rand to produce a different sequence of random
❖ There are b-a+1 numbers between a and b with a and numbers for each program execution. The following syntax is
b inclusive. used to seed the rand srand(time(NULL));
❖ There are b-a-1 numbers between a and b with a and b The function prototype for time is in <time.h>.
exclusive To generate a different sequence of random numbers each
Shifting value : time, we use the time.h library.
In this case the first value is a.
Hence the instruction: Therefore, two libraries are used to generate a different
• a + Random() MOD (b-a+1); will generate random sequence of random whole numbers during each program
numbers between a and b with a and b inclusive execution:
• a+1 + Random() MOD (b-a-1); will generate random
#include<stdlib.h> and #include<time.h>
numbers between a and b with a and b excusive.

1.3.13 A Common Technique: The Flag Principle


The flag principle, is a small flag, which will remain down as long as the expected event does not occur. And, as
soon as this event takes place, the small flag rises (the Boolean variable changes value). This is implemented using
a Boolean variable (Variable of type Boolean). This variable is initially assigned the value False. The value stays
FALSE until the expected event takes place. When the expected event takes place, the value of the variable is
changed to TRUE. So, the value final of the Boolean variable allows the programmer to know if the event took
place or not.
Example: Boolean: FUNCTION find(Integer n)
/*Objective: find if the integer n is in a Tab array of 10 integers */
/*Argument: the value n to be searched for, suppose Tab is a global variable/
Variable: Boolean: flag
Integer: i
Start
flag←FALSE
i←0
WHILE(NOT(Flag) AND i<10) DO
IF(Tab[i] = n) THEN
flag← TRUE
ENDIF
i←i+1
ENDWHILE
Return (Flag)
Stop 46
1.3.14 Algorithm and Programming Examples
Program 1: Greatest Common Divisor
Write a C program to find the Greatest Common Divisor using recursion and determine if the numbers are coprime. Use the gcd to
determine the LCM of the numbers
The greatest common divisor of two integers is the largest integer that divides them both. The problem is to calculate the GCD of two non-
negative integers m and n recursively.
If n divides m, then by the definition of GCD, gcd(m, n) = n. n divides m if and only if (m % n) = 0.
So, the base case is when (m % n) = 0.
❖ If m > n at the start, then gcd(n, m % n) is a smaller problem than gcd(m, n).
❖ If m < n at the start then (m % n) = m and the first recursive step gcd(n, m mod n) is equivalent to gcd(n, m). This has the effect of
exchanging the parameter values m and n. So after the first call, it is back to the situation where the first parameter is greater than the
second.
❖ In this function, the result from the smaller problem gcd(n, m % n) is the solution to the current larger problem gcd(m, n).
𝑏, 𝑖𝑓 𝑏 𝑑𝑖𝑣𝑖𝑑𝑒𝑠 𝑎
GCD (a, b) ={
𝐺𝐶𝐷(𝑏, 𝑎 𝑚𝑜𝑑 𝑏), 𝑜𝑡ℎ𝑒𝑟𝑤𝑖𝑠𝑒

❖ Two numbers a and b are coprime if gcd(a,b)=1


𝒂×𝒃
❖ LCM of two numbers a and b is obtained from their gcd using LCM =
𝑮𝑪𝑫(𝒂,𝒃)

Pseudocode C-Code
Algorithm GCD #include <stdio.h>
Variable: int gcd(int, int); /* function prototype */
Integer: a, b, k, L int lcm(int, int);
Start int main()
Write (“Enter two integers, a and b: ”) {
Read (“a, b”) int i, j, g, L;
k= GCDR (a, b) printf(“\n Enter the numbers :”);
Write (“The GCD is: ”, k) scanf(“%d% d”, &i, &j);
IF (k = =1 ) THEN g= gcd(i, j)
Write (“The integers a and b are coprime”) printf(“\n The GCD of %d and %d is %d”, i, j, g ); /* function call */
ELSE if(g==1)
Write (“The integers a and b are not coprime ”) {
ENDIF printf(“The numbers are coprime\n”);
L= lcm(a,b) }
Write (“The LCM is: ”, L) else
Stop {
printf(“The numbers are not coprime\n”);
}
Integer FUNCTION GCDR (Integer x, Integer y) L=lcm(i, j);
Start printf(“\n The LCM of %d and %d is %d”, i, j, L ); /* function call */
Variable return 0;
Integer: rem; }
Rem = x mod y; /*********************************************/
IF (Rem = = 0) THEN /* Recursive function gcd() */
Return y; /*********************************************/
ELSE int gcd(int a, int b)
Return (GCD(y, rem)); {
ENDIF int remainder;
Stop remainder = a % b;
if(remainder == 0)
return b;
Integer FUNCTION lcm(integer m, integer n) else
Start return gcd(b, remainder);
return (m*n)/gcd(m,n); }
Stop int lcm(int m, int n)
{
return (m*n)/gcd(m,n);
}

47
𝒏
Program 2: Calculation of 𝑪𝒓𝒏 or ( ) and 𝑷𝒓𝒏 using the factorial function developed recursively
𝒓
The recursive function has been created using the following recursive definition of the factorial
1 𝑖𝑓 𝑛 = 0
❖ n! = {
𝑛 ∗ (𝑛 − 1)! 𝑖𝑓 𝑛 > 0

𝒏!
❖ 𝑪𝒓𝒏 = (𝒏−𝒓)!𝒓!
𝒏!
❖ 𝑷𝒓𝒏 = (𝒏−𝒓)!

Pseudocode C-Code
Algorithm Facto #include <stdio.h>
Variable: int facto(int); /* function prototype */
Integer: n, r, nCr, nPr int main()
Start {
Write(“Enter n :”); int n, r, nCr, nPr;
Read(n); printf(“\n Enter n :”);
Write(“Enter r :”); scanf(“%d”, &n);
Read(r); printf(“\n Enter r :”);
scanf(“%d”, &r);
nCr←facto(n)/(facto(n-r)*facto(r));
nPr←facto(n)/(facto(n-r)); nCr=facto(n)/(facto(n-r)*facto(r));
nPr=facto(n)/(facto(n-r));
Write(“\n %d C%d =%d”, n, r, nCr );
Write(“\n %d P%d =%d”, n, r, nPr ); printf(“\n %d C%d =%d”, n, r, nCr );
printf(“\n %d P%d =%d”, n, r, nPr );
Stop
Integer: FUNCTION fact (Integer n) return 0;
Begin }
IF n==0 THEN /*********************************************/
Return 1; /* Recursive function facto() */
ELSE /*********************************************/
Return (n*fact(n-1)) int facto(int n)
ENDIF {
End if(n == 0)
return 1;
else
return (n*facto(n-1));
}

Program 3: Prime Numbers


A prime number has only two factors; 1 and itself. Devise a C function that checks whether a given number is prime or
not and illustrate its use in the main

48
Pseudocode C-Code
Algorithm Prime #include<stdio.h>
Variable: int prime(int no); //_Function declaration
Integer: num int main()
{
Start
int num;
Write(“Enter the number to be checked:”); printf(“Enter the number to be checked:\t”);
Read(num); scanf(“%d”, &num);
IF (prime(num)=0) THEN if(prime(num)==0)
Write(Number is not prime) printf(“Number is not prime\n”);
ELSE else
Write(Number is prime); printf(“Number is prime\n”);
ENDIF return 0;
}
Stop int prime(int no) //_Function definition
Integer: FUNCTION prime (Integer no) {
Begin int i;
Integer : i for(i=2;i<no; i++)
FOR (i← 2 TO no-1) DO if(no % i==0)
IF(no mod i = 0) THEN return 0;
Return 0 return 1;
ENDIF }
ENDFOR
Return 1
End
Program 4 : Devise a C function that sums all the elements of an array. Illustrate its use
Pseudocode C-Code
Algorithm Sumall #include<stdio.h>
Variable: int sumall(int array[], int num);
Integer: num, i, result int main()
Elements : ARRAY[20] of Integers {
int num, i, result, elements[20];
Start printf(“Enter the number of elements in the array (max.
Write(“Enter the number of elements in the set (max. 20):\t”);
20)”) scanf(“%d”, &num);
Read (Num) printf(“Enter the elements:\n”);
Write (“Enter the elements”)
FOR (i←0 TO Num-1) DO
for(i=0;i<num; i++)
Read(Elements[i]) scanf(“%d”, &elements[i]);
ENDFOR result=sumall(elements, num);
Result ← sumall(elements, num); printf(“The sum of all the elements of the array is %d”, result);
Write (“The sum of all the elements of the array is return 0;
”,result); }
Stop int sumall(int array[], int num) //_Function definition
{
int i, sum =0;
Integer: FUNCTION sumall (Integer arr[], int no) for(i=0;i<num; i++)
Begin sum=sum+ array[i];
Integer : i, sum return sum;
Sum ← 0 }
FOR (i← 0 TO no-1) DO
Sum ← Sum + arr[i]
ENDFOR
Return Sum
End

Program 5 Devise a C function that checks whether two matrices can be multiplied or not. If yes, multiply them. Illustrate the
use of the developed function
Two matrices can be multiplied with each other if the number of columns in the first matrix is equal to the number of rows in the second
matrix. Therefore, m x n matrix A can be multiplied with a p x q matrix B if n=p. The dimension of the product matrix is m x q. The elements
of two matrices can be multiplied by writing:
𝐶𝑖,𝑗 = ∑ 𝐴𝑖,𝑘 𝐵𝑘,𝑗 𝑓𝑜𝑟 𝑘 = 1 𝑡𝑜 𝑛

49
Given two matrices A and B

𝐴 𝐴12 𝐵 𝐵12 𝐵13


A = ( 11 ) and B = ( 11 )
𝐴21 𝐴22 𝐵21 𝐵22 𝐵23

The result of the matrix multiplication is given as:

𝐴 𝐵 + 𝐴12 𝐵21 𝐴11 𝐵12 + 𝐴12 𝐵22 𝐴11 𝐵13 + 𝐴12 𝐵23
𝐶2𝑥3 = 𝐴2𝑥2 𝐵2𝑥3 = ( 11 11 )
𝐴21 𝐵11 + 𝐴22 𝐵21 𝐴21 𝐵12 + 𝐴22 𝐵22 𝐴21 𝐵13 + 𝐴22 𝐵23

Pseudocode C-Code
Algorithm PRODUCT //Matrix Multiplication with the help of functions
Variables #include<stdio.h>
Mat1 : ARRAY[10][10] of Integers #include<stdlib.h>
Mat2 : ARRAY[10][10] of Integers
int mat_multiply (int mx1[][10], int m1, int n1, int mx2[][10], int m2, int
Mx3 : ARRAY[10][10] of Integers
n2, int mx3[][10]);
m1, n1, m2, n2, i, j, indicator: Integers
Start int main()
Write(“Enter the order of the matrix 1(max. 10 by 10):”) {
Read(m1, n1) int mx1[10][10], mx2[10][10], mx3[10][10]={0};
Write(“Enter the elements of the matrix:”) int m1, n1, m2, n2, i, j, indicator;
FOR (i←0 TO m1-1) DO printf(“Enter the order of matrix-1 (max. 10 by 10)\t”);
FOR (j←0 TO n1-1) DO scanf(“%d %d”,&m1, &n1);
Read(Mat1[i][j]) printf(“Enter the elements of matrix-1:\n”);
ENDFOR
for(i=0;i<m1;i++)
ENDFOR
Write(“Enter the order of the matrix 2(max. 10 by 10):”) {
Read(m2, n2) for(j=0;j<n1;j++)
Write(“Enter the elements of the matrix:”) scanf(“%d”,&mx1[i][j]);
FOR (i←0 TO m2-1) DO }
FOR (j←0 TO n2-1) DO printf(“Enter the order of matrix-2 (max. 10 by 10)\t”);
Read(Mat2[i][j]) scanf(“%d %d”,&m2, &n2);
ENDFOR printf(“Enter the elements of matrix-2:\n”);
ENDFOR
for(i=0;i<m2;i++)
{
indicator← mat_multiply(mx1, m1, n1, mx2, m2, n2, mx3);
for(j=0;j<n2;j++)
IF (indicator=0) THEN scanf(“%d”,&mx2[i][j]);
Write(“Matrices are not compatible”); }
ELSE
Write(“The result of matrix multiplication is:\n”); indicator=mat_multiply(mx1, m1, n1, mx2, m2, n2, mx3);
FOR (i←0 TO m1-1) DO
FOR (j←0 TO n2-1) DO if(indicator==0)
Write(Mx3[i][j]) printf(“Matrices are not compatible for multiplication\n”);
ENDFOR else
ENDFOR {
ENDIF printf(“The result of matrix multiplication is:\n”);
Stop for(i=0;i<m1;i++)
{
for(j=0;j<n2;j++)
Integer: FUNCTION mat_multiply(int mx1[][10], int m1, int printf(“%d \t”,mx3[i][j]);
n1, int mx2[][10], int m2, int n2, int mx3[][10])
printf(“\n”);
Start }
Integer : i, j, k }
IF(n1≠m2) THEN return 0;
Return 0
}
ELSE
FOR (i←0 TO m1-1) DO int mat_multiply(int mx1[][10], int m1, int n1, int mx2[][10], int m2, int
FOR (j←0 TO n2-1) DO n2, int mx3[][10])
FOR (k←0 TO n1-1) DO {
Mx3[i][j] ← 𝑀𝑥3[i][j]+Mat1[i][k]*Mat2[k][j]; int i, j, k;
ENDFOR if(n1!=m2)
ENDFOR return 0;
ENDFOR else
Return 1 {
ENDIF for(i=0;i<m1;i++)
Stop for(j=0;j<n2;j++)
for(k=0;k<n1;k++)
mx3[i][j]=mx3[i][j]+mx1[i][k]*mx2[k][j];
return 1;
}
}

50
Program 6: Write a program to fill a square matrix with value zero on the diagonals, 1 on the upper right triangle, and
–1 on the lower left triangle.
This program should use two functions:
1. read_matrix() that reads the element into the matrix in the stated order
2. display_matrix() that displays the matrix
Along the main (i.e. principal) diagonal, the row and column number are equal. That is i=j where i represents row and j
column for all elements on the principal diagonal
Above the principal diagonal, i<j, that’s the row number is less than the column number
Below the principal diagonal, i>j, that’s the row number is greater than the column number

Pseudocode C-Code
Algorithm Matrix #include <stdio.h>
Variables void read_matrix(int mat[5][5], int);
Mat1 : ARRAY[5][5] of Integers void display_matrix(int mat[5][5], int);
row: Integers
int main()
Start
Write(“Enter the order of the square matrix(max. 5 by 5”) {
Read(row) int row;
read_matrix(mat1, row); int mat1[5][5];
display_matrix(mat1, row); printf("\n Enter the number of rows of the matrix:");
Stop scanf("%d", &row);
read_matrix(mat1, row);
display_matrix(mat1, row);
PROCEDURE read_matrix (Integer arr[5][5], int r) return 0;
Begin }
Integer : i, j void read_matrix(int mat[5][5], int r)
FOR (i←0 TO r-1) DO {
FOR (j←0 TO r-1) DO int i, j;
IF (i=j) THEN for(i=0; i<r; i++)
arr[i][j] ←0; {
ELSE IF(i>j) for(j=0; j<r; j++)
arr[i][j] ← –1; {
ELSE if(i==j)
arr[i][j] ← 1; mat[i][j] = 0;
ENDIF else if(i>j)
ENDFOR mat[i][j] = –1;
ENDFOR else
End mat[i][j] = 1;
}
}
PROCEDURE display_matrix (Integer arr[5][5], int r) }
Begin void display_matrix(int mat[5][5], int r)
Integer : i, j {
FOR (i←0 TO r-1) DO int i, j;
FOR (j←0 TO r-1) DO for(i=0; i<r; i++)
Write(arr[i][j]) {
ENDFOR printf("\n");
ENDFOR
for(j=0; j<r; j++)
End printf("\t %d", mat[i][j]);
}
}

Program 7: Calculation of Area under a Curve: 𝒇(𝒙) = 𝒙𝟐 + 𝟏


One of the applications of computers in numerical analysis is computing the area under a curve. One simple method of
calculating the area under a curve is to divide the area into a number of trapezoids of same width and summing up the area
of individual trapezoids. The area of a trapezoid is given by
Area = 0.5 * (h1 + h2) * b
where h1 and h2 are the heights of two sides and b is the width as shown in the figure below

51
Area under a curve
The task is to calculate the area for a curve of the function f(x) = 𝒙𝟐 + 1 between any two given limits, say, A and B.
❖ Input
1. Lower limit (A)
2. Upper limit (B)
3. Number of trapezoids
❖ Output
1. Total area under the curve between the given limits.
❖ Algorithm
1. Input the lower and upper limits and the number of trapezoids.
2. Calculate the width of trapezoids.
3. Initialize the total area.
4. Calculate the area of trapezoid and add to the total area.
5. Repeat step-4 until all the trapezoids are completed.
6. Print total area.
The algorithm is implemented in top-down modular form as shown below

The evaluation of f(x) has been done using a separate function so that it can be easily modified to allow other functions to be
evaluated. The output for two runs shows that better accuracy is achieved with larger number of trapezoids. The actual area
for the limits 0 and 3 is 12 units (by analytical method).

52
Pseudocode C-Code
Algorithm AREA #include <stdio.h>
Variables
start_point, end_point, total_area : Real /* GLOBAL VARIABLES */
numtraps: Integers
Start float start_point, end_point, total_area;
Write(“AREA UNDER A CURVE”); int numtraps;
Input()
total_area ←find_area(start_point, end_point, numtraps); /* Function prototype */
Write(TOTAL AREA = , total_area) float function_x(float x);
Stop float trap_area(float h1,float h2,float base);
void input(void);
PROCEDURE input () float find_area(float a,float b,int n);
Begin
Write (Enter lower limit) int main( )
Read (start_point); {
Write (Enter upper limit) printf ("AREA UNDER A CURVE\n");
Read (end_point) input( );
Write (Enter number of trapezoids) total_area = find_area(start_point,end_point,numtraps);
Read (numtraps) printf("TOTAL AREA = %.2f",total_area);
End return 0;
}
Real: FUNCTION trap_area(Real height_1, Real height_2, Real
base) void input(void)
Start {
/* LOCAL VARIABLE */ printf("\n Enter lower limit:");
Real area; scanf("%f",&start_point);
area ← 0.5 * (height_1 + height_2) * base; printf("Enter upper limit:");
Return (area) scanf("%f",&end_point);
Stop printf("Enter number of trapezoids:");
scanf("%d",&numtraps);
Real FUNCTION function_x (Real x) }
Start
/* F(X) = X * X + 1 */ float find_area(float a,float b,int n)
Return (x*x + 1) {
Stop /* LOCAL VARIABLES */
float base,lower,h1,h2,T_area=0.0;
base=(b-a)/n;
Real: FUNCTION find_area(Real a, Real b, Integer n) for(lower =a; lower<= b-base; lower=lower+base)
Stop {
/* LOCAL VARIABLES */ h1=function_x(lower);
Real base, lower, h1, h2, T_area=0.0; h2=function_x(lower+base);
base ← (b-a)/n T_area+=trap_area(h1,h2,base);
FOR (lower ←a TO b-base) DO }
h1 ← function_x(lower); return (T_area);
h2 ←function_x(lower + base); }
T_area ← T_area + trap_area(h1, h2, base);
ENDFOR float trap_area(float height_1,float height_2,float base)
Return (T_area) {
Stop /* LOCAL VARIABLE */
float area;
area = 0.5 * (height_1 + height_2) * base;
return (area);
}

float function_x (float x)


{
/* F(X) = X * X + 1 */
return (x*x + 1);
}

53
PROBLEM 8: QUADRATIC EQUATION MODULARIZED (SUBROUTINES CREATED FOR EACH MODULE)
The roots of a quadratic equation 𝒂𝒙𝟐 + 𝒃𝒙 + 𝒄 = 𝟎 can be obtained by using the expression

−𝑏 ± √𝑏 2 − 4𝑎𝑐
𝑥=
2𝑎
where 𝑏 2 − 4𝑎𝑐 is called discriminant.
− If 𝑏 2 − 4𝑎𝑐 > 0, the roots are real and unequal.
𝑏
− If 𝑏 2 − 4𝑎𝑐 = 0, the roots are real and equal, i.e 𝑥 = −
2𝑎

− If 𝑏 2 − 4𝑎𝑐 < 0, the roots are imaginary


MODULARIZATION
Breaking down the problem into smaller modules and analyzing each one before putting them together to solve the quadratic
equation.

1. Module: “calculateDiscriminant”

− Input: Coefficients “a”, “b”, and “c”


− Output: Discriminant value
− Description: This module calculates the discriminant value using the formula 𝒃𝟐 − 𝟒𝒂𝒄 and returns the result.
2. Module: “calculateRootsRealDifferent”

− Input: Coefficients “a”, “b”, and “discriminant”


− Output: Roots “root1” and “root2”
− Description: This module calculates the roots of the quadratic equation with a positive discriminant value. It uses the
formula `(-b + sqrt(discriminant)) / (2a)` and `(-b - sqrt(discriminant)) / (2a)` to compute the roots and stores them in
`root1` and `root2`.
3. Module: “calculateRootsRealSame”

− Input: Coefficients `a`, `b`


− Output: Roots `root1` and `root2`
− Description: This module calculates the roots of the quadratic equation with a zero discriminant value. It uses the formula
`-b / (2a)` to compute the roots and stores the same value in `root1` and `root2`.

4. Module: “calculateRootsComplexDifferent”

− Input: Coefficients `a`, `b`, and `discriminant`


− Output: Roots `realPart` and `imaginaryPart`
− Description: This module calculates the roots of the quadratic equation with a negative discriminant value. It computes the
real and imaginary parts separately using the formulas `-b / (2a)` and `sqrt(-discriminant) / (2a)`. The roots are then
stored in `realPart` and `imaginaryPart`.
COUPLING THE MODULES
− The global variables `a`, `b`, `c`, `discriminant`, `root1`, `root2`, `realPart`, and `imaginaryPart` are declared outside of
any subroutines, making them accessible throughout the program.
− The subroutines that calculate the discriminant and the roots now operate on these global variables.

54
#include <stdio.h>
#include <math.h>
double a, b, c;
double discriminant, root1, root2, realPart, imaginaryPart;
double calculateDiscriminant();
void calculateRootsRealDifferent() ;
void calculateRootsRealSame() ;
void calculateRootsComplexDifferent() ;
int main()
{
printf("Enter coefficients a, b, and c: ");
scanf("%lf %lf %lf", &a, &b, &c);
discriminant = calculateDiscriminant();
if (discriminant > 0)
{
calculateRootsRealDifferent();
printf("Roots are real and different.\n");
printf("Root 1 = %.2lf\n", root1);
printf("Root 2 = %.2lf\n", root2);
}
else if (discriminant == 0)
{
calculateRootsRealSame();
printf("Roots are real and same.\n");
printf("Root 1 = Root 2 = %.2lf\n", root1);
}
else
{
calculateRootsComplexDifferent();
printf("Roots are complex and different.\n");
printf("Root 1 = %.2lf + %.2lfi\n", realPart, imaginaryPart);
printf("Root 2 = %.2lf - %.2lfi\n", realPart, imaginaryPart);
}
return 0;
}
double calculateDiscriminant()
{
return b * b - 4 * a * c;
}
void calculateRootsRealDifferent()
{
root1 = (-b + sqrt(discriminant)) / (2 * a);
root2 = (-b - sqrt(discriminant)) / (2 * a);
}
void calculateRootsRealSame()
{
root1 = root2 = -b / (2 * a);
}
void calculateRootsComplexDifferent()
{
realPart = -b / (2 * a);
imaginaryPart = sqrt(-discriminant) / (2 * a);
}

55
PROBLEM 9: ROTATING A SORTED ARRAY
Rotating sorted arrays can be used in encryption and decryption algorithms. By applying a rotation operation on the elements
of an array based on a given key or rule, the data can be encrypted. The reverse rotation operation can then decrypt the data.
This technique is used in various encryption algorithms and cryptographic systems.
MODULES
To solve the problem of creating and displaying a rotated sorted array using subroutines and modularization in C
programming, we can break it down into the following modules:
1. Generate Sorted Array:
− This module generates a sorted array of integers in ascending order.
− It assigns each element of the array with a value equal to its index plus one.
2. Rotate Array:
− This module takes a sorted array and rotates it by a specified number of positions.
− It shifts the elements of the array to the right by the specified number of positions.
− It uses a temporary variable to store the last element before shifting the remaining elements.
3. Display Array:
− This module displays the elements of an array.
− It iterates through the array and prints each element.
4. Create and Display Rotated Sorted Array:
− This is the main subroutine that combines the above modules to create and display a rotated sorted array.
− It calls the "Generate Sorted Array" module to create a sorted array.
− It then calls the "Rotate Array" module to rotate the sorted array by a specified number of positions.
− Finally, it calls the "Display Array" module to display the rotated sorted array.
ROTATE ARRAY MODULE
Here's a step-by-step explanation of the algorithm:
1. Initialize a temporary variable `temp` to store the last element of the array.
2. Iterate `rotations` number of times (the specified number of rotations).
3. Inside the loop, start a nested loop from the last element (`size - 1`) to the second element (`j > 0`).
4. In each iteration of the nested loop, shift the elements to the right by assigning the value of the element at `j - 1` to
the current element at index `j`.
5. After the nested loop completes, assign the value of the temporary variable `temp` to the first element of the array
(`nums[0]`).
6. Repeat the above steps for the next rotation until all specified rotations are completed.
The last element is moved to the first position, and all other elements are shifted to the right.
COUPLING THE MODULES
− In this solution, the main function prompts the user to enter the size of the array and the number of rotations. It then calls the
`create_and_display_rotated_array` subroutine, passing the size and rotations as arguments.
− The `create_and_display_rotated_array` subroutine creates an array of the specified size, generates a sorted array using
`generate_sorted_array`, rotates the array using `rotate_array`, and displays the rotated array using `display_array`.
− The `generate_sorted_array` subroutine fills the array with sorted values from 1 to `size`.
− The `rotate_array` subroutine shifts the elements of the array to the right by the specified number of rotations.
− The `display_array` subroutine iterates through the array and prints each element.

56
C Code
#include <stdio.h>
void generate_sorted_array(int nums[], int size);
void rotate_array(int nums[], int size, int rotations) ;
void display_array(int nums[], int size) ;
void create_and_display_rotated_array(int size, int rotations) ;
int main()
{
int size, rotations;
printf("Enter the size of the array: ");
scanf("%d", &size);
printf("Enter the number of rotations: ");
scanf("%d", &rotations);
create_and_display_rotated_array(size, rotations);
return 0;
}

void generate_sorted_array(int nums[], int size)


{
for (int i = 0; i < size; i++)
{
nums[i] = i + 1;
}
}
void rotate_array(int nums[], int size, int rotations)
{
int temp;
for (int i = 0; i < rotations; i++)
{
temp = nums[size - 1];
for (int j = size - 1; j > 0; j--)
{
nums[j] = nums[j - 1];
}
nums[0] = temp;
}
}
void display_array(int nums[], int size)
{
for (int i = 0; i < size; i++)
{
printf("%d ", nums[i]);
}
printf("\n");
}
void create_and_display_rotated_array(int size, int rotations)
{
int nums[size];
generate_sorted_array(nums, size);
rotate_array(nums, size, rotations);
display_array(nums, size);
}

57
1.4 Structures
A structure is a collection of variables under a single name and provides a convenient way of grouping several pieces of
related information together. Unlike arrays, it can be used for the storage of heterogeneous data (i.e. data of different types).

A structure (sometimes called records) is data structure that allows items of different types that define a particular
i object to be stored together. The elements of a record are called fields or members.
We often declare structures globally (i.e. out of the main function).

1.4.1 Defining a Structure


There are three aspects of working with structures:
1. Defining a structure type, i.e. creating a new type
2. Declaring variables and constants (i.e. objects) of the newly created type
3. Using and performing operations on the objects of the structure type
Unlike arrays, structures must be defined first for their format that may be used later to declare structure variables. Consider
a book database consisting of book name, author, number of pages, and price. We can define a structure to hold this
information as follows:
struct book_bank
{
char title[20];
char author[15];
int pages;
float price_in_dollars;
};

The keyword struct declares a structure to hold the details of


four data fields, namely title, author, pages, and price.
These fields are called structure elements or members. Each
member may belong to a different type of data.
Book_bank is the name of the structure and is called the
structure tag. The tag name may be used subsequently to
declare variables that have the tag’s structure.
Note that the above definition has not declared any variables. It
simply describes a format called template to represent
information as shown beside

The General Format of a Structure Definition is as Follows:


Pseudocode C-Programming
Structure Declaration Type_Identifier = RECORD struct struct–name
Field_Type1 : Field_Name1 {
Field_Type2 : Field_Name2 data_type1 var–name1;
……… data_type2 var–name2;
Field_Typen : Field_Namen ..............
ENDRECORD data_typen var–namen;
};
Declaring variables and constants (i.e. Variable struct struct–name Variable_Name;
objects) of the newly created Type_Identifier Variable_Name
structure

1.4.2 Declaring Structure Variables


After defining a structure format, we can declare variables of that type. A structure variable declaration is similar
to the declaration of variables of any other data types. It includes the following elements:
1. The keyword struct.
2. The structure tag name.
3. List of variable names separated by commas.
4. A terminating semicolon.
For example, the statement struct book_bank book1, book2, book3; declares book1, book2, and book3 as
variables of type struct book_bank.
58
The complete declaration might look like this: It is also allowed to combine both the structure
definition and variables declaration in one statement.
struct book_bank struct book_bank
{ {
char title[20]; char title[20];
char author[15]; char author[15];
int pages; int pages;
int price; int price;
}; } book1, book2, book3;
struct book_bank book1, book2, book3;
− Examples
Object Remark Pseudocode C-Programming
Book To store information about a Book = RECORD struct book
book, we need to store its title, the String : Title {
author’s name, number of pages, String : Author char title [25];
and price of the book. Integer : Pages char author[20];
The structure will have four Integer : Price int pages;
members ENDRECORD int price;
};
Declaring Book Book1, Book2; struct book book1, book2;
variables
Complex A complex number is represented Complex = RECORD struct complex
Number as Z = a+bi. Real : a {
The structure used to store such a Real : b float a;
number will have two fields: ENDRECORD float b;
Real part and imaginary parts };
To properly use these numbers in
programs, using a structure is
quite convenient
Declaring Complex Z1,Z2; struct complex Z1, Z2;
variables
Coordinates A point in the 2D-cartesian Point = RECORD struct point
of a point coordinate system is represent as Real : x {
P(x,y). Real : y float x;
ENDRECORD float y;
};
Declaring Point P1, P2; struct point P1, P2;
variables
Name A name consists of two names: Name = RECORD struct name
first name and last name. String: first_name {
String: last_name char first_name[20];
ENDRECORD char last_name[20];
};
Declaring Name N1,N2,N3; struct name N1, N2, N3;
variables
Phonebook A phonebook entry consists Phonebook_entry = RECORD struct phonebook_entry
entry of the name of a person and his Name : person_name {
mobile number. This structure String : mobile_no struct name person_name;
contains another structure hence a ENDRECORD char mobile_no[10];
nested structure };

1.4.3 Typedef DECLARATIONS


The storage class specifier typedef is used for creating a synonym name or alias for a known type. The syntax of the typedef
declaration is: typedef type_name synonym_name;
Complex data type like structure can use the typedef keyword. For example,
typedef struct point
{
int x;
int y;
} Dot;

59
Dot left, right; [The word Dot has become an alias of struct point. Therefore, Dot left, right; is
now the same as struct point left, right;]
Dot left, right; shows that left and right are the structure variables of structure type point.
1.4.4 Operations on Structures
The operations that can be performed on an object (i.e. variable or constant) of a structure type are classified into two
categories:
1. Aggregate operations
2. Segregate operations
1.4.5 Aggregate Operations
An aggregate operation treats an operand as an entity and operates on the entire operand as a whole instead of
operating on its constituent members. The four aggregate operations that can be applied on an object of a structure
type are as follows:
1. Accessing members of an object of a structure type
2. Assigning a structure object to a structure variable
3. Address of a structure object
4. Size of a structure (i.e. either structure type or a structure object)
1.4.5.1 Accessing Members of an Object of a Structure Type
The members of a structure object can be accessed by using:
1. Direct member access operator (i.e. ., also known as dot operator).
2. Indirect member access operator (i.e. ->, also known as arrow operator).
The dot operator accesses a structure member via structure object name while the arrow operator accesses a structure
member via a pointer to the structure.
The general form of using a dot operator is:
structure_object_name . structure_member_name
1.4.5.2 Assigning a Structure Object to a Structure Variable
Like simple variables, a structure variable can be assigned with or initialized with a structure object (i.e. variable or
constant) of the same structure type.
1.4.5.3 Use of sizeof Operator on Structures
When the sizeof operator is applied to an operand of a structure type, the result is the total number of bytes that an
object of such type will occupy in the memory. The general form of sizeof operator is:
a. sizeof expression or the sizeof(expression)
b. sizeof (type i.e structure_type)
The expression
sizeof(struct x)
will evaluate the number of bytes required to hold all the members of the structure x. If y is a simple structure
variable of type struct x, then the expression
sizeof(y)
would also give the same answer. However, if y is an array variable of type struct x, then
sizeof(y)
would give the total number of bytes the array y requires. This kind of information would be useful to determine the number
of records in a database. For example, the expression, would give the number of elements in the array y.
sizeof(y)/sizeof(x)

1.4.6 Arrays of Structures


Just as there can be arrays of basic types such as integers and floats, so also there can be arrays of structures
We use structures to describe the format of a number of related variables. For example, in analyzing the marks obtained by
a class of students, we may use a template to describe student name and marks obtained in various subjects and then declare
all the students as structure variables. In such cases, we may declare an array of structures, each element of the array
representing a structure variable. For example:
struct class student[100];
Defines an array called student, that consists of 100 elements.
Consider the following declaration:
struct marks
{
int subject1;
int subject2;
int subject3;

60
};
int main()
{
struct marks student[3] = {{45,68,81}, {75,53,69}, {57,36,71}};
}
This declares the student as an array of three elements student[0], student[1], and student[2] and initializes their members
as follows:
student[0].subject1 = 45;
student[0].subject2 = 65;
....
....
student[2].subject3 = 71;
Since student is an array, we use the usual array-accessing methods to access individual elements and then the member
operator to access members. Each element of student array is a structure variable with three members.
1.4.7 Arrays Within Structures
C permits the use of arrays as structure members. We can use single-dimensional or multi-dimensional arrays of type int or
float or char. For example, the following structure declaration is valid:
struct marks
{
int number;
float subject [3];
} student [2];
Here, the member subject contains three elements, subject [0], subject[1] and subject[2]. These elements can be accessed
using appropriate subscripts. For example, student[1].subject[2]; Refers to the marks obtained in the third subject by the
second student.
1.4.8 Structures Within Structures
A structure can be placed within another structure, i.e., a structure may contain another structure as its member. A
structure that contains another structure as its member is called a nested structure.
For example
typedef struct
{
char first_name[20];
char mid_name[20];
char last_name[20];
}NAME;
typedef struct
{
int dd;
int mm;
int yy;
}DATE;
typedef struct
{
int r_no;
NAME name;
char course[20];
DATE DOB;
float fees;
} student;
In this example, we see that the structure student contains two other structures, NAME and DATE. Both these structures
have their own fields. The structure NAME has three fields: first_name, mid_name, and last_name. The structure DATE also has
three fields: dd, mm, and yy, which specify the day, month, and year of the date
Now, to assign values to the structure fields, we will write
student stud1;
stud1.r_no = 01;
stud1.name.first_name = "Jonas";
stud1.name.mid_name = "Pierre";
stud1.name.last_name = "Che";
stud1.course = "BCA";
stud1.DOB.dd = 15;
stud1.DOB.mm = 09;
61
stud1.DOB.yy = 1990;
stud1.fees = 45000;

1.4.9 Structures and Functions


For structures to be fully useful, we must have a mechanism to pass them to functions and return them. A function may
access the members of a structure in three ways:
1. Passing each member of a structure object as a separate argument
2. Passing the entire structure object by value
3. Passing the structure object by address/reference
1.4.9.1 Passing the Entire Structure
Just like any other variable, we can pass an entire structure as a function argument. When a structure is passed as an
argument, it is passed using the call by value method, i.e., a copy of each member of the structure is made. The general
syntax for passing a structure to a function and returning a structure can be given as,
struct struct_name func_name(struct struct_name struct_var);
The above syntax can vary as per the requirement. For example, in some situations, we may want a function to receive
a structure but return a void or the value of some other data type.
− Example: Consider the structure below
struct complex
{
int re;
int im;
};
Write a function that stores information about a given complex number

struct complex add()


{
struct complex Z;
printf(“Enter the real part of the complex number:\n”);
scanf(“%d”, &Z.re)
printf(“Enter the imaginary part of the complex number:\n”);
scanf(“%d”, &Z.im);
return Z;
};

− Program analysis
Key Statement Purpose
struct complex Z; Declares a variable Z, of type struct complex. The format of struct complex is
defined already in the question.
scanf(“%d”, &Z.re) The dot operator is used to access the re field/member of the variable Z and the real
part appropriately stored.
scanf(“%d”, &Z.im); The dot operator is used to access the im field/member of the variable Z and the
real part appropriately stored.
return Z; With the real part and imaginary part appropriately stored in the variable Z, the
variable Z is returned to the calling function.

1.4.10 Unions and Structures


Unions are a concept borrowed from structures and therefore follow the same syntax as structures. However, there is major
distinction between them in terms of storage. In structures, each member has its own storage location, whereas all the
members of a union use the same location. This implies that, although a union may contain many members of different types,
it can handle only one member at a time. Like structures, a union can be declared using the keyword union.

62
1.5 Strings
A string is a sequence of characters that is treated as a single data item. Any group of characters (except double quote sign)
defined between double quotation marks is a string constant
In C, a string is a null-terminated character array. This means that after the last character, a null character ('\0') is stored
to signify the end of the character array.
.

Importance of Terminating Null Character


i The terminating null character in strings is very important. Every string operation checks the presence of the null
character to determine the end of a string

1.5.1 String Library Functions


#include<string.h>
Function Role Example
strcpy() Copies one string over another strcpy(S1, S2);
Copies string S2 into string S1
strcmp() Compares two strings strcmp(S1, S2);
strcmpi Compares two strings without case sensitivity Returns:
0 if S1 and S2 are the same
Less than 0 if S1<S2
Greater than 0 if S1>S2
strcat() Concatenates two strings strcat(S1, S2);
Concatenates string S2 onto the end of S1
strlen() Calculates the length of a string strlen(s1);
Returns the number of characters in the string S1.
strrev() Reverses the content of a string strrev(s1);
Reverses the content of a string s1
strchr() Scans a string for the first occurrence of a strchr(s1, c)
given character
strstr() Finds the first occurrence of a substring strstr(s1, s2);
in another string Finds the first occurrence of a substring (i.e. s2) in
another string (i.e. s1)

1.5.2 Declaring and Initializing String Variable

Pseudocode Implementation in C
String_name : ARRAY[size] of Characters char string_name[ size ];
Size = The number of characters to be stored in the array plus 1. The extra space is to store the null
character (‘\o’). For example, if we want to store the name John, size will be 5. The first four spaces will
be used to store the four letters of the name and the fifth space will be used to store the null character.

1.5.3 Reading Strings From Terminal

1 Using scanf Function: To read a single word


C-Syntax Example
❖ The function scanf can be used with %s format char address[10];
specification to read in a string of characters. scanf(“%s”, address);
❖ Disadvantage: It terminates its input on the first white
space it finds. A white space includes blanks, tabs, carriage
returns, form feeds, and new lines.
❖ In the case of character arrays, the ampersand (&) is not
required before the variable name.

63
2 Using getchar and gets Functions: For reading a Line of Text
C-Syntax Example
❖ getchar () can be used repeatedly to read successive single The getchar function call takes the form:
characters from the input and place them into a character ❖ char ch;
array. (This is done using the while loop). Thus, an entire ❖ ch = getchar( );
line of text can be read and stored in an array. The reading
is terminated when the newline character (‘\n’) is entered The code segment:
and the null character is then inserted at the end of the ❖ char line [80];
string. Note that the getchar function has no parameters. ❖ gets (line);
❖ gets (str); Reads a line of text from the keyboard such as
❖ str is a string variable declared properly. It reads characters “Jones Nji”
into str from the keyboard until a new-line character is
encountered and then appends a null character to the string.
❖ Advantage: Unlike scanf, gets() it does not skip whitespaces.

1.5.4 Displaying Strings

1 Using printf Function


C-Syntax Example
The format %s can be used to display an array of characters printf(“%s”, name);
that is terminated by the null character. can be used to display the entire contents of the
array name

1 Using putchar and puts Functions


C-Syntax Example
C support character handling function putchar to output the putchar:
values of character variables. The function putchar requires one char ch = ‘A’;
parameter. putchar (ch);
Another way of printing string values is to use the function puts. puts:
This is a one parameter function and invoked as under: char line [80];
puts ( str ); where str is a string variable containing a string gets (line);
value. This prints the value of the string variable str and then puts (line);
moves the cursor to the beginning of the next line on the
screen.

1.5.5 Arithmetic Operations on Characters

The C library supports a function that converts a string of digits into their integer values. The function takes the form
x = atoi(string);
x is an integer variable and string is a character array containing a string of digits. Consider the following segment of a
program:
number = “1988”;
year = atoi(number);
number is a string variable which is assigned the string constant “1988”. The function atoi converts the string “1988”
(contained in number) to its numeric equivalent 1988 and assigns it to the integer variable year. String conversion functions
are stored in the header fi le <stdlib.h>.
1.5.6 List of Strings
We often use lists of character strings, such as a list of the names of students in a class, list of the names of employees in an
organization, list of places, etc. A list of strings can be stored in two ways:
❖ Using an array of strings
❖ Using an array of character pointers

64
1. Array of strings
If an application requires the storage of multiple strings, an array of strings can be used to store them. Since a string itself is
stored in a one-dimensional character array, the list of strings can be stored by creating an array of one-dimensional
character arrays, i.e. two-dimensional character array
For example, a character array student [30] [15] may be used to store a list of 30 names, each of length not more than 14
characters. The Figure below depicts an array of strings. The Array’s name is declared as char Names[3][9];
This means the array can store 3 names of maximum length 8 characters each(The extra character stores the null
character ‘\0’ to signify the end of the string).
[0] [1] [2] [3] [4] [5] [6] [7] [8]
First [0] N j i e E s o ‘\O’
String
Second [1] J o h n s o n ‘\O’
String
Third [2] C h e R o m ‘\O’
String

− Remark
Names is the name of the 2-D array. Names[0] corresponds to the first string, Names[1] corresponds to the
second string, and Names[2] corresponds to the third string. i.e
− Names[0]=Njie Eso
− Names[1]=Johnson
− Names[2]=Che Rom
Therefore, to access the individual strings, a single for loop can be used as shown below.
Displaying the Elements of the Names Array Above
Pseudocode C Programming
PROCEDURE Display(String: Names) void Display(char Names[][9])
Variable: {
Integer: i int i;
Start for(i=0;i<3; i++)
FOR(i←0 TO 2) DO {
Write(Names[i]) printf("%s\n", Names[i]);
ENDFOR }
Stop }

Reading Strings into the Names Array Above


Pseudocode C Programming
PROCEDURE Insert(String: Names) void Insert(char Names[][9])
Variable: {
Integer: i int i;
Start for(i=0;i<3; i++)
FOR(i←0 TO 2) DO {
Read(Names[i]) gets(Names[i]);
ENDFOR }
Stop }

65
1.6 Sorting and Searching
1.6.1 Sorting
1.6.1.1 Introduction
A sorting algorithm is an algorithm that puts the elements of a list in a certain order, which can be either numerical
order, lexicographical order, or any user-defined order.
Sorting means arranging the elements of an array so that they are placed in some relevant order which may be
either ascending or descending (For example arranging names in ascending lexicographic or alphabetical order).
That is, if A is an array, then the elements of A are arranged in a sorted order (ascending order) in such a way that
A[0] < A[1] < A[2] < ...... < A[N].
.

i Sorting is a programming technique which is used to arrange a list of pre-stored data in an ascending or
descending order according to a preset criterion.

1.6.1.2 Sorting on Multiple Keys


When performing real-world applications, it is desired to sort arrays of records using multiple keys. For example,
in a big organization we may want to sort a list of employees on the basis of their departments first and then
according to their names in alphabetical order.
Other examples of sorting on multiple keys can be:
− Telephone directories in which names are sorted by location, category (business or residential), and
then in an alphabetical order.
− In a library, the information about books can be sorted alphabetically based on titles and then by
authors’ names.
− Customers’ addresses can be sorted based on the name of the city and then the street.
Data records can be sorted based on a property. Such a component or property is called a sort key. A
i sort key can be defined using two or more sort keys. In such a case, the first key is called the primary
sort key, the second is known as the secondary sort key, etc.

Consider the data records given below:

Name Department Salary Phone Number


Itoe Telecommunications 1000000 651205111
Njie Computer Science 890000 651110258
Mokube Electronics 900000 654780258
Che Telecommunications 1100000 658901473
Beri Computer Science 750000 659321487
Now if we take department as the primary key and name as the secondary key, then the sorted order of records
can be given as:
Name Department Salary Phone Number
Beri Computer Science 750000 659321487
Njie Computer Science 890000 651110258
Mokube Electronics 900000 654780258
Che Telecommunications 1100000 658901473
Itoe Telecommunications 1000000 651205111
Observe that the records are sorted based on department. However, within each department the records are
sorted alphabetically based on the names of the employees.
The various sorting algorithms include: Bubble Sort, Selection Sort, Insertion Sort, Merge Sort, Quick Sort, Heap
Sort algorithms.

66
1.6.1.3 Bubble Sort
This is a technique for putting data in order by repeatedly stepping (or passing) through an array (or list),
comparing adjacent elements and swapping them if necessary, until the array is in order. This sorting algorithm
proceeds by looking at the list from left to right:
❖ Each adjacent pair of elements is compared.
❖ Whenever a pair is found not to be in order, the elements are exchanged.
Therefore, after the first pass, the largest element bubbles up to the right end of the list.
The whole process is repeated for the first (n-1) terms in the list, then its repeated for (n-2) and so on until the
list is sorted.

i Bubble sort compares each adjacent pair of items in a list in turn, swapping the items if necessary, and
repeating the pass through the list until no swaps are done.

EXAMPLE:
1. Consider the following array.
18 3 2 33 21
Trace the Implementation of the Bubble Sort on the array above.

2. Consider the following array.


4 3 2 1
Trace the Implementation of the Bubble Sort on the array above.
We will just show the state of the array after each pass or scan
Pass Array
Initial 4 3 2 1
1st Pass 3 2 1 4
2 Pass
nd 2 1 3 4
3rd Pass 1 2 3 4

67
3. Consider the following array.
42 60 26 55 34 28
Trace the Implementation of the Bubble Sort on the array above.

Pass Array
Initial 42 60 26 55 34 28
1st Pass 42 26 55 34 28 60
2nd Pass 26 42 34 28 55 60
3rd Pass 26 34 28 42 55 60
4 th Pass 26 28 34 42 55 60
5 th Pass 26 28 34 42 55 60

Let N be the number of elements in the list, P be the number of passes or Scans and Sw be the number of Adjacent
Comparisons
Passes, P:
For N=1, P=0
For N=2, P=1
For N=3, P=2
….
For N=n, P=n-1
Therefore, we can use one outer for loop to run n-1 times representing the passes for a list of n elements in the
worst case.
Adjacent Comparisons, Sw:
For First Pass, Sw=n-1 [Sw=n-J where J represents the pass number]
For the Second Pass, Sw=n-2 [Sw=n-J where J represents the pass number]
…..
For the (n-1)th Pass, Sw=1. [[Sw=n-J where J represents the pass number]
Generally, the inner loop will run for N-I, where N is the number of elements in the array and I is the current
pass.

BUBBLE SORT
Pseudocode C-Code
PROCEDURE BubbleSort (int A[], int n) void BubbleSort (int A[], int n)
Start {
Variable: int j, i, temp;
Integer: i, j, Temp for(i=0;i<n; i++)
FOR (i ← 0 TO n-1 ) DO {
FOR (j ← 0 TO n-i-2 ) DO
for(j=0;j<n–i–1;j++)
IF ( A[i]>A[i+1]) THEN
Temp ← A[j] {
A[j]← A[j+1] if(A[j] > A[j+1])
A[j+1] ← Temp {
ENDIF temp = A[j];
ENDFOR A[j] = A[j+1];
ENDFOR A[j+1] = temp;
Stop }
}
}
}

68
− Program analysis
Key Statement Purpose
for(i=0;i<n; i++) − Outer For Loop Using the Counter variable i
− Controls the number of passes or scans of bubble sort algorithm
− For value of i, the body of the for loop will be executed
for(j=0;j<n–i–1;j++) − Inner For Loop Using the Counter variable j.
− This loop is dependent on the outer for loop (n-1-i)
− Compares the array elements in each pass of bubble sort
algorithm.
− However, the frequency of the inner loop will decrease with
every pass because after every pass, one element will be in its
correct position.
if(A[j] > A[j+1]) Compares two adjacent elements and Swaps (Exchanges) the two
{ adjacent array elements that are not in order.
temp = A[j]; To sort the list in descending order, the test condition should be
A[j] = A[j+1];
modified to if(A[j] < A[j+1])
A[j+1] = temp;
}

A VARIANT OF BUBBLE SORT WITH SAME EFFICIENCY AS ABOVE


Pseudocode C-Code
PROCEDURE BubbleSort (int A[], int n) void BubbleSort (int A[], int n)
Start {
Variable: int pass, i, temp;
Integer: Pass, I, Temp for(pass=n-1; pass>=1; pass--)
FOR (Pass ←n-1 (-1) 1 ) DO {
FOR (i ← 0 (1) Pass-1 ) DO for(i=0; i<=pass-1; i++)
IF ( A[i]>A[i+1]) THEN {
Temp← A[i] if (A[i]>A[i+1])
A[i]← A[i+1] {
A[i+1]← Temp temp = A[i];
ENDIF A[i] = A[i+1];
ENDFOR A[i+1] = temp;
ENDFOR }
Stop }
}

1.6.1.4 Bubble Sort Optimization


Consider a case when the array is already sorted. In this situation no swapping is done but we still have to continue
with all n–1 passes. We may even have an array that will be sorted in 2 or 3 passes but we still have to continue with
rest of the passes. So, once we have detected that the array is sorted, the algorithm must not be executed further. This
is the optimization over the original bubble sort algorithm. In order to stop the execution of further passes after the
array is sorted, we can have a variable flag which is set to TRUE before each pass and is made FALSE when a swapping
is performed.
Original Algorithm takes O (𝒏𝟐 ) (even in best case). We can improve it by using one extra flag. No more swaps
indicate the completion of sorting. If the list is already sorted, we can use this flag to skip the remaining passes.

69
Improved BUBBLE SORT (More Efficient)
Pseudocode C-Code
PROCEDURE ImprovedBubbleSort (int A[], int n) void ImprovedBubbleSort (int A[], int n)
Start {
Variable: int i, j, temp;
Integer: i, j, Temp for(i=0; i<n; i++)
Boolean: Flag {
FOR (i ← 0 TO n-1 ) DO flag = 0;
Flag←FALSE for(j=0; j<n–i–1; j++)
FOR (j ← 0 TO n-i-2 ) DO {
IF ( A[i]>A[i+1]) THEN if(A[j]>A[j+1])
Flag←TRUE {
Temp ← A[j] flag = 1;
A[j]← A[j+1] temp = A[j+1];
A[j+1] ← Temp A[j+1] = A[j];
ENDIF A[j] = temp;
ENDFOR }
IF (NOT(Flag)) THEN }
Return; if(flag == 0) // array is sorted
ENDIF return;
ENDFOR }
}
Stop

Using Bubble Sort Procedure in a Complete C Program


Write a program to enter n numbers in an array. Redisplay the array with elements being sorted in ascending order.
#include <stdio.h>
void BubbleSort (int A[], int n);
int main()
{
int i, Num, temp, j, arr[10];
printf("\n Enter the number of elements in the array : ");
scanf("%d", &Num);
printf("\n Enter the elements: ");
for(i=0;i<n; i++)
{
scanf("%d", &arr [i]);
}
BubbleSort(arr, Num); //the array arr and the num of elements are passed into the procedure as arguments
printf("\n The array sorted in ascending order is :\n");
for(i=0;i<Num;i++)
{
printf("%d\t", arr[i]);
}
return 0;
}

void BubbleSort (int A[], int n)


{
int j, i, temp;
for(i=0;i<n; i++)
{
for(j=0;j<n–i–1;j++)
{
if(A[j] > A[j+1])
{
temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
}

70
1.6.1.5 Selection Sort
It works by finding the smallest element in the whole array and placing it at the first element position. It then finds the
second smallest element in the array disregarding the first element and places it in the second position. Next, it finds
the smallest element in the array disregarding the elements placed in position 1 and 2.
This process of selection and exchange (i.e., a pass) continues in this fashion until all the elements in the list are sorted.
Thus, in selection sort, two steps are important— selection and exchange.

Selection sort is an algorithm which orders items by repeatedly looking through remaining items to find the
i
least one and moving it to a final location.

Technique
The implementation algorithm for selection sort may be stated as follows:
1. Examine each element in the array or list to find the smallest.
2. Swap the element found in step 1 with the first element in the array or list.
3. Repeat steps 1 and 2, each time ignoring the element at the start of the last sort. Stop when only one
element has to be sorted.
A single iteration of the selection sorting technique that brings the smallest element at the beginning of the list is
called a pass or scan. Hence, we can say that selection sort requires n–1 passes to sort an array of n elements.
Example:
1. Consider the following array.
18 3 2 33 21
Trace the Implementation of the Selection Sort on the array above

Represents the Smallest Element Found

⏟. Represents the element to be exchanged


with the smallest element found

71
2. Consider the following array.
9 39 81 45 90 27 72 18
Trace the Implementation of the Selection Sort on the array above
Pass Comparison Resultant Array

1
9 39 81 45 90 27 72 18 9 39 81 45 90 27 72 18
9 is the new smallest element. It is already correctly located

2
9 39 81 45 90 27 72 18 9 18 81 45 90 27 72 39
18 is the new smallest element. It swaps places with 39

3 9 18 27 45 90 81 72 39
9 18 81 45 90 27 72 39
27 is the new smallest element. It swaps places with 81

4
9 18 27 45 90 81 72 39 9 18 27 39 90 81 72 45
39 is the new smallest element. It swaps places with 45

5
9 18 27 39 90 81 72 45 9 18 27 39 45 81 72 90
45 is the new smallest element. It swaps places with 90

6
9 18 27 39 45 81 72 90 9 18 27 39 45 72 81 90
72 is the new smallest element. It swaps places with 81

7
9 18 27 39 45 72 81 90 9 18 27 39 45 72 81 90
81 is the new smallest element. It stays on same location

We find the smallest element in the part of the list


excluding the ones in the right positions i.e. excluding
the ones already in bold

SELECTION SORT
Pseudocode C-Code
PROCEDURE SelectionSort (int A[], int n) void SelectionSort (int A[], int n)
Start {
Variable: int min, j, i, temp;
Integer: min, j, i, temp; for(i=0; i<n-1; i++)
FOR (i ← 0 TO n-2 ) DO {
min← 𝑖 min=i;
FOR (j ← 𝑖 + 1 TO n-1 ) DO for(j=i+1; j<n; j++)
IF (A[j]<A[min]) THEN {
min←j if (A[j]<A[min])
ENDIF {
ENDFOR min=j;
IF (min != i) THEN }
temp ← A[min]; }
A[min] ← A[i]; if(min != i)
A[i] ← temp; {
ENDIF temp = A[min];
ENDFOR A[min] = A[i];
Stop A[i] = temp;
}
}
}

72
− Program analysis
Key Statement Purpose
for(i=0; i<n-1; i++) − Outer For Loop
− Controls the number of passes
− For each small value found, it places the smallest value in its proper
position
for(j=i+1; j<n; j++) − Inner For Loop
{ − For a given value of i, it finds the location (or finds the index or
if (A[j]<A[min]) position) of smallest element from i to the end of the list
{
min=j;
− This could be packaged into a function called smallest() and the
} function will just be called for each value of i to return the
} position of the smallest element in the remaining part of the list

if(min != i) − Swaps (or interchanges) the array elements to move the smaller
{ element in its proper position
temp = A[min];
A[min] = A[i];
A[i] = temp;
}

73
Using Selection Sort Procedure in a Complete C Program
Write a program to enter n numbers in an array. Redisplay the array with elements being sorted in ascending order.
#include <stdio.h>
#include <stdlib.h>
int smallest(int arr[], int k, int n);
void selection_sort(int arr[], int n);
int main()
{
int arr[10], i, n;
printf("\n Enter the number of elements in the array: ");
scanf("%d", &n);
printf("\n Enter the elements of the array: ");
for(i=0;i<n; i++)
{
scanf("%d", &arr[i]);
}
selection_sort(arr, n);
printf("\n The sorted array is: \n");
for(i=0;i<n; i++)
{
printf(" %d\t", arr[i]);
}
return 0;
}
int smallest(int arr[], int k, int n)
{
int pos = k, small=arr[k], i;
for(i=k+1;i<n; i++)
{
if(arr[i]< small)
{
small = arr[i];
pos = i;
}
}
return pos;
}
void selection_sort(int arr[], int n)
{
int k, pos, temp;
for(k=0;k<n; k++)
{
pos = smallest(arr, k, n);
temp = arr[k];
arr[k] = arr[pos];
arr[pos] = temp;
}
}

74
1.6.1.6 Insertion Sort
Given a list of numbers, it divides the list into two parts—sorted part and unsorted part. The first element becomes the
sorted part and the rest of the list becomes the unsorted part. It picks up one element from the front of the unsorted
part and inserts it at its proper position in the sorted part of the list. This insertion action is repeated till the unsorted
part is exhausted.
Consider a scenario where an array A containing n elements needs to be sorted. Now, each pass of the insertion sorting
method will insert the element A[i] into its appropriate position in the previously sorted subarray, i.e., A[0], A[1], A[2], …,
A[i–1].
The following list describes the tasks performed in each of the passes:
− Pass 1: A[1] is compared with A[0] and inserted either before or after A[0]. This makes A[0], A[1] a sorted sub array.
− Pass 2 A[2] is compared with both A[0] and A[1] and inserted at an appropriate place. This makes A[0], A[1], A[2] a
sorted sub array.
− Pass n–1 A[n-1] is compared with each element in the sub array A[0], A[1], A[2], … A[n-2] and inserted at an
appropriate position. This eventually makes the entire array A sorted.
Hence, we can say that insertion sort requires n–1 passes to sort an array of n elements.
1. Consider the following array.
18 3 2 33 21
Trace the Implementation of the Insertion Sort on the array above

Pass Resultant

1
18 3 2 33 21 3 18 2 33 21

2
3 18 2 33 21 2 3 18 33 21

3
2 3 18 33 21 2 3 18 33 21

4
2 3 18 33 21 2 3 18 21 33

− Unshaded part of the list is sorted and Shaded Part is unsorted


− For each pass, the first element from the unsorted part is selected.
− The selected element is compared to elements in the sorted part.
− Elements greater that the selected element are shifted one place to the right
− This process continues until:
▪ Either an element less than the selected element is met
▪ Or
▪ We have reached the end of the list
− When these conditions are met, the selected element is inserted appropriately
− After each pass, the sorted list grows by one element while the unsorted decreases by one
element.

2. Consider the following array.


4 3 2 1
Trace the Implementation of the Insertion Sort on the array above
Pass Resultant Array
1 3 4 2 1
2 2 3 4 1
3 1 2 3 4

3. Consider an array of integers given below. Sort the values in the array using insertion sort.

75
39 9 45 63 18 81 108 54 72 36

Pass Resultant Array


1 9 39 45 63 18 81 108 54 72 36
2 9 39 45 63 18 81 108 54 72 36
3 9 39 45 63 18 81 108 54 72 36
4 9 18 39 45 63 81 108 54 72 36
5 9 18 39 45 63 81 108 54 72 36
6 9 18 39 45 63 81 108 54 72 36
7 9 18 39 45 54 63 81 108 72 36
8 9 18 39 45 54 63 72 81 108 36
9 9 18 36 39 45 54 63 72 81 108

INSERTION SORT
Pseudocode C-Code
PROCEDURE InsertSort (int A[], int n) void insertSort (int A[], int arr_size)
Start {
Variable: int i, j, temp;
Integer: j, i, temp; for (i=1; i < arr_size; i++)
FOR (i ← 1 TO n-1) DO {
temp ←A[i] temp = A[i];
j←i j = i;
WHILE ((j > 0) AND (A[j-1] >temp)) DO while ((j > 0) && (A[j-1] >temp))
A[j] ←A[j-1]; {
j ← j - 1; A[j] = A[j-1];
ENDWHILE j = j - 1;
A[j] ← temp; }
ENDFOR A[j] = temp;
Stop }
}

− Program analysis
Key Statement Purpose
temp = A[i]; Gets the element to be inserted from the unsorted part of the list,
and stores it in the temp variable
while ((j > 0) && (A[j-1] >temp)) Identifies the point of insertion for the element in the
{ previously sorted sub array
A[j] = A[j-1];
j = j - 1;
}

A[j] = temp; Inserts the element at the identified location.

76
Using Insertion Sort Procedure in a Complete C Program
Write a program to enter n numbers in an array. Redisplay the array with elements being sorted in ascending
order.
#include <stdio.h>
#define size 5
void insertion_sort(int arr[], int n);
int main()
{
int arr[size], i, n;
printf("\n Enter the number of elements in the array: ");
scanf("%d", &n);
printf("\n Enter the elements of the array: ");
for(i=0;i<n; i++)
{
scanf("%d", &arr[i]);
}
insertion_sort(arr, n);
printf("\n The sorted array is: \n");
for(i=0;i<n; i++)
{
printf(" %d\t", arr[i]);
}
return 0;
}
void insertion_sort(int arr[], int n)
{
int i, j, temp;
for(i=1;i<n; i++)
{
temp = arr[i];
j = i-1;
while((temp < arr[j]) && (j>=0))
{
arr[j+1] = arr[j];
j--;
}
arr[j+1] = temp;
}
}

77
1.6.1.7 Merge Sort
▪ The divide-and-conquer approach:
The divide-and-conquer approach involves three steps at each level of the recursion:
− Divide the problem into a number of subproblems that are smaller instances of the same problem.
− Conquer the subproblems by solving them recursively. If the subproblem sizes are small enough,
however, just solve the subproblems in a straightforward manner.
− Combine the solutions to the subproblems into the solution for the original problem.
Merge sort is a sorting technique that is based on divide-and-conquer approach. It divides a list into several sub lists of equal
sizes and sorts them individually. It then merges the various sub lists in pairs to eventually form the original list, while
ensuring that the sort order is not disturbed.
If you had a list with one element it is, by definition, sorted. Therefore, if you start with a large list of elements, all
you need to do is break the list down into a series of smaller lists each containing one single element. You can then
compare the lists and merge them back together to produce a sorted list.

Merge sort is a technique for putting data in order by splitting lists into single elements and then merging them back
i together again.

The basic steps of a merge sort algorithm are as follows:


− If the array is of length 1, then it is already sorted.
− Otherwise, divide the unsorted array into two sub-arrays of about half the size.
− Use merge sort algorithm recursively to sort each sub-array.
− Merge the two sub-arrays to form a single sorted list.
If the array has an odd number of elements, one of those “halves” is by one element larger than the order. The
subarrays are divided over and over again into halves until you end up with arrays that have only one element
each.
1 Sort the array given below using merge sort.

39 9 81 45 90 27 72 18

− Merging of lists
It is an operation in which two ordered lists are merged into a single ordered list. The merging of two lists PAR1 and
PAR2 can be done by examining the elements at the head of the two lists and selecting the smaller of the two. The
smaller element is then stored into a third list called mergeList.
For example, consider the lists PAR1 and PAR2 given below. Let Ptr1, Ptr2, and Ptr3 variables point to the first
locations of lists PAR1, PAR2, and PAR3, respectively. The comparison of PAR1[Ptr1] and PAR2[Ptr2] shows that the
element of PAR1 (i.e., ‘2’) is smaller. Thus, this element will be placed in the mergeList as per the following operation:

78
Since an element from the list PAR1 has been taken to mergeList, the variable Ptr1 is accordingly incremented to
point to the next location in the list. The variable Ptr3 is also incremented to point to next vacant location in
mergeList.
This process of comparing, storing and shifting is repeated till both the lists are merged and stored in mergeList as
shown below.

Note that during this merging process, a situation may arise when we run out of elements in one of the lists. We must,
therefore, stop the merging process and copy rest of the elements from unfinished list into the final list.

Example
Consider the figure below which shows how we merge two lists to form one list. For ease of understanding, we
have taken two sub-lists each containing four elements. The first array is considered to be made up of two
Subarrays of four elements each. (First Subarray =[ 9, 39, 45, 81] and Second Subarray=[ 18, 27, 72, 90]. Both
Subarrays are sorted. Our task is creating a single new sorted array called TEMP from these two Subarrays )

Compare ARR[I] and ARR[J], the smaller of the two is placed in TEMP at the location specified by INDEX and
subsequently the value I or J is incremented.

When I is greater than MID, copy the remaining elements of the right sub-array in TEMP.

79
MERGE SORT
Pseudocode C-Code
PROCEDURE MERGE (ARR, Beg, Mid, End) void merge(int arr[], int beg, int mid, int end)
Start {
I ← Beg int i=beg, j=mid+1, index=beg, temp[size], k;
J ← Mid + 1 while((i<=mid) && (j<=end))
Index ←0 {
WHILE (I ≤ Mid) AND (J≤ End) DO if(arr[i] < arr[j])
IF ARR[I] < ARR[J] THEN {
TEMP[INDEX] ← ARR[I] temp[index] = arr[i];
I←I+1 i++;
ELSE }
TEMP[INDEX] ← ARR[J] else
J ←J + 1 {
ENDIF temp[index] = arr[j];
Index ← Index + 1 j++;
ENDWHILE }
IF (I > Mid) THEN index++;
WHILE (J ≤ End) DO }
TEMP[Index] ← ARR[J] if(i>mid)
Index ← Index + 1 {
J←J+1 while(j<=end)
ENDWHILE {
ELSE temp[index] = arr[j];
WHILE (I ≤Mid) DO j++;
TEMP[Index] ← ARR[I] index++;
Index ← Index + 1 }
I←I+1 }
ENDWHILE else
ENDIF {
K←0 while(i<=mid)
WHILE (K < Index) DO {
ARR[K] ← TEMP[K] temp[index] = arr[i];
K← K+1 i++;
ENDWHILE index++;
Stop }
PROCEDURE MERGE_SORT(ARR, BEG, END) }
Start for(k=beg; k<index; k++)
IF (Beg < End) THEN {
Mid ← (Beg + End)/2 arr[k] = temp[k];
MERGE_SORT (ARR, Beg, Mid) }
MERGE_SORT (ARR, Mid + 1, End) }
MERGE (ARR, Beg, Mid, End) void merge_sort(int arr[], int beg, int end)
ENDIF {
Stop int mid;
if(beg<end)
{
//split list in half and carry out recursive call
mid = (beg + end)/2;
merge_sort(arr, beg, mid);
merge_sort(arr, mid+1, end);
//Merge the results.
merge(arr, beg, mid, end);
}
}

80
Using Merge Sort Procedure in a Complete C Program
Write a program to enter n numbers in an array. Redisplay the array with elements being sorted in ascending order.
#include <stdio.h>
#define size 100
void merge(int a[], int, int, int);
void merge_sort(int a[],int, int);
int main()
{
int arr[size], i, n;
printf("\n Enter the number of elements in the array : ");
scanf("%d", &n);
printf("\n Enter the elements of the array: ");
for(i=0;i<n; i++)
{
scanf("%d", &arr[i]);
}
merge_sort(arr, 0, n-1);
printf("\n The sorted array is: \n");
for(i=0;i<n; i++)
printf(" %d\t", arr[i]);
return 0;
}
void merge(int arr[], int beg, int mid, int end)
{
int i=beg, j=mid+1, index=beg, temp[size], k;
while((i<=mid) && (j<=end))
{
if(arr[i] < arr[j])
{
temp[index] = arr[i];
i++;
}
else
{
temp[index] = arr[j];
j++;
}
index++;
}
if(i>mid)
{
while(j<=end)
{
temp[index] = arr[j];
j++;
index++;
}
}
else
{
while(i<=mid)
{
temp[index] = arr[i];
i++;
index++;
}
}
for(k=beg; k<index; k++)
{
arr[k] = temp[k];
}
}
void merge_sort(int arr[], int beg, int end)
{
int mid;
if(beg<end)
{
mid = (beg + end)/2;
merge_sort(arr, beg, mid);
merge_sort(arr, mid+1, end);
merge(arr, beg, mid, end);
}
}

81
1.6.1.8 Quick Sort
This method also uses the technique of ‘divide and conquer’.
On the basis of a selected element (called pivot element or key value) from the list, it partitions the rest of the list
into two parts—a sub-list that contains elements less than the pivot and other sub-list containing elements greater
than the pivot (equal values can go either way). The pivot is inserted between the two sub-lists (This is called the
partition operation). The algorithm is recursively applied to the sub-lists until the size of each sub-list becomes 1,
indicating that the whole list has become sorted.
After each iteration, one element (pivot) is always in its final position. Hence, with every iteration, there is one
less element to be sorted in the array.
The choice of the pivot element may have a direct impact on the performance of the quick sort algorithm,
Note considering that there could be some pre-existing sort order present in the input list. As a result, different
implementations of the quick sorting technique use first, last, middle or at times some randomly chosen
element as the pivot element.

Technique
Quick sort works as follows:
1. Set the index of the first element in the array to loc and left variables. Also, set the index of the last element
of the array to the right variable. That is, loc = 0, left = 0, and right = n–1 (where n in the number of
elements in the array)
2. Start from the element pointed by right and scan the array from right to left, comparing each element on
the way with the element pointed by the variable loc. That is, a[loc] should be less than a[right].
a. If that is the case, then simply continue comparing until right becomes equal to loc. Once right =
loc, it means the pivot has been placed in its correct position.
b. However, if at any point, we have a[loc] > a[right], then interchange the two values and jump to
Step 3.
c. Set loc = right
3. Start from the element pointed by left and scan the array from left to right, comparing each element on
the way with the element pointed by loc. That is, a[loc] should be greater than a[left].
a. If that is the case, then simply continue comparing until left becomes equal to loc. Once left = loc,
it means the pivot has been placed in its correct position.
b. However, if at any point, we have a[loc] < a[left], then interchange the two values and jump to
Step 2.
c. Set loc = left.
Note: Two sub-lists can be safely joined when every element in the first sub-list is smaller than every element in the
second sub-list.
1. Sort the elements given in the following array using quick sort algorithm

27 10 36 18 25 45

(We take the first element in the array as pivot.)

82
Now left = loc, so the procedure terminates, as the pivot element (the first element of the array, that is, 27) is
placed in its correct position. All the elements smaller than 27 are placed before it and those greater than 27 are
placed after it.
The left sub-array containing 25, 10, 18 and the right sub-array containing 36 and 45 are sorted in the same
manner. This is continued until the array is sorted.

83
Using Quick Sort Procedure in a C Program
Write a program to enter n numbers in an array. Redisplay the array with elements being sorted in ascending order.
#include <stdio.h>
#define size 100
int partition(int a[], int beg, int end);
void quick_sort(int a[], int beg, int end);
int main()
{
int arr[size], i, n;
printf("\n Enter the number of elements in the array: ");
scanf("%d", &n);
printf("\n Enter the elements of the array: ");
for(i=0;i<n; i++)
{
scanf("%d", &arr[i]);
}
quick_sort(arr, 0, n-1);
printf("\n The sorted array is: \n");
for(i=0;i<n; i++)
printf(" %d\t", arr[i]);
return 0;
}
int partition(int a[], int beg, int end)
{
int left, right, temp, loc, flag;
loc = left = beg;
right = end;
flag = 0;
while(flag != 1)
{
while((a[loc] <= a[right]) && (loc!=right))
right--;
if(loc==right)
flag =1;
else if(a[loc]>a[right])
{
temp = a[loc];
a[loc] = a[right];
a[right] = temp;
loc = right;
}
if(flag!=1)
{
while((a[loc] >= a[left]) && (loc!=left))
left++;
if(loc==left)
flag =1;
else if(a[loc] <a[left])
{
temp = a[loc];
a[loc] = a[left];
a[left] = temp;
loc = left;
}
}
}
return loc;
}
void quick_sort (int a[], int beg, int end)
{
int loc;
if(beg<end)
{
loc = partition(a, beg, end);
quick_sort(a, beg, loc-1);
quick_sort(a, loc+1, end);
}
}

84
1.6.1.9 Shell Sort
This sorting algorithm is a generalization of insertion sort. Insertion sort works efficiently on input that is already
almost sorted. Shell sort is also known as n-gap insertion sort. Instead of comparing only the adjacent pair, shell
sort makes several passes and uses various gaps between adjacent elements (ending with the gap of 1 or classical
insertion sort).
In insertion sort, comparisons are made between the adjacent elements. The variation used in shell sort is to avoid
comparing adjacent elements until the last step of the algorithm. So, the last step of shell sort is effectively the
insertion sort algorithm. It improves insertion sort by allowing the comparison and exchange of elements that are
far away

Note Shell sort is considered an improvement over insertion sort as it compares elements separated by a
gap of several positions. This enables the element to take bigger steps towards its expected position

1.6.2 Searching
A search algorithm is a method of locating a specific item in a large collection of data.
If the element is found to be present in the large collection of data then the search is considered as successful, otherwise it
is considered as an unsuccessful search. The search operation returns the location or address of the element found.
There are various searching methods that can be employed to perform search on a data set. Common search algorithms
are sequential search and binary search.
The choice of a particular searching method in a given situation depends on a number of factors, such as
1. Order of elements in the list, i.e., random or sorted
2. Size of the list
1.6.2.1 Sequential or linear search
It is one of the conventional searching techniques that sequentially searches for an element in the list. It typically
starts with the first element in the list and moves towards the end in a step-by-step fashion. In each iteration, it
compares the element to be searched with the list element, and if there is a match, the location of the list element
is returned (the index of that number is returned). If we reach the end of the list and no match has been found, we can
indicate that the key does not exist in the array by returning –1.

Sequential search is a simple technique for searching an item in a list by comparing each element with the
i element searched for, beginning with the first element until the element is found.

Note! Linear search is mostly used to search an unordered list of elements (array in which data elements
are not sorted).

Consider an array of integers A containing n elements. Let k be the value that needs to be searched. The linear
search technique will first compare A[0] with k to find out if they are same. If the two values are found to be same
then the index value, i.e., 0 will be returned as the location containing k. However, if the two values are not same
then k will be compared with A[1]. This process will be repeated until the element is found or the array elements
have been exhausted. If the last comparison between k and A[n–1] is also negative then the search will be
considered as unsuccessful.
The figure below depicts the linear search technique performed on an array of integers.

The value k is repeatedly compared with


each element of the array A. As soon as the
element is found, the corresponding index
location is returned and the search
operation is terminated

85
SEQUENTIAL OR LINEAR SEARCH
Pseudocode C-Code
Integer FUNCTION Lsearch(int ArrayElement[], int int Lsearch(int ArrayElement[], int key, int ArraySize)
key, int ArraySize) {
START int i ;
i ; Integer for (i = 0; i < ArraySize; i++)
FOR (i ← 0 TO ArraySize-1) DO if (ArrayElement[i] == Key)
if (ArrayElement[i] = Key) {
Return (i) ; return (i) ;
ENDFOR }
Return (-1); return (-1);
STOP }

Using Linear Search Function in a C Program


Write a C program to perform linear search on an array of N elements.
#include <stdio.h>
#define size 100
int Lsearch(int [], int, int);
int main()
{
int arr[size], i, n, p, k;
printf("\n Enter the number of elements in the array: ");
scanf("%d", &n);
printf("\n Enter the elements of the array: ");
for(i=0;i<n; i++)
{
scanf("%d", &arr[i]);
}
printf(“\n Enter the element to be searched:\n”);
scanf(“%d”, &k);
p=Lsearch(arr, k, n); /*Calling linear function*/
/*Printing search results*/
if(p = = -1)
{
printf(“\n ELEMENT NOT FOUND”);
}
else
{
printf(“\n ELEMENT FOUND AT POSITION %d”, p);
}
return 0;
}
int Lsearch(int ArrayElement[], int key, int ArraySize)
{
int i ;
for (i = 0; i < ArraySize; i++)
if (ArrayElement[i] == Key)
{
return (i) ;
}
return (-1);
}

86
1.6.2.2 Binary search
The precondition of binary search is that it requires sorted data to operate on. The basic technique is to compare the
search element with the element which is in the middle of the search space and then to restrict further searching in the
appropriate half of the search space (this can be done because the search space is sorted). Then at each step, the process
is repeated (cutting the remaining search space in half at each step) until either the search element is found or we have
run out of elements to compare and the element was not in the search space.

Note! Binary search technique has a prerequisite – it requires the elements of the data structure (list)
to be already arranged in a sorted manner before search can be performed in it.

The binary search follows the following steps:


Step
− The middle element is tested for the required entry. If found, then its position is reported else the following
test is made.
− If Val < A[middle], search the left half of the list, else search the right half of the list.
− Repeat step 1 and 2 on the selected half until the entry is found otherwise report failure.

Example:
Search for 7 in the list using binary search
1 3 4 5 7 8 9
[0] [1] [2] [3] [4] [5] [6]
First Last
First=0
Last=6
Middle= (first + last)/2=(0+6)/2=3
1 3 4 5 7 8 9
[0] [1] [2] [3] [4] [5] [6]
First Middle Last

List[3]<7 Hence, first=middle+1=3+1=4

1 3 4 5 7 8 9
[0] [1] [2] [3] [4] [5] [6]
First Last
Middle=(first + last)/2=(4+6)/2=5
1 3 4 5 7 8 9
[0] [1] [2] [3] [4] [5] [6]
First Middle Last

List[5]>7, Hence, Last=middle-1=5-1=4

1 3 4 5 7 8 9
[0] [1] [2] [3] [4] [5] [6]
First=Last=4
Middle=(4+4)/2=4
List[4]=7 Hence, Element is found and the search is successful. Return middle=4.

87
BINARY SEARCH
Pseudocode – Iterative Version C-Code
FUNCTION ITERATIVE-BINARY-SEARCH (A, v, low, high) int binarysearch(int a[], int n, int key)
Start {
WHILE (low ≤high) DO int end, beg, mid;
mid = ⌊(𝑙𝑜𝑤 + ℎ𝑖𝑔ℎ)/2⌋ beg=0; end=n-1;
IF (v==A[mid]) THEN while(beg<=end)
return mid {
ELSEIF v>A[mid] THEN mid=(beg + end)/2;
low=mid+1 if(key==a[mid])
ELSE return mid;
high=mid-1 else if(key>a[mid])
ENDIF beg=mid+1;
ENDWHILE else
return -1 end=mid-1;
}
Stop return -1;
⌊. ⌋ = 𝐹𝑙𝑜𝑜𝑟 𝑉𝑎𝑙𝑢𝑒
}
⌊2.25⌋ = 2

BINARY SEARCH - RECURSIVE


Pseudocode – Recursive Version C-Code
FUNCTION RECURSIVE-BINARY-SEARCH (A, v, low, high) int search(int x[ ], int k, int low, int high)
Start {
IF (low > high) THEN int mid;
return -1 if(low > high)
ENDIF {
mid = ⌊(𝑙𝑜𝑤 + ℎ𝑖𝑔ℎ)/2⌋ return (-1);
IF (v==A[mid]) THEN }
return mid mid = (low + high) /2;
ELSEIF (v>A[mid]) THEN if( k= =x[mid])
Return RECURSIVE-BINARY-SEARCH (A, v, mid+1, high) {
ELSE return mid;
Return RECURSIVE-BINARY-SEARCH (A, v, low, mid-1) }
ENDIF else if( k < x[mid])
Stop {
return search(x, k, low, mid – 1);
}
else
{
return search(x, k, mid+1, high);
}
}

88
Using Binary Search Function in a C Program
Write a C program to perform binary search on an array of N elements.
#include <stdio.h>
#define size 100
int binarysearch(int a[], int n, int key);
int smallest(int arr[], int k, int n);
void selection_sort(int arr[], int n);
int main()
{
int arr[size], i, n, p, k;
printf("\n Enter the number of elements in the array: ");
scanf("%d", &n);
printf("\n Enter the elements of the array: ");
for(i=0;i<n; i++)
{
scanf("%d", &arr[i]);
}
selection_sort(arr, n); // Added to sort the array
printf("\n The sorted array is: \n");
for(i=0;i<n; i++)
{
printf(" %d\t", arr[i]);
}
printf("\n Enter the element to be searched:\n");
scanf("%d", &k);
p= binarysearch (arr, n, k); /*Calling the search function*/
/*Printing search results*/
if(p==-1)
{
printf("\n ELEMENT NOT FOUND");
}
else
{
printf("\n ELEMENT FOUND AT POSITION %d", p);
}
return 0;
}
int binarysearch(int a[], int n, int key)
{
int end, beg, mid;
beg=0; end=n-1;
while(beg<=end)
{
mid=(beg + end)/2;
if(key==a[mid])
return mid;
else if(key>a[mid])
beg=mid+1;
else
end=mid-1;
}
return -1;
}
int smallest(int arr[], int k, int n)
{

89
int pos = k, small=arr[k], i;
for(i=k+1;i<n; i++)
{
if(arr[i]< small)
{
small = arr[i];
pos = i;
}
}
return pos;
}
void selection_sort(int arr[], int n)
{
int k, pos, temp;
for(k=0;k<n; k++)
{
pos = smallest(arr, k, n);
temp = arr[k];
arr[k] = arr[pos];
arr[pos] = temp;
}
}

90
1.7 Pointers
1.7.1 Introduction
Any variable manipulated in a program is stored somewhere in the computer’s memory. This memory is divided
into bytes and identified by a sequential number called address. By convention, an address is noted in
hexadecimal and preceded by 0x. To declare a variable is to assign a name to an area of memory. This area is
defined by:
— its position, i.e. the address of its first byte;
— its size, i.e. the number of bytes.
Example: The following code is shown in the figure below:
Variable
Integer: n
Start
n←8
Stop

To access the value contained in a variable, we use its name (in this case the name of the variable is n). The position
(address) of variable n is 0x3C29 and its size is 4 Bytes.

A pointer is a variable that holds the address of another variable.


i

The pointer is said to point to the variable whose address it contains. A pointer is associated with a type of variable
to which it can point. In effect, even though the value of a pointer (an address) is always an integer (represented
as hexadecimal), the “type” of a pointer depends on the type of the variable pointed to. Therefore, a pointer to an
integer can only point to integers. A pointer is itself a variable and as such has an address.
Pointers can be used to:
− Call by address, thereby facilitating the changes made to a variable in the called function to become
permanently available in the function from where the function is called
− Return more than one value from a function indirectly
− Pass arrays and strings more conveniently from one function to another
− Manipulate arrays more easily by moving pointers to them (or to parts of them) instead of moving the
arrays themselves
− Create complex data structures, such as linked lists and binary trees, where one data structure must
contain references to other data structures
− Communicate information about memory, as in the function malloc() which returns the location of free
memory by using a pointer

91
− Compile faster, more efficient code than other derived data types such as arrays
1.7.2 Declaration and Manipulation of a Pointer
A pointer variable is declared with the following statement:

Pseudocode C Language
↓ typeOfPointedVariable PointerName typeOfPointedVariable* PointerName;
or
typeOfPointedVariable * PointerName;
or
typeOfPointedVariable *PointerName; [We will use
this version more]
Where typeOfPointedVariable is the data type of the A pointer variable declaration consists of a data type
pointed object. specifier (i.e. referenced type),
punctuator * and an identifier (i.e. name of pointer
variable).

Examples
Pseudocode C Language
↓ 𝐼nteger iptr //iptr is a pointer to an integer int *iptr; //iptr is pointer to an integer
↓Real fptr; //fptr is pointer to a Real number float *fptr; //fptr is pointer to a float
↓ 𝐶haracter cptr //cptr is a pointer to a character char *cptr; //cptr is pointer to a character

To manipulate pointers, we need the following operators:


Pseudocode C Language
— address of, noted @ address of, noted &
— content of, noted © content of, noted *

The "address of" operator is used to access the address of a variable. Its syntax is:
@Variable_Name
Thus, @n equals 0x3C29 (address of the first byte of variable n). This address can be used to initialize the value
of a pointer. The "address of" operator can only be applied to variables. It cannot be applied to constants.
The "content of" operator, © (also called the indirection operator) provides access directly to the value of the
pointed variable (we say that we dereference a pointer). Dereferencing a pointer consists of extracting the value
of the variable on which it points to. The syntax is as follows:
©PointerName
Thus, if p is a pointer to an integer n, © p denotes the value of n. We can also change the value of a variable pointed
to through a dereferenced pointer.

− Referencing Operation
In referencing operation, a pointer variable is made to refer to an object. The reference to an object can be created with
the help of a reference operator (i.e. & in C Language or @ in Pseudocode). The reference operator is also known as
address-of operator
− Dereferencing a Pointer
The object pointed to or referenced by a pointer can be indirectly accessed by dereferencing the pointer. A
dereferencing operation allows a pointer to be followed to the data object to which it points. A pointer can be
dereferenced by using a dereference operator (i.e. * in C Language or © in Pseudocode).). The dereference operator
is also known as indirection operator or value-at operator.
− Assigning to a Pointer
A pointer can be assigned or initialized with the address of an object. A pointer variable cannot hold a non-address
value. A pointer to a type cannot be initialized or assigned the address of an object of another type.

92
There is an exception to this rule. The constant zero can be assigned to a pointer. For example, int *iptr=0; is valid. Assignment or
initialization with zero makes the pointer a special pointer known as the null pointer (A null pointer is a special pointer that does
i not point anywhere. It does not hold the address of any object or function. It has numeric value 0. The following declaration statement
declares nptr as a null pointer: int *nptr=0;).

Example 2:
Variable:
↓Integer: pe //pe is a pointer to an integer
Integer: n;
Start
n←10
p← @n // p contains the address of n
Write (© p) // displays 10
Stop

The figure below illustrates the memory just before the "stop" statement in the Example above

We then have:
− n: the content of n (i.e. 10)
− @n: the address of n (i.e. 0x3C2B)
− p: the content of p (i.e. 0x3C2B)
− ©p: the content of n (i.e. 10)
− @p: the address of p (i.e. 0x1A40)
− ©n is wrong because n is not a pointer.
1.7.3 Pointer arithmetic
The value of a pointer being an integer, we can apply the arithmetic operators to it:
— The addition of an integer i to a pointer p (p + i): the result is a pointer of same type as the p pointer.
— The subtraction of an integer i from a pointer p (p - i): the result is a pointer of the same type as the pointer p.
— the difference of 2 pointers (p1-p2), it is absolutely necessary that the two pointers point to objects of the same
type T: The result is an integer whose value is equal to: (p1-p2) div nbByte(T).
NB: Let i be an integer and p a pointer to an object of type T (therefore declared by the instruction T: ↓p ;). Then
p+i (respectively p-i) denotes a pointer to an object of type T. Its value is equal to that of incremented p
(respectively decremented) by i*NbByte(T). (NbByte() is the same as sizeof() operator in C. This generates the
storage size of an expression or a data type)
1.7.4 Illegal Pointer Operations
The following operations on pointers are not allowed:
1. Addition of two pointers is not allowed.

93
2. Only integers can be added to pointers. It is not valid to add a float or a double value to a pointer.
3. Multiplication and division operators cannot be applied on pointers.
4. Bitwise operators cannot be applied on pointers.
5. A pointer of one type cannot be assigned to a pointer of another type (except void*) without explicit type casting.
6. A pointer variable cannot be assigned a non-address value (except zero).
1.7.5 Initializing a pointer
Like any variable, a pointer must be initialized. This initialization can be done in three different ways:
— Assignment of the address of another variable to p
If the variable is a pointer, we can do the assignment directly, otherwise we must use the "address of" operator.
— Assignment of p to the value NIL
We can say that a pointer does not point to anything by initializing it to NIL (Not Identified Link).
Note: Never dereference a null pointer. Before dereferencing a pointer, it is always necessary to be certain that it
is not zero.
— Direct assignment of "contents of" p (the memory area pointed to by p)
To do this, you must first allocate to © p (content of p) a memory space of adequate size (that of the type pointed
to by p). The address of this memory space will be the value from p. This operation consists of reserving a memory
space to store the pointed variable is called a dynamic allocation.
− Double Indirection
A Pointer that holds the address of another pointer variable is known as a pointer to a pointer
When a pointer points to another pointer, there is double indirection (figure below):

We can access n from p1 using the dereferencing operator twice:


©©p1 =© p2 = n

1.7.6 Dynamic Memory Allocation


There are two ways to allocate a memory location for a variable:
− either by declaration, as is done in the declaration of variables;
− or by dynamic allocation.
The declaration allows us to allocate a location in a part of the memory called stack. Variables declared in the
stack have a name. They are created as soon as they enter scope and destroyed as soon as they leave their scope.
Dynamic allocation allows you to allocate a slot in another part memory called heap (set of bytes with no
particular structure, in which we try to allocate or free up space according to needs).
The Heap variables are not declared, they are created by a specific statement. They do not have a name but can
be accessed by their address. They can be used everywhere and until destroyed (there is no range for heap
variables).
− Dynamic Allocation Functions
The operation consisting in reserving a memory space is carried out by the function "allocate()" which takes as
an argument the size of the space we want to reserve. This size is given by the "nbByte()" function which takes

94
the type of the variable you want to create. The allocate() function returns the address of the variable and assigned
to a pointer of the same type. Its syntax is as follows:
nameOfPointer ←allocate(nbByte(typeVariableOfPointed))

Example :
Variable:
↓Real p
Start
p ←allocate(nbByte(Real))
Stop
The "allocate()" function allocates a location in the heap having the size of the type specified in argument and it
provides in return the corresponding address that we assign to the variable p. Then we can directly access this
location by dereferencing the pointer:
© p← 18.5
The "allocate()" function also allows to allocate spacing for several variables:
Example :
...
Variable:
↓Real p
Start
p ←allocate(2*NbByte(real)) //allocation for 2 reals
© p ←14
©(p+1) ←10 //p+1 is a pointer of the same type as p
...
Stop
− Deallocate() function
When we no longer need the space dynamically allocated by the allocation function, this space must be freed.
This is done using the following syntax:
deallocate(PointerName)
Example:
...
Start
...
deallocate(p) //this function returns nothing.
Stop

Memory Allocation Function


Pseudocode C Language Role
NbByte() sizeof() Returns the total number of bytes that an object will occupy in the memory.
Allocate() malloc(u) Allocates u bytes of memory. Return a pointer to the beginning of the allocated
space.
Deallocate() free(p) Free a block of allocated memory whose beginning is indicated by p.

95
1.7.7 Application of pointers.
1.7.7.1 Functions
− Returning more than one value from a function
Functions usually return only one value and when arguments are passed by value, the called function cannot alter
the values passed and have those changes reflected in the calling function. Pointers allow the programmer to
‘return’ more than one value by allowing the arguments to be passed by address, which allows the function to
alter the values pointed to, and thus ‘return’ more than one value from a function.
▪ Example:

Function Compute() Receives the radius of a circle from the main function, it calculates and “returns” the
Area and Perimeter of the Circle
Pseudocode C-Language
ALGORITHM Permutation #include <stdio.h>
Variable: float compute(float r, float *p)
Real: r, Area, Perimeter int main()
Start {
Write(“Enter the radius of the circle:”)
float r, area, perimeter;
Read(r) printf(“\n enter the radius of the circle:”);
scanf(“%f”, ,&r);
Area← 𝐶𝑜𝑚𝑝𝑢𝑡𝑒(r, @perimeter)
area=compute(r, &perimeter);
Write(“AREA = ”, Area)
printf(“\n AREA = %f”, area);
Write(“PERIMETER = ”, Perimeter)
printf(“\n PERIMETER = %f”, perimeter);
Stop return 0;
FUNCTION Compute (𝑅𝑒𝑎𝑙: r, ↓integer p) }
Variables: float compute(float r, float *p)
Real: A; {
Start float a;
A← 3.1415 * r * r; a=(float)3.1415 * r * r;
©p← (float)3.1415 * 2 * r; *p=(float)3.1415 * 2 * r;
Return A return a;
Stop }

− Call by address
▪ When we want to swap the values of two variables passed to a function, we do not create copies of values and
pass to the function (as in call by value) but the function is allowed to access the original values.
▪ This means that if the function modifies such values, then the modification will affect the original value and
will persist once the function execution is finished.
▪ To make a function be able to modify a certain variable, the function must be provided with information about
the location of the variable in memory (i.e., its address). If the function knows where the variable is in memory,
it will be able to access that area of memory by using pointers and change its content. This is known as call by
address.
▪ The way to obtain the desired effect is for the calling program to pass pointers to the values to be changed.
For example, swap(&x, &y); Since the operator & produces the address of a variable, &x is a pointer to x. In
swap itself, this will arrive to the function in the form of a pointer. That is, the parameters are declared as
pointers, and the operands are accessed indirectly through them

96
▪ Example:

Swaps the Content of 2 Variables Passed to The Function from the Main Program
Pseudocode C-Language
ALGORITHM Permutation #include <stdio.h>
Variable: void swap(int *,int *);
Integer: x, y int main()
Start {
x←10 int x=10, y=20;
y←20 printf(“%d %d\n”, x, y);
Swap (@x, @y) //px points to x and py points to y swap(&x, &y);
Stop printf(“%d %d\n”, x, y);
PROCEDURE Swap (↓integer: px, py) return 0;
Variables: }
Integer: Temp; void swap(int *px, int *py)
Start {
Temp←© px int temp;
©px ←©py temp = *px;
©py← Temp *px = *py;
Stop *py = temp;
}

− Temp←© px //Temp takes the value of the variable pointed to by px


− ©px ←©py /* the variable pointed to by px takes as its value, the value of the variable pointed to by py */
− ©py← Temp // the variable pointed to by py takes the value Temp
1.7.7.2 Array
The name of an array is the beginning address of the array, called the base address of the array., that is, the base address
of an array is the address of the zeroth element of the array. The array name is referred to as an address constant

The name of an array refers to the address of the first element of the array.
i

Constant
MAX = 5
Variable
tab = Array[MAX] of integer
Integer: i
↓Integer: p
Start
FOR (i ←0 (1) MAX-1 DO
tab[i] ← i*i
ENDFOR
...
Stop
The declaration tab defines an array of MAX integers and tab is a constant pointer (not modifiable) whose value
is the address of the first element of the array.
In other words, tab has the value @tab[0] (ie 0x1A40). We can use a pointer initialized to tab to iterate through
the elements of the array.

97
As we access the element of index i of the array tab by the expression tab[i], we can infer the relationship between
[ ] and © following:
tab[i] = © (tab + i)
Example:
Start
...
p ←tab
FOR (i ←0 (1) MAX-1 DO
Write (©p)
p←p+i
ENDFOR
Stop

tab[0] tab is a pointer to the first array element


tab[1]
tab[2]
tab[3]
tab[4]

We then have the following equalities:


— tab +1 = @(tab[1]) (address of the 2nd element)
—© (tab + 1) = tab[1] (content of the 2nd element)
—© tab = tab[0] (content of 1st element)
—© (tab + i) = tab[i] (content of (i+1)th element)
— tab + i = @(tab[i]) (address of (i+1)th element)
The manipulation of arrays has some drawbacks due to the fact that an array is a constant pointer; we cannot
therefore create arrays:
− Whose size is a program variable;
− Two-dimensional whose rows do not all have the same number of elements.
These operations become possible as soon as allocated pointers are manipulated dynamically.
▪ Management of Array whose size is a program variable
In pseudo code, and in C programming language, the size of an array must be known in the declaration part. This
causes a problem when we want this size to be known only when the algorithm is executed. This problem can be
solved using dynamic allocation, as shown in the following example:
Example:
Variable:
↓Real: p
Integer: n
Start
Write ("enter the number of elements? ")
Read (n)
p ←allocate(n*NbByte(real)) //allocation for an array of n reals
...
deallocate (p)
Stop
An element of rank i of this array can then be denoted either p[i] or © (p + i).
98
PROBLEM 1: QUADRATIC EQUATION MODULARIZED (SUBROUTINES CREATED FOR EACH MODULE)
The roots of a quadratic equation 𝒂𝒙𝟐 + 𝒃𝒙 + 𝒄 = 𝟎 can be obtained by using the expression

−𝑏 ± √𝑏 2 − 4𝑎𝑐
𝑥=
2𝑎
where 𝑏 2 − 4𝑎𝑐 is called discriminant.
− If 𝑏 2 − 4𝑎𝑐 > 0, the roots are real and unequal.
𝑏
− If 𝑏 2 − 4𝑎𝑐 = 0, the roots are real and equal, i.e 𝑥 = −
2𝑎

− If 𝑏 2 − 4𝑎𝑐 < 0, the roots are imaginary


MODULARIZATION
Breaking down the problem into smaller modules and analyzing each one before putting them together to solve the quadratic
equation.

1. Module: “calculateDiscriminant”

− Input: Coefficients “a”, “b”, and “c”


− Output: Discriminant value
− Description: This module calculates the discriminant value using the formula 𝒃𝟐 − 𝟒𝒂𝒄 and returns the result.
2. Module: “calculateRootsRealDifferent”

− Input: Coefficients “a”, “b”, and “discriminant”


− Output: Roots “root1” and “root2”
− Description: This module calculates the roots of the quadratic equation with a positive discriminant value. It uses the
formula `(-b + sqrt(discriminant)) / (2a)` and `(-b - sqrt(discriminant)) / (2a)` to compute the roots and stores them in
`root1` and `root2`.
3. Module: “calculateRootsRealSame”

− Input: Coefficients `a`, `b`


− Output: Roots `root1` and `root2`
− Description: This module calculates the roots of the quadratic equation with a zero discriminant value. It uses the formula
`-b / (2a)` to compute the roots and stores the same value in `root1` and `root2`.

4. Module: “calculateRootsComplexDifferent”

− Input: Coefficients `a`, `b`, and `discriminant`


− Output: Roots `realPart` and `imaginaryPart`
− Description: This module calculates the roots of the quadratic equation with a negative discriminant value. It computes the
real and imaginary parts separately using the formulas `-b / (2a)` and `sqrt(-discriminant) / (2a)`. The roots are then
stored in `realPart` and `imaginaryPart`.

99
C-Code: Using Local Variables and Passing Data Between Subroutines Using Parameters and Return Values [Call By Reference: Pointers]
#include <stdio.h>
#include <math.h>
double calculateDiscriminant(double a, double b, double c) ;
void calculateRootsRealDifferent(double a, double b, double discriminant, double* root1, double* root2) ;
void calculateRootsRealSame(double a, double b, double* root1, double* root2) ;
void calculateRootsComplexDifferent(double a, double b, double discriminant, double* realPart, double* imaginaryPart) ;
int main()
{
double a, b, c;
double discriminant, root1, root2, realPart, imaginaryPart;
printf("Enter coefficients a, b, and c: ");
scanf("%lf %lf %lf", &a, &b, &c);
discriminant = calculateDiscriminant(a, b, c);
if (discriminant > 0)
{
calculateRootsRealDifferent(a, b, discriminant, &root1, &root2);
printf("Roots are real and different.\n");
printf("Root 1 = %.2lf\n", root1);
printf("Root 2 = %.2lf\n", root2);
}
else if (discriminant == 0)
{
calculateRootsRealSame(a, b, &root1, &root2);
printf("Roots are real and same.\n");
printf("Root 1 = Root 2 = %.2lf\n", root1);
}
else
{
calculateRootsComplexDifferent(a, b, discriminant, &realPart, &imaginaryPart);
printf("Roots are complex and different.\n");
printf("Root 1 = %.2lf + %.2lfi\n", realPart, imaginaryPart);
printf("Root 2 = %.2lf - %.2lfi\n", realPart, imaginaryPart);
}
return 0;
}

double calculateDiscriminant(double a, double b, double c)


{
return b * b - 4 * a * c;
}
void calculateRootsRealDifferent(double a, double b, double discriminant, double* root1, double* root2)
{
*root1 = (-b + sqrt(discriminant)) / (2 * a);
*root2 = (-b - sqrt(discriminant)) / (2 * a);
}
void calculateRootsRealSame(double a, double b, double* root1, double* root2)
{
*root1 = *root2 = -b / (2 * a);
}
void calculateRootsComplexDifferent(double a, double b, double discriminant, double* realPart, double* imaginaryPart)
{
*realPart = -b / (2 * a);
*imaginaryPart = sqrt(-discriminant) / (2 * a);
}

100
1.8 STACKS and QUEUES
1.8.1 Stacks
Stack is a linear data structure that maintains a list of elements in such a manner that elements can be inserted or
deleted only from one end of the list. This end is referred as top of the stack (TOS). Stack is based on the Last-In-
First-Out (LIFO) principle, which means the element that is last added to the stack is the one that is first removed
from the stack.
1.8.1.1 Stack Operations
There are two key operations associated with the stack data structure: push and pop. Adding an element to the
stack is referred as push operation while removing an element from the stack is referred as pop operation
1.8.1.2 Push
The push operation involves the following subtasks:
1. Receiving the element to be inserted
2. Incrementing the stack pointer, top
3. Storing the received element at new location of top
Thus, the programmatic realization of the push operation requires implementation of the above-mentioned
subtasks
1.8.1.3 Pop
The pop operation involves the following subtasks:
1. Removing the element at the top of the stack.
2. Decrementing the stack pointer, top

Thus, the programmatic realization of the pop operation requires implementation of the above-mentioned
subtasks
1.8.1.4 Stack Implementation
Stack implementation involves choosing the data storage mechanism for storing stack elements and
implementing methods for performing the two stack operations, push and pop.
We can implement stacks by using arrays or linked lists. Both implementation types have their own usage in
specific situations.
1.8.1.5 Array Implementation of Stacks
The array implementation of stacks involves allocation of fixed size array in the memory. Both stack operations
(push and pop) are made on this array with a constant check being made to ensure that the array does not go out
of bounds.
− Push Operation
The push operation involves checking whether or not the stack pointer is pointing at the upper bound of the array.
If it is not, the stack pointer is incremented by 1 and the new item is pushed (inserted) at the top of the stack.
Implementation of the Push Operation under Array Representation of Stacks.
Pseudocode C Language
PROCEDURE Push(stack[MAX], element) void push(int element, int n)
Start {
IF (top = MAX-1) THEN //top is a global variable
if(top==n-1)
Display (”Stack Full”)
{
Exit printf(“Stack is Full.\n”);
ELSE exit(1);
top ←top + 1 }
stack[top] ←element else
ENDIF {
Stop top=top+1;
stack[top]=element;
}
}
101
The above algorithm inserts an element at the top of a stack of size MAX.

− Pop Operation
The pop operation involves checking whether or not the stack pointer is already pointing at NULL (empty stack).
If it is not, the item that is being currently pointed is popped (removed) from the stack (array) and the stack
pointer is decremented by 1.
Implementation of the Pop Operation under Array Representation of Stacks.
Pseudocode C Language
PROCEDURE Pop(stack[MAX]) void push()
Start {
IF (top = -1) THEN //top is a global variable
if(top==-1)
Display (”Stack is empty”)
{
Exit printf(“Stack is Empty.\n”);
ELSE exit(1);
top ←top - 1 }
ENDIF else
Stop {
top=top-1;
}
}
The above algorithm removes the element at the top of the stack

A program to implement a stack using arrays and perform its common operations.
#include <stdio.h>
int stack[100];
int top=-1;
void push(int);
void pop();
void display();
int main()
{
int choice;
int num1=0,num2=0;
while(1)
{
/*Creating an interactive interface for performing stack operations*/
printf(“Select a choice from the following:”);
printf(“\n[1] Push an element into the stack”);
printf(“\n[2] Pop out an element from the stack”);
printf(“\n[3] Display the stack elements”);
printf(“\n[4] Exit\n”);
printf(“\n\t Your choice: “);
scanf(“%d”, &choice);
switch(choice)
{
case 1:
{
printf(“\n\t Enter the element to be pushed into the stack: “);
scanf(“%d”,&num1);
push(num1); /*Inserting an element*/
break;
}
case 2:
{
pop(); /*Removing an element*/
printf(“\n\t Element popped out of the stack\n\t”);
break;
102
}

case 3:
{
display(); /*Displaying stack elements*/
break;
}
case 4:
exit(1);
break;
default:
printf(“\n Invalid choice!\n”);
break;
}
}
return 0;
}
void push(int element)
{
if(top==99) /*Checking whether the stack is full*/
{
printf(“Stack is Full.\n”);
exit(1);
}
else
{
top=top+1;
stack[top]=element;
}
}
void pop()
{
if(top==-1) /*Checking whether the stack is empty*/
{
printf(“\n\t Stack is Empty.\n”);
exit(1);
}
top=top-1;
}
void display()
{
int i;
printf(“\n\t The various stack elements are:\n”);
for(i=top; i>=0;i--)
printf(“\t %d\n”, stack[i]); /*Printing stack elements*/
}

− Program analysis

Key Statement Purpose


int stack[100]; Declares an array to represent a stack
int top=-1; Declares and initializes the stack pointer
while(1) signifies an infinite looping condition that’ll continue to execute the statements within until a
jump statement is encountered
push(num1); Calls the push() function for inserting an element into the stack
display(); Calls the display() function for displaying the stack elements
top=top+1; Inserts an element at the top of the stack and updates the stack pointer
stack[top]=element;

103
1.8.2 Queues
Queue is a linear data structure that maintains a list of elements in such a manner that elements are inserted from one end
of the queue (called rear) and removed from the other end (called front). Queue is based on the First-In-First-Out (FIFO)
principle, which means the element that is first added to the queue is also the one that is first removed from the queue.
1.8.2.1 Queue Implementation
Queue implementation involves choosing the data storage mechanism for storing queue elements and implementing
methods for performing the two queue operations, enqueue and dequeue. Like stacks, we can implement queues by using
arrays or linked lists. There are two variables i.e. front and rear, that are used in the case of every queue implementation.
Front and rear point to the position from where insertions and deletions are performed in the queue.
Initially, rear=front=-1, which represents an empty queue.
1.8.2.2 Array Implementation of Queues
The array implementation of queues involves allocation of fixed size array in the memory. Both queue operations (enqueue
and dequeue) are performed on this array with a constant check being made to ensure that the array does not go out of
bounds.
Enqueue Operation: The enqueue operation involves checking whether or not the queue pointer rear is pointing at the upper
bound of the array. If it is not, rear is incremented by 1 and the new item is added at the end of the queue
Implementation of the Enqueue Operation under Array Representation of Queues
Pseudocode C Language
PROCEDURE insert(integer num) void insert(int num)
Start {
IF(rear = MAX-1) THEN if(rear == MAX-1)
print(“\n OVERFLOW”) {
Return; printf(“\n OVERFLOW”);
ELSEIF(front = -1 AND rear =-1) THEN return;
front = rear = 0; }
ELSE else if(front == -1 && rear == -1)
rear++; {
ENDIF front = rear = 0;
queue[rear] = num; }
Stop else
{
rear++;
}
queue[rear] = num;
}

Dequeue Operation: The dequeue operation involves checking whether or not the queue pointer front is already pointing
at NULL (empty queue). If it is not, the item that is being currently pointed is removed from the queue (array) and the front
pointer is incremented by 1.

Implementation of the Dequeue Operation under Array Representation of Queues


Pseudocode C Language
PROCEDURE delete_element() void delete_element()
Start {
Variable: int val;
integer val; if(front == -1 || front>rear)
IF(front = -1 OR front>rear) THEN {
print(“\n UNDERFLOW”) printf(“\n UNDERFLOW”);
ELSE return -1;
front++; }
IF (front > rear) THEN else
front = rear = -1; {
ENDIF front++;
Stop if(front > rear)
front = rear = -1;
}
}

104
1.9 Case Studies
1. Matrix Rotation
Images in computers are stored as two-dimensional arrays. A black-and-white image (Figure 1) is stored as
a 10 × 10 two-dimensional array named MAT (Figure 2). Each element of MAT holds a number for a colour;
1 represents the colour black and 0 represents the colour white.

The simple black-and-white image The corresponding two-dimensional array MAT

In an application, the black-and-white image can be inverted (all white pixels are changed to black, and all black
pixels are changed to white).Method invert(N,A)accepts a positive integer N and an N × N two-dimensional array
A that holds the data for a simple black-and-white image; it returns the inverted N × N two-dimensional array A.
a) Construct an algorithm in pseudocode for the method invert(N, A).
In the application, it is also possible to rotate an image clockwise by 90 degrees (90°). For example, when the
simple black-and-white image is rotated, the corresponding 10 × 10 two-dimensional array MAT is updated. This
would mean the first row of the original MAT is the last column in the rotated MAT, the second row is the second-
to-last last column, … and the last row is the first column.

105
The simple black-and-white image rotated by 90° The corresponding two-dimensional array MAT
(clockwise)

Consider the following algorithm fragment:


K=input()
loop for M=0 to (K mod 4)-1
A=rotate(N,A)
end loop
where:
− N is an integer and A is the N × N two-dimensional array that holds data about an image
− K(K>=0) is an integer showing how many times the image should be rotated
− Method rotate(N,A) accepts an integer N and an N × N two-dimensional array A representing an image. It
returns an N × N two-dimensional array representing the image rotated clockwise by 90°.
b)
i. State the number of degrees by which the image will be rotated if the input value of K is 3.
ii. Outline why it is more efficient that the loop in the given algorithm fragment executes (K mod 4) times
instead of K times. You may give an appropriate example in your answer
The algorithm for method rotate(N,A) uses an additional N × N two-dimensional array, named B. The N × N
dimensional array B is initialized and updated using the values from A to represent the image rotated clockwise
by 90°.
c) Construct the algorithm in pseudocode for the method rotate(N,A) described above.
To avoid inefficient use of memory, a new algorithm for the method rotate(N,A) is constructed. The N × N two-
dimensional array A should be rotated clockwise by 90°, without the use of any additional arrays. One way of
rotating the two-dimensional array A clockwise by 90° is to transpose A, and then reverse each row of A.
The transpose of A is formed by turning all the rows of A into columns. For example, the value in the first row and third
column (A[1][3]) is swapped with the value in the third row and first column (A[3][1]).

106
d) Construct the new algorithm in pseudocode for the method rotate(N,A)described above.
e) Transform the pseudocode for the rotate(N, A) method written in d) above and invert() method in a) into
programming language functions or procedures
f) Write the execution part of the main program that:
− Declares two 2-D 10 x 10 arrays MAT and MATINVERT. MATINVERT will store the inverted image of MAT.
− Calls the read() procedure that reads the 0s and 1s into the array MAT. This procedure prompts the user to enter the
values in the matrix as shown above. MATINVERT is initialized with values from MAT
− Calls the invert subroutine to invert MATINVERT .
− Cals the rotate subroutine to rotate the matrix MAT.
− Calls the display() function 4 times to display original image, the inverted image, the rotated matrix for k=1 and k=3;
Solution
a)
Pseudocode C language
PROCEDURE Invert(integer: A[10][10],N) void Invert(int A[10][10], int N)
Variable: {
Integer: i, j int i, j;
Start for(i=0;i<N; i++)
FOR(i←0 to N-1)DO {
FOR(j←0 to N-1)DO for(j=0; j<N, j++)
IF(A[i][j]=1) THEN {
A[I][J]←0 if(A[i][j]==1)
ELSE {
A[I][J]←1 A[i][j]=0;
ENDIF }
ENDFOR else
ENDFOR {
Stop A[i][j]=1
}
}
}
}
Or (Smarter Approach 😊) void Invert(int A[10][10], int N)
PROCEDURE Invert(integer: A[10][10],N) {
Variable: int R=0, C=0, I=0;
Integer: R, C, I while (I< N*N)
Start {
R←0 if(A[R][C]==0)
C←0 {
I←0 A[R][C]=1;
WHILE (I< N*N) DO }
IF (A[R][C]=0) THEN else
A[R][C]←1 {
ELSE A[R][C]=0;
A[R][C]←0 }
ENDIF C=C+1;
C←C+1 if(C>N-1)
IF (C>N-1) THEN {
C←0 C=0;
R←R+1 R=R+1;
ENDIF }
I←I+1 I=I+1;
ENDWHILE }
Stop }

107
b)
i. K=3
(3 Mod 4)-1=2
The loop will execute for M=0, 1 and 2. For each iteration, the image is rotated 90 degrees.
Hence, it will rotate through 270 (degrees);
ii. A rotation by 360 degrees returns the image/matrix to its original value, so no action need to be taken. A
rotation by 360+N degrees is equivalent to a rotation by N degrees
By using K Mod 4, unnecessary calls to the method rotate() which would make the algorithm less efficient
are avoided. For example, repeating 10 times and repeating 2 (=10 mod 4) times, both return the array
holding the image rotated by 180 degrees.
c)
Pseudocode C language
PROCEDURE Rotate(integer: A[][], N) void Rotate(int A[][10], int B[][10], int N)
Variable: {
Integer A[][], B[][] i, j int i, j;
Start for(i=0;i<N; i++)
FOR (i←0 TO N-1) DO {
FOR (j←0 TO N-1) DO for(j=0; j<N;j++)
B[i][j] ← A[i][j]; {
ENDFOR B[i][j]= A[i][j];
ENDFOR }
FOR (i←0 TO N-1) DO }
FOR (j←0 TO N-1) DO for(i=0;i<N; i++)
B[i][j] ← A[N-j-1][i]; {
//Or B[j][N-1-i] = A[i][j] for(j=0; j<N; j++)
ENDFOR {
ENDFOR B[i][j]= A[N-j-1][i];
Return B }
Stop
}
}
d)
Pseudocode C language
PROCEDURE Rotate(integer: A[][], N) void Rotate(int A[][10], int N)
Variable: {
Integer A[][], i, j, Start, End int i, j, Temp;
Start for(i=0;i<N; i++)
//Transpose of A {
FOR (i←0 TO N-1) DO for(j=0;j<=i-1;j++)
FOR (j←0 TO i-1) DO {
Temp ← A[i][j] Temp =A[i][j];
A[i][j]←A[j][i] A[i][j]=A[j][i];
A[j][i]←Temp A[j][i]=Temp;
ENDFOR }
ENDFOR }
//Reverses each row of transposed matrix A for(i=0;i<N;i++)
FOR (i←0 TO N-1) DO {
Start← 𝟎 int start=0, end=N-1;
End ←N-1 while(start<end)
WHILE (Start<End) DO {
Temp ← A[i][Start] Temp=A[i][start];
A[i][Start]←A[i][End] A[i][start]=A[i][end];
A[i][End]← Temp A[i][end]= Temp;
Start← Start+1 start++;
End ←End+1 end--;
ENDFOR }
ENDFOR }
Stop }

108
#include <stdio.h>
#include <stdlib.h>
void display(int A[][10], int N);
void read(int A[][10], int N);
void Rotate(int A[][10], int N);
void Invert(int A[10][10], int N);
int main()
{
int MAT[10][10], K, MATINVERT[10][10], size, i, j;
printf("Enter the value of N: !\t");
scanf("%d", &size);
printf("Enter the elements of MAT: !\t");
read(MAT, size);
for(i=0;i<size; i++)
{
for(j=0;j<size; j++)
{
MATINVERT[i][j]=MAT[i][j];
}
}
display(MAT, size);
Invert(MATINVERT, size);
printf("The inverted matrix of MAT is\n");
display(MATINVERT, size);
printf("Enter the value of K:\t");
scanf("%d", &K);
for(i=0;i<=((K%4)-1);i++)
{
Rotate(MAT, size);
}
printf("Matrix rotated %d times is\n", K);
display(MAT, size);
return 0;
}
void read(int A[][10], int N)
{
int i, j;
for(i=0;i<N; i++)
{
for(j=0;j<N;j++)
{
scanf("%d",&A[i][j]);
}
printf("\n");
}
}

void display(int A[][10], int N)


{
int i,j;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
printf("%d\t",A[i][j]);
}
printf("\n");
}
}

109
void Invert(int A[10][10], int N)
{
int R=0, C=0, I=0;
while (I< N*N)
{
if(A[R][C]==0)
{
A[R][C]=1;
}
else
{
A[R][C]=0;
}
C=C+1;
if(C>N-1)
{
C=0;
R=R+1;
}
I=I+1;
}
}

void Rotate(int A[][10], int N)


{
int i, j, Temp;
for(i=0;i<N;i++)
{
for(j=0;j<=i-1;j++)
{
Temp =A[i][j];
A[i][j]=A[j][i];
A[j][i]=Temp;
}
}
for(i=0;i<N;i++)
{
int start=0, end=N-1;
while(start<end)
{
Temp=A[i][start];
A[i][start]=A[i][end];
A[i][end]= Temp;
start++;
end--;
}
}
}

2. Matrix Operations
1. In the main function, create a 5x3, 2-D array consisting of random integers in the range 0 to 9, including the end
points
2. Call a function named printArray that will print the array, appropriately labeled, 3 numbers per line with a space
between each
3. Call a function named findSmallest that will find and print, appropriately labeled, the smallest number in the
array
4. Call a function named findAverage that will find and print, appropriately labeled, the average numbers in the
array

110
5. Call a function named remEvens, that will modify the array such that all even numbers are replaced by the
number -1
6. Call a function named printArray discussed in part 2 above and print the array as modified in part 5

#include <stdio.h>
#include <stdlib.h>
#include<time.h>
void printArray(int A[][3]);
int findSmallest(int A[][3]);
float findAverage(int A[][3]);
void remEvens(int A[][3]);
int main()
{
srand(time(NULL));
int Arr[5][3];
int i, j;
for(i=0;i<5;i++)
{
for(j=0;j<3;j++)
{
Arr[i][j]=rand()%10;
}
}
printArray(Arr);
printf("The smallest value in the matrix is %d\n", findSmallest(Arr));
printf("The average of the values in the matrix is %.2f\n", findAverage(Arr));
remEvens(Arr);
printArray(Arr);
getch();
return 0;
}
void printArray(int A[][3])
{
int i,j;
for(i=0;i<5;i++)
{
for(j=0;j<3;j++)
{
printf("%d\t",A[i][j]);
}
printf("\n");
}
}
int findSmallest(int A[][3])
{
int i,j,min;
min=A[0][0];
for(i=0;i<5;i++)
{
for(j=0;j<3;j++)
{
if(A[i][j]<min)
{
min=A[i][j];
}
}
}

111
return min;
}

float findAverage(int A[][3])


{
int i,j,count=0;
float sum=0.0,average;
for(i=0;i<5;i++)
{
for(j=0;j<3;j++)
{
sum=sum+A[i][j];
count++;
}
}
average=sum/count;
return average;
}
void remEvens(int A[][3])
{
int i,j;
for(i=0;i<5;i++)
{
for(j=0;j<3;j++)
{
if(A[i][j]%2==0)
{
A[i][j]=-1;;
}
}
}
}

3. Class Sports
A class has 10 students. All student names (strings) and student ID numbers (five-digit integers) are held in two
separate one-dimensional arrays named SID and SNAMES.

SID SNAMES
Index ID Index NAME
[0] 10011 [0] Itoe Peter
[1] 10002 [1] Mokube James
[2] 11876 [2] Sakwe John
[3] 10122 [3] Mbi Joe
[4] 22103 [4] Che Josh
[5] 32000 [5] Neba Ngwa
[6] 34250 [6] Ngu Pierre
[7] 35200 [7] Ngwa Mary
[8] 35247 [8] Jones Paul
[9] 36250 [9] Namandia Jona

For example, student Mokube James has ID number 10002. A binary search algorithm is not used to find a
particular name in array SNAMES.
a) State the reason for not using a binary search.
112
The school offers its sporting program to students and has a basketball team, a tennis team and a football team.
Each student must choose at least one of these three sports. Each sporting program has 5 registered students for
the class.
Three collections, BASKETBALL, TENNIS and FOOTBALL, are created. When a student chooses a sporting
activity, their ID number is added to the appropriate collection. For example:
− BASKETBALL={10011,11876,10122,35247,10002};
− TENNIS={10011,11876,10002,36250,32000}
− FOOTBALL={10011,10002,22103,32000,11876}
The method isIn(X, COL) is available, where:
− X is a five-digit integer representing an ID number
− COL is a collection that holds student ID numbers.
The method isIn(X, COL) returns True if the ID number X is in the collection COL; False otherwise. For example:
isIn(11876, BASKETBALL) returns True. isIn(35247, FOOTBALL) returns False
b) Construct an algorithm in pseudocode for the method isIn(X, COL).
The football and tennis training sessions are held at the same time. The football coach would like to know how
many students will not be able to attend the football training session because they will be attending the tennis
training session.
c) Construct an algorithm in pseudocode that will output the number of students who have chosen both
tennis and football. The method isIn() should be used in your answer.
The school coordinator would like to check whether there are students who have not yet chosen any one of the
three sports.
d) Construct an algorithm in pseudocode that will output the names of students who have not yet chosen any
one of the three sports. An appropriate message should be displayed if every student has chosen a sport.
e) Write the execution part of the program using the C programming language that utilizes the functions
above. Declare the data structures SID, TENNIS, BASKETBALL, FOOTBALL, SNAMES. Initialize with the
given values.

Solution
a) Because the array SNAMES is not sorted/ordered
b Boolean: FUNCTION isIn(X, COL)
Pseudocode C Language
Boolean: FUNCTION isIn(X, COL) int isIn(int X, int COL[])
Variable: {
Boolean: Flag int Flag, Count;
Integer: Count Flag=0;
Start Count=0;
Flag←FALSE while((Count<5)&&(Flag==0))
Count←0 {
WHILE(Count<5 AND NOT Flag) DO if(COL[Count]==X)
IF(COL[Count]=X) THEN {
Flag←TRUE Flag=1;
ENDIF }
Count←Count+1 Count++;
ENDWHILE }
Return Flag return Flag;
Stop }

113
c Algorithm Tennis and Football
Pseudocode C Language
Algorithm Tennis_FootBall while(Count<5)
Variable: {
Boolean: Found Found=isIn(Tennis[Count],Football);
Integer: Count, Number if(Found==1)
Start {
Number← 𝟎 Number=Number+1;
Count←0 }
WHILE(Count<5) DO Count=Count+1;
Found←isIn(Tennis[Count],Football) }
IF(Found=True) THEN printf("Number of students taking Football and
Number←Number+1; Tennis is %d\n", Number);
ENDIF
Count←Count+1
ENDWHILE
Write(“Number of students taking Football
and Tennis is”, Number)
Stop

d Algorithm Tennis and Football and Basket Ball


Pseudocode C Language
Algorithm Basket_Tennis_FootBall while(Index<10)
Variable: {
Boolean: Found=FALSE res1=isIn(SID[Index],Football);
Integer: Count res2=isIn(SID[Index],Tennis);
Start res3=isIn(SID[Index],BasketBall);
Count←0 if(res1!=1)
WHILE(Count<10) DO {
IF(NOT isIn(Tennis[Count],Football) THEN if(res2!=1)
IF(NOT isIn(Tennis[Count],Tennis) THEN {
IF(NOT isIn(Tennis[Count], Basketball) THEN if(res3!=1)
Write(“Name:” SNAMES[Count]) {
Found=True printf("\n Name:%s is not doing any
ENDIF sport\n", SNames[Index]);
ENDIF Flag=1;
ENDIF }
Count←Count+1 }
ENDWHILE }
IF(Found=False) THEN Index=Index+1;
Write(“every student has chosen a sport.”) }
ENDIF if(Flag==0)
Stop {
printf("Every student has chosen a
sport\n");
}

114
#include<stdio.h>
int isIn(int X, int COL[]);
int main()
{
int Count=0,i,Number=0,Flag,Found=0,Index=0;
int res1,res2,res3;
char SNames[10][20]={"Itoe Peter", "Mokube James" ,"Sakwe John", "Mbi Joe", "Che Josh", "Neba Ngwa", "Ngu
Pierre", "Ngwa Mary", "Jones Paul", "Namandia Jona"};
int SID[10]={10011,10002,11876,10122,22103,32000,34250,35200,35247,36250};
int Tennis[5]={10011,11876,10002,36250,32000};
int Football[5]={10011,10002,22103,32000,11876};
int BasketBall[5]={10011,11876,10122,35247,10002};
while(Count<5)
{
Found=isIn(Tennis[Count],Football);
if(Found==1)
{
Number=Number+1;
}
Count=Count+1;
}
printf("Number of students taking Football and Tennis is %d\n", Number);
while(Index<10)
{
res1=isIn(SID[Index],Football);
res2=isIn(SID[Index],Tennis);
res3=isIn(SID[Index],BasketBall);
if(res1!=1)
{
if(res2!=1)
{
if(res3!=1)
{
printf("\n Name:%s is not doing any sport\n", SNames[Index]);
Flag=1;
}
}
}
Index=Index+1;
}
if(Flag==0)
{
printf("Every student has chosen a sport\n");
}
getch();
return 0;
}
int isIn(int X, int COL[])
{
int Flag, Count;
Flag=0;
Count=0;
while((Count<5)&&(Flag==0))
{
if(COL[Count]==X)
{
Flag=1;
}
Count++;
}
return Flag;
}

115
4. Your class teacher is not a programmer and he wants to use a computer application to record the marks for all his students.
He needs this application to:
− Allow him give a student’s number and put a mark against it
− Classify the students in order of merit, and
− Search for a given student and publish his/her mark.
A list of the marks of 10 students is given below:

Reg. NO NAME SCORE


1 Tiko 3.5
2 Tambe 11.5
3 Ngum 17.25
4 Fabian 11.5
5 Ndong 9.75
6 Tata 12
7 Ayuk 13
8 Nchang 9.25
9 Ndongmo 16
10 Ibrahim 14.8

Insert_sort()
Begin
For i=1 to n do
t[i].mark← 0
t[i].num← −1
End
For i=0 to n-1 do /***i=1 to n in PASCAL***/
Prompt user to give number and mark
Read number into result.num
Read mark into result.mark
For j←0 to j←i-1 do
If(result.mark<t[j]) then
aux ←t[j]
t[j]←result
result←aux
Endif
Endfor
t[i]←result
Endfor
End

To develop a programming solution to the teacher’s problem using an imperative programming language, you need some
data structures:
− A record (call it result) for each student, containing integer and real fields for registration number (num) and mark
respectively.
− An array t of these records.
a) In your answer booklet, give a declaration of the data structures in either C or PASCAL
b) Write the programming language (PL) procedure or function called insert_sort(), that reads a registration number and
the corresponding mark into the record result and inserts it into an array t of such records, in order of merit, for all n
(=10) students as given in the algorithm above
c) Write another PL procedure or function called search() that searches the array for a given registration number and prints
the student’s number and mark, if found. However, if the number is not found, the statement “STUDENT NOT FOUND” is
printed
d) Write the main program that calls insert_sort() procedure, and then loops, printing all records in array t. Afterwards, it
prompts for a student registration number and calls the search procedure to look for it. It then prints the entry if found,
or a suitable error message. The output of array t is in a tabular form with a colon separating each registration number
and its mark, for example, we have :
i. 3: 17.25
ii. 7: 13.00
e) Run the program, capture its terminal output, save it and then print it. Also save and prints all source codes
116
a
struct result
{
int num;
float mark;
};
struct result t[10];

b
void insert_sort(struct result A[])
{
struct result B, aux;
int i, j;
for(i=0;i<10;i++)
{
A[i].mark=0.0;
A[i].num=-1;
}
for(i=0;i<10;i++)
{
printf("Registration Number:\t");
scanf("%d",&B.num);
printf("Mark:\t");
scanf("%f",&B.mark);
for(j=0;j<=i-1;j++)
{
if(B.mark<A[j].mark)
{
aux=A[j];
A[j]=B;
B=aux;
}
}
A[i]=B;
printf("\n");
}
}

c
void search(struct result A[], int n)
{
int i, flag=0;
for(i=0;i<10;i++)
{
if(A[i].num==n)
{
flag=1;
printf("Student Info\t%d :%.2f",A[i].num, A[i].mark);
}
}
if(flag==0)
{
printf("NO STUDENT FOUND WITH THAT REGISTRATION NUMBER\n");
}
}

117
d Main Program
#include <stdio.h>
#include <stdlib.h>
struct result
{
int num;
float mark;
};
void insert_sort(struct result A[]);
void search(struct result A[], int n);
int main()
{
int i, no;
struct result t[10];
printf("Enter the registration numbers and the marks for the 10 students!\n");
insert_sort(t);
printf("The students registration numbers and marks:\n");
for(i=0;i<10;i++)
{
printf("%d\t\t%.2f\n" ,t[i].num ,t[i].mark);
}
printf("Enter the registration number of the student whose mark you wanna view\n");
printf("REGISTRATION NUMBER:\t");
scanf("%d", &no);
search(t, no);
return 0;
}
void insert_sort(struct result A[])
{
struct result B, aux;
int i, j;
for(i=0;i<10;i++)
{
A[i].mark=0.0;
A[i].num=-1;
}
for(i=0;i<10;i++)
{
printf("Registration Number:\t");
scanf("%d",&B.num);
printf("Mark:\t");
scanf("%f",&B.mark);
for(j=0;j<=i-1;j++)
{
if(B.mark<A[j].mark)
{
aux=A[j];
A[j]=B;
B=aux;
}
}
A[i]=B;
printf("\n");
}
}

118
void search(struct result A[], int n)
{
int i, flag=0;
for(i=0;i<10;i++)
{
if(A[i].num==n)
{
flag=1;
printf("Student Info\t%d :%.2f",A[i].num, A[i].mark);
}
}
if(flag==0)
{
printf("NO STUDENT FOUND WITH THAT REGISTRATION NUMBER\n");
}
}

5. The maximum and the minimum temperatures on each day of a city are collected over each week and then processed to
determine:
− Average minimum temperature of the week
− Average maximum temperature of the week
− Lowest temperature during the week.
− Highest temperature during the week.
The table below shows the list of minimum temperatures and maximum temperatures collected within a given week
Week
Days Monday Tuesday Wednesday Thursday Friday Saturday Sunday
Maximum 35.5 34.75 29.25 28.32 34 35 36
Temperature/℃
Minimum 28.5 29.4 27.3 26.57 30 31 32.25
Temperature/℃

1. Write a function/procedure called read() that will read the temperatures into the appropriate data structure(s)
2. Write a function/procedure called average() that will determine the average minimum temperature and average
maximum temperature
3. Write a function/procedure called bubblesort() that will arrange the maximum and minimum temperatures in ascending
order.
4. Write a function/procedure called display() that displays the ordered maximum and minimum temperatures in the
following way:

Maximum Temperatures Minimum Temperatures


28.32 26.57
29.25 27.3
34 28.5
34.75 29.4
35 30
35.5 31
36 32.25

5. Write a function/procedure called merge() that will merge the two ordered lists above into one ordered list
6. Test these functions/procedures by calling them in your main program. Within the main, display the merged list, display
the Lowest temperature during the week and Highest temperature during the week using the merged ordered list created
and displayed above.

119
a void read(float A[])
void read(float A[])
{
int i;
for(i=0;i<7;i++)
{
printf("Day[%d]\t",i+1);
scanf("%f", &A[i]);
}
printf("\n");
}

b float average(float A[])


float average(float A[])
{ int i;
float sum=0.0,av;
for(i=0;i<7;i++)
{
sum=sum + A[i];
}
av=sum/7.0;
return av;
}

c void bubblesort(float A[])


void bubblesort(float A[])
{
int i, j;
float temp;
for(i=0;i<7;i++)
{
for(j=0;j<6;j++)
{
if(A[j]>A[j+1])
{
temp=A[j];
A[j]=A[j+1];
A[j+1]=temp;
}
}
}
}

d void display(float A[], float B[])


void display(float A[], float B[])
{
int i;
printf("Minimum temperatures\t\t Maximum temperatures\n");
for(i=0;i<7;i++)
{
printf("%5.2f\t\t\t\t\t%.2f",A[i],B[i]);
printf("\n");
}

120
e void merge(float A[],float B[], float C[], int a, int b)
void merge(float A[],float B[], float C[], int a, int b)
{
int i=0, j=0, index=0;
while(i<a && j<b)
{
if(A[i]<B[j])
{
C[index]=A[i];
i++;
}
else
{
C[index]=B[j];
j++;
}
index++;
}
if(i==a)
{
while(j<b)
{
C[index]=B[j];
j++;
index++;
}
}
else if (j==b)
{
while(j<b)
{
C[index]=A[i];
i++;
index++;
}
}
}

f Main Program
#include<stdio.h>
#include<stdlib.h>
void read(float A[]);
float average(float A[]);
void display(float A[], float B[]);
void merge(float A[],float B[], float C[], int a, int b);
void bubblesort(float A[]);
int main()
{
int i;
float Min[7],Max[7],Combined[14];
printf("Enter the minimum temperatures:\n");
read(Min);
printf("Enter the maximum temperatures:\n");
read(Max);
bubblesort(Min);
bubblesort(Max);
printf("The sorted list of temperatures for the week is:\n");

121
display(Min, Max);
printf("\n");
printf("The average minimum temperature for the week is: %.2f\n", average(Min));
printf("The average maximum temperature for the week is: %.2f",average(Max));
merge(Min,Max,Combined,7,7);
printf("\n");
printf("A combined sorted list of minimum and maximum temperatures:\n");
for(i=0;i<14;i++)
{
printf("%.2f\n", Combined[i]);
}
printf("The lowest temperature during the week is %f\n", Combined[0]);
printf("The highest temperature during the week is %f\n", Combined[13]);
return 0;
}

We use two one dimensional arrays to store the data. One to store the minimum temperatures. Another to
store the maximum temperatures. The merged list of temperatures is stored in another array.

6 Complex Numbers
A complex number z is defined by its real part a and its imaginary part b. z = a + ib
— (a + ib) + (c + id) = (a + c) + i(b + d)
— (a + ib) × (c + id) = (ac - bd) + i(ad + bc)
The conjugate of z, represented as 𝑧 ∗ is given as 𝑧 ∗ = 𝑎 − 𝑖𝑏. The modulus of z is given as
|𝑧| = √𝑎2 + 𝑏 2
1. Declare the tComplex type for storing complex numbers
2. Write the functions that will give the attributes of a complex number (real part, imaginary part, module, argument) as
well as the functions to perform the addition and multiplication on complex numbers.
3. Use the previous questions to write a main program that reads first two complex numbers c1 and c2, performs addition,
and multiplication of c1 and c2, calculates the conjugate, and modulus of c1 and then displays the result of these operations.
a Data Structures
struct complex
{
int re;
int im;
};
typedef struct complex COMP;
COMP no1, no2, result;

b COMP add(COMP no1, COMP no2)


COMP add(COMP no1, COMP no2)
{
COMP result;
result.re=no1.re+no2.re;
result.im=no1.im+no2.im;
return result;
}

c COMP mult(COMP no1, COMP no2)


COMP mult(COMP no1, COMP no2)
{
COMP result;
result.re=no1.re*no2.re – no1.im*no2.im;
result.im=no1.re+no2.im + no1.im* no2.re;
return result;
}
122
d COMP conjugate(COMP no)
COMP conjugate(COMP no)
{
COMP result;
result.re=no.re;
result.im=-no.im;
return result;
}

e float modulus(COMP no)


float modulus(COMP no)
{
float result;
result=pow((no.re*no.re+no.im*no.im), 0.5);
return result;
}

e Main Program
#include<stdio.h>
#include<math.h>
struct complex
{
float re;
float im;
};
typedef struct complex COMP;
COMP add(COMP, COMP);
COMP mult(COMP, COMP);
COMP conjugate(COMP);
float modulus(COMP);
int main()
{
COMP no1, no2, result;
float mod;
printf("Enter the real and imaginary part of first complex number:\n");
scanf("%f %f", &no1.re, &no1.im);
printf("Enter the real and imaginary part of second complex number:\n");
scanf("%f %f", &no2.re, &no2.im);
result=add(no1, no2);
printf("%.2f + %.2f i\n", result.re, result.im);
result=mult(no1, no2);
printf("%.2f + %.2f i\n", result.re, result.im);
result=conjugate(no1);
printf("%.2f + %.2f i\n", result.re, result.im);
mod=modulus(no1);
printf("%.2f",mod);
return 0;
}

7 Book Shop Inventory


A book shop uses a personal computer to maintain the inventory of books that are being sold at the shop. The list includes
details such as author, title, price, publisher, stock position, etc. Whenever a customer wants a book:
− The shopkeeper inputs the title and author of the book and the system replies whether it is in the list or not.
− If it is not, an appropriate message is displayed.
− If book is in the list, then the system displays the book details and asks for number of copies.
− If the requested copies are available, the total cost of the books is displayed; otherwise the message “Required copies
not in stock” is displayed.
123
Analysis
To accomplish this task, the program uses a template to define the structure of the book. The date of publication, a member
of record structure, is also defined as a structure. When the title and author of a book are specified, the program searches for
the book in the list using the function
look_up (table, s1, s2, m)
The parameter table which receives the structure variable book is declared as type struct record. The parameters s1 and s2
receive the string values of title and author while m receives the total number of books in the list. Total number of books is
given by the expression
sizeof(book)/sizeof(struct record)
The search ends when the book is found in the list and the function returns the serial number of the book. The function
returns –1 when the book is not found. That the serial number of the first book in the list is zero.
The program terminates when we respond “NO” to the question Do you want any other book?. Note that we use the
function gets(string) to get title, author, etc. from the terminal. This enables us to input strings with spaces such as “C
Language”.
We cannot use scanf to read this string since it contains two words. Since we are reading the quantity as a string using the
gets(string) function, we have to convert it to an integer before using it in any expressions. This is done using the atoi()
function.

a Data Structures
typedef struct
{
char month[10];
int year;
}DATE;
struct record
{
char author[20];
char title[30];
int price;
DATE date;
char publisher[10];
int quantity;
};
struct record book[];
char btitle[30], bauthor[20];
int index, no_of_records;
char response[10], bquantity[10];

b int look_up(struct record table[],char s1[],char s2[],int m)


int look_up(struct record table[],char s1[],char s2[],int m)
{
int i;
for(i = 0; i < m; i++)
{
if ((strcmpi(s1,table[i].title)==0&&strcmpi(s2,table[i].author)==0))
{
return (i); /* book found */
}
}
return(-1); /* book not found */
}

124
c Main Program
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct
{
char month[10];
int year;
}DATE;
struct record
{
char author[20];
char title[30];
int price;
DATE date;
char publisher[10];
int quantity;
};
int look_up(struct record table[],char s1[],char s2[],int m);
int main()
{
char btitle[30],bauthor[20];
int index, no_of_records;
char response[10], bquantity[10];
struct record book[]={{"Ritchie","C Language",45,{"May",1977},"PHI",10},{"Kochan","Programming in
C",75,{"July",1983},"Hayden",5},{"Bsamy","BASIC",30,{"January",1984},"TMH",0},{"Bsamy","COBOL",60,{"
December",1988},"Macmillan",25}};
no_of_records=sizeof(book)/sizeof(struct record);
do
{
printf("Enter title and author name as per the list:\n");
printf("\n Title:\t ");
gets(btitle);
printf("Author:\t");
gets(bauthor);
index=look_up(book, btitle, bauthor, no_of_records);
if(index != -1) /* Book found */
{
printf("\n %s %s %d %s %d %s\n\n", book[index].author, book[index].title,
book[index].price, book[index].date.month, book[index].date.year,
book[index].publisher);
printf("Enter number of copies:");
gets(bquantity);
if(atoi(bquantity)<book[index].quantity)
{
printf("Cost of %d copies = %d\n", atoi(bquantity),book[index].price*atoi(bquantity));
}
else
{
printf("\n Required copies not in stock\n\n");
}
}
else

125
{
printf("\n Book not in list\n Do you want any other book? (YES / NO):\n");
gets(response);
}
}while(response[0]=='Y'||response[0]=='y');
printf("\n\nThank you. Good bye!\n");
return 0;
}

8 Product of Polynomials
We can represent a polynomial 𝑃(𝑥), of degree n by an array tab of size n+1 such that tab[i] = 𝑎𝑖 for (0≤ 𝑖 ≤ 𝑛).
𝑛

𝑃(𝑥) = ∑ 𝑎𝑖 𝑥 𝑖
𝑖=0
Consider the polynomials 𝑓(𝑥) 𝑎𝑛𝑑 𝑔(𝑥) given by
𝑛

𝑓(𝑥) = ∑ 𝑎𝑖 𝑥 𝑖 = 𝑎𝑛 𝑥 𝑛 + 𝑎𝑛−1 𝑥 𝑛−1 + ⋯ + 𝑎1 𝑥 + 𝑎0


𝑖=0
𝑚

𝑔(𝑥) = ∑ 𝑏𝑖 𝑥 𝑖 = 𝑏𝑚 𝑥 𝑚 + 𝑏𝑚−1 𝑥 𝑚−1 + ⋯ + 𝑏1 𝑥 + 𝑏0


𝑖=0
The product of 𝑓(𝑥) 𝑎𝑛𝑑 𝑔(𝑥) is given by
𝑚+𝑛

ℎ(𝑥) = 𝑓(𝑥)𝑔(𝑥) = ∑ 𝑐𝑘 𝑥 𝑘
𝑘=0
Where 𝑐𝑘 is the coefficient of 𝑥 𝑘
𝑐𝑘 = ∑ 𝑎𝑖 𝑏𝑗
𝑖+𝑗=𝑘
For example, 𝑐𝑜 = 𝑎𝑜 × 𝑏𝑜 and 𝑐1 = 𝑎1 × 𝑏0 + 𝑎𝑜 × 𝑏1
𝑃(𝑥) = 𝑥 2 − 𝑥 + 20
𝑄(𝑥) = 12𝑥 2 − 𝑥 − 40
Consider h(x) defined by:
ℎ(𝑥) = 𝑃(𝑥) × 𝑄(𝑥), and ℎ𝑘 is the coefficient of 𝑥 𝑘
a) Determine ℎ0 , ℎ1 , ℎ2 , ℎ3 and ℎ4
b) Write a procedure product() which takes in two polynomials and return a polynomial which represents the product of
the two polynomials.
c) Write the execution part of the main program which:
− reads two polynomials 𝑃(𝑥) and 𝑄(𝑥)
− calls the product() procedure to multiply the two polynomials and display the result

a
ℎ𝑘 = ∑ 𝑎𝑖 𝑏𝑗, 𝑘 𝑣𝑎𝑟𝑖𝑒𝑠 𝑓𝑟𝑜𝑚 0 𝑡𝑜 𝑚+𝑛(2+2=4)
𝑖+𝑗=𝑘
ℎ0 ℎ0 = 𝑎0 × 𝑏0 = 20 × −40 = −800
ℎ1 ℎ1 = 𝑎0 × 𝑏1 + 𝑎1 × 𝑏0 = (20 × −1) + (−1 × −40) = 20
ℎ2 ℎ2 = 𝑎1 × 𝑏1 + 𝑎0 × 𝑏2 + 𝑎2 × 𝑏0 = (−1 × −1) + (20 × 12) + (1 × −40) = 201
ℎ3 ℎ3 = 𝑎1 × 𝑏2 + 𝑎2 × 𝑏1 = (−1 × 12) + (1 × −1) = −13
ℎ4 ℎ4 = 𝑎2 × 𝑏2 = 12 × 1 = 12

126
b void read(float A[],int nb)
void read(float A[],int nb)
{
int i;
printf("Enter the coefficients of the polynomials starting with coefficient of x^%d\n", nb);
for(i=nb; i>=0; i--)
{
printf("a^%d\t", i);
scanf("%f", &A[i]);
}
printf("\n");
}

c void display(float A[],int nb)


void display(float A[],int nb)
{
int i;
printf("The polynomial is ");
for(i=nb; i>=0; i--)
{
if(A[i]<0)
{
printf("%.1f",A[i]);
printf("x^%d", i);
}
else if(A[i]>0)
{
printf("+%.1f",A[i]);
printf("x^%d" ,i);
}
}
printf("\n");
}

d void poly_product(float A[],float B[],float C[],int p, int nb)


void poly_product(float A[],float B[],float C[],int p, int nb)
{
int i, j;
for(i=nb; i>=0; i--)
{
C[i]=0;
}
for(i=0; i<=p; i++)
{
for(j=0; j<=p; j++)
{
C[i+ j] = C[i + j] + A[i]*B[j];
}
}
}

127
e Main Program
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
#define n 15
void read(float A[],int nb);
void poly_product(float A[],float B[],float C[],int p, int nb);
void display(float A[],int nb);
int main()
{
int deg,deg_re,deg2=2*n+1;
float poly1[n],poly2[n],poly4[deg2];
printf("Enter the degree of the polynomials:\t");
scanf("%d", &deg);
printf("\n");
printf("Polynomial 1\n");
read(poly1,deg);
display(poly1,deg);
printf("\n\n");
printf("Polynomial 2\n");
read(poly2,deg);
display(poly2,deg);
printf("\n");
deg_re =deg*2+1;
poly_product(poly1, poly2,poly4,deg,deg_re);
printf("\n");
printf("PRODUCT OF THE POLYNOMIALS\n\n");
display(poly4,deg_re);
printf("\n");
return 0;
}

9. Peter .T is a manager at AWAH and SON’S LTD Company. He recruits workers of various categories A, B, C, D. Peter. T pays
workers of various categories as follows;
Apart from the base salaries by category mentioned above, AWAH and SON’S LTD also provides incentive payment for extra
time services. Every one hour of extra time costs 2.000 F. The base salary as given above CAN BE CHANGED over time by
board members. The take home salary is the sum of base salary and extra time payment.
Peter .T goes through a nightmare of calculations to produce the pay voucher every month end. You are contracted to provide
a software solution to Peter’s problem.
From the paragraph above we need a RECORD that keeps each category and the corresponding base salary and another
record that keeps information about a worker (at least the worker’s name) and his/her category as well as the extra hours
he/she has done.
To be able to calculate a worker’s take home payment, we read his category and then reference the corresponding base salary
from the salary table. We then add this salary to the product of extra hours and hour rate. Note that hour rate (HR) for extra
hours is 2000F/hour for every worker.
Implementation
a)
− Declare the data structure needed to keep information about a worker of the company, bearing in mind that a worker
has a name, a category and extra hours which are counted as whole numbers.
− Declare the structure that keeps a category and the corresponding salary.
− Declare the data structure that keeps the records for all workers in the company AWAH and SON’S LTD.
− Declare the data structure that keeps the record for all categories and the corresponding salaries for the company
AWAH and SON’S LTD.
− Initialize the first five entries of the data structures above with the following values:

128
Category Base Salary Name Category Extra hours
A 150,000 F Mr. George A 20
B 120,000 F Mr. Ayuk C 20
C 100,000 F Mme. Neba B 10
D 80,000 F Mr. Wirba A 15
Mme. Agbor D 30
b)
− Write a programming language (PL) function that takes as parameter, the name of a worker, calculates and returns
his/her take home salary, or returns -1 if the given worker is not found. Bear in mind that the data structures above
are global variables.
− Write the main function in which the user is prompted to give the name of a worker. You invoke the function above
to automatically calculate and print the take home salary of the worker whose name is given as prompted. If the
worker is not recognized the message “NOT AN EMPLOYEE” should be printed.
c) Sample Output Results
Test your function on the following input:
− Name: Mme. Neba
− Name: Mr. Franck

a Data Structures
struct category
{
char cat;
int salary;
};
struct employee
{
char name[17];
char cate;
int ehours;
};
struct employee E[N]={{"Mr. George",'A',20},{"Mr. Ayuk",'C',20},{"Mme. Neba",'B',10},{"Mr.
Wirba",'A',15},{"Mme. Agbor",'D',30}};
struct category C[NC]={{'A',150000},{'B',120000},{'C',100000},{'D',80000}};

b int takehome(char A[])


int takehome(char A[])
{
int i, j, sa;
for(i=0;i<N; i++)
{
if(strcmpi(A,E[i].name)==0)
{
for(j=0;j<NC; j++)
{
if(C[j].cat==E[i].cate)
{
sa=C[j].salary +E[i].ehours*Rate;
return sa;
}
}
}
}
return -1;
}

129
c Main Program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 5
#define NC 4
#define Rate 2000
int takehome(char A[]);
struct category
{
char cat;
int salary;
};
struct employee
{
char name[17];
char cate;
int ehours;
};
struct employee E[N]={{"Mr. George",'A',20},{"Mr. Ayuk",'C',20},{"Mme. Neba",'B',10},{"Mr.
Wirba",'A',15},{"Mme. Agbor",'D',30}};
struct category C[NC]={{'A',150000},{'B',120000},{'C',100000},{'D',80000}};
int main()
{
char Ename[17];
int finalsal;
printf("Enter the name of the worker whose salary you want to calculate:\t");
gets(Ename);
finalsal=takehome(Ename);
if(finalsal==-1)
{
printf("EMPLOYEE NOT FOUND\n");
}
else
{
printf("TAKE HOME SALARY: %d\n", finalsal);
}
return 0;
}
int takehome(char A[])
{
int i, j, sa;
for(i=0;i<N; i++)
{
if(strcmpi(A,E[i].name)==0)
{
for(j=0;j<NC; j++)
{
if(C[j].cat==E[i].cate)
{
sa=C[j].salary +E[i].ehours*Rate;
return sa;
}
}
}
}
return -1;
}

130
10 The following represents the names of students in a classroom of 12 students.
Fru Miguel Suntchia Danita Ngambi Talla Ngouane Nzesse Enzo Lesly Beri Djoukam
We wish to write a program that can permit us store the names, search the list for specific names, and arrange the list
following various criteria.
a) Give a declaration in your chosen programming language (PL), of a data structure to store the names of the students
which is immediately initialized to names above
b) Using your favorite editor, implement a PL function (or procedure) called Display that takes as parameters an array and
its size, and displays the content of the array
c) Implement a PL function/procedure called:
i. lexicographic_sort, that sorts the list in alphabetic order using a named sorting technique.
ii. lexicographic_sort_reverse, that sorts the list in reverse alphabetic order
iii. sort_by_length, that sorts the list in terms of the length of the name
iv. search_char, that displays the names of all the students that start with a particular character entered by the
user.
v. disName, that enables the user to know if a particular student is found in the class. It searches a particular
name entered by the user and displays its position in the list or displays not found if name isn’t found
d) Write a main program that calls the subroutines doDisplay, lexicographic_sort, lexicographic_sort_reverse, disNameCha,
disName and sort_by_length. You are expected to call the doDisplay procedure after every sorting procedure is applied
on the list to view the new re-arranged list.

a Data Structure: Nb is the number of students.


Char list[nb][15]={"Fru","Miguel","Suntchia","Danita","Ngambi","Talla","Ngouane",
"Nzesse", "Enzo", "Lesly", "Beri", "Djoukam"};

b void display(char A[][15], int n)


void display(char A[][15], int n)
{
int i;
for(i=0;i<n;i++)
{
printf("%s\n",A[i]);
}
}

c void lex_sort(char A[][15], int n)


void lex_sort(char A[][15], int n)
{
int i,j;
char temp[15];
for(i=0;i<n-1;i++)
{
for(j=0;j<n-1;j++)
{
if(strcmp(A[j],A[j+1])>0)
{
strcpy(temp, A[j]);
strcpy(A[j],A[j+1]);
strcpy(A[j+1],temp);
}
}
}
}

131
d void lex_sort_rev(char A[][15], int n)
void lex_sort_rev(char A[][15], int n)
{
int i, j;
char temp[15];
for(i=0;i<n-1;i++)
{
for(j=0;j<n-1;j++)
{
if(strcmp(A[j],A[j+1])<0)
{
strcpy(temp, A[j]);
strcpy(A[j],A[j+1]);
strcpy(A[j+1],temp);
}
}
}
}

e void sort_lenght(char A[][15], int n)


void sort_length(char A[][15], int n)
{
int i, j;
char temp[15];
for(i=0;i<n-1;i++)
{
for(j=0;j<n-1;j++)
{
if(strlen(A[j])>strlen(A[j+1]))
{
strcpy(temp, A[j]);
strcpy(A[j],A[j+1]);
strcpy(A[j+1],temp);
}
}
}
}

f void search_char(char A[][15], int n, char ch)


void search_char(char A[][15], int n, char ch)
{
int i;
for(i=0;i<n; i++)
{
if(tolower(A[i][0])==tolower(ch))
{
printf("%s\n", A[i]);
}
}
}

132
g int search(char A[][15], int n, char ch[])
int search(char A[][15], int n, char ch[])
{
int i;
for(i=0;i<n; i++)
{
if(strcmpi(A[i],ch)==0)
{
return i;
}
}
return -1;
}

h Main Program
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<ctype.h>
void display(char A[][15], int n);
void lex_sort(char A[][15], int n);
void lex_sort_rev(char A[][15], int n);
void sort_length(char A[][15], int n);
void search_char(char A[][15], int n, char ch);
int search(char A[][15], int n, char ch[]);
#define nb 12
int main()
{
char c;
char ch1[15];
int pos;
char list[nb][15]={"Fru","Miguel","Suntchia","Danita","Ngambi","Talla","Ngouane","Nzesse","Enzo",
"Lesly", "Beri", "Djoukam"};
printf("The list of students in the class is:\n");
display(list, nb);
printf("\n");
lex_sort(list, nb);
printf("The List Sorted in Alphabetic Order\n");
display(list, nb);
printf("\n");
lex_sort_rev(list, nb);
printf("The List Sorted in Reverse Alphabetic Order\n");
display(list, nb);
printf("\n");
printf("The List Sorted With Respect to Length of Name\n");
sort_length(list, nb);
display(list, nb);
printf("Enter the first letter of the names you want displayed:\t");
scanf("%c", &c);
printf("\n");
search_char(list, nb, c);
133
printf("Enter the name you want to search:\t");
scanf("%s",ch1);
printf("\n");
pos=search(list,nb,ch1);
if(pos==-1)
{
printf("Name not found\n");
}
else
{
printf("Name Found in position %d", pos);
}
return 0;
}

11 Consider the dimensions of the following shapes:


— Square: one side
— Rectangle: a length and a width
— Circle: a radius
We want to create a program that can store information about 50 shapes and calculate for each of them the perimeter and
the surface area.
a) Create the following types:
− Type Record tDimension consisting of area, perimeter, the shape of the figure and dimensions above. This stores
information about a single shape
− Type Array tTabFig of 50 records.
b) Write a function calcul() which calculates the perimeter and area from the dimensions of a figure with a given shape
(Rectangle, Circle or Square).
c) Write a main program that allows a user to:
− enter the dimensions of the desired number of figures using a procedure, read()
− call the calcul() procedure to calculate the perimeter and area of each figure,
− to display the calculated perimeter and area using an appropriate display subroutine.

a Data Structures
struct tDimension
{
float Perimeter;
float sArea;
char form[15]; //stores the shape of the figure
float radius;
float side;
float length;
float width;
};
struct tDimesion tFig[50];

b void calcul(int num)


void calcul(int num)
{
int i;
for(i=0;i<num; i++)
{
if(strcmpi(tFig[i].form, "circle")==0)
{
tFig[i].Perimeter=3.14*tFig[i].radius*tFig[i].radius;
134
tFig[i].sArea=2*tFig[i].radius*3.14;
}
else if (strcmpi(tFig[i].form, "rectangle")==0)
{
tFig[i].Perimeter=2*(tFig[i].lenght + tFig[i].width);
tFig[i].sArea=tFig[i].lenght*tFig[i].width;
}
else if (strcmpi(tFig[i].form, "square")==0)
{
tFig[i].Perimeter=4*(tFig[i].side);
tFig[i].sArea=tFig[i].side*tFig[i].side;
}
}
}

c void read(int num)


void read(int num)
{
int i;
for(i=0;i<num; i++)
{
printf("Enter the form of the figure:\t");
scanf("%s", tFig[i].form);
if(strcmpi(tFig[i].form, "square")==0)
{
printf("Enter the side:\t");
scanf("%f", &tFig[i].side);
}
else if (strcmpi(tFig[i].form, "rectangle")==0)
{
printf("Enter the lenght:\t");
scanf("%f", &tFig[i].lenght);
printf("Enter the width:\t");
scanf("%f", &tFig[i].width);
}
else if (strcmpi(tFig[i].form, "circle")==0)
{
printf("Enter the radius:\t");
scanf("%f", &tFig[i].radius);
}
}
}

d void display(int num)


void display(int num)
{
int i;
for(i=0;i<num; i++)
{
printf("Shape: %s\n", tFig[i].form);
printf("Perimeter:%.2f\n", tFig[i].Perimeter);
printf("Surface Area:%.2f\n", tFig[i].sArea);
printf("++++++++++++++++++++++++\n");
}
}

135
e Main Function
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
struct tDimesion
{
float Perimeter;
float sArea;
char form[15];
float radius;
float side;
float lenght;
float width;
};
struct tDimesion tFig[50];
void read(int num);
void display(int num);
void calcul(int num);
int main()
{
int numf;
printf("Calculation of perimeters and surface areas of different figures!\n");
printf("Enter the number of figures:\t");
scanf("%d", &numf);
read(numf);
calcul(numf);
printf("\n\n++++++++++++++++++++++\n");
display(numf);
return 0;
}

12 ENEO BILLING SYSTEM


ENEO is a cooperation that provides electricity in Cameroon. ENEO charges its clients according to units of electricity
consumed. When the number of units exceed a certain level, the rate of payment changes from domestic to industrial scale.
We suggest that the rating for domestic consumption should be 65F CFA per unit, while industrial rating should be 100F CFA
per unit.
When the total number of units consumed in a month is far greater than 100 units, the electricity consumption is considered
industrial, otherwise it is domestic. ENEO also charges a fixed rent (RENT) of 500F CFA per month on each of its electricity
meters.
Value Added Tax (VAT) is charged on the total amount payable for consumption (i.e. not including taxes). The VAT is 1.8%
of this amount. That is, if number of units consumed is X, and rate per unit is Y then the total untaxed amount (TUA) =XY and
VAT=1.8% of XY.
The net amount payable (NET) by client is the sum of RENT, TUA and VAT, that is NET = TUA + VAT + RENT
To calculate the units consumed per month, previous meter readings (R1) below, subtracted from the current readings (R2)
R1
Meter No 1 2 3 4 5 6
Reading 1023 1101 1011 1199 1110 1210

R2
Meter No 1 2 3 4 5 6
Reading 1103 1225 1110 1203 1210 2100

TASK 1
I. Using C programming environment, write a program that uses the tables (arrays): R1, R2, and R3 to hold the units
consumed for the six meters readings. Each array should be able to hold six elements.
The program should prompt the user to enter the previous and current readings for each meter. It reads these entries
into R1 and R2 respectively, and then prints a table with columns for the previous reading, the current reading and the
units consumed, in that order. For example, for the first two meters we have the table:

136
Previous Reading Current Reading Units Consumed (UC)
1023 1103 80
1101 1225 124

TASK 2
II. Write a programming language function that takes as parameter the number of units consumed (UC) and then calculates
and returns the net amount payable (NET) by the client
III. Test this function by calling it in your main program above, using UC, as parameter. Update the program to print the net
amount payable in the fourth column of the table for various units consumed (elements of R3)

a void read(int R[6])


void read(int R[6])
{
int i;
for(i=0;i<6;i++)
{
scanf("%d", &R[i]);
}
}

b void display(int R1[6],int R2[6],int R3[6])


void display(int R1[6],int R2[6],int R3[6])
{ int i;
printf("\n\n");
printf("Previous Reading\t\t Current Reading\t\t Units Consumed\n");
for(i=0;i<6;i++)
{
printf("%d\t\t\t\t %d\t\t\t %d\n",R1[i],R2[i],R3[i]);
}
}

c float NETPayable(int UC)


float NETPayable(int UC)
{
int TUA,Y;
float VAT, NET;
if(UC>100)
{
Y=100;
}
else
{
Y=65;
}
TUA=UC*Y;
VAT=(1.8*TUA)/100;
NET=TUA+VAT+RENT;
return NET;
}

137
d Main Function
#include<stdio.h>
#include<math.h>
#define RENT 500
void read(int R[6]);
void display(int R1[6],int R2[6],int R3[6]);
float NETPayable(int UC);
int main()
{ int i;
int R1[6],R2[6],R3[6];
float R4[6];
printf("Enter the six previous meter readings\n");
read(R1);
printf("Enter the six current meter readings\n");
read(R2);
for(i=0;i<6;i++)
{
R3[i]=R2[i]-R1[i];
}
display(R1,R2,R3);
for(i=0;i<6;i++)
{
R4[i]=NETPayable(R3[i]);
}
printf("\n\n");
printf("Previous Reading\t\t Current Reading\t\t Units Consumed\tNetAmountPayable\n");
for(i=0;i<6;i++)
{
printf("%d\t\t\t\t%d\t\t\t%d\t\t%.2f\n",R1[i],R2[i],R3[i],R4[i]);
}
return 0;
}

13 Consider the following declaration representing an array of bits.

Type
Ch1[N] = Array of Integers
Ch2[M] = Array of Integers

1. Write the execution part of the main program which:


— reads 2 integers from the keyboard n and m and which swaps the values of n and m if n > m;
— calls the read() subroutine twice to initialize ch1 (resp. ch2) with n (resp. m) bits;
— calls the display() subroutine twice to display ch1 and ch2;
— calls the match() subroutine to display the number of times ch1 appears in ch2.
— calls the first_match() subroutine to display the first position s of pattern ch1 in ch2 or -1 if ch1 does
not appear in ch2. ;
2. Write the following subroutines:
a) read() which initializes a binary number (ch) of n bits, n passed as the argument. This subroutine uses the predefined
function Random() which randomly returns an integer belonging to the interval [0;+∞[. Example: the statement
n←Random(); assigns to the variable n an integer in the interval [0;+∞[. ; we will have to bring n back into [0; 1]
b) display() which displays a sequence of bits passed to it;
c) is_equal() which returns TRUE if 2 binary numbers of equal length, passed as arguments are equal; is_equal() returns
FALSE otherwise.
d) match() which here consists of finding the number of occurrences nb of positions s such that ch1[i] = ch2[i + s] (with i
traversing ch1). This function uses a single iterative loop and the previous is_equal() function. ch1 and ch2 are among
the arguments of the function. Example: If ch1=0001 and ch2=000010001010001 then match() returns "3"
138
Ch1 0 0 0 1

Ch2 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1

e) first_match() which modifies match() so that it returns the first position s of pattern ch1 in ch2; it returns -1 if ch1 does
not appear in ch2. Example: On the previous example, first_match() returns "2"

a void read(int A[], int p)


void read(int A[],int p)
{
int i;
srand(time(NULL));
for(i=0;i<p; i++)
{
A[i]=rand()%2;
}
}

b void display(int A[],int p)


void display(int A[],int p)
{
int i;
for(i=0;i<p; i++)
{
printf("%d\t", A[i]);
}
printf("\n");
}

c int is_equal(int A[], int B[], int p, int s)


bool is_equal(int A[], int B[], int p, int s)
{
int i, flag=true;
for (i=0;i<p; i++)
{
if(A[i]!=B[i+s])
{
flag=false;
break;
}
}
if(flag==true)
{
return true;
}
else
{
return false;
}
}

139
d int match(int A[], int B[], int r, int q)
int match(int A[], int B[], int r, int q)
{
bool equal=false;
int s, nb=0;
for (s=0;s<q; s++)
{
if(s+r-1<q)
{
equal=is_equal(A, B, r, s);
if(equal==true)
{
nb++;
}
}
}
return nb;
}

e int first_match(int A[], int B[], int r, int q)


int first_match(int A[], int B[], int r, int q)
{ bool equal;
int s;
for (s=0;s<q; s++)
{
if(s+r-1<q)
{
equal=is_equal(A, B, r, s);
if(equal==true)
{
return s;
}
}
}
return -1;
}

f Main Function
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<time.h>
#define N1 20
#define M1 20
void read(int A[],int p);
void display(int A[],int p);
int is_equal(int A[], int B[], int p, int s);
int match(int A[], int B[], int r, int q);
int first_match(int A[], int B[], int r, int q);
int main()
{
int ch1[N1], ch2[M1];
int n, m, temp, oc=0, fm;
printf("Enter the number of bits n and m\n");
printf("n:\t");
140
scanf("%d", &n);
printf("\n");
printf("m:\t");
scanf("%d", &m);
printf("\n");
if(n>m)
{
temp=m;
m=n;
n=temp;
}
read(ch1,n);
read(ch2,m);
printf("The first sequence of bits is:\n");
display(ch1,n);
printf("The second sequence of bits is:\n");
display(ch2,m);
oc=match(ch1, ch2, n, m);
if(oc==0)
{
printf("Zero occurrence\n");
}
else
{
printf("Number of occurrences of ch1 in ch2 are: %d\n", oc);
}
fm=first_match(ch1,ch2,n,m);
if(fm==-1)
{
printf("No Match\n");
}
else
{
printf("First is at position %d\n",fm+1);
}
return 0;
}

14 A chief has 6 triangular pieces of land. He wishes to calculate the area of each piece of land and determine the largest
amongst his lands. He pays a land surveyor to determine the dimensions of the lands. With these dimensions, he consults you
to enable him perform the calculation. You decide to build a simple tool to solve this problem. The dimensions of the lands
are given below
Plot No a b Angle
1 137.4 80.9 0.78
2 155.2 92.62 0.89
3 149.3 97.93 1.35
4 160..0 100.25 9
5 155.6 68.95 1.25
6 149.7 120.0 1.75

The area of a triangle can be computed by the sine law when 2 sides of the triangle and the angle between them are known.
Area = (1/2) ab sin(angle).
1. Using C programming environment, write a program that uses the arrays: R1, R2, R3 and R4 to hold the plot number, the
sides a and b, and the angle respectively. Each array should be able to hold six elements.

141
2. The program should prompt the user to enter the plot number, the sides a and b, and the angle respectively for each land.
It reads these entries into R1, R2, R3 and R4 respectively
3. Write a programming language function/procedure area() that takes as parameter the sides a and b and the angle for a
given piece of land and then calculates and returns the area of the piece of land.
4. Write a programming language function/procedure largest() that takes as parameter the area of the six lands and then
returns the plot no of the piece of land with the largest area.
5. Test these functions/procedures by calling them in your main program above. Update the program to print the area in
the fifth column of the table for various lands. Call the largest() function/procedure in the main to display the largest
plot. The output should be in the format:
THE LARGEST PLOT
Plot No 3: Area 17.25

a float area(float a, float b, float c)


float area(float a, float b, float c)
{
float ar, arr;
arr=a*b*sin(c);
ar=arr/2.0;
return ar;
}

b int largest(float D[])


int largest(float D[])
{
int i, max=0;
for(i=1;i<6;i++)
{
if(D[i]>D[max])
{
max=i;
}
}
return max;
}

c Main Function
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
float area(float a,float b,float c);
int largest(float D[]);
int main()
{
int i,pos;
int R1[6];
float R2[6],R3[6],R4[6],R5[6];
printf("Enter info about the 6 lands\n");
for(i=0;i<6;i++)
{
printf("----------------\n");
printf("Plot no:\t");
scanf("%d",&R1[i]);
printf("Side a:\t");
scanf("%f",&R2[i]);
printf("Side b:\t");
scanf("%f",&R3[i]);
printf("Angle:\t");
142
scanf("%f",&R4[i]);
printf("----------------\n");
}
for(i=0;i<6;i++)
{
R5[i]=area(R2[i],R3[i],R4[i]);
}
printf("Plot no\t\tSide a\t\tSide b\t\tAngle\t\tArea\n");
for(i=0;i<6;i++)
{
printf("%5d\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f\n",R1[i],R2[i],R3[i],R4[i],R5[i]);
}
pos=largest(R5);
printf("\n\nThe Largest piece of land\n");
printf("Plot no %d\t: Area %.2f",R1[pos],R5[pos]);
return 0;
}

15 Pascal’s Triangle
Binomial expansions are sometimes aided by a tool known as the Pascal triangle. Pascal’s triangle is an array of numbers
which is triangular in nature. An example is shown below
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1

The Pascal Triangle

Here, we realize that it is an N x N matrix where N is a natural number. The leading diagonal of the matrix and the first column
are made of 1’s only.
That’s, if the matrix is A, then all A[i,1] are 1’s and all A[i, i] are 1’s for each line (row) i of the pascal triangle. Elements of each
line run from A[i, 1] to A[i, i] but A[i, 1] and A[i, i] are 1’s and can be filled in advance.
To fill each cell A[i, j] within the rest of the triangle, we go from A[i, 2] to A[i, i-1], with j ranging from 2 to i-1. So, every A[i, j]
= A[i-1, j] + A[i-1, j-1]
a) Attach the next two lines to the Pascal’s triangle.
b) Write an algorithm to fill the leading diagonal of a Pascal triangular matrix A (n rows and n columns)
c) Write another algorithm to fill the first column of the Pascal triangle. It then fills the remaining columns of the matrix A
with zeros
d) Write yet another algorithm to fill the rest of the row, apart from the first and the last element of the Pascal’s triangle
e) Transform the algorithms above into programming language function or procedures
f) Write a PL function or procedure that prints all the elements of an NxN matrix
g) Write the main program that calls the procedures above in the right order so as to populate and print the elements of
the matrix.

a Next Two Lines Added


1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1

143
Leading Diagonal
b Pseudocode C Language
Algorithm Leading_Diagonal void LDiagonal(int A[][10], int N)
Variables {
A: ARRAY[10][10] of Integer int i, j;
N, i, j: Integers
for(i=0;i<N; i++)
Start
Write(“Enter the number of rows or the Pascal’s
{
triangle:”) for(j=0;j<N;j++)
Read(N) {
FOR (i←0 TO N-1) DO if(i==j)
FOR (j←0 TO N-1) DO {
IF(i=j) THEN A[i][j]=1;
A[i][j] ← 1; }
ENDIF }
ENDFOR }
ENDFOR
}
Stop

First Column
c Pseudocode C Language
Algorithm First_Column void FColumn(int A[][10], int N)
Variables {
A: ARRAY[10][10] of Integer int i, j;
N, i, j: Integers for(i=0;i<N; i++)
Start {
Write(“Enter the number of rows or the Pascal’s for(j=0;j<N;j++)
triangle:”) {
Read(N) if(j==0)
FOR (i←0 TO N-1) DO {
FOR (j←0 TO N-1) DO A[i][j]=1;
IF(j= 0) THEN }
A[i][j] ← 1; else
ELSE {
A[i][j] ← 0; A[i][j]=0;
ENDIF }
ENDFOR
ENDFOR }
Stop }
}

Rest of the Triangle


d Pseudocode C Language
Algorithm RTriangle void RTriangle(int A[][10], int N)
Variables {
A: ARRAY[10][10] of Integer int i, j;
N, i, j: Integers for(i=2;i<N; i++)
Start {
Write(“Enter the number of rows or the Pascal’s triangle:”) for(j=1;j<=i-1;j++)
Read(N) {
FOR (i← 2 TO N-1) DO A[i][j]=A[i-1][j]+A[i-1][j-1];
FOR (j← 1 TO N-1) DO }
A[i][j] ←A[i-1][j]+A[i-1][j-1]; }
ENDFOR }
ENDFOR
Stop

144
Display of the Triangle
e Pseudocode C Language
Algorithm Display void Display(int A[][10], int N)
Variables {
A: ARRAY[10][10] of Integer int i, j;
N, i, j: Integers for(i=0;i<N; i++)
Start {
FOR (i← 0 TO N-1) DO for(j=0;j<=i; j++)
FOR (j← 0TO i) DO {
Write("arr[i][j]”); printf("\t %d", A[i][j]);
ENDFOR }
ENDFOR printf("\n");
Stop }
}

f Main Function
#include<stdio.h>
void FColumn(int A[][10], int N);
void LDiagonal(int A[][10], int N);
void RTriangle(int A[][10], int N);
void Display(int A[][10], int N);
#define size 10
int main()
{
int arr[size][size],row;
printf("Enter the number of rows of the Pascal Triangle:\t");
scanf("%d", &row);
FColumn(arr, row);
LDiagonal(arr, row);
RTriangle(arr, row);
Display(arr, row);
return 0;
}

16 PRIME NUMBERS [SIEVE OF ERATOSTHENES ALGORITHM]


You are to design a program to help pupils in primary school learn to list all the prime numbers found within a given range
of positive integers. A prime number is divisible only one and itself. However, 1 is not considered prime. Use the following
algorithm to get the desired list of prime numbers.

1. Get the maximum value of a range from the user. Call it N


2. Fill the array with numbers from 1 to N. Take your array size to be 100
3. Starting from the beginning of the array, eliminate the number 1 from the array by setting it to zero. Then locate the
first prime number
4. Set all its multiples to zero-except, of course, the number itself- and then move to the next number
5. Repeat step (4) for each new number there, until you get to the square root of N. Call this square root rootN. Obtain it
via the square root function and round it up (or down) to an integer value. [NOTE: Rounding may be through a round

145
function (or whatever your programming language environment might offer) or truncation to an integer value such as
through a type cast, integer arithmetic or assignment to integer variables]
6. Display all the numbers in the array that are different from zero. They should all be prime numbers

Illustration:

Here, we illustrate how the algorithm works.

1. You declare an array Tab[100] of integers


2. Suppose the maximum value of the range given is N=10.
3. Fill the array Tab with N numbers

1 2 3 4 5 6 7 8 9 10

4. Set entry 1 to zero

0 2 3 4 5 6 7 8 9 10

Now we identify all the prime numbers from 2 to rootN and then set to zeros their multiples found in the array as follows:

5. Round up the square root of N (.i.e. of 10) to get 4


6. Identify 2 as a prime number
7. Excluding 2 itself, set to zero all multiples of 2, right up to N. So, we reset the numbers 4, 6, 8 and 10 to obtain:

0 2 3 0 5 0 7 0 9 0

8. Identify the next prime number i.e. 3


9. Again excluding 3, we set all the multiples of 3 to obtain

0 2 3 0 5 0 7 0 0 0

10. The next available non-zero number, 5, is greater than rootN (i.e. 4) so we stop. We now display all the non-zero
numbers of the array as the prime numbers found between 1 and 10, viz, 2, 3, 5 and 7.

Application
Here, we develop the required program by following the steps below:

a) Give a more detailed version of the algorithm in pseudocode. In it, let N=20
b) Write a subprogram called initialize(tab, n) that fills the array tab with numbers from 1 to n
c) Write a subprogram called verifyprime(x) that takes a number x and verifies whether it is a prime number or not. For
this, x is not divisible by any non-zero number less than it in the array tab
d) Write a subprogram called setzero(tab, n, y) that takes a number y and sets all its multiples in the array tab to zero,
except the number itself as explained earlier
e) Write a subprogram called doDisplay(tab, n) that displays all the nonzero elements of array tab, up to those in array
position n

146
f) Write a main program that makes use of the above subprograms to identify prime numbers in a positive integer range.
Make sure your program works
g) Test your program with N=100
a Pseudocode
Algorithm Prime_Numbers
Variables
Tab : Array[100] of Integers
i, j, N, Flag: Integers
Start
Write(“Enter the maximum value in the range”)
Read (N) //N=20
FOR (i←0 TO N-1) DO
Tab[i] ← 𝑖 + 1
ENDFOR
Tab[0] ← 0
FOR (i← 2 TO ⌈√𝑁 ⌉ DO
Flag← 1
FOR (j← 2 TO i-1) DO
IF (𝑗 ≤ 𝑖 − 1) THEN
IF(i MOD j =0) THEN
Flag← 0
ENDIF
ENDIF
ENDFOR
IF(Flag=1) THEN
FOR (j← i TO N-1) DO
IF (Tab[j] MOD i = 0) THEN
Tab[j]← 0
ENDIF
ENDFOR
ENDIF
ENDFOR
FOR (i←0 TO N-1) DO
IF(Tab[i] ≠ 0) THEN
Write(“Tab[i]”)
ENDIF
ENDFOR
Stop

b void initialise(int A[],int n)


void initialise(int A[],int n)
{
int i;
for(i=0;i<n; i++)
{
A[i]=i+1;
}
}

147
c int verifyprime(int x)
int verifyprime(int x)
{
int i;
for(i=2;i<x; i++)
{
if(x % i==0)
{
return 0;
}
}
if(x==1||x==0)
{
return 0;
}
return 1;
}

d void setzero(int A[], int n, int y)


void setzero(int A[], int n, int y)
{
int i;
for(i=y; i<n; i++)
{
if(A[i]%y==0)
{
A[i]=0;
}
}
}

e void doDisplay(int A[],int n)


void doDisplay(int A[],int n)
{
int i;
for(i=0;i<n; i++)
{
if(A[i]!=0)
{
printf("%d\t", A[i]);
}
}
}

148
f Main Program
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
void initialise(int A[],int n);
int verifyprime(int x);
void setzero(int A[], int n, int y);
void doDisplay(int A[],int n);
int main()
{
int Tab[100];
int N, flag, i;
printf("Enter the maximum value in the range N:\t");
scanf("%d", &N);
initialise(Tab, N);
printf("\n List of numbers from 1 to %d\n" ,N);
doDisplay(Tab, N);
Tab[0]=0;
for(i=2;i<=ceil(sqrt(N));i++)
{
flag=verifyprime(i);
if(flag==1)
{
setzero(Tab, N, i);
}
}
printf("\n\n");
printf("Prime numbers in the range\n");
doDisplay(Tab, N);
printf("\n\n\n");
return 0;
}

17 An English language teacher recorded the scores of a test which he sorted (i.e. in ascending or descending order). He
knows that you are a computer Science student so he asks you to use the sorting algorithm (given in pseudocode) below to
help him order his marks.

Pseudocode
Start
N, Table [1000], C, D, T : Integers
Enter the number of elements to be sorted N
Enter N integers
For C = 0 to C less than N do
Read the Table
EndFor
For C = 1 to C less than N-1 do
D = C;
While D is different from 0 and the Table [D] is Less than Table [D-1] Do
T = Table [D];
Table [D] = Table [D-1];
Table [D-1] = T;
Decrease D;
EndFor
/*output a list sorted in ascending order*/
149
For C= 0 to C less than or equal to N
Print (Table[C])
EndFor
Return 0;
End

a) Transform the algorithm into a program to sort elements in an array. Make sure the program works.
b) Run the program using 10 as the number of marks record. Save and print a copy of your output.
c) Modify the program to sort in descending order. Save and print a copy of the program.
d) Run the program and use 10 as the number of marks to record. Save and print a copy of output.

a Sorting in Ascending Order


#include <stdio.h>
#define size 1000
int main()
{
int Table[size], c, n, t, d;
printf("\n Enter the number of elements to be sorted: ");
scanf("%d", &n);
printf("\n Enter the %d integers:\n", n);
for(c=0;c<n; c++)
{
scanf("%d", &Table[c]);
}
for(c=1;c<n; c++)
{
d=c;
while((d!=0)&&(Table[d]<Table[d-1]))
{
t=Table[d];
Table[d]=Table[d-1];
Table[d-1]=t;
d=d-1;
}
}
printf("\n The sorted list in ascending order is: \n");
for(c=0;c<n; c++)
{
printf(" %d\n", Table[c]);
}
return 0;
}

b Sorting in Descending Order


#include <stdio.h>
#define size 1000
int main()
{
int Table[size], c, n, t, d;
printf("\n Enter the number of elements to be sorted: ");
scanf("%d", &n);

150
printf("\n Enter the %d integers:\n" ,n);
for(c=0;c<n; c++)
{
scanf("%d", &Table[c]);
}
for(c=1;c<n; c++)
{
d=c;
while((d!=0)&&(Table[d]>Table[d-1]))
{
t=Table[d];
Table[d]=Table[d-1];
Table[d-1]=t;
d=d-1;
}
}
printf("\n The sorted list in descending order is: \n");
for(c=0;c<n; c++)
{
printf(" %d\n", Table[c]);
}
return 0;
}

18
a) With reference to the algorithm in the flow chart, construct this algorithm in pseudocode so that it
performs the same function.
b) State the type of sort in the algorithm constructed below

151
a Pseudocode
Algorithm Sort
Variables:
Values : Array[10] of Integers
Temporary, Counter, Limit: Integers
Flag : Boolean
Start
Flag←TRUE
Limit← 4
WHILE (Flag=TRUE) DO
Flag← 𝐹𝐴𝐿𝑆𝐸
FOR (Counter←0 TO Limit-1) DO
IF (Values[Counter] > Values[Counter + 1]) THEN
Temporary ← Values [Counter]
Values[Counter] ← Values[Counter + 1]
Values[Counter + 1] ← Temporary
Flag ← TRUE
ENDIF
ENDFOR
ENDWHILE
Stop

b Bubblesort

19 SPIRAL MATRIX
Task 1
A two-dimensional array, A, has N rows and N columns, where N is a positive integer. The following algorithm is
written to fill array A with the numbers 1, 2, 3, …., 𝑁 2
N= input(‘Enter an integer greater than zero’)
K=1
Loop for ROW= 0 to N-1
Loop for COLUMN=0 to N-1
A[ROW][COLUMN]=K
K=K+1
End Loop
End Loop
End
Figure 1.

a) Use the algorithm to insert values in the a 2 – D array for N=3


Task 2
There are many different ways of placing the numbers 1 to 𝑁 2 into an N x N two-dimensional array. The following two-
dimensional array, with dimensions 5X5, has been filled in a circular(spiral) pattern with numbers 1 to 5².
An algorithm to fill an NxN two-dimensional array, in a circular(spiral) pattern, with numbers from 1 to N² is given as follows:
• Initialize Z=1
• Initialize TOP, BOTTOM, LEFT, and RIGHT.
• Iterate until the whole array is filled.
• Each time Z is placed correctly increase the value Z by 1.
• Fill the elements of the TOP row starting from LEFT to RIGHT.
• Increase TOP by 1 before filing the elements of the RIGHT column.
• Fill the elements of the RIGHT column starting from TOP to BOTTOM.
152
• Decrease RIGHT by 1 before filing the elements of the BOTTOM row.
• And continue filing the BOTTOM row and LEFT column in a similar way, adjusting TOP, RIGHT, BOTTOM,
and LEFT accordingly

LEFT RIGHT
[0] [1] [2] [3] [4]
TOP
[0] 1 2 3 4 5

[1] 16 17 18 19 6

[2] 15 24 25 20 7

[3] 14 23 22 21 8

BOTTOM [4] 13 12 11 10 9

Figure 2
a) State the initial values for TOP, BOTTOM, LEFT, and RIGHT
b) Write in a programming language (PL), a program to fill an NxN two-dimensional array, in a circular (spiral) pattern,
with numbers from left 1 to 𝑁 2 as described above. You can do that by writing first the following
functions/procedures which you will call the main program.
i. The procedures FillRowForward(A, top, left, right, z) which takes the array A, the top, left and right as
parameters and iterates through top row from left to right to fill the row. Z is as used in the algorithm.
ii. The procedure FillRowBackward( A, bottom, left, right, z) which take the array A, the bottom, left and right
as parameters, iterates through bottom row from right to the left to fill the row.
iii. The procedure FillColumnDownward(A, top, bottom, right, z) which takes the array A, the top, bottom and
right as the parameters and iterates through the right column from top to bottom to fill the column.
iv. The procedure FillColumnUpward(A, top, bottom, left, z) which takes the array A the top, bottom, and left
as the parameters and iterates through the left column from bottom to top to fill the column.
c) Write the PL function/procedure that calls the functions above appropriately, while adjusting variables top, bottom,
left and right accordingly; these four variables and the 2-D arrays should be global variables. The end result should
be the array (matrix) filled in a spiral manner. You may use the pseudo code in figure 3.

SpiralOrder
Begin
k=1; initialize top, bottom, left, and right;
while k<N*N do
call Fill Row Forward(A, top, left, right, k);
increment Top by 1;
call Fill Column Downward(A, top, bottom, right, k);
decrement right by 1;
call Fill Row Backward(A, bottom, left, right, k);
decrement bottom by 1;
call Fill Column Upward(A, top, bottom, left, k);
increment left by 1;
Endwhile
End
Figure 3

153
Task 3
To test your program;
a) Modify and implement the algorithm in figure 1, such that instead of inserting the numbers into the matrix, it should
print the numbers already inserted in the matrix, line after line, with equal spaces between the numbers. After each
line is printed the cursor should go to the next line.
b) Adapt the PL procedures in bi, ii, iii and iv such that instead of inserting the number z into the array cells, they should
rather print the values found in the cells. That is:
i. Adapt Fill Column Forward(A, top, bottom, left, right, z) to PrintRowForward(A, top, left, right) so that it
prints the top row.
ii. Adapt Fill Column Backward(A, top, bottom, left, right, z) to PrintRowBackward(A, bottom, left, right) so
that it prints the backward row.
iii. Adapt Fill Column Downward(A, top, bottom, right, z) to PrintRowBackward(A, top, bottom, left, right) so
that it prints the right column.
iv. Adapt Fill Column Upward(A, top, bottom, left, z) to PrintRowUpward(A, top, bottom, left) so that it
prints the left column.
c) Adapt the PL function (SpiralOrder), implemented above to PrintSpiralOrder such that it rather calls the adapted
functions PrintRow Forward, Print Row Backward, Print Column Downward, Print Column Upward respectively in
places where their Fill procedure/functions were called.

a) 1 2 3
4 5 6
7 8 9
b) Initialization
TOP=0
BOTTOM=N-1
LEFT=0
RIGHT=N-1

void fillRowForward(int A[N][N], int top, int left, int right)


Implemented Using the While Loop Implemented Using the For Loop
void fillRowForward(int A[N][N], int top, int left, int void fillRowForward(int A[N][N], int top, int left, int right)
right) {
{ int i;
int i = left; for(i=left; i< right+1;i++)
while (i <right+1) {
{ A[top][i] = z;
A[top][i] = z; z++;
z=z+1; }
i=i+1; }
}
}

void fillRowBackwards(int A[N][N], int bottom, int left, int right)


Implemented Using the While Loop Implemented Using the For Loop
void fillRowBackwards(int A[N][N], int bottom, int void fillRowBackwards(int A[N][N], int bottom, int left, int right)
left, int right) {
{ int i;
int i = right; for(i=right; i>left-1;i--)
while (i > left-1) {
{ A[bottom][i]=z;
A[bottom][i] = z; z++;
z=z+1; }
i=i-1; }
}
}

154
void fillColumnDownard(int A[N][N], int top, int bottom, int right)
Implemented Using the While Loop Implemented Using the For Loop
void fillColumnDownard(int A[N][N], int top, void fillColumnDownard(int A[N][N], int top, int bottom,
int bottom, int right) int right)
{ {
int i = top; int i;
while (i< bottom+1) for(i=top; i<bottom+1;i++)
{ {
A[i][right] = z; A[i][right]=z;
z=z+1; z++;
i=i+1; }
} }
}

void fillColumnUpward(int A[N][N], int top, int bottom, int left)


Implemented Using the While Loop Implemented Using the For Loop
void fillColumnUpward(int A[N][N], int top, int void fillColumnUpward(int A[N][N], int top, int bottom, int
bottom, int left) left)
{ {
int i = bottom; int i;
while (i > top-1) for(i=bottom; i>top-1;i--)
{ {
A[i][left] = z; A[i][left] = z;
z=z+1; z++;
i=i-1; }
} }
}

void spiralOrder(int N)
Implemented Using the While Loop
void spiralOrder(int N)
{
z = 1;
top = 0;
right = N - 1;
bottom = N - 1;
left = 0;
while (z<(N * N)+1)
{
fillRowForward();
top++;
fillColumnDownard();
right--;
fillRowBackwards();
bottom--;
fillColumnUpward();
left++;
}
return;
}

155
void preprint(int A[N][N], int N)
void preprint(int A[N][N], int N)
{
int i, j ;
for (i = 0; i <= N-1; i++)
{
for (j = 0; j <= N-1; j++)
{
printf(“%d\t”, A[i][j]);
}
printf(“\n”);
}
}

void PrintRowForward(int A[N][N], int top, int left, int right)


Implemented Using the While Loop Implemented Using the For Loop
void PrintRowForward(int A[N][N], int top, int left, void PrintRowForward(int A[N][N], int top, int left, int right)
int right) {
{ int i;
int i = left; for(i=left; i<right+1;i++)
while (i <right+1) {
{ printf("%d ",A[top][i]);
printf(“%d ”, A[top][i]); z++;
i=i+1; }
z++ }
}
}

void PrintRowBackwards(int A[N][N], int bottom, int left, int right)


Implemented Using the While Loop Implemented Using the For Loop
void PrintRowBackwards(int A[N][N], int bottom, void PrintRowBackwards(int A[N][N], int bottom, int left, int
int left, int right) right)
{ {
int i = right; int i;
while (i > left-1) for (i=right; i>left-1;i--)
{ {
printf(“%d ”, A[bottom][i] ); printf("%d ",A[bottom][i]);
i=i-1; z++;
z++ }
} }
}

void PrintColumnDownard(int A[N][N], int top, int bottom, int right)


Implemented Using the While Loop Implemented Using the For Loop
void PrintColumnDownard(int A[N][N], int top, int void PrintColumnDownard()
bottom, int right) {
{ int i;
int i = top; for (i=top; i<bottom+1; i++)
while (i< bottom+1) {
{ printf("%d ",A[i][right] );
printf(“%d ”, A[i][right] ); z++;
i=i+1; }
z++; }
}
}

156
void PrintColumnUpward(int A[N][N], int top, int bottom, int left)
Implemented Using the While Loop Implemented Using the For Loop
void PrintColumnUpward(int A[N][N], int top, int void PrintColumnUpward(int A[N][N], int top, int bottom, int
bottom, int left) left)
{ {
int i = bottom; int i ;
while (i > top-1) for(i=bottom; i>top-1;i--)
{ {
printf(“%d ”, A[i][left] ); printf("%d ",A[i][left] );
i=i-1; z++;
} }
} }

void PrintspiralOrder(int N)
Implemented Using the For Loop
void PrintspiralOrder(int N)
{
z=1;
top = 0;
right = N - 1;
bottom = N - 1;
left = 0;
while(z<(N*N)+1)
{
PrintRowForward();
top++;
PrintColumnDownard();
right--;
PrintRowBackwards();
bottom--;
PrintColumnUpward();
left++;
}
}

Inserting the Numbers in the Spiral Matrix and Displaying the Matrix Using a Modification of the Algorithm in task 1
#include <stdio.h>
void fillRowForward();
void fillRowBackwards();
void fillColumnDownard();
void fillColumnUpward();
void spiralOrder(int N);
int A[15][15];
int top, right, bottom, left, z;
int main()
{
int N, i, j;
printf("Enter the order of the matrix:\t");
scanf("%d", &N);
spiralOrder(N);
for (i=0;i<N; i++)
{
for (j=0;j<N;j++)
{
printf("%d\t", A[i][j]);
}
printf("\n");
}
return 0;
}

157
void spiralOrder(int N)
{
z = 1;
top = 0;
right = N - 1;
bottom = N - 1;
left = 0;
while (z<(N * N)+1)
{
fillRowForward();
top++;
fillColumnDownard();
right--;
fillRowBackwards();
bottom--;
fillColumnUpward();
left++;
}
return;
}
void fillRowForward()
{
int i;
for(i=left; i< right+1;i++)
{
A[top][i] = z;
z++;
}
}
void fillRowBackwards()
{
int i;
for(i=right; i>left-1;i--)
{
A[bottom][i]=z;
z++;
}
}
void fillColumnDownard()
{
int i;
for(i=top; i<bottom+1;i++)
{
A[i][right]=z;
z++;
}
}
void fillColumnUpward()
{
int i;
for(i=bottom; i>top-1;i--)
{
A[i][left] = z;
z++;
}
}
Note: The Five Variables top, bottom, left, right, and z; and the 2-D arrays are declared globally. Therefore, it is needless passing
these variables as parameters in the implementation.

158
20 Program Description: Voting Program
A program is to be written which simulates the election of ICT club leaders in your school. When the potential students
aspiring for executive positions of the ICT club are nominated, their names are registered into the program as shown below
(List A, B, C, and D have been used for demonstration). The program displays the list of potential students into some of the
leadership positions of the ICT club. Each student is required to vote by entering a number corresponding to his/her choice.
At the end of the voting, the final statistics for all the students are displayed. The candidate with the highest votes becomes
the winner.
We will design the solution in a top-down manner. A first attempt at listing the major tasks to be performed might be:
− Define Candidate1 “List A”
− Define Candidate2 “List B”
− Define Candidate3 “List C”
− Define Candidate4 “List D”
Initialize votes of each candidate (choice, votescount1, votescount2, votescount3, votescount4, and nullVotes) to zero

Do // Display the menu


DISPLAY 1 to Cast Vote
DISPLAY 2 to Find vote count
DISPLAY 3 to Find leading candidate
DISPLAY 0 to Quit
GET user’s choice
// Call a routine to
Case 1: Call a routine to CastVote, or
Case 2: Call a routine to votesCount, or
Case 3: Call a routine to getLeadingCandidate
Default: DISPLAY “Goodbye”
While Choice is Not Zero
Choice ← 𝐔𝐒𝐄𝐑𝐈𝐍𝐏𝐔𝐓

Task
The major tasks can be split into subroutines, which can each be tested independently. We need the following subroutines:
− SUB castVote // For the students to vote
− SUB VotesCount // Count the votes
− SUB getLeadingCandidate //display the statistics from votes count
For casting a vote to be done, let us write the subroutine castVote which will do the following
We have to design the subroutine votesCount to display the votes case for each candidate,
SUB VotesCount
Display “Voting Results”
DISPLAY “Candidate 1”, votesCount1
DISPLAY “Candidate 2”, votesCount2
DISPLAY “Candidate 3”, votesCount13
DISPLAY “Candidate 4”, votesCount14
DISPLAY “nullVotes”, nullVotes
ENDSUB

SUB CastVote
DISPLAY all candidates for the election
Choose candidate corresponding to your choice
Switch Choice
Case of Candidate 1, SET votescount1 ++
Case of Candidate 2, SET votescount2 ++
Case of Candidate 3, SET votescount3 ++
Case of Candidate 4, SET votescount4 ++
Case of none of the above, SET nullVotes ++
Default “Wrong Choice, retry”
Display “Thanks for vote”
ENDSWITCHCASE
ENDSUB
159
In order to have the winner, we have to design a subroutine getLeadingCandidate which will do the following:

SUB getLeadingCandidate
DISPLAY “Leading Candidate is:”
If (votescount1 is highest)
DISPLAY “Candidate 1”
Else If (votescount2 is highest)
DISPLAY “Candidate 2”
Else If (votescount3 is highest)
DISPLAY “Candidate 3”
Else If (votescount4 is highest)
DISPLAY “Candidate 4”
Else
DISPLAY “A tie!!! No win situation”
ENDSUB
In the main program, the subroutines are called when the voter enters his/her choice from the list of options, as seen in the
figure below:

############## Welcome to Election Voting for ICT Club #############


1. Cast the Vote
2. Find Vote Count
3. Find Leading Candidate
0. Exit
Please enter your choice: _

Work required:
a) Write the following subroutines using an appropriate Programming Language
− CastVote
− VotesCount
− getLeadingCandidate
b) Write the main program called mainProg which calls subroutines CastVote, votesCount, and getLeadingCandidate.

a void castVote()
void castVote()
{
printf("\n Please Choose Your Candidate\n");
printf("1. %s\n",CANDIDATE1);
printf("2. %s\n",CANDIDATE2);
printf("3. %s\n",CANDIDATE3);
printf("4. %s\n",CANDIDATE4);
printf("5. %s\n", "None of These");
printf("Input your choice [1-5]\n");
scanf("%d", &choice);
switch(choice)
{
case 1:
votesCount1++;
break;
case 2:
votesCount2++;
break;
160
case 3:
votesCount3++;
break;
case 4:
votesCount4++;
break;
case 5:
nullVotes++;
break;
default:
printf("Invalid Choice\n");
}
}

b void menu()
void menu()
{
printf("\n\n########Welcome to Election Voting for ICT Club######\n");
printf("1. Cast the Vote\n");
printf("2. Find Vote Count\n");
printf("3. Find Leading Candidate\n");
printf("0. Exit\n");
printf("#####################################################\n");
}
c votesCount()
void votesCount()
{
printf("\n##### Voting Results######\n");
printf("%s- %d\n",CANDIDATE1,votesCount1);
printf("%s- %d\n",CANDIDATE2,votesCount2);
printf("%s- %d\n",CANDIDATE3,votesCount3);
printf("%s- %d\n",CANDIDATE4,votesCount4);
printf("%s- %d\n", "Null Votes", nullVotes);
}

d void getLeadingCandidate()
void getLeadingCandidate()
{
printf("\n The Leading Candidate is: \t");
if(votesCount1>votesCount2&&votesCount1>votesCount3&&votesCount1>votesCount4)
{
printf("%s\n",CANDIDATE1);
}
else if(votesCount2>votesCount1&&votesCount2>votesCount3&&votesCount2>votesCount4)
{
printf("%s\n",CANDIDATE2);
}
else if(votesCount3>votesCount1&&votesCount3>votesCount2&&votesCount3>votesCount4)
{
printf("%s\n",CANDIDATE3);
}
else if(votesCount4>votesCount1&&votesCount4>votesCount2&&votesCount4>votesCount3)
{
printf("%s\n",CANDIDATE4);
}
else
{
printf("A tie!!! No Candidate Wins\n");
}
}

161
e Main Program
#include <stdio.h>
#include <stdlib.h>
#define CANDIDATE1 "List A"
#define CANDIDATE2 "List B"
#define CANDIDATE3 "List C"
#define CANDIDATE4 "List D"
void menu();
void votesCount();
void castVote();
void getLeadingCandidate();
int choice=0,votesCount1=0,votesCount2=0,votesCount3=0,votesCount4=0,nullVotes=0;
int main()
{
int choice1;
do
{
menu();
printf("Please Enter Your Choice[0-3]:\t");
scanf("%d",&choice1);
switch(choice1)
{
case 1:
castVote();
break;
case 2:
votesCount();
break;
case 3:
getLeadingCandidate();
break;
case 0:
printf("Good Bye\n");
break;
default:
printf("Invalid Choice\n");
break;
}
} while(choice1!=0);
return 0;
}

162
21 A public transport agency wants to computerize the reservation (booking) of bus seats by customers. The seats for every
bus that is being loaded are numbered 1 to 70. Once a seat has been booked, the status of the seat changes from 0 to 1.
A seat has the properties below:
− A seat has a number and a status
− Before booking passengers need to know which seats are available for booking.
− Once a seat is booked, it is no longer available for booking
A seat therefore is a record of number and status. A vehicle (bus) is an array of seats.
Your major duty is to write a program for the booking of seats.
The flowchart below shows the procedure to book for a seat once available seats have been displayed.

When a seat number is read, the procedure checks for the validity first i.e. checks if the seat number is a number from 1 to
70. (These numbers represent seat numbers in the 70 seats vehicle). After checking for the validity of entered seat number,
the procedure then checks the seat status in the array of seats. If the status is 0, the seat is then booked, if not, the user is
given the opportunity to book for a different seat.
a) In the C programming language, declare a record called seat with two fields: num (for seat number) and status (for seat
status)
b) Declare an array A of records of type seat
c) Write a procedure to fill the array A with data (seat number and status) for all seats. With all seat status =0.
d) Write a procedure to implement the booking procedure described in the flowchart above.
e) Write a procedure (seat display) that lists all seats that haven’t been booked (seats with status =0)
f) Write a main program that calls the seat display procedure, allows user choose a seat by calling the booking procedure
and then displaying the available seats again.

a
struct seat
{
int num;
int status;
};
163
b
struct seat A[70];

c void fill(struct seat B[])


void fill(struct seat B[])
{
int i;
for(i=0;i<70;i++)
{
B[i].num=i+1;
B[i].status=0;
}
}

d void display(struct seat C[])


void display(struct seat C[])
{
int i;
for(i=0;i<70;i++)
{
if(C[i].status!=1)
{
printf("%d\t", C[i].num);
}
}
}

e void booking(struct seat vehicle[])


void booking(struct seat vehicle[])
{
int number;
printf("\n Enter a seat number you want to reserve!:\t");
scanf("%d", &number);
if(number<1||number>70)
{
printf("Invalid Seat Number\n");
booking(A);
}
else
{
if(vehicle[number-1].status==0)
{
vehicle[number-1].status=1;
printf("Seat successfully reserved!\n");
}
else
{
printf("Seat Taken\n");
printf("Please take another seat\n");
booking(A);
}
}
}

164
f void booking(struct seat vehicle[])
Another Implementation of the booking procedure using goto (You may do another implementation
using while loops )
void booking(struct seat vehicle[])
{
int number;
L: printf("Enter a seat number you want to reserve:\n");
scanf("%d", &number);
if(number<1||number>70)
{
printf("Invalid Seat\n");
goto L;
}
else
{
if(vehicle[number-1].status==0)
{
vehicle[number-1].status=1;
printf("Your seat has been reserved!\n");
}
else
{
printf("Seat Taken\n");
printf("Please take another seat\n");
goto L;
}
}
}

Main Function
#include<stdio.h>
#include<string.h>
struct seat
{
int num;
int status;
};
struct seat A[70];
void fill(struct seat B[]);
void booking(struct seat vehicle[]);
void display(struct seat C[]);
int main()
{
fill(A);
char ch[4];
printf("########Seats Reservation System###########\n");
printf("The following seats are available for booking\n");
display(A);
do
{
booking(A);
printf("The seats not reserved are:\n");
display(A);
printf("\n Do you wish to continue reserving seats?: Y or N\n");
scanf("%s" ,ch);
}while(strcmpi(ch, "Yes")==0||strcmpi(ch, "Y")==0);
return 0;
}

165
22 Council data
The local council I your area has decide to record information about all its inhabitants. It started this activity by
recording the name of all the people in the council area. You have been contracted to propose a computer
application to carry out this task.
Bert Jeff Gary Neba Chang Olga Nora Mary Vera Rami Neil Jill Cain Lara Bart

Table 1.
The algorithm given in the figure are in a pseudocode based on C and Pascal and where is for assignment and //
starts a command.

Procedure SelectionSort (Array) Boolean found ←false; //global variable


For i ←1 to sizeOfArray – 1 Integer position ← 1; //global variable
//set current element as minimum Procedure Bin_Search_Rec(Array, Name, Min, Max)
Integer min ← i Integer bottom←min;
//check the element to be minimum Integer top← max;
For j ←i+1 to sizeOfArray Do If(min<=max) then
If Array[j] <Array[min] mid←(min+max) div 2;//integer division
Then If Array[mid] =name then //mark item as
min ← j found ←true //found and store
EndIf position ←mid // its position
//swap the minimum element Else if Array[mid] < name then //in right
// with the current element // half of range
Tmp ←a[i] Bin_Search_Rec (Array, name, bottom, mid-1,top)
a[i] ←a[min] Else //in left half of range.
a[min] ← Tmp Bin_Search_Rec(Array, name,bottom,mid-1)
EndFor Endif
EndFor Endif
EndProcedure
EndProcedure
Procedure Bin_Search (Array, Name, Min, Max)
Figure 1: Selection Sort Algorithm
Bin_Search_Rec( Array, Name, Min, Max)
If found = false then print “Name not found”
Else print Array[position] //print the value found
EndProcedure

Figure 2: Binary Search Algorithm

a) Give a declaration, in your chosen programming language [PL], of an array data structure which is
immediately initialized to values as given in table 1. The size of the array is the same as the number of
inhabitants in the council.
b) Implement a PL function [or procedure] called doDisplay that takes as arguments an array and its size, as
defined above, and then displays the names of council inhabitants.
c) Using the algorithm for selection sort in Figure 1, give a PL procedure or function called select sort that
sorts the content of the array above in alphabetical order. Add a main program unit (if need be) and call
the subroutines do display and select sort from it.
d) Using the algorithm for a recursive binary search in Figure 2, give a PL procedure called bin search that
takes an array, a name to search, and the bounds min and max of the search range within the array. In
then calls the recursive procedure Bin_Search_Rec with matching arguments. The procedure bin search
then prints the given name if found. Otherwise, the massage “Name not found” is printed [Note: In Figure
2, vehicles found and position are global]

166
e) Modify your main program above so that it calls the select_sort procedure, then prompts for a name that
it uses to call procedure Bin_Search with.

a
char list[Inhabitants][15]={"Bert","Jeff","Gary","Neba","Chang","Olga","Nora","Mary","Vera","Rani",
"Neil", "Jill", "Cain", "Lara", "Bart"};

b void doDisplay(char A[][15], int n)


void doDisplay(char A[][15], int n)
{
int i;
for(i=0;i<n; i++)
{
printf("%s\n", A[i]);
}
}

c void select_sort(char A[][15], int n)


void select_sort(char A[][15], int n)
{
int i, min, j;
char temp[15];
for(i=0;i<n-1;i++)
{
min=i;
for(j=i+1;j<=n-1;j++)
{
if(strcmp(A[j],A[min])<0)
{
min=j;
}
}
strcpy(temp, A[i]);
strcpy(A[i], A[min]);
strcpy(A[min], temp);
}
}

d void bin_search(char A[][15],char name[],int min, int max)


void bin_search(char A[][15],char name[],int min, int max)
{
bin_search_rec(A, name, min, max);
if(found==0)
{
printf("\n Name Not Found\n");
}
else
{
printf("%s Found at Position %d\n",name,position+1);
}
}

167
e void bin_search_rec(char A[][15],char name[],int min, int max)
void bin_search_rec(char A[][15],char name[],int min, int max)
{
int mid;
if(min>max)
{
found=0;
}
if(min<=max)
{
mid=(max + min)/2;
if(strcmpi(A[mid],name)==0)
{
found=1;
position=mid;
}
else if (strcmpi(A[mid],name)<0)
{
bin_search_rec(A,name,mid+1,max);
}
else
{
bin_search_rec(A,name,min,mid-1);
}
}
}

f Main Function
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define Inhabitants 15
void doDisplay(char A[][15], int n);
void select_sort(char A[][15], int n);
void bin_search_rec(char A[][15],char name[],int min, int max);
void bin_search(char A[][15],char name[],int min, int max);
int found, position;
int main()
{
char list[Inhabitants][15]={"Bert","Jeff","Gary","Neba","Chang","Olga","Nora","Mary","Vera","Rani",
"Neil", "Jill", "Cain", "Lara", "Bart"};
char item[15];
printf("\n List Of Inhabitants\n");
doDisplay(list, Inhabitants);
printf("\n Sorted List Of Inhabitants\n");
select_sort(list, Inhabitants);
doDisplay(list, Inhabitants);
printf("\n");
printf("Enter the name you wish to search:\t");
gets(item);
bin_search(list, item, 0, Inhabitants-1);
return 0;
}
168
23 Consider the flowchart below :

a) Write a pseudo code for the procedure “jangi credit()” as designed by the flow chart above.
b) Implement the algorithm above and make sure the variables are correctly initialized.
c) Assuming that the total amount available is 65 million, modify and run the program with the following
inputs and fill this grid below.

Fon_name Membership Date Loan Life_of_loan Interest Net amount to be paid

Momo 1 02/02/2014 3
Simo Tenkue 0 01//03/2014 3
Fozao 0 01/03/2014 2
Nganya 1 03/04/2014 3

169
a Pseudocode
PROCEDURE jangicredit()
Variables
Interest, Amount_Paid: Real
Name: ARRAY [20] of Characters;
Member, Loan, Life_Loan: Integers
DATE = RECORD
Day: Integer
Month: String
Year: Integer
ENDRECORD
Start
Write("Enter Fon's Name:")
Read(Name)
Write("Enter his membership:")
Read(Membership)
Write("Enter the Date")
Read("Date")
Write("Enter the Amount Needed:")
Read(Loan);
Write("Enter Life OF Loan")
Read(Life_Loan);
IF (Loan>Total_Amount_Available) THEN
EXIT
ELSE
IF(Member=1) THEN
Interest←0.04*Life_Loan*Loan
ELSE
Interest←0.06*Life_Loan*Loan;
ENDIF
ENDIF
Amount_Paid←Loan-Interest;
Total_Interest←Total_Interest+Interest;
Write("Your Amount to be paid is %.2f",Amount_Paid);
Stop

170
b jangicredit()
void jangicredit()
{
float Interest, Amount_Paid;
char Name[20];
int Member;
struct date D;
int Loan;
int Life_Loan;
printf("Enter Fon's Name:\t");
gets(Name);
printf("Enter his membership:\t");
scanf("%d", &Member);
printf("Enter the Date\n");
printf("Day[1-31]:\t");
scanf("%d",&D.day);
printf("\n Month:\t");
scanf("%s", D.month);
printf("\n Year:\t");
scanf("%d",&D.year);
printf("Enter the Amount Needed:\t");
scanf("%d",&Loan);
printf("Enter Life OF Loan\t");
scanf("%d",&Life_Loan);
if(Loan<=Total_Amount)
{
if(Member==1)
{
Interest=0.04*Life_Loan*Loan;
}
else
{
Interest=0.06*Life_Loan*Loan;
}
Amount_Paid=Loan-Interest;
Total_Interest=Total_Interest+Interest;
printf("Your Amount to be paid is %.2f",Amount_Paid);
return;
}
else
{
printf("Amount Not Available. Contact the Financial Secretary\n");
return;
}
}

c Main Function
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
struct date
{
int day;
char month[11];
int year;
171
};
void jangicredit();
float Total_Interest=0;
float Total_Amount=65000000;
int main()
{
char Response[7];
do
{
jangicredit();
printf("\n Do you wish to continue issuing loans ?Yes/No:\t");
scanf("%s", Response);
getchar();
}while(strcmpi(Response, "Yes")==0||strcmpi(Response, "Y")==0);

return 0;
}

24 Biological applications often need to compare the DNA of two (or more) different organisms to know how
closely related the two organisms are. For example, the DNA of one organism may be S1 =
ACCGGTCGAGTGCGCGGAAGCCGGCCGAA, and the DNA of another organism may be S2 =
GTCGTTCGGAATGCCGTTGCTCTGTAAA.
A measure of the similarity of strands S1 and S2 is by finding a third strand S3 in which the bases in S3 appear in
each of S1 and S2. The longer the strand S3 we can find, the more similar S1 and S2 are. In our example, the longest
strand S3 is GTCGTCGGAAGCCGGCCGAA.
S3 is called the longest common subsequence. A subsequence of a given sequence is just the given sequence with
0 or more elements left out (The elements of the subsequence may not occupy consecutive positions within the
original sequence). The subsequence must be a strictly increasing sequence of the indices of both S1 and S2. For
example, if S1= {BCDAACD}. Then {ADB} cannot be a subsequence of S1 (The order of the elements is not the
same as in the original string S1. That is the elements are not in increasing order with respect to their positions
or index e.g. index of B is less than index of A.).
If S1={BCDAACD} and S2={ACDBAC}, then some common subsequences are {BC}, {CDAC}, {DAC}, {AAC}, {AC},
{CD}. {CDAC} is the longest common subsequence.
The following algorithm is used to find the longest common subsequence:

1. Create a table of dimension (n+1)×(m+1) where m and n are the lengths of the two strings S1 and S2
respectively. The first row and the first column are filled with zeros.
2. Fill each cell of the table using the following logic
a. If the character corresponding to the current row and current column are matching, then fill the
current cell by adding one to the diagonal element. Point an arrow to the diagonal cell using the
diagonal arrow (↖ )symbol
b. Else take the maximum from the previous column and previous row element for filling the
current cell. Point an arrow to the cell with maximum value. If they are equal, point to any of
them.
3. Step 2 is repeated until the entire table is filled.
4. The value in the last row and last column is the length of the longest common subsequence
5. In order to find the longest common subsequence, start from the last element and follow the direction of
the arrow. The elements corresponding to the diagonal arrow (↖ )symbol form the longest common
subsequence.
172
Illustration:
Consider the two strings X={ACADB} and Y={CBDA}. Use the algorithm above to find the longest common
subsequence between X and Y

1. Create a table of dimension (1+length(X))×(1+length(Y)) and fill the first row and first column with zeros.

C B D A
0 0 0 0 0
A 0
C 0
A 0
D 0
B 0

2. Fill the rest of the cells using the logic described in the algorithm
C B D A
0 0 0 0 0
A 0 ↑ 0 ↑ 0 ↑0 ↖1
C 0 ↖1 ←1 ←1 ↑1
A 0 ↑1 ↑1 ↑1 ↖2
D 0 ↑1 ↑1 ↖2 ↑2
B 0 ↑1 ↖2 ↑2 ↑2

3. The bottom right corner (i.e. the last element) is the length of the longest common subsequence of X and Y
4. To find the longest common subsequence, start from the last element and follow the direction of the arrows.
The elements corresponding to ↖ form the longest common subsequence.

C B D A C B D A
0 0 0 0 0 0 0 0 0 0
A 0 ↑0 ↑0 ↑0 ↖1 A 0 ↑0 ↑0 ↑0 ↖1
C 0 ↖1 ←1 ←1 ↑1 C 0 ↖1 ←1 ←1 ↑1
A 0 ↑1 ↑1 ↑1 ↖2 A 0 ↑1 ↑1 ↑1 ↖2
D 0 ↑1 ↑1 ↖2 ↑2 D 0 ↑1 ↑1 ↖2 ↑2
B 0 ↑1 ↖2 ↑2 ↑2 B 0 ↑1 ↖2 ↑2 ↑2
Path from the last element, following the arrow Along that path, elements with the diagonal
arrow ↖symol, constitute the longest common
subsequence. Hence the longest common
subsequence between X and Y is CA
Implementation
a) Using the pattern in the algorithm, generate the formula used to fill out the values in the table (excluding the first row
and first column which are obviously filled with zeros)
b) Give a more detailed version of the algorithm in pseudocode.
c) Write a subprogram called initialize (tab, m, n) that fills the first row and first column of tab with zeros. M is the number
of rows and N is the number of columns of the table, tab.
d) Write a subprogram called LCS (S1, S2, Tab, m, n) that takes the strings S1 and S2, the table tab as well as the row and
column as parameters. LCS fills the rest of the entries in the table and returns the length of the longest subsequence.
e) Write a subprogram called SubSeq (S1, S2, Tab, LS, m, n, index) that displays the longest common subsequence. Index
corresponds to the length of the longest common subsequence determined above.
173
f) Write a main program that:
− Prompts the user to enter two strings S1 and S2
− Determines the length of the longest common subsequence
− Displays the longest common subsequence.
g) Test your program using S1=ACADB and S2=CBDA.
a
1 + Tab[i − 1][j − 1], if S1[i] = S2[j]
Tab[i][j]={
Max(Tab[i][j − 1], Tab[i − 1][j]), Otherwise

b Pseudocode
Algorithm Longest_Common_Subsequence
Variables
S1 : Array[50] of Characters
S2 : Array[50] of Characters
Tab : Array[51….51] of Characters
i, j, N, M, Index: Integers
Start
Write(“Enter the string S1”)
Read (S1)
Write(“Enter the string S2”)
Read (S2)
M←Length(S1)
N←Length(S2)
FOR (i← 0 TO M) DO
Tab[i][0] ← 0
ENDFOR
FOR (i←0 TO N) DO
Tab[0][i]← 0
ENDFOR
FOR (i← 1 TO N DO
FOR (j← 1 TO M) DO
IF(S1[i-1]=S2[j-1]) THEN
Tab[i][j] ← 1 + Tab[i − 1][j − 1]
ELSE IF (Tab[i-1][j]≥Tab[i][j-1]) THEN
Tab[i][j]← Tab[i − 1][j]
ELSE
Tab[i][j]← Tab[i][j − 1]
ENDIF
ENDFOR
ENDFOR
Index←Tab[M][N]
Write(“The length of the longest common subsequence is”, Index)
Char LS[index+1]; //LS represents the longest common subsequence. Index is its length
LS[Index]← ′\0′ // Strings are terminated with a null character. We proceed to fill other characters

i← M
j← N
WHILE(i>0 AND j>0) DO
IF(S1[i-1]=S2[j-1]) THEN
LS[Index-1]←S1[i-1]
i←i-1
j← j-1
Index← Index-1
ELSE IF (Tab[i-1][j]>Tab[i][j-1]) THEN
i←i-1
ELSE
j← j-1
ENDIF
174
ENDWHILE
Write(“The Longest Common Sequence is”, LS)

Stop

c void initialize(int C[][51], int a, int b)


void initialize(int C[][51],int a, int b)
{
int i;
for (i = 0; i <= a; i++)
{
C[i][0] = 0;
}
for (i = 0; i <= b; i++)
{
C[0][i] = 0;
}
}

d int LCS(char X[],char Y[],int C[][51], int a, int b)


int LCS(char X[],char Y[],int C[][51],int a, int b)
{
int i, j;
for(i=1;i<=a; i++)
{
for(j=1;j<=b; j++)
{
if(X[i - 1] == Y[j - 1])
{
C[i][j] = C[i - 1][j - 1] + 1;
}
else if(C[i - 1][j] >= C[i][j - 1])
{
C[i][j] = C[i - 1][j];
}
else
{
C[i][j] = C[i][j - 1];
}
}
}
return C[a][b];
}

e void SubSeq(char X[],char Y[],int C[][51], int a, int b, int p)


void SubSeq(char X[],char Y[],int C[][51],int a, int b, int p)
{
char LS[50];
int pos=p;
LS[pos] = '\0';
int i=a, j=b;
while(i>0&&j>0)
{

175
if(X[i - 1]==Y[j - 1])
{
LS[pos-1]=X[i-1];
i--;
j--;
pos--;
}
else if(C[i - 1][j]>=C[i][j - 1])
{
i--;
}
else
{
j--;
}
}

// Printing the sub sequences


printf("S1 : %s \nS2 : %s \n", X, Y);
printf("Longest Common Subsequence: %s\n", LS);
}

f Main Function
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void initialize(int C[][51],int a, int b);
int LCS(char X[],char Y[],int C[][51],int a, int b);
void SubSeq(char X[],char Y[],int C[][51],int a, int b, int pos);
int main()
{
char S1[50],S2[50];
int Tab[51][51],index, M, N;
printf("Enter string S1:\t");
gets(S1);
printf("Enter string S2:\t");
gets(S2);
M=strlen(S1);
N=strlen(S2);
initialize(Tab, M, N);
index=LCS(S1,S2,Tab,M,N);
printf("The Length of the Longest Common Subsequence is %d\n", index);
SubSeq(S1,S2,Tab,M,N,index);
return 0;
}

g Test

176
g Test

25. The following code snippet is written to exchange the values of variables A and B.
Temp ← A
B ← Temp
A←B

a)
i. Assume A = 3 and B = 5. State the values of A and B after execution of the code snippet above. (1 Mark)
ii. Suggest how the code snippet above would need to be modified to successfully exchange the values of variables
A and B. (1 Mark)
iii. Write another code snippet that exchanges the values of A and B without the use of a third variable Temp (2
Marks)
Method swapRows(MAT,K,L) swaps the elements of two rows (row K and row L) in the two‑dimensional
Array MAT. For example,
The initial contents of the two- The contents of the two-dimensional array MAT after
dimensional array MAT execution of method swapRows(MAT,1,4)
[0] [1] [2] [3] [0] [1] [2] [3]
[0] 7 1 2 3 [0] 7 1 2 3
[1] 4 0 0 0 [1] 5 0 -1 0
[2] 6 0 -3 0 swapRows(MAT,1,4) [2] 6 0 -3 0
[3] 4 0 0 4 [3] 4 0 0 4
[4] 5 0 -1 0 [4] 4 0 0 0
[5] 5 -6 0 9 [5] 5 -6 0 9

b) Use pseudocode to construct an algorithm for the method swapRows(). (4 Marks)


A game consists of four rounds. In each round a player can score up to 100 points. The data about the game is stored
in the memory as follows:

PLAYERS ROUNDS TOTALS


[0] [1] [2] [3]
[0] Paul [0] 45 00 00 60 [0] 105
[1] Hugh [1] 60 38 42 90 [1] 230
[2] Annie [2] 70 10 23 03 [2] 106
[3] Boris [3] 40 00 50 90 [3] 180
[4] Robby [4] 55 00 15 10 [4] 80
[5] Tammy [5] 51 60 20 90 [5] 221

Where:
− PLAYERS is an array holding names of players
− ROUNDS is an array holding players’ scores.
177
− TOTALS is an array holding total scores.
A. Data Entry Subroutines
c) Write the subroutine ReadNames() to enter the names of the players above into the Players array. ReadNames()
receives an array as parameter and the number of players.
d) Write the subroutine ReadScores() to enter the scores of the players for all the rounds into the Rounds array, one
player at a time. ReadScores() receives an array as parameter, the number of players and the number of rounds.
e) Write a subroutine TotalScore() that calculates the total score for each player and stores it in the Totals arrays.
B. Data Display Subroutines
f) Write the subroutine Display() that displays the data entered i.e. the names of players, scores per round and the
total scores. It receives the arrays Players, Rounds and Totals
C. SORTING
All the data stored in memory could be sorted in descending order of total score using selection sort. For example, after
sorting, the data given will be held in memory as follows:

PLAYERS ROUNDS TOTALS


[0] [1] [2] [3]
[0] Hugh [0] 60 38 42 90 [0] 230
[1] Tammy [1] 51 60 20 90 [1] 221
[2] Boris [2] 40 0 50 90 [2] 180
[3] Annie [3] 70 10 23 3 [3] 106
[4] Paul [4] 45 0 0 60 [4] 105
[5] Robby [5] 55 0 15 10 [5] 80

g) Construct an algorithm for the subroutine sorttotal() that will sort all the data in descending order of total score
using selection sort. In your solution you should call method swapRows() given above
All the data stored in memory could also be sorted in ascending order of name using selection sort. For example, after sorting,
the data given will be held in memory as follows

PLAYERS ROUNDS TOTALS


[0] [1] [2] [3]
[0] Annie [0] 70 10 23 3 [0] 106
[1] Boris [1] 40 0 50 90 [1] 180
[2] Hugh [2] 60 38 42 90 [2] 230
[3] Paul [3] 45 0 0 60 [3] 105
[4] Robby [4] 55 0 15 10 [4] 80
[5] Tammy [5] 51 60 20 90 [5] 221

h) Construct an algorithm for the subroutine sortnames() that will sort all the data in ascending order of name using
selection sort. In your solution you should call method swapRows() given above
i) Write the subroutine to display the menu menu() that lets the user choose to either sort by name, or by total score
or to quit the program.
Menu
1. Sort in ascending order of names
2. Sort in descending order of total scores
3. Quit

178
D. Main Program
Perform the following in the main function:
− Declare the data structures to store players’ names, their scores and the total scores
− Call the appropriate subroutines to read user data into the data structures defined above
− Call the TotalScore() subroutine to calculate the total scores
− Call the display() subroutine to display the entire data entered and the calculated totals.
− Call the menu() subroutine to display the menu and read the user’s choice.
− Perform the appropriate sort based on user’s choice.
− Display the data after the appropriate sort and redisplay the menu. The program ends after the user selects the quit
option
a)
i. A = 3 and B = 3;
ii. The algorithm does not correctly swap the values because the value of B is overwritten/lost in the second line
of the algorithm.
To obtain the correct result the line B ← Temp should be swapped with the line A ← B. The order of statements
should be changed as follows:
Temp ← A
A←B
B ← Temp

iii.
A←A+B
B←A-B
A←A-B

void swapRows(int Mat[][M], int a, int b)


b void swapRows(int Mat[][M], int a, int b)
{
int temp, i;
for(i=0;i<M; i++)
{
temp=Mat[a][i];
Mat[a][i]=Mat[b][i];
Mat[b][i]=temp;
}
}

c void ReadNames(char A[][Nl])


void ReadNames(char A[][Nl])
{
int i;
for(i=0;i<N; i++)
{
scanf("%s", A[i]);
}
}
d void ReadScores(int Mat[][M])
void ReadScores(int Mat[][M])
{
int i, j;

179
for(i=0;i<N;i++)
{
printf("Enter scores for player %d\n",i+1);
for(j=0;j<M;j++)
{
scanf("%d",&Mat[i][j]);
}
printf("\n");
}
}

e void Totalscore(int T[], int Mat[][M])


void Totalscore(int T[], int Mat[][M])
{
int i,j;
for(i=0;i<N; i++)
{
T[i]=0;
}
for(i=0;i<N; i++)
{
for(j=0;j<M; j++)
{
T[i]=T[i]+Mat[i][j];
}
}
}

e void display(int T[], int Mat[][M],char A[][Nl])


void display(int T[], int Mat[][M],char A[][Nl])
{
int i,j;
printf("\nPlayers\t\t Scores\t\tTotals\n");
for(i=0;i<N;i++)
{
printf("%s\t\t",A[i]);
for(j=0;j<M;j++)
{
printf("%d ",Mat[i][j]);
}
printf("\t%d\n",T[i]);
}
}

f void sorttotal(int T[], int Mat[][M],char A[][Nl])


void sorttotal(int T[], int Mat[][M],char A[][Nl])
{
int i, j, Max, Temp;
char aux[Nl];
for(i=0;i<N; i++)
{
Max=i;
for(j=i+1;j<N; j++)

180
{
if(T[Max]<T[j])
{
Max=j;
}
}
if(Max!=i)
{
Temp=T[i];
T[i]=T[Max];
T[Max]=Temp;
swapRows(Mat, Max, i);
strcpy(aux, A[Max]);
strcpy(A[Max],A[i]);
strcpy(A[i],aux);
}
}
}

f void sortnames(int T[], int Mat[][M],char A[][Nl])


void sortnames(int T[], int Mat[][M],char A[][Nl])
{
int i, j, Min, Temp;
char aux[Nl];
for(i=0;i<N;i++)
{
Min=i;
for(j=i+1;j<N;j++)
{
if(strcmpi(A[Min],A[j])>0)
{
Min=j;
}
}
if(Min!=i)
{
Temp=T[i];
T[i]=T[Min];
T[Min]=Temp;
swapRows(Mat,Min,i);
strcpy(aux,A[Min]);
strcpy(A[Min],A[i]);
strcpy(A[i],aux);
}
}
}
g void menu()
void menu()
{
printf("\nMenu\n");
printf("1. Sort in descending order of Totals\n");
printf("2. Sort in ascending order of Name\n");
printf("3. Quit\n");
printf("Your choice:\t");
}

181
h int main()
#include<stdio.h>
#include<string.h>
#define N 6
#define M 4
#define Nl 6
void ReadScores(int Mat[][M]);
void menu();
void ReadNames(char A[][Nl]);
void Totalscore(int T[], int Mat[][M]);
void display(int T[], int Mat[][M],char A[][Nl]);
void sorttotal(int T[], int Mat[][M],char A[][Nl]);
void sortnames(int T[], int Mat[][M],char A[][Nl]);
void swapRows(int Mat[][M], int a, int b);
int main()
{
int Rounds[N][M], Totals[N],choice;
char Players[N][Nl];
printf("\nEnter the names of the players:\n");
ReadNames(Players);
printf("\n Players Score:\n");
ReadScores(Rounds);
Totalscore(Totals,Rounds);
printf("\nData:\n");
display(Totals,Rounds,Players);
do
{
menu();
scanf("%d", &choice);
switch(choice)
{
case 1:
sorttotal(Totals,Rounds,Players);
printf("\nData:\n");
display(Totals,Rounds,Players);
break;
case 2:
sortnames(Totals,Rounds,Players);
printf("\nData:\n");
display(Totals,Rounds,Players);
break;
case 3:
printf("Good Bye\n");
break;
default:
printf("Invalid Option\n Try again\n");
}
}while(choice!=3);
return 0;
}

182
26. A magic square is a two-dimensional array with n rows and n columns in which each of the integers 1, 2, 3, …, 𝑛2 appears
exactly once and all column sums, row sums and diagonal sums are equal.
The array Mat below is a 7×7 magic square in which all rows, columns and the two main diagonals add up to 175. 175 is
𝑛(1+𝑛2 )
called the magic constant or magic sum, M, and is usually calculated using, 𝑀 =
2

Mat
[0] [1] [2] [3] [4] [5] [6]
[0] 30 39 48 1 10 19 28
[1] 38 47 7 9 18 27 29
[2] 46 6 8 17 26 35 37
[3] 5 14 16 25 34 36 45
[4] 13 15 24 33 42 44 4
[5] 21 23 32 41 43 3 12
[6] 22 31 40 49 2 11 20
− Construction of the Magic Square
The following is the algorithm for constructing a magic square with n rows and n columns for any odd integer n.
− Z=1
− Place Z in the middle of top row
− Loop until all integers 1, 2, 3, …, 𝑛2 are placed in the array
o Z=Z+1
o Move one row up and one column to the right to place the integer Z, unless one of the following occurs
▪ If a move takes you above the top row in the 𝑗𝑡ℎ column, move to the bottom of the 𝑗𝑡ℎ column
and place the integer Z there
▪ If a move takes you outside to the right of the square in the 𝑖 𝑡ℎ row, place the integer Z in the 𝑖 𝑡ℎ
row at the left side
▪ If a move takes you to an already filled square or if you move out of the square at the upper-right
corner, place Z immediately below Z – 1.
a) By applying this algorithm, copy and complete the 5×5 magic square, which has been started below. (5 Marks)
1

b) In your answer booklet, write a subroutine in pseudocode, createSquare(mat, n), which creates the magic square,
mat, with n rows and n columns. (8 Marks)

− Verification of the Magic Square


c) Construct an algorithm for the subroutine Diagonal() which calculates the sum of all elements on the main diagonal
(leading diagonal) (3 Marks)
d) An array with n rows and n columns holds every number from 1 to 𝑛2 . Construct an algorithm for the subroutine
Verify() that checks whether the n × n array, Mat, is a magic square. This subroutine uses the Diagonal() subroutine
above. (6 Marks)
− Implementation
e) Using an imperative programming language of your choice, convert the pseudocodes for createSquare(), Diagonal(),
and Verify() above into programming language functions or procedures. (4, 2, 4 Marks)
f) Write a main program that: (8 Marks)
− Prompts the user to enter a positive integer N.
− Calls the createSquare() subroutine to create the magic square of N rows and N columns.
− Displays the constructed magic square
− Calls Verify () to determine if the square created is a magic square or not. The verify subroutine displays an
appropriate message such as “The array is a magic square” or “The array is not a magic square”.
− Ensure your program works by testing it for N=7 and N=5. Screenshot your outputs and paste it in ms word.

183
a) 17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9

PROCEDURE createSquare(Integer Mat[][], Integer N)


b) PROCEDURE createSquare(Integer Mat[][], Integer N)
Start
Variables:
Integer: i, j, Z, Range
Z← 1
FOR (i ← 0 TO 𝑁-1) DO
FOR (j ← 0 TO 𝑁-1) DO
Mat[i][j] ← 0
ENDFOR
ENDFOR
Range← N× 𝑁
i←0
j ← N DIV 2
Mat[i][j] ← Z;
WHILE (Z ≤ Range) DO
Z← 𝑍 + 1;
IF ((i-1) < 0 AND (j+1) >N-1) THEN
i← 𝑖 + 1
ELSE
IF((i-1) <0) THEN
i ← N-1
j← 𝑗 + 1
ELSE
IF ((j+1) >N-1) THEN
j ← 0;
i← 𝑖 − 1;
ELSE
IF (Mat[i-1][j+1] ≠ 0) THEN
i← 𝑖 + 1
ELSE
i← 𝑖 − 1
j← 𝑗 + 1
ENDIF
ENDIF
ENDIF
ENDIF
Mat[i][j] ← Z;
ENDWHILE
Stop

184
Integer FUNCTION Diagonal (Integer Mat[][], Integer N)
c Integer FUNCTION Diagonal (Integer Mat[][], Integer N)
Start
Variables
Integer: i, Sum
Sum← 0
FOR (i← 0 𝑇𝑂 𝑁 − 1) DO
Sum← 𝑆𝑢𝑚 + 𝑀𝑎𝑡[𝑖][𝑖]
ENDFOR
Return Sum
Stop

PROCEDURE Verify(Integer Mat[][], Integer N)


d PROCEDURE Verify (Integer Mat[][], Integer N)
Start
Variable
Integer: SumD1, SumD2, SumR, SumC
Boolean: Magic
Magic← 𝑇𝑟𝑢𝑒
SumD1←0
SumD2←0
SumD1←Diagonal(Mat, N)
FOR(K←0 TO N-1) DO
SumD2←SumD2+Mat[K, N-K]
ENDFOR
IF(SumD1≠ SumD2 ) THEN
Magic← 𝐹𝑎𝑙𝑠𝑒
ENDIF
K←0
WHILE((K≤ 𝑁 − 1) AND (Magic=True))DO
SumR←0
SumC←0
FOR(Z←0 TO N-1) DO
SumR←SumR+Mat[K, Z]
SumC←SumC+Mat[Z, K]
ENDFOR
IF(SumR ≠ SumD1) OR (SumC≠SumD1) THEN
Magic ← 𝐹𝑎𝑙𝑠𝑒
ENDIF
K←K+1
ENDWHILE
IF(Magic=True)THEN
Print(“The array is a magic square”)
ELSE
Print(“The array is not a magic square”)
ENDIF
Stop

185
void createSquare(int A[][Size], int N)
e.1 void createSquare(int A[][Size], int N)
{
int i, j, Z, Range;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
A[i][j]=0;
}
}
Z=1;
i=0;
Range=N*N;
j=N/2;
while(Z<=Range)
{
A[i][j]=Z;
if((i-1)<0&&(j+1)>N-1)
{
i=i+1;
}
else if((i-1)<0)
{
i=N-1;
j=j+1;
}
else if((j+1)>N-1)
{
j=0;
i=i-1;
}
else if(A[i-1][j+1]!=0)
{
i=i+1;
}
else
{
i=i-1;
j=j+1;
}
Z=Z+1;
}
}

int diagonal(int A[][Size], int N)


e.2 int diagonal(int A[][Size], int N)
{
int i, sum;
sum=0;
for(i=0;i<N; i++)
{
sum=sum + A[i][i];
}
return sum;
}

186
void verify(int A[][Size], int N)
e.3 void verify(int A[][Size], int N)
{
int i, j, SumD1, SumD2, SumR, SumC;
bool Flag;
Flag = true;
SumD1 = diagonal(A,N);
SumD2 = 0;
for(i=0;i<N;i++)
{
SumD2 = SumD2 + A[i][N-1-i];
}
if(SumD1!=SumD2)
{
Flag=false;
}
i=0;
while((i<N)&&(Flag==true))
{
SumR=0;
SumC=0;
for(j=0;j<N;j++)
{
SumR = SumR + A[j][i];
SumC = SumC + A[i][j];
}
if(SumR!=SumC)
{
Flag=false;
}
i=i+1;
}
if(Flag==false)
{
printf("\n\nThe array is a not magic square\n");
}
else
{
printf("\n\nThe array is a magic square\n");
}
}

int main()
f #include<stdio.h>
#include<stdbool.h>
#define Size 15
void createSquare(int A[][Size], int N);
int diagonal(int A[][Size], int N);
void verify(int A[][Size], int N);
int main()
{
int Mat[Size][Size];
int Order, i, j;
printf("Enter the order of the magic square:\t");
scanf("%d", &Order);
createSquare(Mat, Order);
for(i=0;i<Order;i++)
{
for(j=0;j<Order; j++)
{
printf("%d\t", Mat[i][j]);
}
printf("\n");
}
verify(Mat, Order);
return 0;
}

187
− Extra Exercises
1. Plotting of Two Functions
Two functions y1 and y2 are given by: y1 = 50 exp (–0.4x) + 0.5, y2 = 50 exp (-0.4𝑥 2 /2) + 0.5. Our task is to plot the graphs of these
functions for x varying from 0 to 5.0. Write a program that plots these two functions simultaneously. (0 for y1, * for y2, and # for the
common point).
2. Production and Sales Analysis
A company manufactures five categories of products and the number of items manufactured and sold are recorded product-wise every
week in a month. The company reviews its production schedule at every month-end. The review may require one or more of the following
information:
(a) Value of weekly production and sales.
(b) Total value of all the products manufactured.
(c) Total value of all the products sold.
(d) Total value of each product, manufactured and sold.
We shall represent the products manufactured and sold by two two-dimensional arrays M and S respectively. Then,

S11 S12 S13 S14 S15


M11 M12 M13 M14 M15
S21 S22 S23 S24 S25
M21 M22 M23 M24 M25 S=
M= S31 S32 S33 S34 S35
M31 M32 M33 M34 M35
S41 S42 S43 S44 S45
M41 M42 M43 M44 M45
Where Mij represents the number of jth type product manufactured in ith week and Sij the number of jth product sold in ith
week. We may also represent the cost of each product by a single dimensional array C as follows:

C= C1 C2 C3 C4 C5

Where Cj is the cost of jth type product.


We represent the value of products manufactured and sold by two value arrays, namely, Mvalue and Svalue. Then,
− Mvalue[i][j] = Mij x Cj
− Svalue[i][j] = Sij x Cj
1. Write the following subroutines:
− MonthlyProd that returns the total value of all the products manufactured. It takes Mvalue as parameter
− MonthlySales that returns the total value of all the products sold. It takes Svalue as parameter
− MonProdSales that returns the total value of each product, manufactured and sold in a tabular form. For example,
188
Product Production Sales
1
2
3
4
5

2. Write the main program that appropriately uses the subroutines above to generate the required outputs for the monthly
review meeting. Use the following data to test your program.
Amount of each products manufactured per week

Week1 12 10 9 21 21
Week2 25 31 15 26 24
Week3 13 16 17 20 15
Week4 12 14 18 19 14
Amount of each products sold per week

Week1 8 8 7 20 16
Week2 21 25 14 25 22
Week3 9 14 16 19 14
Week4 11 11 17 18 13

Cost of each product 300 250 100 150 75

189
2 RELATIONAL DATABASES
2.1 Introduction
Database is an organized collection of related data, stored in a way that it can be easily manipulated and retrieved.
A relational database models data as mathematical relation, with each relation being composed of tuples of data,
and the data within each tuple being related
When a relational database model is implemented by software, a relational database program will represent each
relation as a table, and each tuple will be a record within a table. The data in different tables can be linked together
to express relationships that exist between the data in the tables.

Creating a relational database involves creating a number of tables and linking up the tables by means of
i common attributes.
i
i
i -A relation is a table in a relational database
NOTE -Relationship: Relationships are named associations between entities
-A relationship is formed when two or more relations (tables) are joined together
2.2 Characteristics of a Relational Table
− A table is perceived as a two-dimensional structure composed of rows and columns.
− Each table row (tuple) represents a single entity occurrence within the entity set.
− Each table column represents an attribute, and each column has a distinct name.
− Each intersection of a row and column represents a single data value.
− All values in a column must conform to the same data format.
− Each column has a specific range of values known as the attribute domain.
− The order of the rows and columns is immaterial to the DBMS.
− Each table must have an attribute or combination of attributes that uniquely identifies each row.
2.3 Relational Database Keys
Key Definition
Superkey An attribute or combination of attributes that uniquely identifies each row in a table
Candidate A minimal (irreducible) superkey; a superkey that does not contain a subset of attributes that is
key itself a superkey
Primary A candidate key selected to uniquely identify all other attribute values in any given row; cannot
key contain null entries
Foreign An attribute or combination of attributes in one table whose values must either match the primary
key key in another table or be null
Secondary An attribute or combination of attributes used strictly for data retrieval purposes
key

A primary key is the attribute or combination of attributes that uniquely identifies entity instances in an entity
i set. To ensure entity integrity, the primary key has two requirements: (1) all of the values in the primary key must
i be unique, and (2) no key attribute in the primary key can contain a null.
i
i NOTE The foreign key is used to link the table with other tables in the database
A foreign key must have the same structure, data type, and field size as the associated primary key
2.4 Selecting Primary Keys
The main function of the primary key is to uniquely identify an entity instance or row within a table. In particular,
given a primary key value—that is, the determinant—the relational model can determine the value of all
dependent attributes that “describe” the entity
190
Secondly, primary keys and foreign keys are used to implement relationships among entities.
The table below, summarizes desirable primary key characteristics.

Desirable Primary Key (PK) Characteristics


PK CHARACTERISTIC RATIONALE
Unique values The PK must uniquely identify each entity instance. A primary key must be able to
guarantee unique values. It cannot contain nulls.
No change over If an attribute has semantic meaning, it might be subject to updates, which is why names
time do not make good primary keys. If Ayuk Mary is the primary key, what happens if she
changes her name when she gets married? If a primary key is subject to change, the
foreign key values must be updated, thus adding to the database work load.
Furthermore, changing a primary key value means that you are basically changing the
identity of an entity. In short, the PK should be permanent and unchangeable.
Preferably single- A primary key should have the minimum number of attributes possible (irreducible).
attribute Single-attribute primary keys are desirable but not required. Single attribute primary
keys simplify the implementation of foreign keys. Having multiple-attribute primary
keys can cause primary keys of related entities to grow through the possible addition of
many attributes, thus adding to the database workload and making (application) coding
more cumbersome
Security-compliant The selected primary key must not be composed of any attribute(s) that might be
considered a security risk or violation. For example, using a Social Security number as a
PK in an EMPLOYEE table is not a good idea.
Preferably numeric Unique values can be better managed when they are numeric, because the database can
use internal routines to implement a counter-style attribute that automatically
increments values with the addition of each new row.

2.5 Integrity Rules


ENTITY DESCRIPTION
INTEGRITY
Entity integrity is the condition in which each row (entity instance) in the table has its own unique identity. To
ensure entity integrity, the primary key has two requirements: (1) all of the values in the primary key must be
unique, and (2) no key attribute in the primary key can contain a null
Requirement All primary key entries are unique, and no part of a primary key may be null.
Purpose Each row will have a unique identity, and foreign key values can properly reference primary
key values.
Example No invoice can have a duplicate number, nor can it be null; in short, all invoices are uniquely
identified by their invoice number.
REFERENTIAL DESCRIPTION
INTEGRITY
Foreign keys are used to ensure referential integrity, the condition in which every reference to an entity
instance by another entity instance is valid. In other words, every foreign key entry must EITHER BE NULL or
a VALID VALUE in the primary key of the related table.
Requirement A foreign key may have either a null entry, as long as it is not a part of its table’s primary
key, or an entry that matches the primary key value in a table to which it is related;
(every non-null foreign key value must reference an existing primary key value).
Purpose It is possible for an attribute not to have a corresponding value, but it will be impossible to
have an invalid entry; the enforcement of the referential integrity rule makes it impossible to
delete a row in one table whose primary key has mandatory matching foreign key values in
another table.
Example A customer might not yet have an assigned sales representative (number), but it will be
impossible to have an invalid sales representative (number).

191
Other integrity rules that can be enforced in the relational model are the NOT NULL and UNIQUE constraints.
The NOT NULL constraint can be placed on a column to ensure that every row in the table has a value for that
i column. The UNIQUE constraint is a restriction placed on a column to ensure that no duplicate values exist for
i that column.
i
i 2.6 Entity Relationship (ER) Modeling
Entity relationship (ER) model (ERM) is a data model that describes relationships among entities at the
conceptual level with the help of ER diagrams. The ER model is based on the following components:
− Entity
− Attributes
− Relationships
ER models are normally represented in an entity relationship diagram (ERD), which uses graphical
representations to model database components. ERDs depict the database’s main components: entities,
attributes, and relationships
− ERD NOTATIONS
Different notations are used to draw ER diagrams. These include: The original Chen notation, the Crow’s Foot
notation, and the newer Unified Modeling Language (UML). Chen Notation uses a diamond and connecting lines
with symbols to describe relationship while Crow’s Foot Notation uses lines with the three-pronged symbol on
the end to represent the many side of a relationship.
Chen notation system:
− Uses Rectangles to represent entities
− Uses Diamonds to represent relationships
− To display cardinality, Chen Notation uses the letter M to indicate many on one side of the relationship. It
uses a 1 to indicate one and only one.
Crow’s Foot Notation:
− Uses Rectangles to represent entities
− Cardinality is shown using three-pronged symbol on the end to represent the many side of a relationship.
− Relationships are represented by lines connecting the boxes. The lines can be labeled with the nature of
the relation.

▪ The Chen notation favours conceptual modeling.


i ▪ The Crow’s Foot notation favours a more implementation-oriented approach.
i ▪ The UML notation can be used for both conceptual and implementation modeling.
i
Most of our ER diagrams will be drawn using the Chen Notation.
i
2.6.1 Entities
− An entity is a person, place, thing, or event about which data will be collected and stored. Some specific
examples of entities are EMPLOYEES, PROJECTS, INVOICES and APPOINTMENTS
− Usually, when applying the ERD to the relational model, an entity is mapped to a relational table. Each row
in the relational table is known as an entity instance or entity occurrence in the ER model.
− In the Chen, Crow’s Foot, and UML notations, an entity is represented by a rectangle that contains the
entity’s name. The entity name, a noun, is usually written in all capital letters.
2.6.2 Attributes
Attributes are characteristics of entities (or an attribute is a property that describes an entity). For example, an
employee’s name, date of birth (D.O.B) and gender or, a vehicle’s model, color and brand
− In the original Chen notation, attributes are represented by ovals or ellipses and are connected to the
entity rectangle with a line. Each oval contains the name of the attribute it represents.
− In the Crow’s Foot notation, the attributes are written in the attribute box below the entity rectangle

192
DOB

Name Gender

EMPLOYEE
Name
Gender
EMPLOYEE DOB

Chen Notation Crow’s Foot Notation

2.6.3 Identifiers (Primary Keys)


The ERM uses identifiers—one or more attributes that uniquely identify each entity instance. In the relational
model, entities are mapped to tables, and the entity identifier is mapped as the table’s primary key (PK).
Identifiers are underlined in the ERD.
Key attributes are also underlined or starred in a frequently used shorthand notation for the table structure, called
a RELATIONAL SCHEMA, that uses the following format:
TABLE NAME (KEY_ATTRIBUTE 1, ATTRIBUTE 2, ATTRIBUTE 3, … ATTRIBUTE K) or
TABLE NAME (KEY_ATTRIBUTE 1*, ATTRIBUTE 2, ATTRIBUTE 3, … ATTRIBUTE K)
For example, a CAR entity may be represented by
CAR (CAR_ID, CAR_Model, CAR_Colour)

The relational schema, uses the following format:


i
TABLE NAME (KEY_ATTRIBUTE 1, ATTRIBUTE 2, ATTRIBUTE 3, … ATTRIBUTE K)
i
i
− Composite identifier: In ER modeling, a composite identifier is a key composed of more than one attribute.
i
All the attributes that constitute the identifier are underlined in the relational schema.

2.6.4 Relationships
Relationships are named associations between entities
The entities that participate in a relationship are also known as participants, and each relationship is identified
by a name that describes the relationship. The relationship name is an active or passive verb connecting two or
more entities; for example, a STUDENT takes a CLASS, a Teacher teaches a CLASS, a DIVISION is managed by an
EMPLOYEE, and an AIRCRAFT is flown by a CREW.
In an ER diagram using the Chen Notation, a relationship is represented by a diamond.
2.6.4.1 Relationship Degree
A relationship degree indicates the number of entities or participants associated with a relationship. A unary
relationship exists when an association is maintained within a single entity. A binary relationship exists when two
entities are associated. A ternary relationship exists when three entities are associated
2.6.4.2 Cardinality
Cardinality is the maximum number of instances of an entity that can take part in a relationship.
The cardinality ratio is a ratio of the cardinalities of the entities involved in a relationship. It can be one-to-one
(1:1), one-to-many (1:N) or many-to-many (M:N).
In a relationship OWNS between PERSON and HOUSE, a person can own no house or many houses. Therefore, the
cardinality of PERSON in the relationship OWNS is many.
On the other hand, a house is owned by one and only one person (In this particular case under consideration, a
single house can be owned by just one person). The cardinality of HOUSE in the inverse relationship
IS_OWNED_BY, is one. The relationship OWNS is therefore described as a one-to-many (1:N) relationship.

193
(1:N) relationship

In a relationship RECEIVES between STUDENT and SLIP, each student receives one and only one result slip. The
cardinality of student is one. Each result slip is issued to one and only one student. The cardinality of SLIP is one.
This relationship is described as one-to-one (1:1).

(1:1) relationship

In the relationship TEACHES between TEACHER and SUBJECT, a teacher teaches one or many subjects. The
cardinality of TEACHER is many. A subject is taught by one or many teachers. The cardinality of SUBJECT in the
inverse relationship IS_TAUGHT_BY, is many. This relationship is described as many-to-many (M:N).

(M:N) relationship

Note: All diagrams have been drawn using the Chen Notation.

2.6.5 Developing an ER Diagram


Building an ERD usually involves the following activities:
− Create a detailed narrative of the organization’s description of operations.
− Identify the business rules based on the description of operations.
− Identify the main entities and relationships from the business rules.
− Develop the initial ERD.
− Identify the attributes and primary keys that adequately describe the entities.
− Revise and review the ERD.
2.6.6 Conversion of an Entity-Relationship Diagram (ERD) to a Relational Database Model
Here are the basic steps to convert an entity-relationship diagram (ERD) to a relational database model:
1. Identify the entities in the ERD. Entities in an ERD typically map to tables in a relational database.
2. Identify the attributes of each entity. Attributes describe the properties of an entity and map to columns in
database tables.
3. Define the primary key for each table. The primary key uniquely identifies each row/record in a table. It's
usually one of the entity's attributes.
4. Identify relationships between entities. Relationships show how entities are related to each other.
5. For one-to-many relationships, place the primary key of the "one" entity in the table of the "many" entity as a
foreign key.
6. For many-to-many relationships, create a separate junction table with foreign keys to the primary keys of the
related entities.
7. Define data types, nullability constraints, indexes, etc. based on the attributes.
8. Define integrity constraints like foreign key constraints, unique constraints, check constraints to enforce data
rules.
9. Normalize tables to third normal form (3NF) to minimize redundancy and avoid anomalies.

194
2.6.7 Associative Table
An associative table refers to a table in a relational database that links two other tables together. It allows the
building of many-to-many relationships between tables. Associative tables contain the primary keys of the tables
being linked as a composite primary key in the associative table.
Associative tables effectively break out a many-to-many relationship between two tables into two one-to-many
relationships.
An associative table is also commonly known as a junction table, a mapping table, a bridge table, a linking table,
or a cross-reference table
EXAMPLE
A BOOKSTORE DATABASE.
Suppose we have two tables: one for books and another for authors. Each book can have multiple authors, and
each author can write multiple books. This creates a many-to-many relationship between the two tables, which
cannot be directly represented in a traditional relational database.
To solve this problem, we can create an associative table that links the two tables together. This table will contain
two foreign keys: one for the book ID and another for the author ID. Each record in the associative table represents
a relationship between a book and an author.
The relational schema will be:
Book(BookID, BookTitle)
Author(AuthorID, AuthorFirstName, AuthorLastName)
Book_Author(BookID, AuthorID)

2.7 Database Normalization


Normalization is the process of organizing the fields and tables of a relational database to minimize data
redundancies, thereby reducing the likelihood of data anomalies.
Normalization usually involves dividing large tables into smaller and less redundant tables and defining
relationships between them. Normalization works through a series of stages known as normal forms. In order to
achieve one level of normal form, each previous level must be met. The first three stages are described as first
normal form (1NF), second normal form (2NF), and third normal form (3NF). From a structural point of view,
2NF is better than 1NF, and 3NF is better than 2NF. For most purposes in business database design, 3NF is as high
as you need to go in the normalization process.
− Denormalization
A process by which a table is changed from a higher-level normal form to a lower-level normal form, usually to
increase processing speed. Denormalization potentially yields data anomalies.
− Unnormalized data
Raw data in its original state; it might contain redundant data, multivalued data, and/or other data anomalies not
found on normalized data relations
2.7.1 The Normalization Process
The objective of normalization is to ensure that each table conforms to the concept of well-formed relations— in
other words, tables that have the following characteristics:
− Each relation (table) represents a single subject. For example, a COURSE table will contain only data that
directly pertain to courses. Similarly, a STUDENT table will contain only student data.
− Each row/column intersection contains only one value and not a group of values.
− No data item will be unnecessarily stored in more than one table (tables have minimum controlled
redundancy). The reason for this requirement is to ensure that the data is updated in only one place.
− All nonprime attributes in a relation (table) are dependent on the primary key—the entire primary key and
nothing but the primary key. The reason for this requirement is to ensure that the data is uniquely identifiable
by a primary key value.

195
− Each relation (table) has no insertion, update, or deletion anomalies, which ensures the integrity and
consistency of the data.
To accomplish these objectives, the normalization process takes you through steps that lead to successively higher
normal forms
The normalization process works ONE RELATION (TABLE) AT A TIME, identifying the dependencies on that
relation and normalizing the relation.
Normalization starts by identifying the dependencies of a given relation and progressively breaking up the
relation (table) into a set of new relations (tables) based on the identified dependencies.
2.7.2 Dependencies
The role of a key is based on the concept of determination. Determination is the state in which knowing the value
of one attribute makes it possible to determine the value of another. Determination in a database environment is
normally based on the relationships among the attributes. A specific terminology and notation is used to describe
relationships based on determination. The relationship is called functional dependence, which means that the
value of one or more attributes determines the value of one or more other attributes

Functional Dependence Concepts


Concept Definition
Functional dependence The attribute B is fully functionally dependent on the attribute A if each value of A
determines one and only one value of B.
Example: PROJ_NUM → PROJ_NAME
(read as PROJ_NUM functionally determines PROJ_NAME)
In this case, the attribute PROJ_NUM is known as the determinant attribute, and the
attribute PROJ_NAME is known as the dependent attribute.
Functional dependence Attribute A determines attribute B (that is, B is functionally dependent on A) if all
(generalized definition) (generalized definition) of the rows in the table that agree in value for attribute A also
agree in value for attribute B.
Fully functional dependence If attribute B is functionally dependent on a composite key A but not on any subset of
(composite key) that composite key, the attribute B is fully functionally dependent on A.

Two types of functional dependencies that are of special interest in normalization are partial dependencies and
transitive dependencies.
− A partial dependency exists when there is a functional dependence in which the determinant is only part of
the primary key.
For example, if (A, B) → (C, D), B→C, and (A, B) is the primary key, then the functional dependence B → C is a
partial dependency because only part of the primary key (B) is needed to determine the value of C.
− A transitive dependency exists when there are functional dependencies such that X → Y, Y → Z, and X is the
primary key. In that case, the dependency X → Z is a transitive dependency because X determines the value of
Z via Y. Transitive dependency occurs only when a functional dependence exists among nonprime attributes.

Partial dependency: A condition in which an attribute is dependent on only a portion (subset) of the primary key.
i Transitive dependency: A condition in which an attribute [nonprime] is dependent on another attribute that is not part
i of the primary key.

i
i 2.7.3 Conversion to First Normal Form (1NF)
For a database to be in 1NF, the following rules have to be met for each table in the database.
− There must be no tables with multivalued fields. A multivalued field is one that may take several values
for a single record.
− Each data item must be atomic. Atomic means that the data item cannot be broken down any further

196
− Each row must be unique i.e. it has a primary key. The primary key ensures that each row/record in the
table is unique
To put a table into 1NF, there are two methods.
− Method 1: We split the table, carrying the multivalued data into a new table.
− Method 2: We create new rows, placing each value of the multivalued field in a separate row

2.7.4 Conversion to Second Normal Form (2NF)


Conversion to 2NF occurs only when the 1NF has a composite primary key. If the 1NF has a single-attribute
primary key, then the table is automatically in 2NF. For a table to be in 2NF, the following rules have to be met.
− It must be in 1NF
− Every non-key field must be functionally dependent on every part (or the entire) primary key. This means,
there should be no partial dependencies. A partial dependency is when a non-key field depends on only
part of the primary key
To put a table in 2NF, we create separate tables for the fields that are not dependent on the entire primary key.
The primary key for these tables will be the part of the composite key on which those fields are dependent.
2.7.5 Conversion to Third Normal Form (3NF)
For a table to be in 3NF, the following rules have to be met:
− It must be in 2NF
− No non-key field should depend on another non-key field. This type of dependency is called transitive
dependency.
To put the table into 3NF, we eliminate the transitive dependency by placing the transitively dependent field in a
new table

Normal Forms
Normal Form Characteristics
First Normal Form (1NF) Table format, no repeating groups, and PK identified
Second Normal Form (2NF) 1NF and no partial dependencies
Third Normal Form (3NF) 2NF and no transitive dependencies

In a normalized database, many-to-many relationships are eliminated by creating a link table between the
i tables involved in the relationship
i
i Example
i 1. Normalize the database below to 2NF
StudentID Student Name D.o.B Subject Code Subject Title Grade

LS-01 Ayuk J. 05/02/1998 710 Biology D

LS-01 Ayuk J. 05/02/1998 715 Chemistry O

LS-02 Che P. 07/01/1994 755 Geology E

LS-02 Che P. 07/01/1994 796 ICT C

This table is in 1NF and it has the composite key {Student Id, Subject Code}, but it is not in 2NF. This is because it
contains partial dependencies. Some non-key fields are not dependent on the entire primary key.
Functional Dependencies:
197
• {Student Id} → {Student Name}
• {Subject Code} !→ {Student Name}
With a subject code, you cannot know a student’s name. Student Name is therefore not dependent on Subject
Code. Student Name is not dependent on the entire primary key.
• {Student Id → D.o.B};
• {Subject Code !→ D.o.B}
D.o.B is dependent on Student Id but not on Subject Code, so not dependent on the entire primary key.
{Subject Code} → {Subject Title}, but {Student Id} !→ {Subject Title}
Subject title is dependent on Subject Code but it is not dependent on Student Id, so it is not dependent on the
entire primary
− {Student Id, Subject Code} → {Grade}
Student Id alone will not determine Grade and Subject Code alone will not determine Grade. We need both Student
Id and Subject Code in order to know a student’s grade in a subject. For the couple (Student Id, Subject Code) the
grade will always be the same. Every time we have (LS-01, 710), the grade will always be D. Grade is thus
dependent on the entire primary key.
To put the table in 2NF, we create separate tables for the fields that are not dependent on the entire primary key.
The primary key for these tables will be the part of the composite key on which those fields are dependent. Doing
that, we obtain the following three tables.

2 NF
− STUDENT(Student Id, StudentName, D.o.B)
− SUBJECT(SubjectCode, SubjectTitle)
− STUDENT_GRADES(Student Id, Subject Code, Grade)

The STUDENT_GRADES table is a link table between the STUDENT table and the SUBJECT table. This means that
the relationship between STUDENT and SUBJECT is a many-to-many relationship.

2. Consider a first attempt at creating a database for a movie download system shown below.

CustomerID CustomerName Address DateOfDownload MovieID Movie Genre Format FileType


Title
1 John S. 1 High 19/03/15 1 The Comedy LowRes MPEG-2
Street Hangover
19/03/15 2 22 Jump Comedy LowRes MPEG-2
Street
2 Mary J. 14 Acacia 19/03/15 3 The Sci-Fi HiRes MPEG-4
Avenue Hunger
Games
19/03/15 4 Robocop Sci-Fi HiRes MPEG-4
19/03/15 2 22 Jump Comedy LowRes MPEG-2
Street
3 Snow J. 23 Maple 19/03/15 5 How to Children HiRes MPEG-4
Drive Train Your
Dragon
19/03/15 4 Robocop Sci-Fi HiRes MPEG-4

First Normal Form (1NF)


This table is not in first normal form (1NF) because there are repeating groups, which are: DateOfDownload,
MovieID, MovieTitle, Genre, Format and FileType columns.
To put the table into 1NF, we will use Method 1 which involves splitting the table, carrying the repeating
groups into a new table. We then have two tables.

198
As we split the tables, we give reasonable names to the
CustomerID CustomerName Address
newly formed tables. This table consist of NON-
1 John S. 1 High
Street REPEATING GROUPS. Looking at the attributes, we
2 Mary J. 14 Acacia shall name this table CUSTOMER. Using the shorthand
Avenue notation we can represent this table (relation) as:
3 Snow J. 23 Maple CUSTOMER(CustomerID, CustomerName, Address)
Drive
CustomerID is the primary key. It is unique for all
CUSTOMER records, it is NOT NULL and not subject to change. It fits
our desired characteristics

CustomerID DateOfDownload MovieID Movie Genre Format FileType


Title
1 19/03/15 1 The Comedy LowRes MPEG-2
Hangover
1 19/03/15 2 22 Jump Comedy LowRes MPEG-2
Street
2 19/03/15 3 The Sci-Fi HiRes MPEG-4
Hunger
Games
2 19/03/15 4 Robocop Sci-Fi HiRes MPEG-4
2 19/03/15 2 22 Jump Comedy LowRes MPEG-2
Street
3 19/03/15 5 How to Children HiRes MPEG-4
Train Your
Dragon
3 19/03/15 4 Robocop Sci-Fi HiRes MPEG-4

CUSTOMER_DOWNLOAD

This table consist of REPEATING GROUPS. The CUSTOMERID from the first table is retained here to link
both tables. Looking at the attributes, we shall name this table CUSTOMER_DOWNLOAD Using the
shorthand notation we can represent this table (relation) as:
CUSTOMER_DOWNLOAD (CustomerID, MovieID, DateOfDownload, Movie_Title , Genre, Format, FileType)
Each download can now be uniquely identified with a composite key made up of CustomerID and MovieID,
so this could be made into the primary key. It is possible that one customer could download the same movie
again, in which case this primary key would not be adequate, but for this example we will assume that a
customer will only download the same movie once.

1 NF: Our database is now in 1 NF. It has two tables that can be described as:

− CUSTOMER_DOWNLOAD (CustomerID, MovieID, DateOfDownload, Movie_Title , Genre, Format, FileType)


− CUSTOMER(CustomerID, CustomerName, Address)
CustomerID links both tables.
1NF
CUSTOMER_DOWNLOAD (CustomerID, MovieID, DateOfDownload, Movie_Title , Genre, Format, FileType)
CUSTOMER(CustomerID, CustomerName, Address)

2 NF:
Normalizing the database to 2NF involves analyzing ONE RELATION (TABLE) AT A TIME, identifying the
dependencies on that relation and normalizing the relation.

199
− First Relation: CUSTOMER(CustomerID, CustomerName, Address)
The CUSTOMER relation has a single-attribute primary key, this implies it is automatically in 2NF. There is no
partial dependency.
− Second Relation: CUSTOMER_DOWNLOAD (CustomerID, MovieID, DateOfDownload, Movie_Title , Genre,
Format, FileType)
The CUSTOMER_DOWNLOAD relation has a composite key, {CustomerID, MovieID}. We shall proceed by
analyzing the dependence of each of the non key attribute. The non-key attributes are all the other attributes apart
from the primary key.
− Movie_Title is dependent on the MovieID but not on the CustomerID. We use the notation
{Movie𝐈𝐃 →Movie_Title, CustomerID! → Movie_Title}
− Genre is dependent on the MovieID but not on the CustomerID. We use the notation {Movie𝐈𝐃 →Genre,
CustomerID! →Genre}
− Format is dependent on the MovieID but not on the CustomerID. We use the notation {Movie𝐈𝐃 →Format,
CustomerID! →Format}
− FileType is dependent on the MovieID but not on the CustomerID. We use the notation
{Movie𝐈𝐃 →FileType, CustomerID! →FileType}
− DateOfDownload is dependent on both MovieID and CustomerID. We use the notation
{{Movie𝐈𝐃, 𝐂𝐮𝐬𝐭𝐨𝐦𝐞𝐫𝐈𝐃} →DateOfDownload}. This is true since we have assumed that each customer
will download a movie only once
To be in second normal form, any non-key attributes that depend upon part but not all of the primary key should
be removed to another table. This means Movie_Title, Genre, Format, and FileType are going to a new table.

MovieID Movie Genre Format FileType This table consists of attributes that were partially
Title
1 The Comedy LowRes MPEG-2
dependent on the composite key. They form a new table with
Hangover the part of the primary key (MovieID) they were dependent
2 22 Jump Comedy LowRes MPEG-2 on.
Street Looking at the attributes, we shall name this table MOVIE.
3 The Sci-Fi HiRes MPEG-4 Using the shorthand notation we can represent this table
Hunger
(relation) as:
Games
4 Robocop Sci-Fi HiRes MPEG-4 MOVIE(MovieID, Movie_Title, Genre, Format, FileType)
5 How to Children HiRes MPEG-4 MovieID is the primary key. It is unique for all records, it is
Train Your NOT NULL and not subject to change. It fits our desired
Dragon characteristics
MOVIE

This table consists of attributes that were fully dependent on


CustomerID DateOfDownload MovieID
the entire composite key.
1 19/03/15 1
1 19/03/15 2
Looking at the attributes, we shall name this table
2 19/03/15 3 DOWNLOAD. Using the shorthand notation we can represent
2 19/03/15 4 this table (relation) as:
2 19/03/15 2 DOWNLOAD(CustomerID, MovieID, DateOfDownload)
3 19/03/15 5 As we have assumed that each customer will download
3 19/03/15 4 a movie only once, the DOWNLOAD table can have a
composite key made up of CustomerID and MovieID
DOWNLOAD

200
2NF: Our database now in 2NF has 3 tables:

2NF
CUSTOMER(CustomerID, CustomerName, Address)
MOVIE(MovieID, Movie_Title, Genre, Format, FileType)
DOWNLOAD(CustomerID, MovieID, DateOfDownload)

3NF:
Normalizing the database to 3NF involves analyzing ONE RELATION (TABLE) AT A TIME, identifying the
dependencies on that relation and normalizing the relation.
− First Relation: DOWNLOAD(CustomerID, MovieID, DateOfDownload)
This table has only one non-key attribute, DateOfDownload. Hence, it is automatically in 3NF as there can be
no transitive dependency
− Second Relation: CUSTOMER(CustomerID, CustomerName, Address)
The Address and CustomerName both depend on the CustomerID directly, so this table is already in third
normal form.
− Third Relation: MOVIE(MovieID, Movie_Title, Genre, Format, FileType)
The FileType depends upon the Format. All LowRes films are recorded in MPEG-2 format and all HiRes films
are recorded in MPEG-4 format. Therefore, the non-key attribute FileType depends upon the non-key
attribute Format so we can split the format information off from the movie information to create two new
tables
Format FileType
LowRes MPEG-2 MOVIEFORMAT(Format, FileType)
HiRes MPEG-4

MOVIEFORMAT

MovieID Movie Title Genre Format


1 The Hangover Comedy LowRes
2 22 Jump Street Comedy LowRes
3 The Hunger Sci-Fi HiRes
Games MOVIE(MovieID, Movie_Title, Genre, Format)
4 Robocop Sci-Fi HiRes
5 How to Train Children HiRes
Your
Dragon
MOVIE

3NF
CUSTOMER(CustomerID, CustomerName, Address)
DOWNLOAD(CustomerID, MovieID, DateOfDownload)
MOVIE(MovieID, Movie_Title, Genre, Format)
MOVIEFORMAT(Format, FileType)

FULLY NORMALIZED DESIGN


CUSTOMER(CustomerID, CustomerName, Address)
DOWNLOAD(CustomerID, MovieID, DateOfDownload)
MOVIE(MovieID, Movie_Title, Genre, Format)
MOVIEFORMAT(Format, FileType)

201
CUSTOMER DOWNLOAD
CustomerID CustomerName Address CustomerID DateOfDownload MovieID
1 John S. 1 High 1 19/03/15 1
Street 1 19/03/15 2
2 Mary J. 14 Acacia 2 19/03/15 3
Avenue 2 19/03/15 4
2 19/03/15 2
3 Snow J. 23 Maple 3 19/03/15 5
Drive 3 19/03/15 4

MOVIE
MOVIEFORMAT
MovieID Movie Title Genre Format
Format FileType
1 The Hangover Comedy LowRes
LowRes MPEG-2
2 22 Jump Street Comedy LowRes
HiRes MPEG-4
3 The Hunger Sci-Fi HiRes
Games
4 Robocop Sci-Fi HiRes
5 How to Train Children HiRes
Your
Dragon

− The CustomerID is the primary key of the CUSTOMER table and a foreign key in the DOWNLOAD table.
− The MovieID is the primary key of the MOVIE table and a foreign key in the DOWNLOAD table.
− The Format is the primary key of the MOVIEFORMAT table and a foreign key in the MOVIE table.
− The DOWNLOAD table has a composite key made up of CustomerID and MovieID.
− At this point, a database designer might choose to add an additional field, DownloadID, to the DOWNLOAD table
which would be unique for each download. This would mean that the composite key of CustomerID + MovieID could
be replaced by a primary key that was just one field. This might be considered to be an improvement, but it is not
required for normalization.
In summary, the characteristics that a relation database design must have to be fully normalised are:
− All of the data must be atomic / there must be no repeating groups / no repeating attributes.
− There should be no partial dependencies, where a non-key attribute depends upon part but not all of the primary
key.
− There should be no non-key dependencies, where a non-key attribute depends upon another non-key attribute.
3. Is the table below in 3NF? If not, Normalize it to 3NF

Customer Id Customer Name Town Code Town


CUS-001 Ngalla N. N001 Bamenda
CUS-002 Nji J. N001 Bamenda
CUS-003 Nkeng J. S004 Fontem
CUS-004 Che J. N002 Kumbo
CUS-005 Neba P. N002 Kumbo
Functional dependencies:
• {Customer Id} → {Customer Name, Town Code, Town}
• {Town Code} → {Town}
• {Customer Id} → {Town Code} → {Town} : Transitive dependency

To put the table into 3NF, we eliminate the transitive dependency by placing the transitively dependent field in a new table as follows. The
new table called TOWNS will have Town Code as primary key. Notice that Town Code remains as a field in the CUSTOMER table.

Customer Id Customer Name Town Code Town Code Town_Name


CUS-001 Ngalla N. N001 N001 Bamenda
CUS-002 Nji J. N001 S004 Fontem
CUS-003 Nkeng J. S004 N002 Kumbo
CUS-004 Che J. N002
CUS-005 Neba P. N002

202
3NF—FULLY NORMALIZED DESIGN
CUSTOMER(CustomerID, CustomerName, TownCode)
TOWN(TownCode, Town_Name)

2.8 Structured Query Language (SQL)


Structured query language (SQL) is a special-purpose programming language designed for managing data held in
a relational database management system (RDBMS). SQL, is composed of commands that enable users to create
database and table structures, perform various types of data manipulation and data administration, and query
the database to extract useful information. SQL functions fit into several broad categories:
− It is a Data Manipulation Language (DML). SQL includes commands to insert, update, delete, and retrieve
data within the database tables.
− It is a Data Definition Language (DDL). SQL includes commands to create database objects such as tables,
indexes, and views, as well as commands to define access rights to those database objects.
− It is a Transaction Control Language (TCL). The DML commands in SQL are executed within the context of
a transaction, which is a logical unit of work composed of one or more SQL statements, as defined by
business rules. SQL provides commands to control the processing of these statements an indivisible unit
of work.
− It is a Data Control Language (DCL). Data control commands are used to control access to data objects,
such as giving a one user permission to only view a particular table, and giving another user permission
to change the data in a particular table.
2.8.1 Data Definition Language (DDL). [CREATE TABLE, ALTER TABLE, DROP TABLE]
− Creating Table Structures
To create a table the user needs to define the name of the table and each of the attributes including the data type
and length. We can as well define the Primary key and any Foreign key
CREATE TABLE command
CREATE TABLE Tablename
(
column1 data_type(size) [constraint],
column2 data_type(size) [constraint],
………………………
columnn data_type(size) [constraint],
[PRIMARY KEY (column1 [, column2])],
[FOREIGN KEY (column1 [, column2]) REFERENCES Tablename],
[CONSTRAINT constraint]
);
Anything inside square brackets is optional
− The column parameters specify the names of the columns of the tables.
− The data type parameter specifies the type of data the column can hold (e.g. varchar, integer, date, etc.)
− SQL Constraints
Besides the PRIMARY KEY and FOREIGN KEY constraints, the SQL standard also defines the following constraints:
− The NOT NULL constraint ensures that a column does not accept nulls.
− The UNIQUE constraint ensures that all values in a column are unique.
− The DEFAULT constraint assigns a value to an attribute when a new row is added to a table. The end user
may, of course, enter a value other than the default value.
− The CHECK constraint is used to validate data when an attribute value is entered. It checks to see that a
specified condition exists. Examples of such constraints include the following:
− The minimum order value must be at least 10.
− The date must be after April 15, 2018.

203
− If the CHECK constraint is met for the specified attribute (i.e., the condition is true), the
data is accepted for that attribute. If the condition is found to be false, an error message
is generated and the data is not accepted.
The CREATE TABLE command lets you define constraints in two different places:
− When you create the column definition (known as a column constraint)
− When you use the CONSTRAINT keyword (known as a table constraint)
Examples
1. The following SQL statement creates a table with a check constraint that ensures the age of an employee
is between 18 and 65:
CREATE TABLE employees (
emp_id INT,
name VARCHAR(50),
age INT CHECK (age >= 18 AND age <= 65),
email VARCHAR(50)
);

2. The following SQL statement creates a table with a unique constraint on the "email" column:
CREATE TABLE users (
id INT,
name VARCHAR(50),
email VARCHAR(50) UNIQUE
);

3. The following SQL statement creates a table with a default value on the age column:

CREATE TABLE table5 (


name VARCHAR(30),
age INT DEFAULT 18
);

− Altering Table Structures


All changes in the table structure are made by using the ALTER TABLE command followed by a keyword that
produces the specific change you want to make. Three options are available: ADD, MODIFY, and DROP. You use
ADD to add a column, MODIFY to change column characteristics, and DROP to delete a column from a table.
The basic syntax to add or modify columns is:
ALTER TABLE tablename
{ADD | MODIFY} (columnname datatype);

The ALTER TABLE command can also be used to add table constraints. In those cases, the syntax would be:
ALTER TABLE tablename
ADD constraint [ ADD constraint ];

You could also use the ALTER TABLE command to remove a column or table constraint. The syntax would be:
204
ALTER TABLE tablename
DROP {PRIMARY KEY | COLUMN columnname | CONSTRAINT constraintname };

− Deleting a Table from the Database


DROP TABLE command
A table can be deleted from the database using the DROP TABLE command. For example, you can delete a table
called STUDENT with the following command:
DROP TABLE STUDENT;

2.8.2 Data Types


A data type is a specification about the kinds of data that can be stored in an attribute.

Some Common SQL Data Types


CHAR(Size) It is used to specify a fixed length string that can contain numbers, letters, and special
characters. Its size can be 0 to 255 characters. If no length is specified during the
declaration, the default length is 1. If you assign a value to a CHAR(size) column containing
fewer characters than the defined length, the remaining space is filled with blanks
characters.
VARCHAR(Size) It is used to specify a variable length string that can contain numbers, letters, and special
characters. Its size can be from 0 to 65535 characters. The designation VARCHAR2(25) or
VARCHAR(25) will let you store characters up to 25 characters long. However, unlike
CHAR, VARCHAR will not leave unused spaces.
BOOLEAN OR The BOOLEAN data type supports the storage of two values: TRUE or FALSE
BOOL
BIT(Size) It is used for a bit-value type. The number of bits per value is specified in size. Its size can
be 1 to 64. The default value is 1.
INTEGER(size) It is used for the integer value. The size parameter specifies the maximum display width.
or INT(size) Integers cannot be used if you want to store numbers that require decimal places.
DECIMAL(size, It is used to specify a fixed-point number. Its size parameter specifies the total number of
d) or DEC(size, d) digits. The number of digits after the decimal parameter is specified by d parameter. The
maximum value for the size is 65, and the default value is 10. The maximum value for d is
30, and the default value is 0.
FLOAT(size, d) It is used to specify a floating-point number. Its size parameter specifies the total number
of digits. The number of digits after the decimal point is specified by d parameter.
DOUBLE(size, It is a normal size floating point number. Its size parameter specifies the total number of
d) digits. The number of digits after the decimal is specified by d parameter.
DATE It is used to specify date format YYYY-MM-DD. Its supported range is from '1000-01-01' to
'9999-12-31'.
YEAR It is used to specify a year in four-digit format. Values allowed in four-digit format from
1901 to 2155, and 0000.
TIME(fsp) It is used to specify the time format. Its format is hh:mm:ss. Its supported range is from '-
838:59:59' to '838:59:59'
TIMESTAMP(fsp) It is used to specify the timestamp. Its value is stored as the number of seconds since the
Unix epoch('1970-01-01 00:00:00' UTC). Its format is YYYY-MM-DD hh:mm:ss. Its
supported range is from '1970-01-01 00:00:01' UTC to '2038-01-09 03:14:07' UTC.
DATETIME(fsp) It is used to specify date and time combination. Its format is YYYY-MM-DD hh:mm:ss. Its
supported range is from '1000-01-01 00:00:00' to 9999-12-31 23:59:59'.
Note: These data types might vary slightly across different Database Management Systems. For example, some
formats will work in MySQL and not in MS Access. We shall use the appropriate data type based on the database
management system we are using.

205
Summary: SQL Data Definition Commands
Command or Option Description
CREATE TABLE Creates a new table in the user’s database schema
NOT NULL Ensures that a column will not have null values
UNIQUE Ensures that a column will not have duplicate values
PRIMARY KEY Defines a primary key for a table
FOREIGN KEY Defines a foreign key for a table
DEFAULT Defines a default value for a column (when no value is given)
CHECK Validates data in an attribute
ALTER TABLE Modifies a table’s definition (adds, modifies, or deletes attributes or constraints)
DROP TABLE Permanently deletes a table (and its data)
DROP INDEX Permanently deletes an index
DROP VIEW Permanently deletes a view
CREATE TABLE AS Creates a new table based on a query in the user’s database schema
CREATE INDEX Creates an index for a table
CREATE VIEW Creates a dynamic subset of rows and columns from one or more tables

2.8.3 Data Manipulation Language (DML). [INSERT, UPDATE, DELETE, SELECT]


a) Entering and updating data
− Entering Data
SQL requires the use of the INSERT command to enter data (records) into a table.
The INSERT command’s syntax
INSERT INTO TableName (Column1, Column2, …., Column)
VALUES (value1, value2, …, valuen);
For each of the listed columns, a matching value must be specified. In case no column list is specified, then a value
must be given for each column and in the same order as specified in the CREATE TABLE command.
− Character (string) and date values must be entered between apostrophes ( ’ ).
− Numerical entries are not enclosed in apostrophes.
− Attribute entries are separated by commas.
− A value is required for each column in the table.
This version of the INSERT command adds one table row at a time.
− Updating Table Rows
Use the UPDATE command to modify data in a table. To update data, you need to specify the table, column and
identify the item of data that needs updating
The UPDATE command’s syntax
UPDATE TableName
SET columnname = expression [, columnname = expression]
[WHERE conditionlist ];
[] : The part in square brackets is optional.

b) Deleting Table Rows


Deleting data is a similar process to updating data as you have to define the table and then use a selection
statement to identify the data that you want to delete.
The DELETE command’s syntax
DELETE FROM TableName
[WHERE conditionlist ];
If WHERE condition is not used in the DELETE command, then all the records from the specified table will be
deleted.

206
NOTE:
COMMIT: The SQL command that permanently saves data changes to a database (COMMIT;)
ROLLBACK: A SQL command that restores the database table contents to the condition that existed after the last
COMMIT statement (ROLLBACK;).

c) SELECT COMMAND
The SELECT statement is the MAIN DATA RETRIEVAL command in SQL. The SELECT statement is used to QUERY
and retrieve selected data.

The SELECT command’s syntax


SELECT columnlist
FROM tablelist
[WHERE conditionlist ]
[GROUP BY columnlist ]
[HAVING conditionlist ]
[ORDER BY columnlist [ASC | DESC] ];
[] : The part in square brackets is optional.

− The column list represents one or more column names separated by commas. The column list may also include
computed columns, aliases, and aggregate functions. A computed column is represented by an expression or
formula. The FROM clause contains a list of table names.
− The ORDER BY clause is used to sort the output of a SELECT statement. The ORDER BY clause can sort by one
or more columns and can use either ascending (ASC) or descending order (DESC).
− The condition list in the WHERE clause represents one or more conditional expressions separated by logical
operators (AND, OR, and NOT). The conditional expression can contain any comparison operators (=, >, <,
>=, <=, and <>) as well as special operators (BETWEEN, IS NULL, LIKE, IN, and EXISTS).
− Aggregate functions (COUNT, MIN, MAX, and AVG) are special functions that perform arithmetic computations
over a set of rows. The aggregate functions are usually used in conjunction with the GROUP BY clause to group
the output of aggregate computations by one or more attributes. The HAVING clause is used to restrict the
output of the GROUP BY clause by selecting only the aggregate rows that match a given condition.
To Select all the columns of a table, use the * instead of the column list with SELECT.

− RETRIEVING data from more than one Table


To retrieve data from multiple tables, we use the SQL JOIN Clause.
o SQL JOIN Clause.
An SQL JOIN Clause is used to combine rows from two or more tables, based on a common field between them.
SQL specifies two main types of JOIN: INNER JOIN and OUTER JOIN.
− INNER JOIN
The INNER JOIN requires each row in the two JOINED tables to have matching column values. [Returns records
that have matching values in both tables for the common field between them]
INNER JOIN
SELECT columnlist
FROM table1 INNER JOIN table2 ON table1.common_field=table2.common_field
[WHERE conditionlist ]
[GROUP BY columnlist ]
[HAVING conditionlist ]
[ORDER BY columnlist [ASC | DESC] ];

207
− OUTER JOIN
INNER JOIN eliminates the rows that do not match with a row from the other table. OUTER JOINS however,
return all rows from at least on of the tables or views mentioned in the FROM clause, as long as those rows
meet any WHERE or HAVING search conditions. All rows are retrieved from the left table reference with a
LEFT OUTER JOIN, and all rows from the right table referenced in a RIGHT OUTER JOIN. All rows from both
tables are returned in a FULL OUTER JOIN
2.8.4 Common SQL Text Manipulation Functions Along With Their Syntax And Examples
SQL provides several text manipulation functions that allow you to manipulate and transform text data within
your queries for tasks like case changes, trimming, extracting substrings, replacing text, and concatenating. Here
are some commonly used text manipulation functions along with their syntax and example code:

1. UPPER(text) - CONVERTS A STRING TO UPPERCASE

SELECT UPPER('hello') AS uppercase_text;


-- Output: HELLO
2. LOWER(text) - Converts a string to lowercase:

SELECT LOWER('WORLD') AS lowercase_text;


-- Output: world

3. TRIM(text) - Removes spaces from beginning and end of string:

SELECT TRIM(' Hello ') AS trimmed_text;


-- Output: Hello

4. LTRIM(text) - Removes spaces from left side of string:

SELECT LTRIM(' hello');


Output 'hello'
```
5. RTRIM(text) - Removes spaces from right side of string:
SELECT RTRIM('hello ');
Output 'hello'
```
6. SUBSTRING(string, start_position, length) - Extracts a portion of a string based on a specified starting
```
position and length.
SELECT SUBSTRING('Hello World', 7, 5) AS extracted_text;
-- Output: World
```
7. REPLACE(string, search_string,
``` replacement_string) - Replaces all occurrences of a specific substring
within a string with another substring.
SELECT REPLACE('Hello, World!', 'o', 'x') AS replaced_text;
-- Output: Hellx, Wxrld!
```
8. CONCAT(string1, string2,```...) - Concatenates two or more strings together:

SELECT CONCAT('Hello', ' ', 'World') AS concatenated_text;


-- Output: Hello World
```
9. LENGTH(string): Returns the length (number of characters) of a string.
```
208
SELECT LENGTH('Hello') AS text_length;
-- Output: 5
```
10. LEFT(string, length): Extracts
``` a specified number of characters from the beginning (left) of a string.

SELECT LEFT('Hello World', 5) AS left_text;


-- Output: Hello
```
```
11. RIGHT(string, length): Extracts a specified number of characters from the end (right) of a string.

SELECT RIGHT('Hello World', 5) AS right_text;


-- Output: World
```
12. REVERSE(string): Reverses the order of characters in a string.
```
SELECT REVERSE('Hello') AS reversed_text;
-- Output: olleH
```
13. INITCAP(string): Converts
``` the first character of each word in a string to uppercase and the remaining
characters to lowercase.
SELECT INITCAP('hello world') AS initcap_text;
-- Output: Hello World
```
```
These are just a few examples of SQL text manipulation functions. SQL offers many more functions that can
manipulate and transform text data according to your specific requirements. The syntax and available functions
may vary slightly depending on the specific database management system you are using.
2.8.5 Common SQL Date & Time Manipulation Functions Along With Their Syntax And Examples
Dates play a crucial role in SQL queries when dealing with temporal data. SQL provides various date and time
functions to manipulate and compare dates, extract specific components (such as year, month, or day), and
perform calculations involving dates.
1. CURRENT_DATE: Returns the current date.
Syntax: CURRENT_DATE
Example:
SELECT CURRENT_DATE AS current_date;
-- Output: 2023-08-31

2. CURRENT_TIME: Returns the current time.


Syntax:
CURRENT_TIME
Example:
SELECT CURRENT_TIME AS current_time;
-- Output: 15:30:45
3. CURRENT_TIMESTAMP: Returns the current timestamp (date and time).
Syntax:
CURRENT_TIMESTAMP
Example:
SELECT CURRENT_TIMESTAMP AS current_timestamp;
-- Output: 2023-08-31 15:30:45

209
4. EXTRACT: Extracts a specific component (year, month, day, hour, minute, etc.) from a date or timestamp.
Syntax:
EXTRACT(component FROM date)
Example:
SELECT EXTRACT(YEAR FROM '2023-08-31') AS extracted_year;
-- Output: 2023

5. DATE_ADD: Adds a specified interval to a date or timestamp.


Syntax:
DATE_ADD(date, INTERVAL value unit)
Example:
SELECT DATE_ADD('2023-08-31', INTERVAL 1 MONTH) AS new_date;
-- Output: 2023-09-30

6. DATE_SUB: Subtracts a specified interval from a date or timestamp.

Syntax: DATE_SUB(date, INTERVAL value unit)


Example:
SELECT DATE_SUB('2023-08-31', INTERVAL 1 WEEK) AS new_date;
-- Output: 2023-08-24

7. DATE_FORMAT: Formats a date or timestamp as a string using a specified format.

Syntax: DATE_FORMAT(date, format)


Example:
SELECT DATE_FORMAT('2023-08-31', '%Y-%m-%d') AS formatted_date;
-- Output: 2023-08-31

8. TIMESTAMPDIFF: Calculates the difference between two dates or timestamps in a specified unit.
Syntax:
TIMESTAMPDIFF(unit, start_date, end_date)
Example:
SELECT TIMESTAMPDIFF(DAY, '2023-08-01', '2023-08-31') AS day_difference;
-- Output: 30

9. DATE_PART: Extracts a specific component (year, month, day, hour, minute, etc.) from a date or
timestamp.
Syntax: DATE_PART('component', date)
Example:
SELECT DATE_PART('year', '2023-08-31') AS extracted_year;
-- Output: 2023

10. DATEDIFF: Calculates the difference between two dates or timestamps in a specified unit.
Syntax: DATEDIFF(unit, start_date, end_date)
Example:
SELECT DATEDIFF('hour', '2023-08-31 10:00:00', '2023-08-31 15:30:00') AS hour_difference;
-- Output: 5

11. DATEADD: Adds a specified interval to a date or timestamp.

210
Syntax:
DATEADD(interval, value, date)
Example:
SELECT DATEADD('day', 7, '2023-08-31') AS new_date;
-- Output: 2023-09-07
12. SUBDATE: Subtracts a specified number of days from a date.
Syntax:
SUBDATE(date, INTERVAL value DAY)
Example:
SELECT SUBDATE('2023-08-31', INTERVAL 7 DAY) AS new_date;
-- Output: 2023-08-24

13. NOW: Returns the current date and time.


Syntax:
NOW()
Example:
SELECT NOW() AS current_datetime;
-- Output: 2023-08-31 15:30:45

NOTE: These are just a few examples of SQL date manipulation functions. SQL offers many more functions that
can manipulate, transform, and perform calculations on date and time data according to your specific
requirements. The syntax and available functions may vary slightly depending on the specific database
management system you are using.
Application
1. Filtering Data by Date:
You can use dates to filter data based on specific time intervals, such as retrieving records within a certain date
range.
Example:
SELECT *
FROM orders
WHERE order_date >= '2023-01-01' AND order_date <= '2023-12-31';
The above query fetches all orders made between January 1, 2023, and December 31, 2023.
2. Date Arithmetic:
SQL allows performing arithmetic operations on dates, such as adding or subtracting days, months, or years from
a given date.
Example:
SELECT *
FROM employees
WHERE hire_date >= DATE_SUB(CURDATE(), INTERVAL 1 YEAR);
The above query retrieves employees hired within the last year by subtracting one year from the current date.
3. Date Formatting:
SQL allows formatting dates in different ways to present them in a desired format. This is particularly useful when
displaying dates to end-users.
Example:
SELECT order_id, DATE_FORMAT(order_date, '%Y-%m-%d') AS formatted_date
FROM orders;
The above query retrieves the order_id and formats the order_date column in the 'YYYY-MM-DD' format

211
4. Date Comparison:
Dates can be compared using comparison operators such as "=", "<", ">", "<=", ">=", "<>". This allows you to
perform queries based on date relationships.
Example:
SELECT *
FROM orders
WHERE order_date > '2023-01-01';
The above query retrieves all orders placed after January 1, 2023.
2.8.6 Subquery
In SQL, a subquery (also known as an inner query or nested query) is a query nested within another query. It
allows you to use the results of one query as a part of another query. Subqueries are enclosed within parentheses
and can be used in various parts of a SQL statement, such as the SELECT, FROM, WHERE, or HAVING clauses.
2.8.7 Wildcard Characters
Wildcard characters in SQL are special symbols that are used with the LIKE keyword to perform pattern matching
on string values. They enable you to search for specific patterns within text data. The two most commonly used
wildcard characters in SQL are the percent sign (%) and the underscore (_).
A. Percent Sign (%)
The percent sign (%) represents zero, one, or multiple characters. It can be used to match any sequence of
characters.
When used in a LIKE expression, the percent sign (%) can be placed at the beginning, end, or middle of a pattern
to represent any number of characters in that position.
For example, 'cat%' will match any string that starts with "cat" (e.g., "cat", "caterpillar", "category").
Similarly, '%cat' will match any string that ends with "cat" (e.g., "wildcat", "domesticat").
And '%cat%' will match any string that contains "cat" anywhere in the string (e.g., "scatter", "concatenate",
"catch").
B. Underscore (_)
The underscore (_) represents a single character. It can be used to match any single character in a specific position.
When used in a LIKE expression, the underscore (_) can be used to represent a single character that matches any
character.
For example, 'a_c' will match any string that has an "a" as the first character, followed by any character, and then
a "c". It can match "abc", "arc", "axc", etc.
In SQL, the percent sign (%) and underscore (_) are the most commonly used wildcard characters. However, some
database systems support additional wildcard characters that can be used for more advanced pattern matching.
It's important to note that the availability and syntax of these wildcard characters may vary depending on the
specific database system you are using. Here are a few examples of additional wildcard characters:
C. Square Brackets ([ ])
In some database systems, such as Microsoft SQL Server and PostgreSQL, square brackets can be used to define a
character range or set.
Inside the square brackets, you can specify a range of characters or a set of characters. It matches any single
character within the specified range or set.
For example, '[a-z]' matches any lowercase letter, '[0-9]' matches any digit, and '[aeiou]' matches any vowel.
D. Caret (^)
In conjunction with square brackets, the caret symbol (^) can be used to negate a character range or set.
When placed at the beginning of the square brackets, it matches any character that is not in the specified range or
set.
For example, '[^0-9]' matches any character that is not a digit.

212
E. Question Mark (?)
The question mark (?) is a wildcard character used in some database systems, such as Microsoft Access and
SQLite.
It represents a single character and can be used in a similar way to the underscore (_) wildcard.
For example, 'a?c' matches strings with an "a" as the first character, any single character in the middle, and a "c"
as the last character.
2.8.8 LIKE, IN, BETWEEN, DISTINCT & EXIST
1. LIKE
The LIKE keyword is used in SQL commands, particularly in the context of the WHERE clause, to perform pattern
matching on string values. It allows you to search for specific patterns within text data. The LIKE keyword is
typically used with wildcard characters (% and _), which represent any sequence of characters or a single
character, respectively.
Note: The exact behaviour of the LIKE keyword and wildcard characters may vary slightly depending on the
database system being used, so it's recommended to consult the documentation of your specific database for
accurate details.
Here are some common use cases for the LIKE keyword:
A. Pattern Matching
You can use the LIKE keyword to search for records that match a specific pattern. For example, you might want
to find all customers whose names start with "J".
Example:
SELECT *
FROM customers
WHERE customer_name LIKE 'J%';
This query retrieves all customers whose names begin with the letter "J".
B. Wildcard Matching:
Wildcard characters, represented by % and _, can be used with the LIKE keyword to match varying sequences of
characters. The % symbol represents zero or more characters, while the _ symbol represents a single character.
Example:
SELECT *
FROM products
WHERE product_name LIKE 'T_shirt%';
This query retrieves all products with names starting with "T_shirt", followed by any additional characters.
C. Character Matching:
The LIKE keyword can be used to match specific characters within a string. This is useful when you want to search
for records where a particular character appears at a specific position.
Example:
SELECT *
FROM employees
WHERE employee_name LIKE '_ _son';
This query retrieves all employees whose names end with "son" and have exactly two characters before "son".
D. Exclusion Matching:
The NOT LIKE keyword can be used to exclude records that match a specific pattern. This is helpful when you
want to filter out certain records from the result set.
Example:
SELECT *
FROM products
WHERE product_name NOT LIKE '%sale%';
This query retrieves all products whose names do not contain the word "sale".

213
ADVANCED PATTERN MATCHING
In addition to the LIKE keyword, SQL provides several other keywords that can be used in combination with LIKE
for more advanced pattern matching. Here are some commonly used keywords:
− NOT
The NOT keyword can be used with LIKE to negate the pattern matching condition. It retrieves records that do
not match the specified pattern.
Example:
SELECT *
FROM customers
WHERE customer_name NOT LIKE 'J%';
This query retrieves all customers whose names do not begin with the letter "J".
− REGEXP
The REGEXP keyword (or similar variations like REGEXP_LIKE or REGEXP_MATCHES, depending on the database
system) is used for regular expression pattern matching. It provides more advanced and flexible pattern matching
capabilities beyond simple wildcard matching.
− RLIKE
The RLIKE keyword is similar to REGEXP and is used for regular expression pattern matching. It is commonly
supported in databases like MySQL.
Note: It's important to note that the availability and syntax of these wildcard characters may vary depending on
the database system you are using. Therefore, it's recommended to refer to the documentation of your specific
database for accurate details on wildcard characters and their usage.
2. IN
The IN keyword is commonly used in the WHERE clause to filter rows based on specified values. Here are some
examples to illustrate the use of the IN keyword in SQL commands:
− Using IN with a List of Values:
-- Retrieve products with specific IDs
SELECT *
FROM products
WHERE product_id IN (1, 3, 5);
This query retrieves all products whose product_id is either 1, 3, or 5. It matches the rows where the product_id
column value is present in the provided list of values.
− Using IN with a Subquery:
-- Retrieve customers from specific cities
SELECT *
FROM customers
WHERE city IN (SELECT city FROM cities WHERE country = 'USA');
This query retrieves all customers whose city is present in the result of the subquery. The subquery retrieves all
cities from the "cities" table where the country is 'USA', and the main query returns customers from those cities.
− Using IN with String Values:
-- Retrieve products with specific names
SELECT *
FROM products
WHERE product_name IN ('Chair', 'Table', 'Desk');
This query retrieves all products whose product_name is either 'Chair', 'Table', or 'Desk'. It matches the rows
where the product_name column value is present in the provided list of string values.
− Using IN with NULL Values:
-- Retrieve customers with unknown or specific statuses

214
SELECT *
FROM customers
WHERE status IN ('Unknown', NULL);
This query retrieves all customers whose status is either 'Unknown' or NULL. It matches the rows where the
status column value is present in the provided list, including NULL values
3. EXISTS
In SQL, the EXISTS keyword is used to check the existence of rows returned by a subquery. It is often used in
combination with the WHERE clause to conditionally filter rows based on the result of the subquery. The EXISTS
keyword returns a Boolean value of either true or false, indicating whether the subquery returns any rows. Here
are some examples to illustrate the use of the EXISTS keyword in SQL commands:
− Using EXISTS to Filter Rows:
-- Retrieve customers who have placed orders
SELECT *
FROM customers
WHERE EXISTS (SELECT * FROM orders WHERE orders.customer_id = customers.customer_id);
This query retrieves all customers who have placed orders. The EXISTS keyword is used to check if there exists at
least one row in the "orders" table for each customer in the main query. If the subquery returns any rows, the
EXISTS condition is satisfied, and the corresponding customer is included in the result set.
− Using EXISTS with NOT to Filter Rows:
-- Retrieve customers who have not placed any orders
SELECT *
FROM customers
WHERE NOT EXISTS (SELECT * FROM orders WHERE orders.customer_id = customers.customer_id);
This query retrieves all customers who have not placed any orders. The NOT EXISTS keyword combination is used
to check if there does not exist any row in the "orders" table for each customer in the main query. If the subquery
returns no rows, the NOT EXISTS condition is satisfied, and the corresponding customer is included in the result
set.
4. BETWEEN
In SQL, the BETWEEN keyword is used to specify a range of values in a condition. It allows you to retrieve rows
where a column's value falls within a specified range, inclusive of both endpoints. The BETWEEN keyword is
commonly used in the WHERE clause to filter rows based on a range of values. Here are some examples to
illustrate the use of the BETWEEN keyword in SQL commands:
− Using BETWEEN with Numeric Values:
-- Retrieve products with prices between 1000 and 5000
SELECT *
FROM products
WHERE price BETWEEN 1000 AND 5000;
This query retrieves all products whose price falls between 1000 and 5000, inclusive. It matches the rows where
the price column value is within the specified range.
− Using BETWEEN with Date Values:
-- Retrieve orders placed between January 1, 2023, and December 31, 2023
SELECT *
FROM orders
WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31';
This query retrieves all orders that were placed between January 1, 2023, and December 31, 2023. It matches the
rows where the order_date column value is within the specified date range.
− Using BETWEEN with Character Strings:
-- Retrieve customers with names starting from 'A' to 'M'

215
SELECT *
FROM customers
WHERE name BETWEEN 'A' AND 'M';
This query retrieves all customers whose name falls alphabetically between 'A' and 'M', inclusive. It matches the
rows where the name column value is within the specified range of character strings.
− Using BETWEEN with IN clause:
-- Retrieve products with prices between 1000 and 5000 and belong to specific categories
SELECT *
FROM products
WHERE price BETWEEN 1000 AND 5000 AND category_id IN (1, 3, 5);
This query retrieves products with prices between 1000 and 5000 and belonging to specific categories
(category_id 1, 3, and 5). It combines the BETWEEN keyword with the IN clause to apply both range and category
filters.
− Using BETWEEN with NOT:
-- Retrieve customers with ages outside the range of 18 to 65
SELECT *
FROM customers
WHERE age NOT BETWEEN 18 AND 65;
This query retrieves customers whose ages fall outside the range of 18 to 65. It uses the NOT keyword with the
BETWEEN condition to exclude rows that match the specified range.
5. IS NULL
In SQL, the IS NULL keyword is used to check if a column or expression is null. It is typically used in the WHERE
clause to filter rows based on the nullity of a specific column. The IS NULL keyword returns true if the column or
expression is null and false otherwise. Here are some examples to illustrate the use of the IS NULL keyword in
SQL commands:
− Using IS NULL to Filter Null Values:
-- Retrieve customers with no email address
SELECT *
FROM customers
WHERE email IS NULL;
This query retrieves all customers who have no email address. The IS NULL keyword is used to filter rows where
the email column is null, indicating that the customer does not have an email address.
− Using IS NULL with Comparison Operators:
-- Retrieve products with no stock available
SELECT *
FROM products
WHERE stock_quantity = 0 OR stock_quantity IS NULL;
This query retrieves products that have either zero stock quantity or a null value in the stock_quantity column.
The IS NULL keyword is used to include rows where the stock_quantity column is null, indicating that the stock
information is not available.
6. DISTINCT
In SQL, the DISTINCT keyword is used to return unique or distinct values from a query result. It eliminates
duplicate rows from the result set, ensuring that each row is unique based on the specified column or columns.
The DISTINCT keyword is typically used in the SELECT statement to retrieve only unique values. Here are some
examples to illustrate the use of the DISTINCT keyword in SQL commands:
− Using DISTINCT with a Single Column:
-- Retrieve a list of unique countries from the customers table
SELECT DISTINCT country
216
FROM customers;
This query retrieves a list of unique country names from the customers table. The DISTINCT keyword is used with
the country column to eliminate duplicate country names and return only unique values.
− Using DISTINCT with Aggregate Functions:
-- Retrieve the number of unique products sold in the orders table
SELECT COUNT(DISTINCT product_id) AS unique_products
FROM orders;
This query calculates the number of unique products sold in the orders table. The DISTINCT keyword is used
within the COUNT function to count only the distinct or unique values of the product_id column.
2.8.9 SQL Aggregate Functions Along with Their Syntax and Example Code
Aggregate data refers to summarized or calculated information derived from a dataset using aggregate functions
or operations. It represents the collective or combined values of multiple individual data points. Instead of
examining each individual data point, aggregate data provides a higher-level view by grouping, summarizing, or
calculating statistics on subsets of data.
Some commonly used aggregate functions include:
− COUNT: Counts the number of records or rows in a dataset.
− SUM: Calculates the sum of numeric values in a dataset.
− AVG: Computes the average or mean value of numeric data.
− MIN: Finds the minimum value in a dataset.
− MAX: Identifies the maximum value in a dataset.
Aggregate data can be generated by grouping data based on specific criteria, such as categories, time periods, or
other relevant factors. Grouping allows for the creation of subsets or segments of data, and aggregate functions
are then applied to calculate summary values for each group.
For example, given a dataset of sales transactions, aggregate data could include total sales revenue by product
category, average sales quantity by salesperson, or minimum and maximum order values by customer. These
aggregate measures provide a consolidated view of the data, making it easier to understand trends, compare
performance, and draw conclusions.
− COUNT: Returns the number of rows in a specified column or a table.
Syntax: COUNT(column) or COUNT(*)
Example:
SELECT COUNT(*) AS total_rows FROM customers;
- This query will count the total number of rows in the customers table and assign an alias "total_rows" to the
count.
− COUNT(*) and COUNT(column)
The difference between COUNT(*) and COUNT(column) in SQL is:
COUNT(*):
− Counts total rows in the group or table, regardless of whether columns contain NULL values or not.
− Returned count includes rows where the counted column is NULL.
COUNT(column):
− Counts non-NULL values of a column in the group or table.
− Returned count does not include rows where the counted column is NULL.
Example:
SELECT department, COUNT(salary)
FROM employees
GROUP BY department;
Here count(salary) will not include rows whose salary is NULL.
The key differences are:

217
− COUNT(*) counts all rows including those with NULL values.
− COUNT(column) counts only non-NULL values of that column.
In general, for most use cases COUNT(*) is preferred as it consistently returns the count of rows in a group
including rows with NULLs in columns. COUNT(column) should only be used if we want to explicitly exclude NULL
values from the count.
− SUM: Calculates the sum of values in a specified column.
Syntax: SUM(column)
Example:
SELECT SUM(quantity) AS total_quantity FROM orders;
- This query will calculate the sum of the quantity column from the orders table and assign an alias
"total_quantity" to the summed value.

− AVG: Calculates the average of values in a specified column.


Syntax: AVG(column)
Example:
SELECT AVG(price) AS average_price FROM products;
- This query will calculate the average of the price column from the products table and assign an alias
"average_price" to the average value.

− MIN: Returns the minimum value from a specified column.


Syntax: MIN(column)
Example:
SELECT MIN(salary) AS min_salary FROM employees;
- This query will find the minimum value of the salary column from the employees table and assign an alias
"min_salary" to the minimum value.

− MAX: Returns the maximum value from a specified column.


Syntax: MAX(column)
Example:
SELECT MAX(salary) AS max_salary FROM employees;
- This query will find the maximum value of the salary column from the employees table and assign an alias
"max_salary" to the maximum value.

2.8.10 The roles of GROUP BY, ORDER BY and HAVING clauses in SQL select query with aggregate
functions
1. GROUP BY:
− Groups the result-set by one or more columns.
− Used with aggregate functions like COUNT(), SUM(), AVG() etc to perform aggregation on groups.
Examples
a..
SELECT department, COUNT(*) FROM employees
GROUP BY department;
This will count number of employees in each department.
b.
SELECT Product, Region, SUM(SalesAmount) as TotalSales
FROM Sales
GROUP BY Product, Region;
This will return a result set that shows the total sales amount for each product in each region.
2. ORDER BY:
− Sorts the results of query in ascending or descending order of the specified column(s).
218
Examples
a..
SELECT department, COUNT(*) as num_employees
FROM employees
GROUP BY department
ORDER BY num_employees DESC;
This will sort the departments in descending order of number of employees.
b..
SELECT Product, Region, SUM(SalesAmount) as TotalSales
FROM Sales
GROUP BY Product, Region
ORDER BY TotalSales DESC;
This will return a result set that shows the total sales amount for each product in each region, sorted by the total
sales amount in descending order.
3. HAVING
− Used to filter the result set based on a condition that involves an aggregate function
− Must be used along with GROUP BY.
Example
a..
SELECT department, COUNT(*) as num_employees
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;
This will return only those departments having more than 5 employees.
b..
SELECT Product, SUM(SalesAmount) as TotalSales
FROM Sales
GROUP BY Product
HAVING TotalSales > 10000;
This will return a result set that shows the products that have a total sales amount greater than 10,000.
2.8.11 Calculated Fields
A calculated field in SQL is a field that is created by performing a calculation on one or more existing fields in a
table. The calculation can be any arithmetic, logical, or string operation that produces a new value.
Calculated fields are useful for performing calculations on data without altering the original data in the table. They
can be created using various SQL functions, such as mathematical operators, string concatenation functions, and
conditional statements.
Calculated fields can be included in SELECT statements to retrieve the calculated value along with the original
data in the table. They can also be used in UPDATE statements to modify the data in a table based on a calculation.
For example, a calculated field might be used to calculate the total cost of an order, the average age of customers,
or the percentage of sales by product category.
EXAMPLES
1. SELECT statement with a calculated field:
SELECT column1, column2, column3, column4, column5 * 1.10 AS calculated_field
FROM table_name;
In the above example, we're selecting five columns from a table called "table_name", and creating a calculated
field by multiplying the value in column5 by 1.10 (i.e., adding a 10% increase). The result set will include the
original columns as well as the calculated field with the name "calculated_field".

2. UPDATE statement with a calculated field:


219
UPDATE table_name
SET column1 = column2 * 0.75
WHERE column3 = 'value';
In the above example, we're updating the values in column1 of a table called "table_name" by setting them equal
to 75% of the values in column2. We're only updating rows where the value in column3 is equal to 'value'.
3. GROUP BY statement with a calculated field:
SELECT column1, AVG(column2) AS average_column2
FROM table_name
GROUP BY column1;
In the above example, we're selecting two columns from a table called "table_name" and calculating the average
value of column2 for each unique value in column1. The result set will include one row for each unique value in
column1, along with the calculated field "average_column2".
4. JOIN statement with a calculated field:
SELECT table1.column1, table2.column2, table1.column3 * table2.column4 AS calculated_field
FROM table1 INNER JOIN table2 ON table1.column5 = table2.column5;
In the above example, we're joining two tables called "table1" and "table2" on a common column called "column5".
We're selecting three columns from the tables and creating a calculated field by multiplying the value in column3
of "table1" by the value in column4 of "table2". The result set will include the columns from both tables, as well
as the calculated field with the name "calculated_field".

OTHER EXAMPLES

1 Suppose you have a table called "orders" with columns "order_id", "customer_id", "order_date", and
"total_amount". You want to create a new column called "discounted_amount" that is equal to the total amount
minus a 10% discount. Here's how you can do it:
SELECT order_id, customer_id, order_date, total_amount, total_amount * 0.9 AS discounted_amount
FROM orders;
In the above example, the calculated field "discounted_amount" is created using the expression "total_amount *
0.9", which subtracts 10% from the total_amount column.

2 Another example is to concatenate two columns into a single field. Suppose you have a table called
"employees" with columns "first_name" and "last_name". You want to create a new column called "full_name"
that concatenates the first and last name. Here's how you can do it:
SELECT first_name, last_name, CONCAT(first_name, ' ', last_name) AS full_name
FROM employees;
In the above example, the calculated field "full_name" is created using the CONCAT function, which concatenates
the first_name and last_name columns with a space in between.
3 Suppose you have a table called "students" with columns "student_id", "name", "age", and "grade". You want
to create a new column called "pass_or_fail" that indicates whether a student has passed or failed their course
based on their grade. Students with a grade of 60 or higher will be marked as "Pass", while students with a
grade lower than 60 will be marked as "Fail". Here's how you can do it using a conditional statement:

SELECT student_id, name, age, grade,


CASE
WHEN grade >= 60 THEN 'Pass'
ELSE 'Fail'
END AS pass_or_fail
FROM students;
220
In the above example, the calculated field "pass_or_fail" is created using a CASE statement that checks each
student's grade. If the grade is greater than or equal to 60, the pass_or_fail field is set to "Pass". Otherwise, it is set
to "Fail".
Note that the keyword "CASE" starts the conditional statement, and "WHEN" specifies the condition to check.
"THEN" specifies the value to assign if the condition is true, and "ELSE" specifies the value to assign if the condition
is false. The "END" keyword ends the conditional statement.
4 Suppose you have a table called "orders" with columns "order_id", "customer_id", "order_date", and
"total_amount". You want to create a new column called "order_status" that indicates the status of each order
based on the order date and total amount. Orders that were placed more than 30 days ago and have a total
amount greater than 1000 will be marked as "High Risk". Orders that were placed more than 30 days ago but
have a total amount less than or equal to 1000 will be marked as "Medium Risk". Orders that were placed
within the last 30 days will be marked as "Low Risk". Here's how you can do it using multiple conditions:

SELECT order_id, customer_id, order_date, total_amount,


CASE
WHEN order_date < DATEADD(day, -30, GETDATE()) AND total_amount > 1000 THEN 'High Risk'
WHEN order_date < DATEADD(day, -30, GETDATE()) AND total_amount <= 1000 THEN 'Medium Risk'
ELSE 'Low Risk'
END AS order_status
FROM orders;
In the above example, the calculated field "order_status" is created using a CASE statement that checks each
order's order date and total amount. If the order was placed more than 30 days ago and has a total amount greater
than 1000, the order_status field is set to "High Risk". If the order was placed more than 30 days ago but has a
total amount less than or equal to 1000, the order_status field is set to "Medium Risk". Otherwise, the order_status
field is set to "Low Risk".
Note that the multiple conditions are separated by the keyword "WHEN", and the keyword "ELSE" specifies the
default value to assign if none of the conditions are true.

Summary: SQL Data Manipulation Commands


Command or Option or Operator Description
SELECT Selects attributes from rows in one or more tables or views
FROM Specifies the tables from which data should be retrieved
WHERE Restricts the selection of rows based on a conditional expression
GROUP BY Groups the selected rows based on one or more attributes
HAVING Restricts the selection of grouped rows based on a condition
ORDER BY Orders the selected rows based on one or more attributes
INSERT Inserts row(s) into a table
UPDATE Modifies an attribute’s values in one or more table’s rows
DELETE Deletes one or more rows from a table
Comparison operators
=, <, >, <=, >=, <>, != Used in conditional expressions
Logical operators
AND/OR/NOT Used in conditional expressions
Special operators Used in conditional expressions
BETWEEN Checks whether an attribute value is within a range
IN Checks whether an attribute value matches any value within a value list
LIKE Checks whether an attribute value matches a given string pattern
IS NULL Checks whether an attribute value is null
EXISTS Checks whether a subquery returns any rows
DISTINCT Limits values to unique values

221
Aggregate functions Used with SELECT to return mathematical summaries on columns
COUNT Returns the number of rows with non-null values for a given column
MIN Returns the minimum attribute value found in a given column
MAX Returns the maximum attribute value found in a given column
SUM Returns the sum of all values for a given column
AVG Returns the average of all values for a given column

2.9 Case Studies


1 Write the SQL Commands to implement the fully nomalized design below

FULLY NORMALIZED DESIGN


CUSTOMER(CustomerID, CustomerName, Address)
DOWNLOAD(CustomerID, MovieID, DateOfDownload)
MOVIE(MovieID, Movie_Title, Genre, Format)
MOVIEFORMAT(Format, FileType)

DDL.
𝐍𝟎 TASK COMMAND
0 Create the CREATE DATABASE MOVIES;
DATABSE
MOVIES
1 Create CREATE TABLE CUSTOMER (
CUSTOMER CustomerID int NOT NULL UNIQUE,
Relation CustomerName varchar(25) NOT NULL,
Address varchar(20),
PRIMARY KEY(CustomerID));
2 Create CREATE TABLE MOVIEFORMAT(
MOVIEFORMAT Format varchar(7) NOT NULL UNIQUE,
Relation FileType char(6) NOT NULL,
PRIMARY KEY (Format));
3 Create CREATE TABLE MOVIE(
MOVIE MovieID int NOT NULL UNIQUE,
Relation MovieTitle varchar(25) NOT NULL,
Genre varchar(15) NOT NULL,
Format varchar(7),
PRIMARY KEY (MovieID),
FOREIGN KEY (Format) REFERENCES MOVIEFORMAT(Format));
4 Create CREATE TABLE DOWNLOAD (
DOWNLOAD MovieID int NOT NULL,
Relation CustomerID int NOT NULL,
DateOfDownload date NOT NULL,
PRIMARY KEY (MovieID, CustomerID),
FOREIGN KEY (MovieID) REFERENCES MOVIE(MovieID),
FOREIGN KEY (CustomerID) REFERENCES CUSTOMER(CustomerID));

222
Relationships After Running the Commands Above On MS Access

2. The Driving Licensing Agency stores information about individuals who hold a driving license and/or own
vehicles. The following rules apply:

− Each individual may only hold one driving license.


− Each individual may own more than one vehicle.
− Each vehicle may be owned by one individual only
a. Construct the entity-relationship diagram (ERD) that shows the relationship between the individual, their
driving license, and their vehicle(s). [Showing only the entities, Relationships and Cardinalities]
When an individual applies for a driving license, they have to complete a license application form. The following
is an extract from that form:

Extract from driving license application form

Surname

First Name(s)

Mr. Mrs. Miss Ms

Other Title Male Female

Day Month Year


Date of Birth

b. Explain why Date of birth has been separated into three fields.

223
The data in the form shown above is stored in the Person table. The license application form also requires an
individual’s medical information. This is stored in a table called PersonMedical. The following extract is a sample
of the medical questions that are asked.
A sample of the medical questions asked on the license application form

Have you ever had any of any of the


following conditions? No Yes

If you answered “Yes”, please tick all the appropriate boxes

Fits or Blackouts
Repeated Attacks of Sudden Disabling Giddiness
Diabetes Controlled By Insulin

c. Explain two reasons why medical information should not be stored in the Person table
d. Outline two issues caused by storing redundant data.

a.

b.
− The order that a date is written varies by country, e.g. dd/mm/yyyy in UK, mm/dd/yyyy in US. Some dates,
such as 01 June 2018 (01/06/2018) could be confused with 06 January 2018(06/01/2018), leading to
the incorrect information being stored and consequent decisions, e.g. license expired at the wrong time
due to incorrect age. Storing days, months and years separately prevents this confusion
− Integers can be analyzed more quickly than Date/String datatypes.
− It is easier to validate separate integer fields rather than one entire data that will need to be split by
functions [The Date datatype will make validating data more difficult.]
c.
− Privacy
Having confidential data in a separate table allows that table to be only available to people with a certain
permission level. This protects people’s private medical data
d.

224
− May lead to update/deletion anomalies for example address changes may result in duplicate addresses
for different people. If the wrong address is stored and an individual is fined, the fine may go to the wrong
address.
− Storing data multiple times wastes storage space and may slow down data retrieval / data entry

3 WineForAll is a retailer that sells wine in its stores. Each store sells wine from a number of vineyards. The
following extract from the Wine file contains unnormalized data.
NameOfWine Vineyard Description UnitPrice Region StoreID StockQty
Chardonnay Stormy Bay 2015, Dry, 13 % 19000 Gisborne 1 45

Sauvignon Stormy Bay 2017, Dry, 12 % 21000 Gisborne 2 30


Blanc
Sauvignon Stormy Bay 2017, Dry, 12 % 25000 Gisborne 1 15
Blanc
Pelorus Stormy Bay 2016, Brut, 14 % 24250 Gisborne 1 24

Pinot Noir Pecan Block 2016, Fruity, 14 25600 Gisborne 3 72


%
Sauvignon Pecan Block 2017, Dry,13 % 27250 Gisborne 4 45
Blanc
Shiraz James Tree 2013, Fruity, 13.5 18500 Hawkes Bay 3 30
%
Shiraz James Tree 2013, Fruity, 13.5 19000 Hawkes Bay 2 15
%
Merlot James Tree 2014, Fruity, 14 23500 Hawkes Bay 1 10
%
Sauvignon John Glad 2016, Dry, 12.5 % 24000 Gladstone 4 15
Blanc
Chardonnay John Glad 2017, Dry, 13.5 % 23500 Gladstone 2 12

a. Define the term record.


b. Identify the steps to create a query to find the vineyards and names of fruity wines where the quantity in
stock is between 25 and 35 bottles.
c.
i. Identify the steps to create a non-persistent derived field called TotalPrice, which would hold the total
value of wine stored for each record.
d. Construct the 3rd Normal Form (3NF) of the unnormalized Wine file.

a. A record is a collection of multiple related fields that can be treated as a unit


b Alternative
SELECT Vineyard, NameOfWine SELECT Vineyard, NameOfWine
FROM Wine FROM Wine
WHERE (StockQty >= 25 AND StockQty <= 35) WHERE (StockQty BETWEEN 25 AND 35)
AND Description LIKE ‘*Fruity*’; AND Description LIKE ‘*Fruity*’;

c SELECT UnitPrice * StockQty AS TotalPrice


FROM Wine;

c SELECT UnitPrice * StockQty AS TotalPrice


225
FROM Wine;

3NF
Vineyard (Vineyard, Region)
Wine (WineID, Wine, Vineyard(FK), Year, Flavour, ABV, UnitPrice)
Stock (StoreID, WineID(FK), StockQty)
ABV: Alcohol By Volume. Description attribute wasn’t atomic. So, it has been divided into Year, Flavour and
ABV. Wine attribute represents name of wine.

3NF ---Alternative
Vineyard (Vineyard, Region)
Wine (Wine, Vineyard(FK), Year, Flavour, ABV, UnitPrice)
Stock (StoreID, Wine(FK), StockQty)

4. An estate agency makes details of the properties that it has for sale available to potential customers through a
website. The details of the properties and other data that are useful to the agency are stored in a relational
database.
The individual web pages about specific properties that a customer can view are generated dynamically by a
program from the data in the database.
A client-server system, which uses CRUD and REST, is used to provide details of properties in a web page that is
being viewed in a web browser on a client computer Figure below shows the structure of the relations in the
database.
Property(PropertyID, HouseNum, Street, Area, Postcode, Bedrooms, Bathrooms, AskingPrice, SellerID)
Seller(SellerID, Title, Forename, Surname, Telephone)
Buyer(BuyerID, Title, Forename, Surname, Telephone, DesiredArea, MinBedrooms, MaxPrice)
Viewing(BuyerID, PropertyID, ViewingDate, ViewingTime)
Sale(SaleID, PropertyID, BuyerID, SalePrice)

− The Property relation stores details of the properties that are for sale. This includes the number of bedrooms
and the number of bathrooms that a property has.
− The Seller relation stores details of people who are selling the properties.
− The Buyer relation stores details of the people who are looking to buy a property and information about the
type of property they want, including the area that they want to live in, the minimum number of bedrooms
that they need in a property and the maximum price that they are prepared to pay.
− An entry is made in the Viewing relation whenever a buyer arranges to look at a property.
− An entry is made in the Sale relation whenever a property is sold to a buyer. The SalePrice may be different to
the AskingPrice for the property.
a. A composite primary key has been selected for the Viewing relation. This consists of the attributes BuyerID,
PropertyID and ViewingDate. In selecting these attributes to form the primary key, what assumption has the
database designer made about the behaviour of the buyers?
b. Write an SQL query that will retrieve from the database the list of all properties that the buyer with BuyerID
23 might be interested in buying. The properties should:
− be in the buyer’s desired area
− have at least the minimum number of bedrooms the buyer requires
− cost no more than the maximum price that the buyer is prepared to pay.
The list of properties returned should only include, for each property, the following details:
− the PropertyID
− the street that the property is on
− the number of bedrooms that the property has
− the asking price for the property.

226
The list should be ordered with the most expensive property at the top of the list and the least expensive at the
bottom of the list .

a The database designer has assumed that the buyer will only view the same property once on a particular
day.

b SELECT PropertyID, Street, Bedrooms, AskingPrice


FROM Buyer, Property
WHERE BuyerID = 23
AND DesiredArea = Area
AND MinBedrooms <= Bedrooms
AND MaxPrice >= AskingPrice
ORDER BY AskingPrice DESC;
Alternative Solution
SELECT PropertyID, Street, Bedrooms, AskingPrice
FROM Buyer INNER JOIN Property
ON DesiredArea = Area
WHERE BuyerID = 23
AND MinBedrooms <= Bedrooms
AND MaxPrice >= AskingPrice
ORDER BY AskingPrice DESC;
Alternative Solution
SELECT PropertyID, Street, Bedrooms, AskingPrice
FROM Buyer INNER JOIN Property
ON DesiredArea = Area
AND MinBedrooms <= Bedrooms
AND MaxPrice >= AskingPrice
WHERE BuyerID = 23
ORDER BY AskingPrice DESC;
Alternative Solution
SELECT PropertyID, Street, Bedrooms, AskingPrice
FROM (SELECT DesiredArea, MinBedrooms, MaxPrice
FROM Buyer
WHERE BuyerID = 23) AS Requirements
INNER JOIN Property
WHERE DesiredArea = Area
AND MinBedrooms <= Bedrooms
AND MaxPrice >= AskingPrice
ORDER BY AskingPrice DESC;

227
5. A parcel delivery company uses a relational database to store information about the deliveries that it makes.
These details include information about each customer who sends a parcel, the individual parcels being delivered
and pricing details. The company offers three different service speeds, which are "Express", "Standard" and
"Economy". The price that is charged for delivering a parcel depends upon the service speed selected and the
weight of the parcel (to the nearest gram). For each service speed, parcel prices are split into bands for a range of
weights. For example, for the "Express" service, the price bands are as follows:

Minimum Weight (g) Maximum Weight (g) Price


0 249 1500
250 499 2500
500 999 3500
1000 4999 4500
5000 19999 5250

Similar price bands, but with different prices, exist for the "Standard" and "Economy" Services
The details are stored using the three relations shown below
Customer(CustomerID, Title, Forename, Surname)
PriceBand(ServiceSpeed, MinWeight, MaxWeight, Price)
Parcel( ParcelID, ServiceSpeed, Weight, DateSent, CustomerID, RecipientName, HouseNumber, Street, Town,
County, Postcode)

a. The price that is charged for an "Express" delivery, weighing between 1000 and 4999 grams is to be
increased to 5000. Write the SQL statements to make this update.
b. Write a query that will list all of the parcels sent by the customer whose CustomerID is 109. For each
parcel, the list should include the DateSent, the Postcode that the parcel was sent to, the ServiceSpeed that
was used and the Price charged, and no other details. The list should be presented in order, with the parcel
sent the longest time ago at the top of the list and the parcel sent most recently at the bottom.
c. The Street, Town and County parts of a recipient’s address can all be identified from the Postcode. This
means that the Parcel relation is not normalised and contains redundant data. Redesign the Parcel
relation, and create any new relations that you think are necessary, to eliminate this redundancy from the
database to produce a normalised design. Make sure that you underline the attribute(s) that make up the
primary key in each relation.
a UPDATE PriceBand
SET Price = 5000
WHERE ServiceSpeed = "Express" AND MinWeight = 1000 AND MaxWeight = 4999;

b SELECT DateSent, Postcode, ServiceSpeed, Price


FROM Parcel, PriceBand
WHERE CustomerID = 109
AND Parcel.ServiceSpeed = PriceBand.ServiceSpeed
AND Parcel.Weight >= PriceBand.MinWeight
AND Parcel.Weight <= PriceBand.MaxWeight
ORDER BY DateSent;
Alternative Solution
SELECT DateSent, Postcode, ServiceSpeed, Price
FROM Parcel INNER JOIN PriceBand ON Parcel.ServiceSpeed = PriceBand.ServiceSpeed
AND Parcel.Weight >= PriceBand.MinWeight
AND Parcel.Weight <= PriceBand.MaxWeight
WHERE CustomerID = 109
228
ORDER BY DateSent;

c Parcel(ParcelID, ServiceSpeed, Weight, DateSent, CustomerID, RecipientName, HouseNumber, Postcode)


PostcodeLookup(Postcode, Street, Town, County)

6 Marble Reading Book Stores (MRBS) is a chain of bookstores based in London. The stores want to keep
information about the books they sell, the authors of the books and the publishers they work with. The
assumptions made when the database was created were:
− A publisher can publish books from one or more authors
− An author can write one or more books.
a. Construct the entity-relationship diagram (ERD) for this scenario.
Three of the tables in the MRBS database are shown below:
Publisher
Publisher_Name City Country Telephone
Orlando Crux Melbourne Australia 6187675423
Owen Troy Taipei Taiwan 8867843525
Philip Hall Los Angeles USA 1546838382

AUTHOR
Author_Num First_Name Last_Name DOB Publisher_Name
OC80 David Gully 05/06/1974 Orlando Crux
OC89 Clint Donald 02/12/1957 Orlando Crux
OT66 Steve Leking 11/07/1989 Owen Troy
PH54 Mary West 23/12/1990 Philip Hall

BOOK
ISBN Book_Title Genre Author_Num Year_Pub
0-12763-777-1 Recipes of the East Non-Fiction PH54 2014

0-65432-187-1 Ken and his life Fiction OC89 2014


0-66655-916-2 All about the Grand Canyon Geography PH54 2012

0-76544-987-2 Tidings Fiction OT66 2015


0-87022-176-0 The fair price of life Fiction OC80 2014
0-98124-612-2 Seeking the truth Non-Fiction OT66 2016

b. Outline why data validation is difficult for the Book_Title attribute.


c. State the result from the following query:

SELECT Book_Title
FROM BOOK
WHERE Genre = "Non-fiction"
AND ISBN = '0-98124-612-2'
d. Construct a query to find the titles of the books published by “Orlando Crux”.

229
a.

b. The data type of the Book_Title attribute is String/Varchar. This does not allow many validation checks
(like range check etc.)
c. Seeking the truth.

d. SELECT Publisher.Publisher_Name, Book.Book_Title


FROM Author INNER JOIN Book ON PUBLISHER.Publisher_Name=Author.Publisher_Name, ON
Author.Author_Num = Book.Author_Num
WHERE Publisher.Publisher_Name = "Orlando Crux";

7 Armour Hardware Company has the following data about salespersons and the quantities of items sold. Each
salesperson can sell many different products.
SALES_PERSON
Product_ Unit_ Price Product_ Date_And_ Sales_ Sales_ Manager_ Manager_
Number Name Time Person_ Person_ Number Name
Number Name
19440 12500 Saw 03/07/2018 102 Owen 16 Benson
12:23:34

32456 14500 Hammer 03/07/2018


12:56:23

35647 35000 Drill 03/07/2018 199 Dahl 45 Rogers


12:35:02

67895 13250 Wrench 03/07/2018


12:49:56

98760 12250 Pliers 03/07/2018


13:23:34
230
67896 9250 Wrench 03/07/2018 154 Fraser 16 Benson
12:46:23

32456 14500 Hammer 03/07/2018


12:50:16

35647 35000 Drill 03/07/2018 234 Robert 16 Benson


12:55:09

32456 14500 Hammer 03/07/2018


12:57:12

67895 13250 Wrench 03/07/2018


13:25:36

a. Outline why the SALES_PERSON table is not in 1st Normal Form (1NF).
b. Construct the 3rd Normal Form (3NF) of the unnormalized relation shown above.
c. Outline why it is necessary to ensure that referential integrity is maintained in databases.

a. This table is not in first normal form (1NF) because there are multivalued field. These multivalued fields are
Product_Num, Pro_Name, Unit_Price and Date_and_Time

b 3NF
Product( Product_Number, Unit_Price, Product_Name)
Sales_Person (Sales_Person_Number, Sales_Person_Name, Manager_Number)
Manager (Manager_Number, Manager_Name)
Purchases (Purchase_ID, Date_And_Time, Product_Number, Sales_Person_Number)

b 3NF---Alternative
Product( Product_Number, Unit_Price, Product_Name)
Sales_Person (Sales_Person_Number, Sales_Person_Name, Manager_Number)
Manager (Manager_Number, Manager_Name)
Purchases (Date_And_Time, Product_Number, Sales_Person_Number)

c
If referential integrity is not maintained, a user can enter foreign keys that do not match the corresponding
primary key in the related table. This could cause a lot of problems such as mismatched customer data and
mismatched transaction records;
Cascading update
Referential Integrity ensures that if the primary key for a record in the Managers table changes, all corresponding
records in the Employees table are modified. This improves the data integrity
Cascading delete
Referential Integrity ensures that if a record in the Managers table is deleted, all corresponding records in the
Employees table are deleted. This improves the data integrity.

231
8 A theatrical company needs a database to handle bookings for bands. Each band has a number of members. Each
booking is for a venue. Each booking might be for one or more bands. Consider the following booking data sheet used
by the theatrical company. The data collected with the form shown below is stored in a table in the system.
Booking data sheet: 2016/023
Venue Name: Cambridge International
Theatre
Venue Address 1: Camside
Venue Address 2: CA1

Booking date: 23.06.2016

Bands booked Number of band members Headlining


ComputerKidz 5 Y
ITWizz 3 N
DeadlyDuo 2 N

a) Identify an unnormalized list of attributes using the data shown in this form. Make sure that you distinguish
between the repeating and non-repeating attributes.
b) Demonstrate the conversion of the data to first normal form (1NF). The design of two tables should be defined with
the keys identified. Give appropriate names to the tables.
c) Identify the appropriate table and demonstrate the conversion of the table to two tables in second normal form
(2NF). Explain your choice of table to modify. Explain your identification of the keys for these two new tables.
d) Identify which part of your design is not in Third Normal Form (3NF). Hence, put your design in 3NF
e) Using the appropriate datatypes, write the SQL scripts to create the tables in your normalized design. Do not at this
stage identify any keys.
f) Assuming that all tables have been created, write the SQL scripts to assign the primary key in each table and the
foreign keys in the tables.
g) Implement a relational database for the tables above using DBMS of your choice
h) Implement the relationship graph between the entities above
i) Populate the database using the data in the form.
a)
Non-Repeating Attributes: BookingID, VenueName, VenueAddress1, VenueAddress2, DateBook
Repeating Group: BandName, NumberOfMembers, Headlining
b) CONVERSION TO FIRST NORMAL FORM (1NF)
Data from the form stored in an unnormalized table

BookingID Venue Venue Venue Date Band Name Number Headlining


Name Address1 Address2 Of Members
2016/023 Cambridge Camside CA1 23.06.2016 Computer 5 Y
International Kidz
Theatre
2016/023 Cambridge Camside CA1 23.06.2016 ITWizz 3 N
International
Theatre
2016/023 Cambridge Camside CA1 23.06.2016 DeadlyDuo 2 N
International
Theatre
Data stored in an unnormalized table

The conversion to first normal form (1NF) requires splitting the data into two groups. One table contains the non-repeating
group attributes, the other the repeating group attributes. At this stage we represent the data as table definitions. Therefore,
we have to choose table names and identify a primary key for each table.
For the first table a sensible design is:

232
BOOKING(BookingID, VenueName, VenueAddress1, VenueAddress2, DateBook)
The table with the repeating group needs a compound/composite primary key and a foreign key to give a reference to the
first table. The sensible design is:
BAND-BOOKING(BandName, BookingID(fk), NumberOfMembers, Headlining)
The foreign key has been identified, with (fk).
c) CONVERSION TO SECOND NORMAL FORM (2NF)
For conversion to second normal form (2NF), the process is to examine each non-key attribute and ask if it is dependent on
both parts of the compound/composite key. Any attributes that are dependent on only one of the attributes in the compound
key must be moved out into a new table.
− BOOKING table: BOOKING (BookingID, VenueName, VenueAddress1, VenueAddress2, DateBook)
The booking table has a simple primary key therefore, it’s automatically in 2NF. There is no partial dependency.
− BAND-BOOKING table: BAND-BOOKING(BandName, BookingID(fk), NumberOfMembers, Headlining)
Functional Dependencies:
i. NumberOfMembers
• {BandName} → {NumberOfMembers}
• {BookingID} !→ {NumberOfMembers}
We see that NumberOfMembers is only dependent on BandName. NumberOfMembers is not dependent on the entire
primary key.
ii. Headlining
− {BandName, BookingID}→ { Headlining}
Headlining is thus dependent on the entire primary key.
To put the table in 2NF, we create separate tables for the fields that are not dependent on the entire primary key. The primary
key for these tables will be the part of the composite key on which those fields are dependent. We have:
Band-Booking(BandName(fk), BookingID(fk), Headlining)
Band(BandName, NumberOfMembers)
DATABASE IN 2NF: In 2NF there are now three table definitions:
BOOKING(BookingID, VenueName, VenueAddress1, VenueAddress2, DateBook)
BAND-BOOKING(BandName(fk), BookingID(fk), Headlining)
BAND(BandName, NumberOfMembers)

The Band-Booking table now has two foreign keys to provide reference to data in the other two tables.
d) CONVERSION TO THIRD NORMAL FORM (3NF)
For conversion to third normal form (3NF) each table has to be examined to see if there are any non-key dependencies; that
means we must look for any non-key attribute that is dependent on another non-key attribute. If there is, a new table must
be defined.
− BAND table: BAND(BandName, NumberOfMembers)
NumberOfMembers is the only one non-key attribute. Therefore, it is automatically in third normal form.
− BAND-BOOKING table: BAND-BOOKING(BandName(fk), BookingID(fk), Headlining)
Headlining is the only one non-key attribute. Therefore, it is automatically in third normal form.
− BOOKING table: BOOKING (BookingID, VenueName, VenueAddress1, VenueAddress2, Date)
Functional Dependencies:
i. VenueAddress1, VenueAddress2 are dependent on VenueName.
{BookingID } → { VenueName, VenueAddress1, VenueAddress2, Date}
{VenueName } → { VenueAddress1, VenueAddress2}
{BookingID } → { VenueName } → { VenueAddress1, VenueAddress2} : Transitive dependency
To put the table into 3NF, we eliminate the transitive dependency by placing the transitively dependent field in a new table
as follows
Booking(BookingID, Date, VenueName(fk))
Venue(VenueName, VenueAddress1, VenueAddress2)

DATABASE IN 3NF: In 3NF there are now four table definitions


BAND(BandName, NumberOfMembers)
BAND-BOOKING(BandName(fk), BookingID(fk), Headlining)
BOOKING(BookingID, DateBook, VenueName(fk))
VENUE(VenueName, VenueAddress1, VenueAddress2)

233
DDL.
e 𝐍𝟎 TASK COMMAND
1 BAND CREATE TABLE BAND(
BandName varchar(25) NOT NULL,
NumberOfMembers int);

2 VENUE CREATE TABLE VENUE(


VenueName varchar(25) NOT NULL,
VenueAddress1 varchar(25),
VenueAddress2 varchar(25));
3 BOOKING CREATE TABLE BOOKING(
BookingID char(8) NOT NULL,
VenueName varchar(25),
DateBook date);
4 BAND- CREATE TABLE BANDBOOKING(
BOOKING BandName varchar(25) NOT NULL,
BookingID char(8),
Headlining Boolean);
//In access use BIT to represent the Boolean data type

f 𝐍𝟎 TASK COMMAND
1 Band Table ALTER TABLE BAND
Primary Key ADD PRIMARY KEY (BandName);
2 Venue Table ALTER TABLE VENUE
Primary Key ADD PRIMARY KEY (VenueName);

3 Booking Table ALTER TABLE BOOKING


Primary Key ADD PRIMARY KEY (BookingID);

4 Booking Table ALTER TABLE BOOKING


Foreign Key ADD FOREIGN KEY (VenueName) REFERENCES VENUE(VenueName);

5 Band-Booking ALTER TABLE BANDBOOKING


Table Primary ADD PRIMARY KEY (BookingID, BandName);
Key
Band-Booking ALTER TABLE BANDBOOKING
Table Foreign ADD FOREIGN KEY (BookingID) REFERENCES BOOKING(BookingID);
Key
ALTER TABLE BANDBOOKING
ADD FOREIGN KEY (BandName) REFERENCES BAND(BandName);

234
Relationships

e) Populating the database


INSERT INTO BAND
Values(“Computer Kidz”,5);
INSERT INTO BAND
Values(“ITWizz”,3);
INSERT INTO BAND
Values(“DeadlyDuo”,2);
INSERT INTO VENUE
Values(“Cambridge International Theatre”,”Camside”,”CA1”);
INSERT INTO BOOKING
Values(“2016/023”,” Cambridge International Theatre”, ”23/03/2016”);
INSERT INTO BANDBOOKING
Values(“Computer Kidz”, ” 2016/023”, ”Yes”);
INSERT INTO BANDBOOKING
Values(“ITWizz”, ” 2016/023”, ”No”);
INSERT INTO BANDBOOKING
Values(“DeadlyDuo”, ” 2016/023”, “No”);

9 A company is building an e-commerce website. The website will display details of the products that the company
sells and allow customers to place orders. Customers must register on the website before they can place an order
and each order can be for one or more different products. The product, customer and order details will be stored
in a relational database. It was originally proposed that the following three relations were required:

Product(ProductNumber, ProductPrice, ProductDescription, QuantityInStock)


Order(OrderNumber, OrderDate, CustomerID, OrderingComputerIPAddress, ProductNumber, Quantity)
Customer(CustomerID, CustomerName, Address, Postcode, EmailAddress, PaymentCardNumber)

The computer programmer identified a problem with the Order relation and stated that it should be divided up
into two separate relations:
Order(OrderNumber, OrderDate, CustomerID, OrderingComputerIPAddress)
OrderLine(OrderNumber, ProductNumber, Quantity)

a) Describe the problem that the programmer identified with the original Order relation and explain what the
cause of this problem was.
235
b) Write Data Definition Language (DDL) statements to create all the relations, including the key field.
c) The individual web pages that describe each product will be generated dynamically using server-side
scripting. Explain what a server-side script is.
d) A web page is required that will display a summary of the products that are on a particular order. The
summary must include only the ProductNumber, ProductDescription, ProductPrice and the Quantity of the
product that has been ordered. These must be displayed in ascending order of ProductNumber. Write an SQL
query that will find the data needed to produce the order summary web page for order number 4013.
e) Implement the design above using any appropriate DBMS. Let the name of database be Business.
a Problem:
The functionality of this website indicates that a user can have many different products for a single
order. However, with the initial design of the Order relation, a user can have only a single product for
an order. Meaning with this design, if a user wants 5 products, then he has to place 5 different orders.
Any attempt to add more than one product for an order will lead to the duplication of the primary key
OrderNumber. This causes inconsistencies in the system.
The Order relation in its initial require unnecessarily complex queries due to the repeating group of
attributes
Origin:
The origin of the problem is the existence of the ProductNumber attribute in the Order relation that has
OrderNumber as its primary key. Adding many products for a single order (as expected) will
automatically make ProductNumber a repeating group. Splitting the relation normalizes it.

DDL.
b 𝐍𝟎 TASK COMMAND
1 Customer CREATE TABLE Customer (
CustomerID char(7) NOT NULL UNIQUE,
CustomerName varchar(25) NOT NULL,
Address varchar(25) NOT NULL,
Postcode char(9),
EmailAddress varchar(25),
PaymentCardNumber int NOT NULL,
PRIMARY KEY(CustomerID));

2 Product CREATE TABLE Product (


ProductNumber int NOT NULL UNIQUE,
ProductPrice int NOT NULL,
ProductDescription VARCHAR(50),
QuantityInStock int,
PRIMARY KEY(ProductNumber));
3 Order CREATE TABLE Order(
OrderNumber int NOT NULL UNIQUE,
OrderDate date,
OrderingComputerIPAddress varchar(15),
CustomerID char(7),
PRIMARY KEY (OrderNumber),
FOREIGN KEY (CustomerID) REFERENCES Customer(CustomerID));
4 OrderLine CREATE TABLE OrderLine (
OrderNumber int NOT NULL,
ProductNumber int NOT NULL,
Quantity int,
PRIMARY KEY(ProductNumber, OrderNumber),
FOREIGN KEY (OrderNumber) REFERENCES Order(OrderNumber),
FOREIGN KEY (ProductNumber) REFERENCES Product(ProductNumber));

236
c It is program code that is executed or run on the server to generate a web page which the server returns
to the client.

d SELECT ProductNumber, ProductDescription, ProductPrice, Quantity


FROM Product, OrderLine
WHERE OrderNumber = 4013 AND Product.ProductNumber = OrderLine.ProductNumber
ORDER BY ProductNumber ASC;
ALTERNATIVE SOLUTION
SELECT ProductNumber, ProductDescription, ProductPrice, Quantity
FROM Product INNERJOIN OrderLine ON Product.ProductNumber = OrderLine.ProductNumber
WHERE OrderNumber = 4013
ORDER BY ProductNumber ASC;

e CREATE DATABASE Business;

Implementation using MS Access.

Relationships After Running the Commands Above On MS Access

237
10 A company manages subscriptions to thirty different magazines. Customers can subscribe to receive one or
more of the magazines.
− Each magazine has a category such as Gardening or Current Affairs.
− Each magazine has a subscription rate, which is the cost of subscribing to receive the magazine for 12 months.
Details of the subscriptions are to be stored in a database using the following three relations:
Magazine(MagazineID, MagazineName, Category, SubscriptionRate)
Subscription(SubscriptionID, MagazineID, CustomerID, StartDate, EndDate)
Customer(CustomerID, CustomerName, Address, Postcode, TelephoneNumber)

These relations are in Third Normal Form.


a. What does this mean and why is it important that the relations in a database are in Third Normal Form?
b. Draw the Entity-Relationship diagram to show the degree of any 2 relationships that exist between the
entities.[Without Attributes, ONLY entities and relationships]
c. Write Data Definition Language (DDL) statements to create all the relations, including the key field.
d. The company wants to send letters to customers with expired subscriptions to the magazine ‘Computing Now’
to encourage them to subscribe again. The letters must be sent to all customers for this magazine whose
subscription ended before 01/06/2022. A customer’s name, address and postcode must be included in each
letter. Write an SQL query that will find the data needed to produce the letters
e. The magazine named ‘Gardening Monthly’ is to be renamed ‘Garden News’. Write the SQL statement to update
the data in the Magazine table to reflect this change.
f) Implement the design above using any appropriate DBMS. Let the name of database be Business.

a It means the relations contain no repeating groups (of attributes), there are no partial dependencies
and there are no non-key dependencies
OR
It means every attribute in the relation is dependent on the key, the whole key and nothing but the
key.
It helps to eliminate update anomalies, insertion anomalies, deletion anomalies and data
inconsistency
It helps to reduce data redundancy

b.

238
DDL.
c 𝐍𝟎 TASK COMMAND
1 Customer CREATE TABLE Customer (
CustomerID char(7) NOT NULL UNIQUE,
CustomerName varchar(25) NOT NULL,
Address varchar(25) NOT NULL,
Postcode char(9),
TelephoneNumber int NOT NULL,
PRIMARY KEY(CustomerID));
2 Magazine CREATE TABLE Magazine (
MagazineID char(4) NOT NULL UNIQUE,
MagazineName VARCHAR(15),
Category VARCHAR(15),
SubscriptionRate int,
PRIMARY KEY(MagazineID));
3 Subscription CREATE TABLE Subscription(
SubscriptionID int NOT NULL UNIQUE,
MagazineID char(4),
CustomerID char(7),
StartDate date,
EndDate date,
PRIMARY KEY (SubscriptionID),
FOREIGN KEY (MagazineID) REFERENCES Magazine (MagazineID),
FOREIGN KEY (CustomerID) REFERENCES Customer (CustomerID));

d SELECT CustomerName, Address, Postcode


FROM Magazine, Subscription, Customer
WHERE MagazineName = “Computing Now” AND EndDate < #01/06/2022#
AND Magazine.MagazineID = Subscription.MagazineID
AND Subscription.CustomerID = Customer.CustomerID;
ALTERNATIVE
SELECT CustomerName, Address, Postcode
FROM Magazine INNER JOIN Subscription ON
Magazine.MagazineID=Subscription.MagazineID INNER JOIN
Customer ON Subscription.CustomerID=Customer.CustomerID
WHERE MagazineName = “Computing Now” AND EndDate < #01/06/2022#;

e UPDATE Magazine
SET MagazineName= “Garden News”
WHERE MagazineName= “Gardening Monthly”;

239
Relationships After Running the Commands Above On MS Access
11 A library uses a database management system (DBMS) to store details of the books that it stocks, its members and the
loans that it has made. These details are stored in a database using the following three relations:
Book(BookID, Title, Author, Publisher)
Member(MemberID, Surname, Forename, HouseNumber, StreetName, Town, County, Postcode, DateOfBirth,
EmailAddress)
Loan(MemberID, BookID, LoanDate, DueBackDate, Returned)
The library does not stock more than one copy of the same book.
a) The key in the Loan relation is made up of three attributes. What is the name given to a key that is made up of multiple
attributes?
b) The library is holding a ‘meet the author’ event at which members will be able to meet the author Lucas Bailey. The
librarian wants to send e-mails to all of the library members who have read any of his books to invite them to the event.
Write an SQL query to retrieve the EmailAddress, Forename and Surname of the people to whom e-mails should be sent.
c) A new book is to be added to the library stock. The book details are:
BookID: 837023 Author: Karen Matu
Title: Kenyan Safari Publisher: African Travel Guides
Write the SQL commands that will add this book into the database
d) The system requirements have changed. The library now needs to be able to stock more than one copy of the same book.
Two different copies of the same book will have the same BookID. Explain how the database design could be modified to
meet this new requirement, whilst ensuring that the database remains normalized

a Composite key

b SELECT EmailAddress, Forename, Surname


FROM Book, Member, Loan
WHERE Author = “Lucas Bailey” AND Book.BookID=Loan.BookID
AND Member.MemberID=Loan.MemberID;
ALTERNATIVE
SELECT EmailAddress, Forename, Surname
FROM Book INNER JOIN Loan ON Book.BookID=Loan.BookID INNER JOIN Member on
Member.MemberID=Loan.MemberID
WHERE Author = “Lucas Bailey”;

240
c INSERT INTO Book
VALUES ( 837023, “Kenyan Safari”, “Karen Matu”, “African Travel Guides” );
ALTERNATIVE
INSERT INTO Book (BookID, Title, Author, Publisher)
VALUES ( 837023, “Kenyan Safari”, “Karen Matu”, “African Travel Guides” ) ;

d Principle
Create a new table (link table) called BookCopy through which Book and Loan tables will be (indirectly)
linked;
Implementation details using a new primary key
Create a new unique ID/key field (e.g. CopyID) (for each copy);
Store the BookID and the CopyID in the new table that is the BookCopy created.
Replace the BookID in the Loans table with this CopyID.
Note: In this implementation, CopyID is unique, i.e. BookID 1 and 2 cannot both have CopyID 1.
New Design
Book(BookID, Title, Author, Publisher)
Member(MemberID, Surname, Forename, HouseNumber, StreetName, Town, County, Postcode, DateOfBirth,
EmailAddress)
Loan(MemberID, CopyID, LoanDate, DueBackDate, Returned)
BookCopy(CopyID, BookID)

12 A company sells furniture to customers of its store. The store does not keep the furniture in stock. Instead, a
customer places an order at the store and the company then orders the furniture required from its suppliers.
When the ordered furniture arrives at the store a member of staff telephones or e-mails the customer to inform
them that it is ready for collection. Customers often order more than one type of furniture on the same order, for
example a sofa and two chairs.
Details of the furniture, customers and orders are to be stored in a relational database using the following four
relations:
Furniture(FurnitureID, FurnitureName, Category, Price, SupplierName)
CustomerOrder(OrderID, CustomerID, Date)
CustomerOrderLine(OrderID, FurnitureID, Quantity)
Customer(CustomerID, CustomerName, EmailAddress, TelephoneNumber)

a. Using SQL statements, do the following using any DBMS:


i. Create a database and call it SELLS
ii. In SELLS, create all the relations above
b. A fault has been identified with the product that has FurnitureID number 10765. The manager needs a list
of the names and telephone numbers of all of the customers who have purchased this item of furniture so
that they can be contacted. This list should contain no additional details and must be presented in
alphabetical order of the names of the customers. Write an SQL query that will produce the list.
c. Write an SQL query to delete from the database the faulty product with FurnitureID number 10765
d. Alter the table Customer Order to include a field called validation. The field holds a short explanatory text
for faults found in an order, or the word “NONE” if there is no fault

241
DDL.
𝐍𝟎 TASK COMMAND
0 SELLS Database CREATE DATABASE SELLS;
b 1 Customer CREATE TABLE Customer (
CustomerID varchar(6) NOT NULL UNIQUE,
CustomerName varchar(15),
EmailAddress varchar(20),
TelephoneNumber int,
PRIMARY KEY(CustomerID));

2 Furniture CREATE TABLE Furniture(


FurnitureID int NOT NULL UNIQUE,
FurnitureName varchar(15),
Category varchar(15) NOT NULL,
Price int NOT NULL,
SupplyName varchar(10),
PRIMARY KEY( FurnitureID ));
3 CustomerOrder CREATE TABLE CustomerOrder(
OrderID int NOT NULL UNIQUE,
OrderDate date,
CustomerID varchar(6),
PRIMARY KEY (OrderID),
FOREIGN KEY (CustomerID) REFERENCES Customer(CustomerID));
4 CustomerOrderLine CREATE TABLE CustomerOrderLine (
OrderID int NOT NULL,
FurnitureID int NOT NULL,
Quantity int,
PRIMARY KEY(FurnitureID, OrderID),
FOREIGN KEY (OrderID) REFERENCES CustomerOrder(OrderID),
FOREIGN KEY ( FurnitureID ) REFERENCES Furniture( FurnitureID));

Relationships After Running the Commands Above On MS Access

242
c SELECT CustomerName, TelephoneNumber
FROM Customer, CustomerOrder, CustomerOrderLine
WHERE FurnitureID=10765 AND Customer.CustomerID= CustomerOrder.CustomerID
AND CustomerOrder.OrderID= CustomerOrderLine.OrderID
ORDER BY CustomerName (ASC);
ALTERNATIVE
SELECT CustomerName, TelephoneNumber
FROM Customer INNER JOIN CustomerOrder
ON Customer.CustomerID=CustomerOrder.CustomerID INNER JOIN CustomerOrderLine ON
CustomerOrder.OrderID=CustomerOrderLine.OrderID
WHERE FurnitureID = 10765
ORDER BY CustomerName (ASC);

d DELETE FROM Furniture


WHERE FurnitureID=10765;

e ALTER TABLE CustomerOrder


ADD COLUMN Validation Varchar(35) NOT NULL DEFAULT “NONE”;
[The default statement can be executed only through the Access OLE DB. It will return an error message if used through the
Access SQL View user interface]

13 A government agency is responsible for storing information about vehicles and their owners. Each vehicle that
is driven must be registered with this agency. Vehicles must be insured to be driven, so the agency also keeps a
record of vehicle insurance policies.
Details of the vehicles, owners and insurance policies are stored in a relational database using the following three
relations:
Vehicle(RegistrationNumber, OwnerID, Manufacturer, Model, Colour, EngineSize, DateRegistered)
Owner(OwnerID, Title, Forename, Surname, HouseNumber, Street, Town, Postcode)
Insurance(PolicyNumber, RegistrationNumber, DateStarted, PolicyType, ExcessAmount)

In this system, the following restrictions apply to some attributes:


− RegistrationNumber: a mixture of exactly 7 letters and numbers, e.g. MA11FXB
− EngineSize: a whole number value representing the capacity of the engine, e.g. 1597
− PolicyType: can be either ‘Comprehensive’ or ‘Third Party’ and nothing else
− ExcessAmount: a monetary value, e.g. 100
a. Write the Data Definition Language (DDL) statements to create the relations above, including the key field.
b. The owner of the vehicle with registration number DF24JUT has had his car repainted so that its colour is now
pink. Write the SQL statement to update the data in the Vehicle table to reflect this change.
c. A police officer is following a car with registration number AB72XHC. She wants to use the computerised
system to check some details about the car and its owner. Write an SQL query that could be used to retrieve
the Model and Colour of the car and the Forename and Surname of the car’s owner
d. The database is to be extended to store information about vehicle safety certificates. Each year, a vehicle must
be taken to a garage where it will be tested. If the vehicle passes the test, a certificate will be issued. Each
certificate will have a unique Certificate Number. Certificates will last for 12 months so the date that a
certificate is issued must be recorded, as must the name of the garage that issued the certificate. The database
must keep a record of all the certificates that have been issued for each vehicle. For a particular vehicle this
will include the current certificate together with any certificates that have been issued in the past. Explain
how you would change the design of the database so that the information about safety certificates can be
stored.

243
DDL.
b 𝟎 TASK COMMAND
𝐍
1 Owner CREATE TABLE Owner (
OwnerID Varchar(6) NOT NULL UNIQUE,
Title Varchar(6),
Forename Varchar(15),
Surname Varchar(15),
HouseNumber int,
Street Varchar,
Town Varchar(15),
Postcode Varchar(8),
PRIMARY KEY(OwnerID));
2 Vehicle CREATE TABLE Vehicle(
RegistrationNumber char(7) NOT NULL UNIQUE,
OwnerID Varchar(6),
Manufacturer varchar(15),
Model varchar(10),
Colour varchar(10),
EngineSize int,
DateRegistered date,
PRIMARY KEY (RegistrationNumber),
FOREIGN KEY (OwnerID) REFERENCES Owner(OwnerID));
3 Insurance CREATE TABLE Insurance(
PolicyNumber int NOT NULL UNIQUE,
RegistrationNumber char(7),
DateStarted date,
PolicyType varchar(13),
ExcessAmount int,
PRIMARY KEY (PolicyNumber),
FOREIGN KEY (RegistrationNumber) REFERENCES Vehicle( RegistrationNumber));

Relationships After Running the Commands Above On MS Access

b UPDATE Vehicle
SET Colour = "pink"
WHERE RegistrationNumber = "DF24JUT";

244
C SELECT Model, Colour, Forename, Surname
FROM Owner, Vehicle
WHERE RegistrationNumber = "AB72XHC" AND Owner.OwnerID = Vehicle.OwnerID;
ALTERNATIVE
SELECT Model, Colour, Forename, Surname
FROM Owner INNER JOIN Vehicle ON Owner.OwnerID = Vehicle.OwnerID
WHERE RegistrationNumber = "AB72XHC";

d Create a new table called SafetyCertificates with CertificateNumber as the primary key.
Include these fields in new table: CertificateNumber, DateIssued, GarageName.
And finally Add RegistrationNumber into the new table as a foreign key to link to Vehicle table.
CREATE TABLE SafetyCertificates(
CertificateNumber int NOT NULL UNIQUE,
RegistrationNumber char(7),
DateIssued date,
GarageName Varchar(13),
PRIMARY KEY (CertificateNumber),
FOREIGN KEY (RegistrationNumber) REFERENCES Vehicle( RegistrationNumber));

14 A veterinary practice with four different surgeries intends to use a relational database to store the data that it
needs to manage its business.
Customers of the practice are pet owners who bring their pets to one of the surgeries for appointments. The
surgeries are staffed by vets.
− Each customer is identified by a unique identity number and the customer’s forename, surname and telephone
number are recorded.
− Each pet is identified by a unique identity number and the pet’s name, type and date of birth are recorded.
− Each surgery is identified uniquely by its name. The town in which it is located and the surgery’s telephone
number are recorded.
− Each vet is identified by a unique identity number and the vet’s forename and surname are recorded.
A pet is owned by one or more customers and each customer may own any number of pets. Over their lifetimes,
pets may attend many appointments.
To make an appointment for a pet, a customer contacts a surgery. The appointment is made for the pet to take
place on a particular date and time at a specific surgery.
Each vet is associated with one surgery which they work at; each surgery is staffed by several vets.
a) An entity–relationship model is to be created as the first step in a database design. Identify a list of entities.
State the attributes for each entity.
b) Draw an Entity-Relationship diagram for this database, showing ONLY entities, the degree and cardinalities
of the relationship between entities [Without Attributes, ONLY entities and relationships]
c) Develop a FULLY NORMALISED DESIGN for a relational database to store the information required by the
veterinary practice.
Use the format below to list all the relations that will need to be created, together with the attributes that each
will contain. Underline the attribute(s) that will form the entity identifier (primary key) in each relation.
Format: Entity(Attribute1, Attribute2,….,AttributeN)
d) Using the appropriate datatypes, write the SQL scripts to create the relations in your normalized design.
e) Implement a relational database called VETERINARY for the relations above using DBMS of your choice.
f) Implement the relationship graph between the entities above

245
a)
i. Entity: Pet
Attributes: PetID, PetName, Type, DateOfBirth
ii. Entity: Surgery
Attributes: SurgeryName, Town, TelephoneNumber
iii. Entity: Vet
Attributes: VetID, VetForename, VetSurname, SurgeryName
iv. Entity: Customer
Attributes: CustomerID, Forename, Surname, TelephoneNumber
v. Entity: Appointment
Attributes: PetID, Date, Time, SurgeryName

b) Identifying the relationships


The following direct relationships exist:
− Vet with Surgery
− Customer with Pet
− Pet with Appointment.
− Appointment with Surgery

Customer

Owns

Pet

Attends

N
N 1 1 N
Appointment Booked Surgery Staffed Vet

c)

i. Pet(PetID, PetName, Type, DateOfBirth)


ii. Surgery(SurgeryName, Town, TelephoneNumber)
iii. Vet(VetID, VetForename, VetSurname, SurgeryName)
iv. Customer(CustomerID, Forename, Surname, TelephoneNumber)
v. Appointment(PetID, Date, Time, SurgeryName) //or Appointment(AppointmentID, PetID, Date, Time, SurgeryName)
vi. PetOwner(CustomerID, PetID) // or PetOwner(OwnershipID, CustomerID, PetID)

246
DDL.
𝟎 TASK COMMAND
𝐍
1 Pet CREATE TABLE Pet(
PetID char(7) NOT NULL,
PetName varchar(15),
Type varchar(15),
DateOfBirth date,
PRIMARY KEY (PetID));

2 Surgery CREATE TABLE Surgery(


SurgeryName varchar(12) NOT NULL,
Town varchar(16),
STelephoneNumber int,
PRIMARY KEY (SurgeryName));

3 Vet CREATE TABLE Vet(


VetID char(7) NOT NULL,
VetForename varchar(12),
VetSurname varchar(12),
SurgeryName varchar(12),
PRIMARY KEY (VetID),
FOREIGN KEY (SurgeryName) REFERENCES Surgery(SurgeryName));

4 Customer CREATE TABLE Customer (


CustomerID char(7) NOT NULL,
CForeName varchar(15),
CSurname varchar(15),
CTelephoneNumber int,
PRIMARY KEY(CustomerID));

5 Appointment CREATE TABLE Appointment (


PetID char(7) NOT NULL,
AppDate date NOT NULL,
AppTime time NOT NULL,
SurgeryName varchar(12),
PRIMARY KEY (PetID, AppDate, AppTime),
FOREIGN KEY (SurgeryName) REFERENCES Surgery(SurgeryName),
FOREIGN KEY (PetID) REFERENCES Pet(PetID));
6 PetOwner CREATE TABLE PetOwner (
CustomerID char(7) NOT NULL,
PetID char(7) NOT NULL,
PRIMARY KEY (PetID, CustomerID),
FOREIGN KEY (PetID) REFERENCES Pet(PetID),
FOREIGN KEY (CustomerID) REFERENCES Customer(CustomerID));

f) CREATE DATABASE Veterinary;

247
g)

Relationships After Running the commands above on MS Access

15 A garage services and repairs cars. It uses a relational database to keep track of the jobs that customers have
booked for it to carry out. The database includes jobs that have been completed and jobs that are waiting to be
done. The details of the jobs that the garage does, together with the parts that it stocks and uses are stored in the
database using the four relations shown

Job (JobID, CarRegNo, JobDate, InGarage, JobDuration)


Car (CarRegNo, Make, Model, OwnerName, OwnerEmail, OwnerTelNo)
Part (PartID, Description, Price, QuantityInStock)
PartUsedForJob (JobID, PartID, QuantityUsed)

− Each car has a unique CarRegNo.


− A type of car can be uniquely identified by the combination of its Make and Model. Different Makes may use
the same Model name and a particular manufacturer (Make) will produce several different car Models.
− A booking made for a car on a particular date counts as one job, regardless of how many different tasks are
completed upon it.
− A job might require the use of any number of parts, including zero.
− Some of the details are stored in the database as soon as a booking is made and others are only added when a
job has been completed.
a) The attribute JobID is the Entity Identifier (Primary Key) of the Job relation. If the JobID attribute were not
included in the Job relation, which other attribute or attributes that are currently in the relation could
probably be used as an Entity Identifier (Primary Key) instead?
b) It has been suggested that the owner details (OwnerName, OwnerEmail, OwnerTelNo) should not be stored
in the Car relation and that a new relation should be created to store owner details separately from car details.
Explain why storing the owner details separately would improve the design of the database.

248
When an appointment is made for a job, this is represented in the Job relation. At the time of booking, the InGarage
attribute is set to False and the JobDuration attribute is set to 0:00. When the car arrives at the garage the value
of the InGarage attribute is changed to True. When the job is finished the value of the JobDuration attribute is
updated to indicate how long the job took and details of the parts used are recorded in the database.
The Job with JobID 206 has been completed. The job took 1 hour 30 minutes (1:30) and used two of the parts with
PartID 12
c) Write the SQL commands that are required to record the amount of time that the job took in the database.
d) Write the SQL commands that are required to record in the database the fact that two of the parts with
PartID 12 were used.
e) A mechanic needs to produce a list of all of the parts used on the job with JobID 93 for a customer. This list
must include the PartID, Description, Price (each) and QuantityUsed of each part, and no other details. The
parts in the list should be ordered by PartID with the parts with the lowest PartIDs nearest to the top of the
list. Write an SQL query to produce the list.

a CarRegNo AND JobDate;

b − A person may own more than one car (or a person may bring different cars to the garage) and the
owner’s information will have to be stored for each car because of the initial car relation design.
Therefore, using the initial Cars relation means that car owner’s information will be stored multiple
times. These will lead to data redundancy or unnecessary duplication of data. The modified design
reduces data redundancy
− In addition, it might be desired to store details of an owner when the car they own is not yet known.
This can’t be possible with the initial design of the Cars relation. Therefore, the need to create a
separate owner’s relation as in the new design.
− Finally, to transfer car between owners would only have to change one attribute in the car relation
with the modified design.

c INSERT INTO PartUsedForJob


VALUES (206,12,2)
ALTERNATIVE
INSERT INTO PartUsedForJob (JobID, PartID, QuantityUsed)
VALUES (206,12,2)

d SELECT PartID, Description, Price, QuantityUsed


FROM Part, PartUsedForJob
WHERE JobID = 93 AND PartUsedForJob.PartID = Part.PartID
ORDER BY PartID
ALTERNATIVE
SELECT PartID, Description, Price, QuantityUsed
FROM Part INNER JOIN PartUsedForJob ON PartUsedForJob.PartID = Part.PartID
WHERE JobID = 93
ORDER BY PartID

249
16. A council in 2018 set up a scheme to award its registered members “certificates” for any recognized efforts
they made to improve the lives of people in the community. Previously, the council registered these rewards
manually. This year, they have decided to design and implement an electronic database named “COUNCIL”.
Below is a flat file of current awards for registered members.

Member ID Name Phone Date Activity Description Assessor Email


Assessed Code LastName
012010 Ngwa Emile 673453632 21/02/2021 CU0011 Culture Sue [email protected]
14/04/2021 CR0001 Book Binding Mohammed [email protected]
131092 Ngeh Tohnain 678529888 15/04/2021 CR0001 Book Binding Mohammed [email protected]
132099 Shola Nyuyen 655523476 01/03/2021 DG0302 Digital George [email protected]
14/09/2021 CR0009 Photography Mohammed [email protected]
21/10/2021 SC0112 Public Jay [email protected]
Speaking
11/04/2021 DG0201 Animal Sue [email protected]
Welfare
145543 Nsai Polycap 654228286 12/02/2021 CU0011 Culture George [email protected]
02/06/2021 SC0112 Public Jay [email protected]
Speaking
11/07/2021 SP8701 Tree Planting Sarah [email protected]

NOTE: From observation, we notice that the table above is not in 1NF, because the Name field is not atomic
[Looking at a name like Ngwa Emile, you immediately realize we could split it into First Name “Ngwa” and Last
Name “Emile”. Then store them in separate fields] and there are repeating groups of attributes (Date assessed,
Activity code, Description, Assessor Name, and Email).
The above table can be decomposed to two tables in 1NF and represented in standard notation as shown below:
Member(MemberID, FirstName, LastName, Phone)
Certificate(MemberID, ActivityCode, AssessmentDate, Description, AssessorName, AssessorEmail)
i.
a. Write the SQL code to create the “COUNCIL” Database
b. Write the SQL code to create the Member and Certificate Tables identifying the primary key of each
c. Draw an Entity Relationship Diagram that shows the relationship “Awarded” between the Member
and Certificate tables
i. A new member (MemberID=154551, FirstName=Shu, LastName=Paul, Phone=674589346) has been
awarded a certificate. Write SQL code that will add the member in the Member table above
ii. The Member and Certificate tables above are in 1NF. Evaluate the tables and decompose them to their
Second and Third Normal Forms (2NF and 3NF). Include any useful explanations
iii. Using an appropriate DBMS, implement a relational database for the tables obtained above
iv. Implement the relationship graph between entities above.

i a CREATE DATABASE COUNCIL;


b CREATE TABLE Member (
MemberID int NOT NULL,
FirstName varchar(25),
LastName varchar(25),
Phone int,
PRIMARY KEY (MemberID));
CREATE TABLE Certificate (
MemberID int NOT NULL,
ActivityCode char(6) NOT NULL,

250
AssessmentDate date,
Description varchar(25),
AssessorName varchar(25),
AssessorEmail varchar(25),
PRIMARY KEY (MemberID, ActivityCode));

ii SQL code to INSERT new member


INSERT INTO Member (MemberID, FirstName, LastName, Phone)
VALUES(154551, “Shu”, “Paul”, 674589346);

iii. Normalization

− Second Normal Form:


Normalizing the database to 2NF involves analyzing ONE RELATION (TABLE) AT A TIME, identifying the
dependencies on that relation and normalizing the relation.
− First Relation: Member(MemberID, FirstName, LastName, Phone)
The Member relation has a single-attribute primary key, this implies it is automatically in 2NF since every field
depends on the entire primary key.
− Second Relation: Certificate(MemberID, ActivityCode, AssessmentDate, Description, AssessorName,
AssessorEmail)
The Certificate relation has a composite key, {MemberID, ActivityCode}. We shall proceed by analyzing the
dependence of each of the non key attribute. The non-key attributes are all the other attributes apart from the
primary key.
− Description is dependent on the ActivityCode but not on the MemberID. Whenever you see the code
CR0001 you find the description Book Binding. Hence there is partial dependency.
− AssessorName depends on the whole composite key. It is the surname of the assessor who accessed a
specific member for a specific award.
− The rest of the non key attributes also depend on the entire primary key.
To be in second normal form, any non-key attribute that depends upon part but not all of the primary key should
be moved to another table.
Certificate(MemberID, ActivityCode, AssessmentDate, AssessorName, AssessorEmail)
Activity(ActivityCode, Description)

251
2NF
Certificate(MemberID, ActivityCode, AssessmentDate, AssessorName, AssessorEmail)
Activity(ActivityCode, Description)
Member(MemberID, FirstName, LastName, Phone)

− Third Normal Form:

Normalizing the database to 3NF involves analyzing ONE RELATION (TABLE) AT A TIME, identifying the
dependencies on that relation and normalizing the relation.
− First Relation: Member(MemberID, FirstName, LastName, Phone)
This relation (Member) is in 3NF since there is no transitive dependence
− Second Relation: Activity(ActivityCode, Description)
This relation (Activity) is in 3NF since there is no transitive dependence
Third Relation: Certificate(MemberID, ActivityCode, AssessmentDate, AssessorName, AssessorEmail)
The Assessor Name depends upon the Assessor Email [This is arrived at by closely observing the Certificate
Relation and the data in the flat file. Whenever you find a specific assessor email, you find the same assessor name
e.g. [email protected] will always correspond to the assessor Jay]. Therefore, the non-key attribute AssessorName
depends upon the non-key attribute AssessorEmail. There is transitive dependency. We split the Certificate
relation to put it into 3NF:
Certificate(MemberID, ActivityCode, AssessmentDate, AssessorEmail)
Assessor(AssessorEmail, AssessorName)

3NF
Certificate(MemberID, ActivityCode, AssessmentDate, AssessorEmail)
Assessor(AssessorEmail, AssessorName)
Activity(ActivityCode, Description)
Member(MemberID, FirstName, LastName, Phone)

The choice of the AssessorEmail as the primary key of the Assessor relation is a bad choice as assessors can easily
change their email address from time to time. Therefore, we shall introduce a new attribute AssessorID to be the
primary key. The AssessorID will replace the AssessorEmail in the Certificate relation.

FULLY NORMALIZED DESIGN


Certificate(MemberID, ActivityCode, AssessmentDate, AssessorID)
Assessor(AssessorID, AssessorEmail, AssessorName)
Activity(ActivityCode, Description)
Member(MemberID, FirstName, LastName, Phone)

Implementation
DDL.
𝐍𝟎 TASK COMMAND
0 Create the CREATE DATABASE COUNCIL;
DATABSE
COUNCIL
1 Create CREATE TABLE Member (
Member MemberID int NOT NULL,
Relation
FirstName varchar(25),
LastName varchar(25),
Phone int,
PRIMARY KEY (MemberID));
252
2 Create CREATE TABLE Assessor (
Assessor AssessorID int NOT NULL,
Relation
AssessorEmail varchar(25) NOT NULL,
AssessorName varchar(25),
PRIMARY KEY (AssessorID));
3 Create CREATE TABLE Activity (
Activity ActivityCode varchar(25) NOT NULL,
Relation
Description varchar(25),
PRIMARY KEY (ActivityCode));
4 Create CREATE TABLE Certificate (
Certificate MemberID int NOT NULL,
Relation
ActivityCode char(6) NOT NULL,
AssessmentDate date,
AssessorID int,
PRIMARY KEY (MemberID, ActivityCode),
FOREIGN KEY(AssessorID) REFERENCES Assessor(AssessorID),
FOREIGN KEY(MemberID) REFERENCES Member(MemberID),
FOREIGN KEY(ActivityCode) REFERENCES Activity(ActivityCode));

Relationships After Running the Commands Above On MS Access

253
▪ Extra Exercises [Send me a mail in case of any difficulties or if you just want us to analyze your solution]
1. The Library of a school has just been filled with new books. The library attendant has a major problem keeping track of
the book in shelves and those on loan. A Reader in this college may have more than one book out on loan. Apart from the
Reader ID (identity), a Reader may also have the following information of obvious meaning: surname, first name, title
address, town, sex, and a Book: book ID, title, Author, publisher and DateOfPub (i.e. data of publication).
a. Describe these tables in terms of relation and attribute names.
b. From the above tables we cannot say who has which book on loan. Some possibilities include: adding fields to table,
Book or Reader, or creating a third table called Loan. Express the loan relation table as a table having only FOUR FIELDS,
two of which are the date due and date taken fields.
c. Create the table below using the DBMS software selected to complete the fields for Loan. Save and print a copy of each
table.
READER BOOK LOAN
Field Data Field Enumerated Field Data Field Field Data type Field
type size values type size size
Reader ID Text 6 BookID Text 6 Text 6
Surname Text 20 Title Text 20 Text 6
First name Text 20 Author Text 20 Date Date
DatePub Date Date Date Date
Sex Text F, M Publisher Text 20

d. Create an Entity-Relation diagram for the three entities showing the correct cardinalities.
e. Populate the tables with the following data.
BOOK
Book ID Title Author Data of Pub Publisher
Lib001 Csc7 Naty 8/6/2013 Neba printers
Lib002 Ict7 Naty 7/3/2013 Neba printers
Lib003 Csc5 Tazi 4/6/2011 Emengu
Lib004 Advanced computing Tazi 11/7/2012 Emengu
Lib005 Physical geo Cinliar 4/10/2013 Macmillan
Lib006 Econs geo Cincliar 8/7/2012 Emengu
Lib007 College math’s Mbong 2/9/2012 Anucam
Lib008 Advanced physics Newton 10/13/2010 Neba printers
Lib009 Principe of physics Nfor 7/7/2013 Two brothers
Lib010 College Math’s Nabot 2/6/2013 Oxford

READER
Reader ID Surname First Name Address Town Sex
Rd001 MATINES Jones Bp20 Limbe Male
Rd002 MALET Peters Po box 40 Limbe Male
Rd003 TEGHEN Rose Bp45 Buea Female
Rd004 NGALA Joan Bp67 Tiko Female
Rd005 TABA Malam Bp30 Ndop Male
Rd006 TAFAC Vincent Bp9 Nkwen Male
Rd007 NANFACK Georgia Bp70 Bafousam Female
Rd008 NKEMKANG John Bp80 Bafousam Male
Rd009 KAHMBANG Joshua Bp09 Tiko Male
Rd010 ABINI Beatrice Bp76 Batibo Female

254
LOAN
BookID ReaderID DateTaken Date Due
Lib001 Rd001 5/9/2013 10/9/2013
Lib003 Rd005 8/6/2012 1/3/2013
Lib004 Rd001 5/9/2013 9/9/2013
Lib002 Rd002 8/8/2013 9/10/2013
Lib006 Rd004 7/7/2012 10/8/2013
Lib005 Rd004 2/5/2013 8/6/2013
Lib008 Rd010 9/10/2013 10/15/2013
f. Create a query for each of the following
o Books on loan, using only Book ID, title, author and data taken.
o List of female readers who have at least loaned a book using only Reader ID, surname, first name, town, sex, book
title and data taken
o List of books which have been taken at least once and whose data of publication is before January 2013
2. The database system of a company has a table PC for details of its personal computers, and a table Employee for details
of its employees, with attribute names of obvious meanings. No attribute entry in table PC is unique. However, in the
Employee, the entries of EmpNo (for employee number) and UserID are unique to each employee. Table Employee also
contains details that indicate the type of personal computer(s) each employee uses. Sample entries for the tables are the
following.

Table: PC Table: Employee


PC type Processor RAM Disk Size First Last UserID EmpNo PC Processor
(GB) (TB) Name Name Type
HP Core i5 8 1 Joe Bloggs jbloggs 25 HP Core i7

HP Core i7 16 4 Mary Smith msmith 80 Lenovo Dual Core

Lenovo Dual Core 8 1

Task 1
a) Write down the SQL data types you will use to implement your tables described above.
b) Using your favourite database management system (DBMS), create the tables indicated above.
c) For each table, add two rows of data consistent with the expected column entries. They should not be copies or
permutations of the sample entries given.
TASK 2
a) Table Employee is not normalised because it has non-key details of table PC. Using your favourite database management
system (DBMS), create the tables indicated above. Add to table PC an attribute that could be used as a primary key. State
what you did.
b) Create the relation called E_PC that associates each employee with one or more machines. Clearly identify the key of this
relation.
c) Given relation E_PC. modify relations PC and Employee within your DBMS so that they are better normalised. That is, so
that they are at least in 2NF or 3NF.
3. EXAMS DATABASE
a) Create a database called EXAMS using a DBMS of your choice
b) Create a table called MARK_RECORD with two fields STUDENT_NAME and MARK. Record the marks of ten students on
the table. Marks are out of 20.

255
NO NAME SCORE
1 Tiko 3.5
2 Tambe 11.5
3 Ngum 17.25
4 Fabian 11.5
5 Ndong 9.75
6 Tata 12
7 Ayuk 13
8 Nchang 9.25
9 Ndongmo 16
10 Ibrahim 14.8
c) Create a query called SUCCESSFUL, that displays the names and marks of all students who scored a mark of 10 and
above, in order of merit. Execute this query.
d) Create another query that displays the name and mark of the student Ayuk. Execute the query.
4. SCHOOL DATABASE
Consider the following information about the attributes of the entity classes in the library database to be:
Books(ISBN*, Title, Price, AuID, PubID)
Authors(AuID*, AuName, AuPhone)
Publishers(PubID*, PubName)
Note: Starred (*) attributes are primary key fields.
a) Create a database named LIBRARY.
b) In the LIBRARY database, create the tables for corresponding entities of obvious meaning.
c) Populate the database tables with the data given below.
Book
ISBN Title Price AuID PubID
1 A Level CSC Past GCE questions 1500 1 1
2 Decipher 2500 2 2
3 O Level CSC Past GCE questions 2500 1 1
4 O Level Lab Manual 3500 2 1

Publisher Author
PubID PubName AuID AuName AuPhone
1 Univers MultiService 1 Awa 675207619
2 PresBook 2 Reginald 678199869

d) Draw the Entity-Relationship diagram for your database. Highlight only the primary keys of entities, and the relationships (and their
types) among entities
e) Create a query for each of the following. Save and print the query as well as the result from executing it. The queries are:
i. Display Title of books having price above 2000FCFA and authored by AWA
ii. Display AuID, AuName, AuPhone of authors whose books cost more than 2500 FCFA. Sort the list in ascending order by
AuName.

256

You might also like