Book 1
Book 1
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.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
Document: Used when input comes from a document and output goes
to a document.
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
− 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
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
− 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
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
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)
− 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
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
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
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).
20
Simple Test Condition
𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒 𝑉𝑎𝑟𝑖𝑎𝑏𝑙𝑒
/ /
𝐸𝑥𝑝𝑟𝑒𝑠𝑠𝑖𝑜𝑛 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’.
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]);
}
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
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
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;
}
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;
}
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;
}
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;
}
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 }
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
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
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
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
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
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.
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.
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));
}
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 𝐵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]);
}
}
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);
}
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𝑎
1. Module: “calculateDiscriminant”
4. Module: “calculateRootsComplexDifferent”
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;
}
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).
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)
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;
− 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.
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.
.
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.
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.
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 }
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.
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.
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;
}
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
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
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
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
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
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;
}
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.
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
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.
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 }
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.
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
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
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
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.
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
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):
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
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;
}
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
−𝑏 ± √𝑏 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𝑎
1. Module: “calculateDiscriminant”
4. Module: “calculateRootsComplexDifferent”
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;
}
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
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.
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.
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)
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");
}
}
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;
}
}
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;
}
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
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:
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:
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");
}
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;
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;
}
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];
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
𝑛
ℎ(𝑥) = 𝑓(𝑥)𝑔(𝑥) = ∑ 𝑐𝑘 𝑥 𝑘
𝑘=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");
}
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", °);
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}};
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.
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);
}
}
}
}
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;
}
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];
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;
}
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)
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;
}
Type
Ch1[N] = Array of Integers
Ch2[M] = Array of Integers
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"
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;
}
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
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
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.
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 }
}
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;
}
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:
1 2 3 4 5 6 7 8 9 10
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:
0 2 3 0 5 0 7 0 9 0
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
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;
}
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.
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.
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
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 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”);
}
}
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
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:
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];
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.
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"};
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.
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
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--;
}
}
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
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:
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
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
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");
}
}
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);
}
}
}
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)
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
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
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;
}
}
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,
C= C1 C2 C3 C4 C5
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
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.
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.
192
DOB
Name Gender
EMPLOYEE
Name
Gender
EMPLOYEE DOB
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.
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)
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
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
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
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.
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
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:
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
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
3NF
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
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.
202
3NF—FULLY NORMALIZED DESIGN
CUSTOMER(CustomerID, CustomerName, TownCode)
TOWN(TownCode, Town_Name)
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:
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 };
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
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 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.
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:
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
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
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
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.
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".
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:
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
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:
Surname
First Name(s)
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
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
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.
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:
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;
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
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.
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
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
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
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)
233
DDL.
e 𝐍𝟎 TASK COMMAND
1 BAND CREATE TABLE BAND(
BandName varchar(25) NOT NULL,
NumberOfMembers int);
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);
234
Relationships
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:
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));
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.
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)
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));
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
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)
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));
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);
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)
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));
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
Customer
Owns
Pet
Attends
N
N 1 1 N
Appointment Booked Surgery Staffed Vet
c)
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));
247
g)
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
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.
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.
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.
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.
250
AssessmentDate date,
Description varchar(25),
AssessorName varchar(25),
AssessorEmail varchar(25),
PRIMARY KEY (MemberID, ActivityCode));
iii. Normalization
251
2NF
Certificate(MemberID, ActivityCode, AssessmentDate, AssessorName, AssessorEmail)
Activity(ActivityCode, Description)
Member(MemberID, FirstName, LastName, Phone)
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.
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));
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.
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