Professional Documents
Culture Documents
INTRODUCTION TO SOFTWARE
SYSTEM DEVELOPMENT
Introduction 2
1
Introduction
Nowadays software embedded devices and software simulation have become very
common in engineering design work and training programmes. At work places, you
may even be in the decision making body dealing with software companies on how to
get software systems developed and deployed, what software to buy, and what to
negotiate. To make such decisions you should know what activities are being done as
software development.
A software system is the product of many different activities carried out to solve a
problem or realize an idea. This set of activities is called „Software Life Cycle‟. Since
it describes the sequence of activities for the entire lifetime of a product it is also
called „Product Life Cycle‟. A product cycle covers everything from the initial
commercial idea until the final de-installation of the product after its use.
A software process model describes the sequence of activities carried out in the
Software Life Cycle, and the relative order of these activities. Generally, a process
model provides a fixed generic framework that can be tailored to a specific project.
In the first unit, we will discuss about Software systems and their importance,
software classifications, history and features of programming languages briefly and
different program paradigms. Furthermore, basic concepts related to structured
programming and software development life cycle also are discussed.
To develop a software system to solve a problem or realize an idea, the first task you
need to do is to gather requirements and then analyse them. As you saw from the
software life cycle, design can be done after requirements are analysed and the design
is needed to code the programs. Next we discuss requirement elicitation, analysis and
modelling. These sessions will help you understand how to collect the needs from the
stakeholders to develop a successful system and the process of collecting these
different types of requirements using diverse methods. You will learn the ways to
specify these requirements in the correct way, so the system developers will develop
software that actually meets the needs of the stakeholders.
Learning Outcomes
Describe the evolution of software from inception to present
Recognize the need for a disciplined approach to software system development
Describe different approaches to determine requirements: analysis, prototyping,
simulation and modelling, human factors
Apply requirements elicitation methods to discover requirements
Design a solution for a given problem with functional design methods
2
Session 1
Software Systems for Engineers
Contents
Introduction, p 3
1.1 Importance of Software Systems, p 3
1.2. Software system, p 4
1.3 Software Classifications, p 4
1.4. Software Packages, p 9
1.5 Programming languages, p 9
1.6 Software used in Engineering, p 11
1.7 Software Licenses, p 14
Summary, p 17
Learning Outcomes:, p 17
Introduction
This session explains why a software system is very important for engineers, what are
the components of software systems, classifications of software, software packages,
and currently available popular software systems used in engineering. Another
important aspect of software is licensing. At the end of the session we will discuss
different types of licensing as it is very important when purchasing or using software.
For example, modern vehicles are designed to look very elegant and to travel in very
high speed safely with due consideration for aerodynamics and control features,
which also can be purchased at affordable price. How do engineers design and get this
type of vehicles manufactured within the required time? It is with the aid of computer-
based designing and manufacturing tools. Similarly, computer systems controlled by
software systems are playing a major role in the other fields of agriculture, civil,
electrical, communication, mechanical and textile.
3
In general, computer system includes both collections of hardware and software
systems. In this course, we discuss only about software systems. In the next session,
let us study about different components in a software system and how they are
classified.
1.2.2. Software
Software is a set of programs to perform a specific task. Software includes its
configuration programs and files.
1.2.3 Documentation
Documentation is an important part of any software system. Most of the time, it is
hard to see a software system as tangible product. It is system documentation and user
documentation that someone can see as the software product being purchased.
Software can be classified into two broad categories. They are system software and
application software which we will discuss in the next session.
4
Figure 1- 1 Relationship between user, application and system software
Operating Systems
OS is the most important software in a computer. All application software run on top
of an OS as shown in Figure 1- 2. OS manages all the resources in a computer. OS
gives facilities to communicate between hardware, system programs, and other
applications. Modern operating systems have two main user interfaces called
command line interface and Graphical User Interface.
The operating system's tasks, in the most general sense, fall into six categories:
Processor management
Memory management
5
Device management
Storage management
Application interface
User interface
Mobile OS
Mobile operating systems are used in smart phones, tablets, smart watches, or other
mobile devices to run mobile application software and programs. Mobile OS
combines features of personal computers and other features useful for mobile devices
such as touch screen, cellular, blue tooth, Wi-Fi access Wi-Fi Global Positioning
System (GPS), video, pictures, cameras, speech recognition, voice recorder, music
player, near field communication, infrared blaster etc.
Mobile devices with mobile communication contain two mobile operating systems,
one as the main OS where user is interacting with and another, a low level proprietary
real time operating system which operates the radio and other hardware.
Activity 1.1
List down three (3) different mobile operating systems and their major differences.
Device Driver
Device driver is a software program that controls hardware attached to the computer
and allows communication with OS. Hard disk, monitor, key board, and all other
hardware need device drivers to communicate with OS. All operating systems are
bundled with device drivers for most commonly used hardware. If an OS does not
have a device driver for a particular hardware, it should be installed to get the
hardware work. Communication flow between the device and the device driver, OS
and application software are shown in Figure 1- 3.
6
Firmware
Firmware is a program code that is permanently stored in a chip. Programs that are
needed to control hardware with limited amount of controls can be permanently
programmed into a programmable chip called ROM and mounted to hardware. But
now, technology of firmware has evolved from ROM to flash memory to be able to
update easily.
Interpreter
Interpreter converts each instruction of the program code to machine code. If there is
an error in an instruction, it displays when the instruction is interpreted. Relationship
of the interpreter with source code and machine code is shown in Figure 1- 4.
Compiler
Compiler converts all the instruction codes of the high-level programming language to
machine code and save it to a file. Source code is a text file which includes the high-
level program written though an editor. Compiler takes this source code as input and
analyse the source code and converts to another file which includes the machine code.
This machine code file is executable and can run on the OS without the compiler.
Compiler, source code and machine code are shown in Figure 1- 5.
Activity 1.2
Tabularise advantages and disadvantages of compilers and interpreters and write down 3
examples for each.
For example, Microsoft Visual Studio is an IDE from Microsoft. It is used to develop
computer programs for Microsoft Windows, as well as web sites, web applications
and web services. Visual Studio uses Microsoft software development platforms such
as Windows API, Windows Forms, Windows Presentation Foundation, Windows
Store and Microsoft Silverlight. It can produce both native code and managed code.
Built-in languages in Visual studio include C, C++ and C++/CLI (via Visual C++),
VB.NET (via Visual Basic .NET), C# (via Visual C#), and F# (as of Visual Studio
2010). Support for other languages such as M, Python, and Ruby among others is
available via language services installed separately. It also supports XML/XSLT,
HTML/XHTML, JavaScript and CSS.
Utility Software
Utility software is designed to help analyse, configure, optimize or maintain a
computer. For example, you may want to compress a file to let you save it on to a
flash drive. For this task you would choose to use a file compression utility program.
8
example, Ubuntu with LibreOffice and Firefox web browser. Windows with Internet
explorer web browser.
Application software market can be categorized into two types, horizontal and vertical
market application software. Horizontal market software are the most commonly used
software such as word processing, spread sheet work, presentation software, etc.
Vertical market software is application software in a specific field, developed for a
specific industry or specific field such as music, engineering, etc. It is developed and
customized to support a specific business process and targets a smaller number of
users with specific skill set and job responsibilities within an organization.
9
C language - is a very popular programming language in technical fields such as
electronic, communication, embedded systems etc. C is used to program most
microcontrollers.
It is designed with a bias for systems programming (e.g. embedded systems, operating
system kernels), with performance, efficiency and flexibility of use as its design
requirements. C++ has also been found useful in many other contexts, including
desktop applications, servers (e.g. e-commerce, web search, SQL), performance
critical applications (e.g. routers, space probes) and entertainment software, such as
video games.
Java applications are typically compiled to byte code that can run on any Java virtual
machine (JVM) regardless of computer architecture. Java was originally developed by
James Gosling at Sun Microsystem‟s (which has since merged into Oracle
Corporation) and released in 1995 as a core component of Sun Microsystems' Java
platform. The language derives much of its syntax from C and C++, but it has fewer
low-level facilities than either of them.
10
Python is supposed to be a rapidly growing open source programming language. It is
available for most operating systems, including Windows, UNIX, Linux, and Mac OS.
VisiRule - is a graphical tool for designing, developing and delivering business rule
and decision support applications, using flowcharts that represent the decision logic.
GNU Octave executes in a graphical user interface (GUI) and it works as an IDE
which includes a code editor, debugger and interpreter.
11
Scilab - is a programming language with numerical algorithms covering many aspects
of scientific computing problems.
Scilab is a free software and open source software. The software is distributed with
source code, so that the user has access to Scilab‟s most internal aspects. Users can
download and install a binary version of Scilab since the Scilab consortium provides
Windows, Linux and Mac OS executable versions.
OrCAD - is a proprietary software tool suite used primarily for electronic design
automation. This software is used mainly by electronic design engineers and
electronic technicians to create electronic schematics and electronic prints for
manufacturing printed circuit boards.
Planner – is open source project management software developed for Linux OS.
12
PSS/E (Power System Simulator for Engineering):
PSS/E is a comprehensive set of programs for study of power system transmission
network and generation performance in steady-state and dynamic conditions of
electrical power systems. The software can be utilized to facilitate calculations for
variety of analyses such as power flows, faults analysis, equivalency and switching
studies. Basically, PSS/E is very important for transmission planning in electric
utilities.
MESSAGE (Model for Energy Supply System Alternatives and their General
Environmental impacts):
MESSAGE is a software for setting up optimization models of energy supply systems
(coal, oil, gas, wind, etc.) to assess capacity expansion and energy production policies.
MESSAGE optimizes the system expansion and operation based on specified criterion
such as cost minimization and profit maximization. The software is developed by
International Institute for Applied Systems Analysis, Austria.
Simulation Software
Cisco Packet Tracer - It is a network simulation program that allows students to
create network topologies and experiment with network behavior. Packet Tracer
provides simulation, visualisation, authoring, assessment, and collaboration
capabilities and facilitates the teaching and learning of networking concepts.
GNU Radio - is also a free and open-source software development toolkit that
provides signal processing blocks to implement software radios. It can be used with
readily- available low-cost external radio frequency hardware to create software-
defined radios, or a simulation-like environment. It is used in academic and
commercial environments to support both wireless communications research and real-
world radio systems.
13
GNU Radio is licensed under the GNU General Public License (GPL) version 3.
MySQL: is an open source database management system, one of the most popular
DBMS on the web. It is reliable, fast and also flexible.
Microsoft SQL Server: Microsoft developed this relational database server. The
primary function of this software is to store and retrieve the data as requested by other
applications, whether those applications are on the same computer or running on other
computers across the network (including internet).
Software license is a document which gives legally valid guidelines for the use and
distribution of software. Software licenses are broadly categorised as closed source
and open source software. Closed source software are considered as having a
copyright.
14
Copyright begins automatically on the creation of a „work‟ without the need for
compliance with any formalities.”
First box from the right side of Figure 1- 6 is a trade secret. Second box from the right-
hand side is a Proprietary License. Next boxes are freeware/shareware/ freemium,
copyleft FOSS (Free and Open Source Software) License, permissive FOSS License
and public domain.
1.7.3 Freeware/Shareware/Freemium
Freeware – can be obtained without any fee and can be used for unlimited period.
Source code is not provided to user by the developer and ownership is kept with the
developer. Developer can change future releases from freeware to paid software.
15
Freemium – Developer offer software for free of charge without the source code but
should pay for additional features. Actually, it is a business strategy to keep customers
and sell their products.
Copyleft FOSS license
All users under this license have unlimited freedom to use, study and privatively
modify the software. GNU General Public License (GPL) is the first copyleft license.
Under the GPL license, user has freedom to redistribute the software or any
modifications to it.
Copyleft mark is
Public domain
Public-domain software has no ownership such as copyright, trademark or patent and
has been placed in the public domain. Software in the public domain can be modified,
distributed, or sold even without any attribution by anyone.
Activity 1.3
16
Table 1- 2 Comparison of software licenses
Summary
In this session we discussed characteristics and applications of different types of
software, components that an operating system consists of and different programming
languages. We further discussed software licenses and how license enables the use of
software.
Learning Outcomes:
After studying this session you should be able to,
Identify different types of programming languages, packaged
software and Integrated Developing Environments.
Describe the components of an operating system and their function
Explain the differences of Proprietary, Open source and Free
software.
Identify different type of software licenses available.
Reference
Reed, C. (2011), Computer law, OUP Oxford
17
Session 2
Evolution of Programming Paradigms
Contents
Introduction, p 18
2.1 Computer Program, p 18
2.2 History of Programming Languages, p 19
2.3 Features of High-Level Languages, p 22
2.4 Programming paradigms, p 25
Summary, p 32
Learning Outcomes:, p 32
Introduction
We give instructions to computers by means of programs. Programs translate
instructions from a human readable format to a computer readable format. In order to
develop programs, programming languages are being used. Since the evolution of
programming languages in 1940‟s, different programming languages were developed
to serve different purposes. Each language has its own special set of keywords and
syntax, which makes each programming language unique.
This session will provide some background knowledge on programming and different
paradigms of programming languages in brief. It also introduces important
characteristics of programming languages.
18
Manipulate data
Perform operations
Provide results
o Machine language
o Assembly language
o High-level language
Now, let us look at each of these categories.
19
2.2.1 Machine language
Humans do not like to deal with numbers alone, they prefer letters and words. But
strictly speaking, numbers are what machine language is. This lowest level of
language, machine language, represents information as 1s and 0s - binary digits
corresponding to the “on” and “off” electrical states in the computer.
An example of machine language is shown below;
FD 71 431F 4153
F3 63 4267 4321
96 F0 426D
F9 10 41F3 438A
47 40 40DA
47 F0 4050
When its turn comes, each instruction is fetched from main storage by the
control unit and placed in a register. Then the control unit interprets the
instruction and causes its execution by controlling the actions of the
appropriate hardware.
Some instructions prompt the control unit to switch to some other point in the
instruction sequence for the next fetch, and thereby give a mechanism for the
next selecting or repeating particular sequences of instructions.
There are five basic type of machine instruction:
20
The whole process is very time-consuming and inefficient.
Activity 2.1
21
2.3 Features of High-Level Languages
Here are a few distinct features of high-level languages;
PriceOfBook = 440
DISCOUNT_RATE = 0.2
SalesPriceOfBook = PriceOfBook – (DISCOUNT_RATE * PriceOfBook)
(calculation: Sales price is calculated after the discount is subtracted from
the actual price of the book.)
Constants
We can also use identifiers to name other things in programming languages beside
variables. Another important use for identifiers is giving names to values that remain
the same throughout a program. These values are called constants. A good example of
a value that can be used as a constant is
DISCOUNT_RATE.
22
Why do you think we need to give a name to the value for sales DISCOUNT_RATE?
Why not simply use the value 0.2? The answer is that by using constants, we can
easily modify our program to run under different conditions. For example, when
paying cash, the DISCOUNT_RATE may be .2 and when paying by credit card it
may be .15. Now whenever we need the value for the discount rate, we can use the
name DISCOUNT_RATE to refer to it.
Another advantage of using constants is that they make our programs more readable.
The identifier DISCOUNT_RATE is much more readily understood than the number
0.2.
The Table 2- 1 below compares variables and constants to highlight their different
roles.
Variables Constants
Definition A named memory location A named value
Use Value can change while a Value always remains the same while
program is running a program is running
Purpose allows data to be stored in allows programs to be easily modified
computer memory
In most programming languages, identifiers are required to conform to a certain
format. For example, the identifiers in this session all began with letters and were
composed only of letters and numbers. None of the identifiers included spaces, and
constants were written in UPPERCASE letters. This is a typical format for identifiers.
Assignment
How do we tell the computer the value, that a variable or a constant contain should be
represented? This is accomplished through the assignment operation.
In many high-level languages like C++ and Java, the assignment operation is done by
placing an equal sign between a value and a variable. On the left side of the
assignment operator is the name of a variable or constant while the right side has the
value to be assigned.
PriceOfBook = 440
In some other languages like Pascal, the assignment operator is a colon with an equal
sign like this:
DISCOUNT_RATE := 0.2
23
Expressions
Expressions are mathematical combinations of numbers, variables, and constants.
Usually the result of an expression is stored in another variable. You can think of
expressions as being very similar to equations in mathematics. A typical equation
might look like this:
SalesPriceOfBook = PriceOfBook – (DISCOUNT_RATE * PriceOfBook)
What happens when we try to construct a longer expression like the following one?
Result = 8 +10/2 – 3*3
How do we know which operations in the expression to calculate first? The answer to
this question is solved by the rules of operator precedence in a programming language.
These rules define which operations must be performed first. In mathematics, the
multiplication and division operations are performed first and then addition and
subtraction are performed. Using this rule, the value stored in result would be 3.
Result = 8 + 5 – 9
= 13 -9
=4
However, we can change the order of operations by enclosing a part of the expression
in parentheses like this;
Result = (8+10)/2 – 3*3
=9–9
=0
The parentheses tell us to compute the value of (8+ 10) before we perform the
division by 2. With this change, the value stored in result is now 0. By using
parentheses, we can override the normal order of operations in our expressions.
Boolean Expressions
We can also have expressions that represent values which are either true or false.
These expressions are called Boolean expressions. Usually such expressions involve
the comparison of values with the following operators: > (greater than), < (less than),
and = (equals). For example, consider the following three Boolean expressions:
5>7 5>5 5 == 7 5<7
24
Without knowing the value of the variable count we cannot determine the value of the
Boolean expression. Quite often an expression like this is used to control a repetitive
action. Each time the action is performed, the value of count increases until the
expression eventually becomes false. We will see more about this kind of control in a
later session.
Boolean expressions can be joined together to form longer expressions using three
logical operators: AND, OR, and NOT. Suppose we want to test our count variable to
determine if the count is between 0 and 50. We can write a Boolean expression using
the AND operator to do this.
(Count > 0) AND (Count < 50)
Activity 2. 2
2.4.1 Paradigm
Long ago, people thought that the center of the universe is earth, but later people
knew earth is not the center of universe and learned the solar system. Earth centered
concept is one paradigm and solar system concept is another paradigm. Here, the earth
centered paradigm is shifted to solar system paradigm. Paradigm is a set of theories,
25
perceptions, concepts, and practices within the community about a subject at a
particular time. It is a set of generally accepted scientific achievements and models
that defines how to look problems and how to solve them. After some time,
community starts to criticize it and emerge a new paradigm. This process is called
paradigm shift. This shifting takes long time because minds, concepts, attitude of
people need to be change with understanding drawbacks of exiting system. In the
above example, paradigm shift from earth centered to solar system paradigm.
Likewise, programing also has a lot of paradigm and their shifts.
For example in C, following program has 3 commands, first print “Welcome” next
command is print “to” and finally, next command is print “C”.
#include<stdio.h>
int main()
{
printf("Welcome\n");
printf("to\n");
printf("C\n");
return 0;
}
26
Usually, in this paradigm, commands can be grouped and a name can be given for the
group. This is called sub program or sub routine. For example, if a program needs 2
delays for different times, we can write a delay subroutine (sub group) and can send
needed time.
void delay(int x)
{
int i;
for(i=1; i <=x; i++);
printf("Delay is %d\n", x);
}
int main(void)
{
delay(2);
delay(100);
return 0;
}
Another feature is the variable and value of the variable located in a memory location.
Values of the variable can be changed by the user.
There are many programming languages under the imperative programming paradigm
such as C, Pascal etc.
Here, “r” is an independent variable and “c” is dependent on “r”. 2 and are
constants. “c” depends only on the “r”. We cannot change “c” as we want.
In imperative paradigm, output variable of a function can be changed explicitly but in
functional programming paradigm, output cannot be changed explicitly.
Another feature of functional programming is abstraction. Abstraction is hiding the
inside implementation details codes. This can be reused in another place.
27
is_bigger(X, Y) :- bigger(X, Y).
is_bigger(X, Y) :- bigger(X, Z), is_bigger(Z, Y).
For example, SQL command to retrieve registration number and name of the students
in the student table is as follows
SELECT st_reg_no, st_name FROM student;
28
NoSQL
NoSQL is used to manage document-oriented databases. Collection of NoSQL is
29
2.4.4 Object Oriented programming (OOP) paradigm
Object oriented programming paradigm is derived from imperative paradigm and
OOP concepts. OOP concept is writing computer programs considering objects and
their relationships. For example, a car is manufactured by combining several relevant
components such as engine, gear box, wheels, lights and many more. And it has
several actions such as going, turning, accelerating, decelerating, breaking etc. These
components are called attributes and actions are called methods. Template for an
object in a program is called class.
Following picture shows a class called „person‟. Its attributes are name, surname, birth
date, address, telephone, and email. It has only one method named age(). It converts
the date of birth entered into age.
Following python program described the how to program the class Person, its
attributes and the method age().
30
2.4.5 Parallel Programming
In current market, processors of smart phones and computers include more than one
core, usually, five (5) or more. These cores can process programs separately and in
parallel. Running programs simultaneously with multi-processor has less processing
time than running programs with single processor. You can see the difference of
processing time, by comparing time to process with multi processors, and time to
process with single processor. According to the figure 2- 4, the time to call the
function f() 4 times with multi-processor is, and with
single processor is, .
Activity 2.3
List down different types of programming paradigms and give examples for each.
31
Summary
In this session we discussed the evolution of programming languages from the
inception, different paradigms of programming languages and the features of high-
level languages.
A programming language is the key to communicating with the computer and it has
certain definite characteristics. It has a limited vocabulary or a set of keywords. Each
keyword has a precise meaning. There is also a set of rules or syntax to organize the
instructions in a program. Even though a programming language is limited in
keywords, it can still be used, in step-by-step fashion, to solve complex problems.
Learning Outcomes:
After studying this session you should be able to,
Describe evolution of programming languages from machine
language to high level languages
Explain features of high-level languages like identifiers, variable,
constants, assignment and expressions
Identify different types of programming paradigms
32
Session 3
Introduction to Software Engineering
Contents
Introduction, p 33
3.1 Software and Software Engineering, p 33
3.2 The Product Life-Cycle, p 34
3.3 Hardware/Software Differences, p 35
3.4 The Software Life-Cycle, p 36
3.5 Verification and validation, p 38
3.6 Requirement Elicitation, p 38
3.7 Stages of the Software life cycle, p 39
3.8 Waterfall Life Cycle Model, p 40
3.9 Prototyping, p 43
Summary, p 43
Learning Outcomes:, p 44
Introduction
In this session you will be exploring how the term „software engineering‟ emerged
and learn the phases in software life cycle. You will also see the differences between
hardware and software.
The institute of Electrical and Electronics Engineers Inc. (IEEE), in its standard
610.12-1990, defines software as “computer programs, procedures, and possibly
associated documentation and data pertaining to the operation of a computer system”.
33
What we all know is, that a software system is made to solve a certain problem.
Making software therefore begins with understanding the problem and then designing
and constructing the software system to solve the problem.
Low level design: Each main element is broken down into its basic
components. Their functional requirements and quality
requirements are also defined relative to the requirements for the
element or subsystem. Depending on the size and complexity of the
product being designed, there may be many levels of design. The
process of breaking a complex system down progressively into
34
smaller chunks is referred to as hierarchical decomposition. At the
lowest level of design, the specified components are simple enough
to be manufactured or bought in from an outside supplier without
further design work.
It is clear to see that the above life-cycle describes quite well what happens when a
new car is designed and manufactured though the actual sequence of events may vary.
A life-cycle should be regarded as a conceptual model of the process of development
and manufacturing, rather than a fixed sequence of events that must be followed. It is
an abstraction of the real process, and is useful as a tool for reasoning, in order to
plan, estimate resources, and measure the progress.
35
The process of developing software consists of a series of
transformations of the design into more detailed representations
until executable code is obtained. Many copies can then be made
and released to customers. But the copying process is not the
equivalent of hardware manufacture since for all practical purpose
it is perfect, and yields identical copies. (An exception to this could
be the inclusion of an incorrect version of a module.) In this sense,
every software product is a prototype. It is only made once, even
though many copies can be distributed.
Typically, when a hardware component breaks, the system goes
down and ceases to work until it has been repaired. Corrective
maintenance of hardware usually consists of replacing a worn or
broken part with a new part, and this restores the system to its
previous working state.
Hardware maintenance requires the movement of resource persons
and materials. Either the machine must be brought to a workshop,
as when a car is taken to a garage, or service staff must visit the
machine, as when a thermostat in an air-conditioning system needs
to be replaced.
Most of them include the following stages, however, although the order in which they
are carried out may vary:
36
Concept and feasibility: Identify a marketing opportunity, or an
organisational need. On the basis of an outline of the requirements
and a first estimate of the resources needed to develop such a
system, can assess if it should be built.
Activity 3.1
37
3.5 Verification and validation
During the development of a software system (as for any other product), the manager
must continually make measurements to assure that the end product will perform as
required.
The quality of software is another vital factor, where software may perform correctly
but not satisfactorily due to environmental factors such as complex data structure
manipulation, voluminous sorts and communication hangs-ups.
However, it is possible that the requirement specification is less than perfect. Either
requirements capture failed to capture the real world requirements of the customer, or
the requirement specification did not accurately represent these. In this case, we might
end up delivering a product which has been verified as being correct all the way
through the life cycle, but which fails in operation because it does not do what the
customers requires or reasonably expects.
Therefore, Validation requires that the system undergoes a trial: a period of operation
under conditions which are as close as possible to those it will encounter in live use.
The actual staff from the customer's organisation must operate it and the workload
must be as heavy as the worst case likely to be experienced. This is the only way we
can ascertain that software products will work as expected when exposed to reality.
38
3.7 Stages of the Software life cycle
The classic lifecycle is divided in to four major stages as illustrated in Figure 3- 1.
3.7.1 Analysis
Analysis phase includes investigation of the current system in i.e. the problem domain,
to find out the requirements of the proposed system, and whether it is feasible to
implement a solution to satisfy the identified requirements. In this investigative
process (see Figure 3- 2) current bottlenecks, constraints and performance statistics
would be made known.
3.7.2 Design
The next phase is the design of the proposed system. Where the analysis of the
problem domain is best undertaken by a business consultant with the knowledge of
the application area concerned, the design process is best undertaken by a systems
analyst with expertise in design, building and implementing in computer based
information systems.
The system specification document is usually the basis of the contract undertaken to
build the system as per the requirement specification. Thus, it is an extremely
39
important document, encompassing the software and hardware architecture, the
database and data structures proposed and the procedures for manipulating the
database in order to produce the required output.
The design process, in fact, as Figure 3- 3 illustrates, translates the user requirements
into system components which interact to provide these requirements. As in any
architectural procedure, the system specification is the precise document of the design
process and is the basis of the construction phase. It is, therefore, a vital component of
the software configuration of the system. Each component identified by the
specification can be estimated in terms of resource requirement for building it or in
terms of purchase finance, and the entire system can be budgeted for both its hardware
and software components. The design document is written in a natural language but is
accompanied by a variety of graphical forms, such as a structure charts/flow diagrams,
screen and report designs/formats. Sometimes the design may be expressed in a
design language, particularly where reverse engineering is envisaged.
When all the modules have been compiled error free and tested individually and
comprehensively on test data beds, the modules are interlinked and a series of system
test are performed.
40
the waterfall life cycle model can start only after all tasks in the previous phase are
complete. The waterfall life cycle model assumes that activities of a previous phase
need not be repeated after the next phase starts.
Early software developers did not develop software using life cycle models. In the
first few years, software development was essentially seen as a „programming' activity
followed by the 'implementation' activity, with other tasks seen as an extension of the
programming and implementation.
Phases in the Waterfall life cycle model can be briefly described as follows:
Requirements is the phase where the 'what' of the software system
is defined. It involves extensive user participation to gather user
requirements and ends with an approved set of requirements
documented in a Software Requirements Specifications (SRS)
document. These Software Requirements Specifications form the
basis of all further work in the project.
41
wants and the code that will be created to satisfy the requirements.
Some versions of the waterfall life cycle model split the design
phase into architectural design and detailed design phases.
The code that is developed is tested during the testing phase. This
involves unit testing for the lowest level components, integration
testing for groups of components and testing of the system as a
whole. The last activity in testing is usually that of acceptance
testing. Acceptance testing validates that the system fulfills the
'user's needs' and requires considerable user involvement.
42
The assumption that all requirements have to be known at the
beginning in sufficient detail leads to premature decisions.
The waterfall life cycle model is essentially inflexible. It assumes
that software creation activities can be compartmentalized.
3.9 Prototyping
Prototyping is a software engineering technique that has asserted itself very rapidly,
mainly due to the increasing costs of software maintenance. It is a way of ensuring
that the specification and design model are correct before construction which
procedure generally assists in ironing out any incompatibilities between requirements
and the deliverables. The prototype serves as the “initial test system”.
Design for prototyping ignores the functions, internal procedures involved and
focuses instead on top-level architectural structure and on data analysis and design.
Activity 3.2
Summary
In this session we discussed that developing software involves many activities in
addition to coding programs and how software development has been transformed
into an engineering discipline.
43
The classic model of the conventional system engineering cycle has a sequential flow
of phases such as requirement elicitation, requirement analysis, design, coding, testing
and maintenance. This sequential flow has given rise to many problems when
developing software.
After reading this session you should be able to achieve the following outcomes.
Learning Outcomes:
On completion of this session, the learners will be able to,
recognize the need for a disciplined approach to software system
development
identify the key attributes of a software product
describe the software life-cycle
explain the importance of prototyping in software development
44
Session 4
Requirement Elicitation and Documentation
Contents
Introduction, p 45
4.1 Requirements Elicitation, p 45
4.2 Resolving Ambiguities, Platitudes and Omissions, p 47
4.3 How to Resolve Functional and Non-functional Requirements?, p 49
Summary, p 51
Learning Outcomes, p 51
Review Questions, p 52
Introduction
In the software development process the first step is to conduct a feasibility study to
see whether it is really worth developing a new system. We will not discuss feasibility
study in this course. If it is decided to develop a new system after a feasibility study,
the next step is to gather requirements from the stakeholders of the software system.
In this session, we will first discuss different methods of requirement elicitation and
resolving ambiguities, platitude, and omissions in the gathered requirements. Then,
we will differentiate requirements to be functional or non-functional. Finally, you will
see the factors that needed to be considered when making a requirement document. A
requirement document is mainly read by managers, clients and system end-users.
45
Let us now discuss few elicitation methods which are based on commonly accepted
social activities and behaviours.
Use of focus groups: Focus groups are similar to interviews, but with a carefully
selected smaller group of stakeholders. Here, the analyst sets a topic of interest and
lets the group discuss it openly. An important factor in the success of focus groups is
the choice of participants. The analyst must take into consideration the positions of
the participants within the organization, their authorities and abilities to discuss
matters of concern.
During the development of a software prototype, design decisions are often made
early in the software development process, and considerable effort from the software
developers are required. However, a "throw-away" prototype (designed to be
discarded after use), can be used, with care, to validate some functionalities of the
software system. One disadvantage is that, users may draw incorrect conclusions
about other characteristics of the software, based on their evaluation of the prototype
presented to them. Hence the exact purpose of the use of the prototype needs to be
clearly established and understood by both the software developer and the users.
Animation: During animation, features of the software that are difficult to specify are
"role-played" by human beings. Animation has been proposed to resolve some of the
problems associated with software prototype, and specially to reduce their
46
development effort. Since animation emphasizes the effects and the relationships
between processes, instead of how the results are achieved, it is more appropriate for
early requirements elicitation purpose.
Scenario analysis: Used together with prototyping and animation, scenario analysis
allows the software developer to investigate system responses to various conditions.
The user is required to answer when scenarios are given in "IF condition THEN
response" manner. In this way the user has to elicit the behaviours of the system in
specific situations. By appropriate choice of scenarios, the functional requirements of
the software can be comprehensively identified.
Introspection: In this process, the software developer imagines the tasks that the
system would perform. Though introspection has obvious limitations, it is can be
used when there are software features that the user may have little experience with,
such as the user interface. Prototypes can be used for validation of such assumed
features.
Functional requirements are basically the service that the proposed system should
provide whereas non-functional requirements are the concerns of the system
properties such as reliability, storage occupancy and response time. The requirement
document contains both functional and non-functional requirements, so let us see how
we can differentiate them in the next section.
KGF Requirements
Kumudu Garage Follow-up (KGF) system will keep records of customers and their vehicles.
It will send reminders to customers whose vehicles are due for a service in the following
week. When a vehicle is booked in for servicing, it will print a job sheet for the mechanic,
describing the work to be done. When the job is completed, the time spent and the prices of
the spare parts fitted will be added up and an invoice will be sent to the customer. At the end
of the month, it will print a list of all unpaid invoices, and reminders to be posted to all
customers whose invoices have not been paid for some time.
The prices of spare parts will be taken from the garage's existing stock control
database, which is not actually a part of KGF, though it will need to be updated when
spares are taken out of the stores. KGF must run on the garage's existing personal
computer, which is networked with the stock control database, and it must be easy to
use.
47
End of KGF Requirements
Any requirement document made by the user or the business analyst may contain
ambiguities and platitudes. There could be omissions as well. Usually, functional
requirements are mixed up with various types of non-functional requirements. What
questions would you (as the developer of KGF) ask in order to clarify the
requirements?
Here you have been given a suggested set of general questions that should always be
asked. You have also been given certain categories of things that can be wrong with a
requirement definition, which should prompt more specific questions.
Clarify platitudes
1. What does "easy to use" mean? No staff training required. Use of menus, help
screens, etc.
2. What customer data are stored? Name, address, customer number, phone
numbers, etc.
3. What vehicle data are stored? Registration no., make, model, owner NIC.
4. What job data are stored? Date/time of booking in, mechanic, vehicle reg.,
time, hourly rate, parts used, part prices, total cost.
5. What invoice details are stored? Customer, address, date, amount, status (paid,
unpaid, overdue, taken to court, etc.), date of payment (if paid), dates of
reminders sent, etc.
48
Resolve ambiguities
1. What does "in the following week" mean? Obviously, if the vehicle's service is
due on a Monday, there is no point in sending a reminder on the previous
Friday. The reminder must be timed so that there are 5 working days between
the reminder and the due date.
2. What does "when the job is completed" mean? The time spent and parts used
will be recorded by the receptionist after the mechanic has returned the
completed job sheet, with these details filled in. Invoices will be printed at the
end of the working day on which the job is completed, for posting on the
following day.
3. What does "at the end of the month" mean? The last working day of each
calendar month.
4. What does "for some time" mean? Any invoice which has not been marked as
"paid" one full month after the date of posting will be followed up by a polite
reminding letter. After 2 months, a stronger letter will follow.
5. Will the stock control database be updated by KGF? No, the existing stock
control database has been working for some time, and the store-keeper
updates it when a mechanic draws a part out of store. KGF will only need to
obtain the current price of spares used from the other database.
Include omissions
1. How are reminder letters composed? For all levels of reminder, the necessary
information will be extracted from the invoice file and inserted automatically
in the appropriate standard letter.
2. Should the list of unpaid invoices include the date sent, and date and type of
any reminders? Yes.
3. How is time priced? The mechanic fills in the actual hours worked, and these
are multiplied by our standard rate when calculating the price.
4. When is VAT included? The price of all spares is added to the time price to
give the net total, and VAT is added at the current rate?
5. What if current VAT rate changes? Obviously it can happen, and the software
should accommodate for that
6. Are other types of regular servicing required? Yes. The receptionist will check
the date of the next regular service due, taken from the log-book.
Activity 4.1
Write a list of more questions that you would ask the garage owner and provide
reasonable answers. To give the answers, you will have to change roles and
pretend to be the customer.
A non-functional requirement specifies criteria that can be used to judge the operation
of a system, rather than specific behaviors. In general, functional requirements define
what a system is supposed to do whereas non-functional requirements define how a
system is supposed to be.
49
Non-functional requirements can be divided into two main categories:
1. Execution qualities, such as security and usability, which are observable at run
time.
2. Evolution qualities, such as testability, maintainability, extensibility and
scalability, which are embodied in the static structure of the software system.
Here are a few questions that can be used to extract non-functional requirements.
1. The system must be "easy to use": how easy? Our existing staff (receptionist
and myself, the owner) are used to our existing salary package. We have no
specialised computing or programming knowledge. So, KGF must be usable
by either of us with no further training than reading your user manual and
referring to on-line help if absolutely necessary (e.g., for infrequent operations,
such as changing the VAT rate). For all day-to-day operations, KGF must be
capable of being driven solely by menus.
2. Are there any other quality requirements, e.g., reliability? Yes, of course. I do
not expect the system to crash at all in use, and miscalculations of finances, or
sending unjustified reminders.
3. What is your existing hardware? PC with ...etc., etc.
4. Are you prepared to upgrade the PC to run KGF ? No! I want the new system
to run on the existing machine as it is, without affecting our existing work, and
with no additional hard-ware purchase. (.. and so on. The point is that the
contractor must clarify the hardware constraints which the software must
operate.)
For example, if the user says system should be „very fast‟, the business analyst and the
user must come to an agreement to define how fast is „very fast‟. It could be written as
a database with 36,000 records should respond to a simple query in 20 ms.
Activity 4.2
50
Using the information you have acquired, how do you develop the requirement
document to the next level of detail? First, separate functional and non-functional
requirements clearly and give a brief description of each function to be performed.
This is not expected to be a fully-detailed requirements specification, and you need
only provide a brief statement for each function.
Activity 4.3
a) Define the term „stakeholder‟ in the context of a software system. Name three
possible stakeholders of a „student data management system‟ of a University
with few faculties and more than 2000 students.
In the next session we will see how to analyse the gathered requirements before
making the Software Requirement Specification (SRS). SRS is the most
comprehensive document that would be made out of the requirement elicitation and
analysis phase.
Summary
Requirement elicitation practices include various methods such as interviews,
questionnaires, user observation, workshops, brain storming, role playing and
prototyping.
There are two major types of requirements; functional and non-functional. Functional
requirements define what a system is supposed to do, i.e. all functions expected from
the system, whereas non-functional requirements define how a system is supposed
behave in terms of usability, reliability, performance, security etc.
Learning Outcomes
On completion of the session, the learners will be able to:
o Describe the strengths and weaknesses of different approaches to requirements
elicitation
o Identify ambiguities, platitude and omissions in user‟s requirement document
(or statements)
o Categorize requirements into functional and non-functional
o Apply requirements elicitation methods to discover requirements
51
Review Questions
o Discuss how tradeoffs between different system requirements might be
necessary for a proposed computer-based system design. ??
o Describe the importance of feasibility and economic considerations
o Describe different approaches to determine requirements: interviews,
prototyping, role playing, animation
o Identify functional and non-functional requirements
o Explain the quantification issue in non-functional requirements
52
Session 5
Requirement Analysis with Data Flow
Diagram (DFD) and Unified Modeling
Language (UML)
Contents
Introduction, p 53
5.1 Illustrating Requirements with a Data Flow Diagram (DFD), p 53
5.2 User-Centered Development and Use-Case Modeling, p 55
5.3 Modelling Requirements with Use Cases, p 58
5.4 Advanced Use Case Modelling Concepts, p 60
5.5 Illustrating requirements with a Use case diagram, p 61
5.6 Writing a Use case Narrative, p 63
Summary, p 65
Learning Outcomes, p 65
Introduction
In this session we will discuss how to analyze requirements with the use of data flow
diagrams and use case diagrams.
Without going into detail of Unified Modelling Language (UML), we will discuss
basic features of a Use Case diagram in order to apply it to analyze requirements. Use
case narrative is a description to further elaborate what is depicted in a use case
diagram. We will see one example of a Use case narrative also here. When writing a
Software Requirement Specification (SRS), you will have to use one of these
techniques, a DFD or a Use case diagram to illustrate requirements in detail.
53
Now let us draw the context diagram for the Kumudu Garage Follow-up system based
on the details we know.
54
Figure 5- 2 Data Flow Diagram (Level -1)
What is a Use Case? A use case represents a single goal of a system and describes a
sequence of activities and user interactions in trying to accomplish the goal. It is
actually a description of system functions from the view of external users.
55
Figure 5- 3 Actors and business processes
Use-Case Modelling Tools - Use cases are documented using use case diagrams and
use case narratives.
Use-case diagrams – Depict the interactions between the system and external systems
and users. These diagrams graphically describe who will use the system and in what
ways the user expects to interact with the system.
Use-case narratives – Describe in text about business events and how users will
interact with the system to accomplish tasks.
56
Use-Case Symbols
Use case – Symbol for the use case is shown in (b) of the Figure 5- 4. It a subset of
the overall system functionality. It is represented graphically by a horizontal ellipse
with the name of the use case appearing above, below, or inside the ellipse.
Temporal event – a system event triggered by time. Here the actor is time.
57
Figure 5- 5 Relationship between the actor and the use case
However, to effectively estimate and schedule a project, you may need to include
preliminary “system implementation assumptions.”
58
Step 2: Identify Business Requirements Use Cases
During requirements analysis, try to identify and document only the most critical,
complex, and important use cases, often called essential use cases.
The primary inputs that trigger business events are all use cases.
Use cases that are temporal events are identified by analysing the key outputs of a
system - i.e. anything generated on the basis of time or date. Since a use case depicts
an action, name of a use case must denote an action.
Note: a context diagram is an excellent source for identifying actors and finding
potential use cases.
Use-case model can drive the entire development effort. Project manager or systems
analyst uses business requirements use cases to plan (estimate and schedule) the build
cycles of the project. Build cycles are scoped on the basis of the importance of the use
case and the time it takes to implement the use case.
Use-case ranking and evaluation matrix is created to determine the importance of use
cases.
59
5.4 Advanced Use Case Modelling Concepts
Extension use case
A use case consisting of steps extracted from a more complex use case in order to
simplify the original case is called an extension use case.
The relationship between the extension use case and the original use case it is
extending is called an extends relationship.
It is represented as an arrow-headed line beginning at the extension use case and point
to the use case it is extending. The relationship line is labelled “<<extends>>.”
The relationship between the abstract use case and the use case that uses it, is
called a uses (or includes) relationship.
It is depicted as an arrow-headed line beginning at the original use case and
pointing to the use case it is using. Each relationship line is labelled
“<<uses>>.”
Abstract Use
Place New Member Case
Order
<<Uses>>
Revise Postal
Address
<<Uses>>
Submit Change Of
Postal Address
60
Depends On
A use case relationship that specifies which other use cases must be performed before
the current use case. It can help determine the sequence in which use cases need to be
developed.
A use case dependency diagram graphically depicts the dependencies among use
cases.
It provides the following benefits:
A graphical depiction of the system‟s events and their states enhances understanding
of system functionality.
Helps identify missing use cases.
Helps facilitate project management by depicting which use cases are more critical.
(a)
(b)
61
Actors could be
Receptionist
manager
Stock control system
62
Figure 5- 8 Use case Diagram for Kumudu garage follow up system
63
Sample High level use case narrative
Book in vehicle
Author(s):_________________ Date: ______
Version:
Use Case Name: Book in vehicle Use-Case
Use Case ID MSS-BUC002.00 Type
Business
Priority High
Requirements:
Source: Requirement - MSS-R1.00
Primary Business Actor: Receptionist
Other participating Actors: customer (external sender)
Other interested Mechanic - Interested in booking vehicles
stockholders: in order to plan his jobs
Store keeper - Interested in sales activity in
order to replenish inventory.
64
Summary
DFD is a technique to illustrate a business process with the flow of data going in-
between the main functions of the system. Zeroth Level DFD illustrates the overview
of a business scenario. DFDs can be further refined to few levels to depict the
necessary levels of details surrounding each function.
Use-case diagrams depict the main business process of the system and external
entities when requirements are analysed as objects in a domain. Use-case narratives
describe in text about business events and how users will interact with the system to
accomplish tasks. For the same requirement document, we examined how to draw a
use case diagram and how to write the use case narrative for a one business process in
the Use case diagram.
Learning Outcomes
Draw a data flow diagram for a given scenario up to adequate level of detail
Describe the types of relationships that can appear on a use case diagram
Construct a use case model diagram
Prepare a use case narrative
Analyze requirements to identify the conflicts among them
65
Session 6
Structured Programming
Contents
Introduction, p 66
6.1 The Shift to Software, p 66
6.2 Definitions, p 67
6.3 Control constructs, p 68
6.4 Standardized Module Format and Hierarchical Organization, p 71
6.5 Program control structure, p 72
6.6 Documentation, p 73
6.7 Structured Programming Methodologies, p 76
6.8 Choosing a Development Approach, p 81
Summary, p 82
Learning Outcomes:, p 82
Introduction
By the late 1960s it has become obvious that software systems were complex. They
were difficult to design, to write, and to test and virtually impossible to understand
and to maintain. Advances in software technologies lagged far behind those in
hardware technologies. Installations that brought the latest computers continued to use
ad hoc programming methods from the 1950s and early 1960s.
Programming has evolved from rather ad-hoc, egoistic art to a more controlled,
definable science. Namely in order of historical evolution, following are few theories
that explain how to program:
Structured programming
Top- Down programming
Step-wise refinement
66
“The true challenge does not consist in pushing computers to their limits by saving bits and
micro seconds, but in being capable of organizing large and complex programs, and
assuring that they specify a process that for all admitted inputs produces the desired
results.”
There was a critical need for improved software technology and this need became so
severe that it becomes referred to as the “Software Crisis.” The serious shortcomings
of software technologies were discussed at the 1968 NATO conference on Software
Engineering. With such understanding research for software development
methodologies have been carried on. Structured programming evolved as a solution to
ad hoc programming practices that made maintenance of software a nightmare.
The main objective of structured programming was to solve the software crisis by
providing a programming discipline to accomplish the following:
Improve program reliability
Improve program efficiency
Minimize program complexity
Simplify program maintenance
Increase programmer productivity
Provide a discipline program methodology
6.2 Definitions
Rather than one generally accepted definition, there are several schools of thought on
what structured programming is;
In the narrowest sense, the concept of structured programming is
concerned with only the program from the coding process. It is a set of
conventions that the programmer can follow to produce structured
code. The coding rule imposed restrictions on the use of control
constructs, data structures, module composition and documentation.
In its broadest sense, the concept of structured programming encompasses the entire
programming process. It imposes a discipline on each stage of the creation of software
system and the organization of programmers. Structured programming includes ideas
such as:
Analytic verification of algorithm correctness to ensure program
reliability
67
Systemization of the programming process
Relating the programming task to the program design structure and
the programming team structure
Application of management techniques to the programming process
Systematic use of abstraction to control a mass of detail and to
produce meaningful documentation
We can say that Structured programming is a methodology that lends structure and
discipline to the program form, program design, program coding, and program testing.
It is a program methodology for constructing hierarchically ordered, modular program
using standard control constructs.
6.3.1 Sequence
When sequence is used to control program execution, statements are executed in the
same order as they appear in the source code Figure 6- 1 illustrates the sequence
construct.
Figure 6- 1 Sequence
6.3.2 Selection
The selection, iteration and branch structures are used to alter program execution flow
from its normal sequential statement order.
68
When the selection structure is used a condition is tested. Then depending on whether
the test is true or false one of two alternative sets of instructions is executed. Figure 6-
2 illustrates the selection structure.
Figure 6- 2 Selection
Iteration
The iteration structure is used to execute a set of instructions repeatedly, that is to
build a loop. There are two basic forms for the iteration structure: DO UNTIL and DO
WHILE. Either form can be used to create a program loop in a structured program.
69
Figure 6- 4 iteration with Do-while loop
Usually the restriction to allow only these three control constructs in a structured
program is relaxed to include extensions such as the nested IF, the case statement and
the escape. Allowing these extensions makes the program easier to code and maintain.
Nested If
The selection structure has the following basic format:
IF condition
Statement -1
ELSE
Statement -2
Here the statement-1 is executed when the condition is true, and statement-2 is
executed when the condition is false. When statement-1 of selection structure contains
another selection structure, it is called a nested IF. At each level of nesting,
indentation is suggested to make the next level more obvious.
In a structured program, at most three levels of nesting are allowed. The purpose of
this restriction is to control reliability. Beyond three levels of nested IFs, it becomes
difficult for most programs to understand the code.
70
Case Statement
In the case statement n–way branch, the selection structure is extended so that a
choice is made from more than two alternative sets of code depending on a condition
test. In some languages it is implemented using the IF-THEN-ELSE structure or a
special case structure. An example of an n-way branch code using the Pascal is given
below.
case operator of
'*' : result:= number1 * number2;
'/' : result:= number1 / number2;
'+' : result:= number1 + number2;
'-' : result:= number1 - number2;
otherwise invalid_operator := 1
end;
72
executed. When module B has computed its execution, it passes control back to
module A. Program control always enters a module from its entry point and leaves the
module from its exit point.
The rules of program control flow in a structured program are summarized in the box
below. The smallest structured program consists of only a root module. All other
structured program contain one root module and one or more sub-modules.
6.6 Documentation
Documentation is an integral part of a well–structured program. It addresses three
levels of program understanding.
Overview
Program organization
73
Program instruction comments
Each successive level provides a more detailed view of the program. All three levels
are necessary to the understanding and maintenance of the program.
74
A comment block precedes each program module in a structured program. Its purpose
is to introduce the module to the reader by describing what the module does. How the
module works is not described. This is best ascertained by actually reading the code.
6.6.6 Indentation
The rules for writing a conventional language include paragraphing, spacing and
indenting guidelines to improve readability. Similar guidelines for writing structured
programs are used to improve program readability. A basic principle of structured
programming is that the standardized program form will improve readability.
Activity 6.1
75
6.7 Structured Programming Methodologies
Programs can be developed from the top down or from the bottom up. Both of these
are adaptations of Wirth‟s programming by stepwise refinement and Dijkstras‟s
programming by levels of abstraction.
When a system is built bottom up, the designer creates the components first, makes
each component work well, and then fits the components together.
When a designer works top down, he/she first create the overall structure, defining but
not yet building the components. As the design progresses, he/she fills in the details
by building the lower level components.
Top-down and bottom-up designs are practiced in many fields of engineering other
than programming. On complex projects, a combination of top-down and bottom-up
design is usually required.
In top-down programming, the order of the design, coding and testing steps is
different from traditional program development. In traditional program development,
first the entire program is designed, then the program is coded, and finally it is tested.
The three steps are performed separately and sequentially. This is called the phased
approach.
In contrast, the three steps in top-down development are performed in parallel (see
Figure 6- 7). This is called the incremental approach or the step-by-step-approach.
First one module is designed, coded, and tested. Then another module is designed,
coded and tested, until all modules in the program are finished. As part of the testing
step, each newly coded module is integrated and tested with all modules completed to
that point. The program grows gradually, one module at a time. Integration is done in
steps instead of in big chunks at the end of the project as is done in the phased
approach.
In practice, the traditional phased approach has not been very successful. It tends to
delay the discovery of serious problems and the need for project resources, such as
personnel and computer time, until late in the project. Furthermore, problems are
likely to spill over into the maintenance phase, making the program a costly
nightmare to maintain.
76
Figure 6- 7 Program development
In phase program development (Figure 6- 8), serious problems and resource needs
often build up enormously as the projects nears its planned completion point.
The top-down approach can avoid many of these problems. It has the advantage of
beginning testing earlier in the development process. In this way integration problems
can be discovered and corrected earlier and at a lower cost.
77
A second advantage is that the need for resources can be more evenly described
throughout the development process. Finally, a skeleton of the program exists from
the early development steps, giving the user a partial version of the program long
before the entire program is completed.
Step 1: Begin with the examination of the problem and then propose a solution, given
as the general structure of the program. Express the solution as an outline that
identifies the general procedural and data components of the program. At this point
the contents of the components are not defined in detail. The outline is obtained by
cutting the problem into logical pieces reflecting the functional tasks the program
must perform to accomplish its objective. (e.g., calculate gross pay, select screen
format).
Step 2-n: Expand the program outline into the complete program in steps. The
expansion process follows the rules of the refinement process. Program components
are refined into subcomponents, and then the subcomponents are refined, and so on.
The process stops when the program is described as a set of components that can be
directly expressed in the programming language.
After module A has been designed, coded, and tested, top-down development moves
down to modules in level 2. In steps, the stubs for modules B, C, and D are replaced
by the actual modules. The process continuous in downward direction until program
development is complete.
78
Figure 6- 9 Top down programming
Both are compatible with the structured programming methodology. However, they
approach program development from the opposite direction. The construction
technique for program development in top-down programming is decomposition.
Program functions are decomposed into sub-functions and so on until the whole
program can be defined in term of components from the programming language. As
shown in Figure 6- 9, the development direction is from an abstract, high-level
solution to the actual programming environment. In bottom-up programming, the
opposite development direction is followed. The program is built by combining
simple, atomic component to form more abstract, higher-level components. The
construction technique is concatenation.
Figure 6- 10 Top-down and bottom-up programming approach program development from opposite directions
79
6.7.4 Bottom-up Programming
Bottom-up programming develops a program in steps. Just as in top-down
programming, the process can be divided in to two parts. First and initial solution for
the program is proposed. Then the detail components of the program are developed.
Step 1: Begin with an outline of the proposed program. This outline includes the
general functional and data components of the program.
Step 2-n: In explicit steps, develop the program by combining low-level components
to form high-level components. This process is called the concatenation process. The
concatenation process stops when a set of program functions and data structures that
are able to solve the programming problem have been constructed from the elements
available in the actual programming environment.
The development direction moves from the lowest-level modules to the highest- level
module in the steps. Test drivers are used to represent higher-level modules that will
be developed in later steps.
80
Figure 6- 12 The concatenation process
Activity 6.2
Compare and contrast Top-down and Bottom-up programming methodologies with real world
examples (examples of programming solutions/problem domains)
For particular problems, one approach may be preferred over another. Top-down is
preferred when decisions concerning data representations must be delayed. On the
other hand, a bottom-up approach allows a large number of programs to work in
parallel on bottom-level modules. However, following a pure top-down or bottom-up
approach can cause problems. For example, when following a top-down approach,
common functions may not be recognized, or the development process may require
too much time, especially for a large program. Following a pure bottom –up approach
may result in undefined data and poorly tested module interfaces.
A combination approach is often more practical than following a strict top-down and
bottom-up approach. For example, it may be desirable to implement utility or
common modules bottom up since they will be invoked in more than one part of the
program. The rest of the program can be developed top down. This is simpler than
creating a stub everywhere in the program where the utility module is invoked.
81
Summary
In this session we discussed how structured programming emerged and the basic
control constructs.
The concepts of structured programming are based on writing programs using:
Sequence
Selection
Repetition or iteration
We also discussed various documentation types used in software development process
and structured programming methodologies.
Learning Outcomes:
After studying this session you should be able to,
list the objectives of structured programming
explain the 3 basic control constructs
explain the importance of documentation of software projects
apply structured programming methodologies for solving programing
problems
82
Session 7
Function Oriented Design
Contents
Introduction, p 83
7.1 Structured Software Systems Development, p 83
7.2 N-S Chart, p 84
7.3 Data Flow Diagram, p 86
7.4 The System Model, p 92
Learning Outcomes p 94
Introduction
The function oriented model shows how the in-coming data in combination with the
stored, static data can be transformed into the output data that is required by the
system. This transformation is performed by a series of functions.
This session discusses about how and why software design has progressed from early
ad-hoc art into a set of formalized techniques which has become the base for the
function oriented design. Here we also learn to represent a design using three function
oriented design techniques - structure charts, N-S charts and Data Flow Diagrams.
83
Figure 7- 1 Components of a structure chart
When depicting a design using N-S charts, control structures such as sequence,
selection and iteration are illustrated as shown in (a), (b) and (c) of Figure 7- 2.
84
Firstly, here is a problem definition for a merge problem domain:
Given two files A and B, both sorted in ascending order of key values, it is
required to create an output file C, constituting A merged with B, in ascending
order of key value.
Figure 7- 3 shows the basic merge operation. Figure 7- 4 gives the solution in the
form of a structured flowchart.
In Figure 7- 4, consider A-KEY, B-KEY and C-KEY as the values of the key
fields of files A, B and C. The procedure Read-and-Compare is required to read
the keyfields from A and B, compare then and write the one with the lower key
into C.
85
Because each time either A-record or B-record is written into C, it is upto you now to
fill in the remaining tasks within the procedure Copy-Remainder. That is to copy the
remaining records from the non-empty file into C after which control will be passed to
the last procedure whose function is to close all three files.
Activity 7.1
Read the given scenario below and draw a N-S chart to represent the solution.
“To calculate the loan deduction from the salary of an employee, you need to open the
Employee file. Read each record and if loan field is indicated as „yes‟, then read loan
settlement amount and deduct it from the basic salary. After loan deduction, net pay should
be calculated and printed on a report. After reading all the records the file should be closed.
You may make reasonable assumptions about other fields of the Employee file.”
Example of a simple DFD is shown in Figure 7- 6. External entities are customer and
company. Customer gives voice and numeric data to the Telephone call system.
Therefore it becomes a source. Company receives necessary messages from the
system. Therefore it becomes a sink to the system.
86
Figure 7- 6 Example of a simple DFD
87
Figure 7- 8 Process breaking down into levels
DFD for ordering process of books is shown in Figure 7- 9. It has three (3) processors
called 1. Order processing, 2. Ship books, 3. Collect payments. There are two external
entities called customer and warehouse. There are three data stores called orders,
invoice and customers. There are several flowing data to processes and from
processes. Data flow identifiers are written among the data flow arrows.
88
Typically, each of the data flow identifiers such as „customer details‟ would be clearly
annotated as follows:
Customer Details = Customer- name,
Customer- address,
telephone-number.
And
Invoice Details = invoice- no,
Customer- name,
Customer- address,
(book- code, book –name, amount)*,
total –amount
Where * implies iteration over the number of books being purchased i.e. Detail
invoice lines.
Closer to home, we can look at the Open University‟s procedures in respect of student
examinations. Figure 7- 10 shows a section of the procedures involved.
89
The flow of information through a system, as represented by a DFD is fairly easy to
follow. It is also easy for the analyst to structure his analysis of the information
domain through DFD‟s. However, our problem with DFD‟s is that there is no explicit
indication of the temporal order of events. Which precedes which and happens
before what?
If you look at Figure 7- 10 again you will notice that the student receives the
time-table and the venue as well as the notification of results of exam
processing. But of course, the time table will precede the results which can
only happen after the answer scripts have been received back. A better way to
represent this would have been as depicted in Figure 7- 11.
90
Figure 7- 12 A part of Level 1 DFD for determining sales commission
Figure 7- 13 Corresponding part of the Level 2 DFD for determining sales commission
91
Now when we consider the module 1.2, it is named as “Calculate commission”. This
module can be written by a simple algorithm as follows because it is very simple
manageable module. Actually, context diagram breaks down until they become simple
manageable modules.
Process 1.2
CALCULATE commission
Begin
Do while there are more Commissionable–sales amounts
Find salesman–Commissionable-Level from Salesman – File using
Salesman–Code
If Commissionable–Sales–Amount >= Salesman
–Commissionable-Level
Apply Percentage–figure to Commissionable–Sales–Amount
Add to Commission–Amount
End If
End Do
End
Its essential feature is that it provides a methodology for studying complex systems, in
part or in whole, particularly what we think are the essential attributes of the system.
Such attributes defined as being essential are:
1. System behaviour – i.e. Given a set of inputs how a set of outputs are
generated via the internalized functions - This behaviour is highlighted by a
specification which states what the user wants or expects from the system.
2. System internal functions – those processes which are essential in the system
in order to provide the behavioural transformations required. This is embodied
in the design.
3. The project organization – the criteria and constraints involved in the system‟s
life cycle which is embodied in the project plan.
This logical model, a resultant of the analysis and design phase, must now be
converted into a physical solution that will be implemented on a particular
configuration and tools required. This is of course, a function of availability,
capability and finance.
Is such configuration available?
Is the project team capable of implementing the solution or that
configuration using the tools available?
Do we have the budget for the proposed project?
Along with providing these questions to which we formulate the answer dependent on
our estimate of resources.
92
Clearly modularity (breaking up a big problem into little, manageable pieces) and
structures (proposing a hierarchy of modules) are guidelines to the modeling process.
Generally modeling is a top–down process. We arrive at our final model by logically
partitioning the problem domain (i.e. information domain) and then partitioning it still
further and further till all the resultant pieces are manageable. Figure 7- 14 shows
level 1 partitioning and Figure 7- 15 shows level 2 partitioning.
93
Activity 7.2
Read the given scenario below and draw 0th and 1st level of DFDs to represent the solution.
“Problem area – Library Information System (LIS)
Modules needed – file maintenance (to add a new record, delete and update an existing record),
search for books, borrow, return, pay over-dues, and generate reports.
To browse, user is asked which master file to use. Master files are ‘books’ and ‘members’. There
are number of different reports needed.”
Learning Outcomes
On completion of this session the learners will be able to;
construct a structured chart to depict a for a simple problem
solution
draw a N-S chart illustrate a given problem solution
draw a data flow diagram (DFD) for a given scenario up to
adequate level of detail to illustrate a problem solution
Reference
For structure charts: http://www.smartdraw.com/resources/tutorials/Introduction-to-
DFD#/resources/tutorials/Introduction-to-JSD
For N-S charts: http://www.smartdraw.com/resources/tutorials/Introduction-to-
DFD#/resources/tutorials/Introduction-to-Nassi-Shneiderman
For Data Flow Diagrams:
http://www.smartdraw.com/resources/tutorials/Introduction-to-
DFD#/resources/tutorials/Introduction-to-DFD
94
UNIT 2
INTRODUCTION TO PROGRAMMING
Introduction 95
Session 8 Algorithms 96
95
Introduction
At the end of Unit 1, we discussed basic software engineering concepts. A program
created according to structured concepts where the flow of processes is emphasised, is
called procedure-oriented or function-oriented. Here a problem is broken down into
parts and each part is then broken down into further parts. All these parts are known
as modules. They are separate but work together when needed and a main program
centrally controls all modules. C language is widely used to create function oriented
programs.
In this Unit, we discuss how to arrive at a solution for a problem using an algorithm
and then how to code the algorithm in C language while following structured
programming concepts.
Learning Outcomes:
96
Session 8
Algorithms
Contents
Introduction, p 97
8.1 What is an Algorithm?, p 97
8.2 Representation of Algorithms, p 100
8.3 Non-uniqueness of Algorithms p 103
Summary, p 104
Learning Outcomes:104
Introduction
In this session we will discuss how to solve a problem with an algorithm. Here you
will learn the characteristics of an algorithm, differences in representing algorithms in
normal English and structured English, and two formal methods of representing
algorithms. As the two formal methods we will discuss the use of pseudo code and
flowcharts.
Learning to write an algorithm to solve a problem is very important when you learn
programming. You will be also given a task in the Assignment #1 with algorithms and
supporting animations are given in the on-line class.
For example, can you describe someone else how to make a cup of tea? You need to
give step by step instructions how to do that.
97
o First you boil water. Then put 1 teaspoon of tea leaves to the teapot
and pour boiling water into the teapot. Let it stand for 3 minutes. Put
2 teaspoons of milk powder and 1 teaspoon of sugar to a cup.
o Pour some tea and stir the content in the cup with a spoon. See
whether the cup is full, and if not, pour tea until the cup is full.
o Taste and see whether sugar is enough. If sugar is not enough add
another ½ teaspoon of sugar.
Another example for an algorithm is a recipe to make a cake or the set of instructions
that says how to tune a new TV set for the available channels.
When writing algorithms, we have several choices to specify the operations in our
algorithm. Most simple option you may see is to write the algorithm using plain
English as the above example of making a cup of tea. Although plain English may
seem like a good way to write an algorithm, it has many problems. First, plain English
is too wordy. When we write in plain English, we must include many words that
contribute to correct grammar or style but do nothing to help communicate the
algorithm. Second, plain English is too ambiguous. Often an English sentence can be
interpreted in many different ways.
To make the instructions clear and unambiguous we can write the same sequence of
steps in Structured English like what is given below.
o Boil water
o Put 1 teaspoon of tea leaves to the tea pot
o Pour boiling water into the teapot
o Let it stand for 3 minutes
o Put 2 teaspoons of milk powder to a cup
o Add 1 teaspoon of sugar to the cup
o Pour some tea into the cup
o Stir the content in the cup with a spoon until content is dissolved
o See whether the cup is full, and if not pour tea until the cup is full
o Taste and see whether sugar is enough
o If sugar is not enough add another ½ teaspoon of sugar
Activity 8.1
There is no generally accepted single formal definition for an algorithm. Here is one
definition.
98
An algorithm is a well-ordered collection of unambiguous and effectively computable
operations that when executed produces a result and halts in a finite amount of time.
(Schneider and Gersting 1995)
Though the algorithm given to illustrate „how to make a cup of tea‟ seems alright for
us, undoubtedly it is too ambiguous for a computer. In order for an algorithm to be
applicable to a computer, it must have certain characteristics. According to the formal
definition given above, there are five important characteristics of an algorithm as
stated below.
An algorithm is well-ordered.
An algorithm has unambiguous operations.
An algorithm has effectively computable operations.
An algorithm produces a result.
An algorithm halts in a finite amount of time.
Given a list of numbers, you can easily order them from largest to smallest with the
simple instruction "Sort these numbers." A computer, however, needs more detail to
carry out such a task. It must be told how to search for the smallest number, how to
compare two numbers together, etc. The operation "Sort these numbers" is ambiguous
to a computer because the computer has no basic operations for sorting. Basic
operations used for writing algorithms are known as primitive operations (primitives).
When an algorithm is written in computer primitives, the algorithm is unambiguous
and the computer can execute it.
99
plot of land is sand without stones. For computers, many mathematical operations
such as division by zero or finding the square root of a negative number are also
impossible. Operations which are not effectively computable cannot be used in
writing algorithms.
While our algorithm seems to be very clear, there are two problems. First, the
algorithm must have an infinite number of steps because there are an infinite number
of integers greater than one. Second, the algorithm will run forever trying to count to
infinity. These problems violate our definition that an algorithm must halt in a finite
amount of time. Every algorithm must reach some operation that tells it to stop.
100
Figure 8- 1 Flow charting symbols
Figure 8- 2 shows how the solution to the problem of making a cup of tea is
represented with a flowchart.
Activity 8.2
101
Figure 8- 2 Flow chart for making a cup of tea
After writing the algorithm in pseudo code, translation to any programming language
is straightforward.
Example.
write an algorithm for adding all even numbers between 2 and 1000 to the Sum-
Even-numbers
In structured English
Initialize Sum-of-Even-numbers
Intialize an index
Repeat Until index is 1000
Increment the index by 2;
Add index to Sum-of-Even-numbers
102
In Pseudo code
Sum-of-Even-numbers = 0
Number = 0
Repeat
Number = Number +2
Sum-of-Even-numbers = Sum-of-Even-numbers + Number
Until Number == 10
Activity 8.3
Activity 8.4
103
Summary
In this session we started by defining what an algorithm is. In our definition, we saw
five important characteristics that an algorithm must have:
An algorithm is well-ordered.
An algorithm has unambiguous operations.
Algorithms have effectively computable operations.
An algorithm produces a result.
An algorithm halts in a finite amount of time.
Learning Outcomes:
After studying this session you should be able to,
explain what an algorithm is
describe characteristics of an algorithm
represent a simple algorithm with pseudo code
represent a simple algorithm with a flowchart
104
Session 9
Programming with C Language
Contents
Introduction, p 105
9.1 Compiling and Executing a C Program, p 105
9.2 Compile Errors, p 108
9.3 Case Sensitivity in C, p 109
9.4 Structured coding standards, p 110
Summary, p 110
Learning Outcomes:, p 111
Introduction
From this session onwards, we will start programing with C language. This session
introduces step by step procedures needed to follow in order to develop a simple C
program. It also shows the common programming errors, how to locate them and
correct them to run a program successfully.
A programmer can write the program in C using any editor and save the file. The
program that is written is called the source code, hence for the compiler, the input is
the source code and the output is object code. In fact the object code cannot be run in
the computer as it is. Therefore, we need another program called a linker, which is
invoked by the compiler, in order to translate the object file into an executable
program. Only an executable program can be run in the computer.
Here, the compiled object file is also linked with a function library in order to produce
the executable program. A library is a collection of linkable files, which can be linked
to a program. Many libraries are supplied with the C compiler but a progammer can
also create his/her own set of libraries to be linked with the program.
105
For example, a source file saved as hello.c, when compiled generates both the object
file (hello.obj) and the executable file (hello.exe). When the programmer run the
program the executable file is loaded and executed.
1 /* My first program in C */
2 #include <stdio.h>
3 /* function main begins program execution */
4 int main( void )
5 {
6 printf( "Welcome to C!\n" );
7 return 0; /* indicate that program ended successfully */
8 } /* end function main */
Output: Welcome to C!
Note: Most of the programs in this book contain line numbers on the left. These
numbers are only for reference within the book and should not be included in your
program.
106
Functions can return information. The keyword int to the left of main indicates that
main “returns” an integer (whole number) value. (What it means for a function to
“return a value” will be discussed in a later session). Functions also can receive
information when they are called upon to execute. The void in parentheses here means
that main does not receive any information.
Curly braces ({}) shows the body of the main function. What is contained within these
braces is what the function does when it is executed. (Here line 6 and 7 is the body of
the main function which is contained within the braces in line 5 and 8)
This statement generates the visible effect that we can see as the output, „Welcome to
C!‟
The backslash (\) is called an escape character. It indicates that “printf” is supposed to
do something out of the ordinary. When a backslash in a string is seen, the compiler
looks ahead at the next character and combines it with the backslash to form an escape
sequence. The escape sequence \n means new line. When a new line appears in the
string output by a “printf”, the new line causes the cursor to position to the beginning
of the next line on the screen.
return 0;
The keyword return is one of several means that we use to exit a function. When the
return statement is used at the end of main as shown here, the value 0 indicates that
the program has terminated successfully.
107
Semicolon character (;)
In line 6 and 7 the statements end with a semicolon character (;). This character is
used to mark the end of the statement and it is essential to include this at the end of all
expression statements in C programs.
1 /* My first program in C */
2 #include <stdio.h>
3 /* function main begins program execution */
4 int main( void )
5 {
6 printf( "Welcome to C!\n" );
7 return 0; /* indicate that program ended successfully */
In the above program the closing parenthesis ( }) of the main function is missing.
Hence the compiler will generate a compile error like:
Error welcome.c, line 7: Compound statement missing }
welcome.c is the file name and it shows the line number and also the problem.
Compiler assists in finding most of the common compile errors but sometimes the
compiler finds it unable to report complex user errors. In addition, in every identified
compile error it doesn‟t show the correct line numbers. So it is the programmer‟s
responsibility to locate the errors and correct them.
Activity 9.1
1 /* My second program in C */
2 #include <stdio.h>
3 /* function main begins program execution */
4 int main( void )
108
5 {
6 printf( "Welcome" );
7 printf( " toC!\n" );
8 return 0; /* indicate that program ended successfully */
Example 9.1: In declaring variable names the word „age‟ is different from „Age‟,
and both are different from „AGE‟. (The concept „Variables‟ will be discussed
again in the next session)
Therefore, the programmer should be cautious about this factor and use correct
uppercase and lowercase letters when writing C programs.
Activity 9.2
/* My third program in C */
#include <stdio.h>
/* function main begins program execution */
int main( void )
{
printf( "Learning Programming with C-");
printf( " Session 9 ----);
printf( " My third Program!!!")
return 0; /* indicate that program ended successfully */
}
You will get number of compile error statements. Read the compilation errors carefully and fix the
errors and run the program.
109
9.4 Structured coding standards
Structured programs are expected to conform to a set of structured programming
standards. A general list of structuring rules representative of those typically
suggested for high-level, procedure-oriented languages such as C and Pasacal are
given below.
Any program is divided into independent parts called modules. A
module is a self-contained unit whose code is physically and
logically separate from the code of any other module in the
program.
A module represents one unique logical program function. The size
of a module should not exceed 100 instructions.
A module is bounded by one entry point and exit point. During
execution, program control can enter a module only at its entry
point and can leave the module only from its exit point.
Modules are related to one another by a hierarchical control
structure. Each level in the control structure represents a more
detailed functional description of what the program does. It also
dictates the transfer of program control from module to module
during execution.
Each module should begin with a comment block explaining the
function that the module performs, the values passed to the module,
the values returned, the modules that call this module, and the
modules that this module calls.
All comment should be meaningful (i.e., should not repeat
information that is obvious from the code).
All variable and module names should be meaningful. Module
name should suggest the logical function they perform (e.g.,
Calculate_Average), and variable names should suggest their
purpose in the program (e.g., CalAv_mark1).
Names of local variable (i.e., used only in the module) should
begin with the same prefix.
No more than one instruction is coded on a line. If an instruction
requires more than one line, successive lines are indented.
IF statement should not be nested more than three levels.
Summary
A programming language translates instructions from human
readable format to a computer readable format.
A computer program is a collection of instructions that describe a
task or set of tasks to be carried out by a computer. Every program
has 3 basic tasks.
o Manipulate data
o Perform operations
o Provide results
To create an executable C program you should,
o Create a source file, with a .c extension.
110
o Compile the source file. (The compiler creates a file with an .obj
extension)
o Run the program. (Linker link the .obj file with any needed
libraries to produce an executable program)
Learning Outcomes:
After studying this session you should be able to,
to edit, compile, link, and run a given C program.
find out the compile errors in a simple C program and correct them
111
Session 10
Data Types and Variables in C
Contents
Introduction, p 112
10.1 What are Data?, p 112
10.2 Variable Types in C, p 113
10.3 Constants in C, p 117
10.4 Finding the Size of Variable Types, p 119
Summary, p 120
Learning Outcomes:, p 120
Introduction
In the previous session we developed a simple C program which displayed a certain
text. In this session we introduce the concepts of „variables‟ and „data types‟ available
in C. Variables are used to store data and retrieve them later in order to perform
operations. This session also covers basic data types in C and their technical details
such as their sizes and ranges. In addition, this session explains Constants.
Both variables and constants offer various ways to represent and manipulate data in C
applications. When applications are developed it is important to choose the proper
data type in defining variables and constants. Values should be assigned to the
variables and constants according to their data types. Failing to do so will result in
compile errors, unexpected and incorrect outputs. Hence this session provides
guidance to take the right decision to choose the proper data types and to assign
correct values to them. The sizeof operator introduced in this session assist in finding
the size of these data types and even the size of any data item.
112
Each distinct piece of information (e.g. A number or a character) inside a computer
has to be coded into a pattern of bits of the given cell size, or if more bits are required
than that can fit into a single cell, some suitable multiple of size required.
8 bits
cell 0
cell 1
cell 2
.
. .
. .
. .
Type Description
Char Typically a single octet (one byte). This is integer type.
int integer
float A single-precision floating point value
double A double-precision floating point value
void denotes the absence of a type.
113
In defining variables, each variable takes up a fixed amount of space in the
computer‟s memory. The Table 10- 2 illustrates the data types used in C and their size
and range.
Table 10- 2 Data types in C with their size and usage
*Note: The values of the columns „Size‟ and „Range‟ depend on the architecture of
the system where the program is compiled and executed.
114
Example 10.3: Character variables can be used to store characters as shown
below.
char name;
Example 10.4: In order to declare more than one variable of the same type, it can
be declared as separate statements or in a single statement as shown below. In the
three variables mark1, mark2 and mark3, marks of three subjects can be stored.
int mark1;
int mark2;
int mark3;
int mark1, mark2, mark3;
Example 10.5: Variables without the word "unsigned" are assumed to be signed.
Hence both declarations given below are the same.
signed int mySalary;
int mySalary;
Example 10.6: An exception to this general rule is the char type, as we can
declare variables to store even numeric values. Here it is necessary to use either
signed or unsigned keyword in declaring char-sized variable.
unsigned char total;
signed char value;
Example 10.7: In declaring short and long variables, we assume that short is
equivalent to short int and long is equivalent to long int.
short month; is as same as short int month;
115
Assigning values to float variables
float interestRate = 0.05;
float calculation= -99.99 double Fahrenheit = 99.876;
long double Balance = 50899.90;
Activity 10.1
116
Activity 10.2
Use the data and the formula given below in writing your program:
Height of the triangle is 11 and the base of the triangle is 5.
Area = 0.5 * height * base
10.3 Constants in C
Like variables, constants are data storage locations, but once a value is being
initialized to a constant it cannot be changed later in the programme. There are two
types of constants in C named literal and symbolic.
There are two ways to declare a symbolic constant in C using the #define keyword
and the const keyword.
#define keyword
117
const keyword
In defining a constant with the use of const keyword, a type needs to be
specified.
Constants in programs
Output:
Enter your year of birth: 2010
In 2050 you will be 40 years old.
The main advantage in using symbolic constants is, if a certain value needs to be
changed, it can be done efficiently and effectively as there‟s no need to make a
change in every place that the value is being used.
Example 10.11: Suppose in the above program that you need to calculate your
age in 2070.Here if you change the constant to const int FUTURE = 2070, it will
be effective though out the whole program.
This is more effective in larger programs where the programmers do not have to go
through all the coding thus saving time and minimizing errors that can occur.
118
10.4 Finding the Size of Variable Types
Every data type has a size (in bytes) depending on the architecture of the computer. C
language provides a useful operator called sizeof for calculating the size of any data
item or type. It takes a single operand which may be a type name or an expression and
returns the size of the data type in bytes.
int main()
{
printf("Storage size for int : %d \n", sizeof(int));
return 0;
}
Output:
Storage size for int = 4
Activity 10.3
i. If „Pi‟ is defined as Const double Pi = 3.14 in the start of the program, can you assign „3.142‟ to
„Pi‟ later in the program? (i.e. Pi = 3.142)
ii. Write a program to find the sizes of types „char‟, „float‟ and „double‟.
119
Summary
In C, there are four main data types. They are int, float, char and double. We define
variables stating its type followed by the name of the variable. Then values are
assigned to those variables using the assign (=) operator. Constants are C data storage
locations like variables, but once defined constant cannot be changed. There are two
types of constants in C named, literal and symbolic.
Learning Outcomes:
After reading this lesson you should be able to:
Explain preliminary data types
declare and define variables
assign values to variables and to manipulate those values
correctly use constants
write the size of a variable to the screen.
120
Session 11
C Operators and Expressions
Contents
Introduction, p 121
11.1 Assignment Operator and Arithmetic Operators, p 122
11.2 Relational Operators, p 123
11.3 Logical Operators, p 125
11.4 Increment and Decrement Operators p 127
11.5 Bitwise Operations, p 128
11.6 Precedence of Operators, p 129
Summary, p 130
Learning Outcomes:, p 130
Introduction
In order to work with variables and constants and manipulate data, we need a way to
operate with them. C provides „operators‟ for this purpose and keyboard symbols are
used to denote them. This session is designed to introduce different types of operators
used and the different actions they perform on data.
The most commonly used one is the assignment operator, which mainly deals with
assigning values to variables. In addition, this session outlines arithmetic operators,
which are the common mathematical operations found on a calculator. Logical
Calculations also can be performed using the logical operators. Furthermore, C
provides relational operators mostly to compare different types of values in order to
execute statements. There are special types of operators which are unique to most
programming languages. They are called increment and decrement operators which
helps in incrementing and decrementing a given value.
Each operator is assigned a priority and this is called the „precedence of operators‟
which is one of the most important aspects in working with different types of
operators. An operator is a symbol, which performs a certain action in a program. The
symbols are mostly made of signs that are available in all keyboards. Specific actions
are performed using a certain value or values given to variables or constants which are
called operands.
121
11.1 Assignment Operator and Arithmetic Operators
The assignment operator (=) assigns a value to a variable. Assignment operator helps
you to perform several operations on variables.
122
Example 11.2: In using arithmetic operators, a suitable data type needs to be
chosen in defining variables.
You would expect -2 as the answer, but -2 cannot be stored in the unsigned int
variable. Just like we have explained earlier unsigned variables do not hold negative
values. Hence this can lead to unexpected, incorrect outcomes.
As a solution „difference‟ can be defined as a signed integer variable.
signed int difference or int difference
Example 11.3:
int num1= 5;
int num2 = 2;
int division;
division = num1/num2;
You would expect an answer as 2.5 but as „division‟ is defined as an int type variable,
it cannot hold a number with a fraction. Here you get the answer as 2, which is
incorrect. As a solution „division‟ can be defined as a floating point variable.
float division;
Activity 11.1
123
Table 11- 2 Relational operators
Operator Symbol
Action Example
Equal == Is operand 1 equal to operand 2? x==y
Greater than > Is operand 1 greater than operand x>y
2?
Less than < Is operand 1 less than operand 2? x<y
Greater than or equal >= Is operand 1 greater than or equal x >= y
to to operand 2?
Less than or equal to <= Is operand 1 less than or equal to x <= y
operand 2?
Not equal != Is operand 1 not equal to operand x != y
2?
In order to evaluate a comparison between two expressions, relational operators are
being used. The result of a relational operation is a Boolean value that can only be
true or false.
Example 11.5:
o (4 = = 3) // Boolean value is false as 4 is not equal to 3
o (8 > 2) // Boolean value is true as 8 is greater than 2
o (4 != 9) // Boolean value is true as 4 not equals to 9
o (10 >= 10) // Boolean value is true as 10 is equals to 10
o (11 >= 10) // Here this expression also gives the Boolean value as true
since 11 is greater than 10
o (6 < 6) // Boolean value is false as 6 is not less than to 6
o Greater than or equal to‟ and „Less than or equal to‟ operators have to
be used exactly as shown in the above table. Expressions like => and
=< are invalid.
o Characters are valid operands since they are represented by numeric
values. (e.g., ASCII coding) Hence, „A‟<‟F‟ is a valid expression.
Note: Strings cannot be compared using the comparison operators. C provides
separate functions to compare strings.
124
scanf( "%d%d", &num1, &num2 ); /* read two integers */
if ( num1 == num2 ) {
printf( "%d is equal to %d\n", num1, num2 );
} /* end if */
if ( num1 != num2 ) {
printf( "%d is not equal to %d\n", num1, num2 );
} /* end if */
if ( num1< num2 ) {
printf( "%d is less than %d\n", num1, num2 );
} /* end if */
}
Output
Enter two integers, and I will tell you
the relationships they satisfy: 3 7
3 is not equal to 7
3 is less than 7
3 is less than or equal to 7
Operator Symbol
Action Example
Logical and (AND) &&True only if both exp1 and exp2 exp1 && exp2
are true; false otherwise
Logical or (OR) || True only if both exp1 and exp2 exp1 || exp2
or either exp1 or exp2 is true;
false otherwise
Logical negation ! False if exp1 is true; true if exp1 !exp1
(NOT) is false
The operator && denotes Boolean logical operation AND. Truth table is given in
Table 11- 4.
Table 11- 4 Truth table for AND operation
x y x && y
true true true
true false false
false true false
false false false
125
Example 11.6: ((7 == 7)&&(5 > 7))// Boolean value is false (true&&false =
false)
The operator || denotes Boolean logical operation OR. Truth table is given in Table
11- 5.
Table 11- 5 Truth table for OR
x y x || y
true true true
true false true
false true true
false false false
Example 11.7: ((7 == 7)||(5 > 7)) // Boolean value is true (true || false true)
#include <stdio.h>
/* function main begins program execution */
int main( void )
{
int CA; /* CA mark to be read from user */
int finalMark; /* final mark to be read from user */
126
Output:
In the above program only if both the CA marks and final exam marks are more than
40, it will display the message as passing the subject.
Example 11.9:
x=2;
y=++x; //After a single execution x=3 and y=3.
x=2;
y=x++; //After a single execution y=2 and x=3
Example 11.10:
x += 3; //this is equal to x=x+3
amount -= 2; //this is equal to amount=amount – 2
*Note: increment and decrement operators work only with integer variables.
127
Use of the increment and decrement operators
/*Pre-incrementing and post-incrementing */
#include <stdio.h>
/* function main begins program execution */
int main( void )
{
int c; /* define variable */
/* demonstrate post-increment */
c = 5; /* assign 5 to c */
printf("%d\n", c ); /* print 5 */
printf("%d\n", c++ ); /* print 5 then post-increment */
printf("%d\n\n", c ); /* print 6 */
/* demonstrate pre-increment */
c = 5; /* assign 5 to c */
printf("%d\n", c ); /* print 5 */
printf("%d\n", ++c ); /* pre-increment then print 6 */
printf("%d\n", c ); /* print 6 */
A bitwise operation is directly supported by CPU. There are many bitwise operators
defined in C.
These are,
bitwise AND (&),
bitwise inclusive OR (|),
bitwise exclusive OR (^),
left shift (<<),
right shift (>>), and
complement (~)
128
11.6 Precedence of Operators
In C there is an established order for the priority of each operator. This is called the
precedence of operators. The precedence is established for all the operators which can
appear in C. The priority order is shown in the Table 11- 7.
Table 11- 7 Precedence of operators
129
Activity 11.2
Summary
An operator is a symbol, which performs a certain action in a
program. Mainly there are 5 categories of operators namely,
assignment operator, arithmetic operator, logical operator,
relational operator, increment and decrement operator.
The assignment operator (=) assigns a certain value to a variable.
There are 5 basic arithmetic operators. They are addition (+),
subtraction
(-), multiplication (*), division (/) and modulus (%).
Relational operators are used for comparing numeric quantities.
There are 6 relational operators, which are equal, greater than, less
than, greater than or equal to, less than or equal to and not equal.
Logical operators in C evaluate to Boolean value true or false.
Three basic logical operators are logical AND (&&), logical OR
(||), logical negation (!).
The increment operator (++) and the decrement operator (--)
increase or reduce the value stored in a variable.
In C there is an established order for the priority of each operator.
This is called the precedence of operators.
Learning Outcomes:
After reading this lesson you should be able to:
manipulate data using C operators
evaluate expressions using precedence of operators
apply bitwise operations in programming
130
Session 12
Control Structures in C
Contents
Introduction, p 131
12.1 Conditional Statements, p 131
12.2 Iteration Structures (loops), p 134
12.3 Multiple initializations and increments, p 138
12.4 Nested Control Structures, p 138
Summary, p 139
Learning Outcomes:, p 140
Introduction
When you write a program to solve a problem you may need to branch off to different
parts depending on a condition i.e. take decisions or repeat a code segment. Such
„control structures‟ assist in serving special purposes. In addition they can be nested in
order to produce more complex and powerful programs.
If you can remember, „selection‟ is one of the three basic control constructs in
programming.
The program checks for the condition and when the condition is true, the statement is
executed and when the condition is false, the statement is ignored (not executed) and
the program continues.
131
Example 12.1: if (balance>0)
interest = balance * credit rate;
The if statement can control the execution of multiple statements using a compound
statement, or a block. (A block is a group of two or more statements enclosed in curly
braces) Any number of statements can be included inside this block given as;
if (condition)
{
Statement 1;
Statement 2;
}
Example 12.2:
if (balance>0)
{
interest = balance * credit_rate;
balance = balance + interest;
}
132
12.1.3 The ‘else if’ statement
In C, nested if statements can be used as shown below.
if ( ch>=‟0‟ && ch<=‟9‟ )
type = digit;
else
{
if ( ch>= „A‟ && ch<= „Z‟ )
type = capital_letter;
else
{
if ( ch>= „a‟ && ch<= „z‟ )
type = simple_letter;
else
type = special;
}
}
To simplify the compound statements given above else if statements can be used.
if ( ch>=‟0‟ && ch<=‟9‟ )
type=digit;
else if ( ch>= „A‟ && ch<= „Z‟ )
type = capital_letter;
else if ( ch>= „a‟ && ch<= „z‟ )
type = simple_letter;
else
type = special;
#include <stdio.h>
void main()
{
// Input two integer values
printf( "Enter integer 1: " ); /* prompt for input of an integer*/
scanf( "%d", &value1 ); /* read value1 for input 1 from user */
printf( "Enter integer 2: " ); /* prompt for input of another integer*/
scanf( "%d", &value2 ); /* read value2 for input 2 from user */
Activity 12.1
Write a program which inputs a person‟s height (in meters) and weight (in kilograms) and the
output as one of the messages: underweight, normal or overweight.
Underweight: BMI<18.5
Normal: 18.5<= BMI <=25
Overweight BMI>25
Use the formula given below to calculate a persons BMI value:
BMI (Body Mass Index) = (weight) kg/ (height*height) m
The while loop consists of either a single statement or a set of multiple statements.
When there is more than one statement it has to be included inside curly braces which
we call a block as shown below;
while (condition)
{
Statement1,
Statement2;
}
134
Use of „while‟ loop
#include<stdtio.h>
void main()
{
int x = 0;
while (x<3)
{
printf("Before increment:",%d,x\t);
x++;
printf("After increment:" :",%d,x\n);
}
}
Output: The Table 12- 1 illustrates the operations of the while loop
The do-while loop also can have a single statement or multiple statements to execute.
135
Use of „do-while’ statement
1 #include<stdio.h>
2 void main() //will display the entered number until 100 is given as input
3 {
4 unsigned short number;
5 do
6 {
7 printf( "Enter number (0 to 999): ");
8 sacnf(“%d”, & number);
9 printf"(You entered: " :",%d\n, number,”\n");
10 }
11 while ( number != 100 );
12 return 0;
13 }
14
Output:
Enter number (0 to 999): 344
You entered: 344
Enter number (0 to 999): 100
You entered: 100
In the above program, every time the message in line 7 will be displayed for the user
to enter a value and then it will be displayed as „You entered:‟(line 9), followed by the
number the user entered. This continues until the user enters the value 100. Then it
will also be displayed as „You entered: 100‟ and only after displaying the message it
will check for the condition whether 100!=100. Here as the condition becomes false it
will exit the loop and the program will be terminated.
The most common use of for loops is for situations where a variable is incremented or
decremented with every iteration of the loop.
Use of „for’ loop
136
/*Summation with for */
#include <stdio.h>
/* function main begins program execution */
} /* end for */
}
Output:
Sum is: 10
Sum is: 20
Sum is: 30
Sum is: 40
Sum is: 50
Sum is: 60
Sum is: 70
Sum is: 80
Sum is: 90
Sum is: 100
The for loop also operates in a similar way to the while loop. The loop first initializes
„number‟ to 10. Then it checks for the condition and if the condition is true it
performs the operations inside the body. Then it increments the value of „number‟ by
10 and then checks the condition (whether number <= 10) and this continues until the
condition becomes false.
Activity 12.2
1. Write a C program to find the smallest alphabet character from entered 5 alphabet
characters.
2. Modify your program to take 10 alphabet characters and find the smallest.
137
12.3 Multiple initializations and increments
In the above example, only a single variable is initialized and incremented in a for
loop, but it is possible to initialized multiple variables and they can be incremented or
decremented accordingly.
Output:
In the above example „a‟ is incremented and „b‟ is decremented at the same time and
when variable „a‟ becomes 3 the condition becomes false and the program exits from
the „for‟ loop.
a=0 b=3
a=1 b=2
a=2 b=1
138
Output: (1,1)
(1,2)
(1,3)
(2,1)
(2,2)
(2,3)
(3,1)
(3,2)
(3,3)
Activity 12.2
Write a program, which produces the following output. (Hint: Use nested loops)
******
******
******
******
******
Summary
Conditional statements are used to make an execution choice in a
programme based on a given conditions. There are two main
control structures: if and else.
The else if statements are used to reduce the complexity of
compound statements.
The iteration structures help to execute a set of statements
repeatedly. There are three main iteration structures, while loop,
do-while loop and the for loop.
All the iteration structures first perform the operations in the
initialization, and then evaluate the condition. If the condition is
true, it executes the action statement and the loop. When the
condition becomes false it exits the loop.
There are three iteration structures in C and they are slightly
different in nature because of their operation and use.
The while loop first checks the given condition, and when the
condition is true, it executes the statement or statements inside the
block.
139
The do-while loop first execute the statements and then check
whether the given condition is true. Hence in do-while loops the
statements are being evaluated at least once.
The for loop is more flexible to use than the other iteration
structures.
When a loop appears inside another loop we call them nested
control statements and conditional statements can also be included
inside loops.
Learning Outcomes:
After reading this lesson you should be able to:
branch your programming code based on conditions
design iteration in programming
140
Session 13
Basic Input Output
Contents
Introduction, p 141
13.1 The getchar() & putchar() Functions, p 142
13.2 The gets() & puts() Functions, p 142
13.3 The scanf() and printf() Functions, p 143
13.4 How characters stored in memory (ASCII), p 144
Summary, p 145
Learning Outcomes:, p 145
Introduction
Programs given as examples in the previous sessions provided very little interaction
with the user. Using the standard input and output library (stdio), which we have
already used, we will be able to interact more with the user by printing messages on
the screen and getting the user's input from the keyboard. This session outlines these
basic input and output operations used in C.
In C, there are special formatting characters which help to increase the readability of a
program and it also assists in producing special effects in the program like making an
alert sound etc. Whitespace in C also helps to increase the readability and comments
helps to properly document a program.
In the previous session, data types in C were introduced stating their data type and
size in bytes. In this session, we will also introduce simple type conversions which
help in converting one data type to another.
Input and output operations are used to interact with the user. C programming
language treats all the devices as files. So, devices such as the display are addressed in
the same way as files and following three files are automatically opened when a
program executes to provide access to the keyboard and screen.
141
Table 13- 1 Devices in C
#include <stdio.h>
int main( )
{
int c;
printf( "Enter your name :");
c = getchar( );
printf( "\nYou entered: ");
putchar( c );
return 0;
}
Output:
Enter your name : Malinka
You entered: M
142
Use of input/output of a string
#include <stdio.h>
int main( )
{
char str[100];
printf( "Enter Your Name :");
gets( str );
printf( "\nYou entered: ");
puts( str );
return 0;
}
Output
Enter your name : Malinka
You entered: Malinka
The format can be a simple constant string, or you can specify %s, %d, %c, %f, etc.,
to print or read strings, integer, character or float respectively. There are many other
formatting options available which can be used based on requirements.
143
Activity 13.1
Modify the program in session 8 activity under 8.2 (calculating the area of a triangle) to ask the
user to enter the height and the base of the triangle.
#include <stdio.h>
int main( )
{
int char = 71;
printf( "Character having ASCII value 75 is %c”, chr);
return 0;
}
Activity 13.2
Following program is designed to input five characters and find the character with minimum
ASCII value. Suppose you entered D, C, W, B, R. Minimum character is B.
#include<stdio.h>
#include <string.h>
int main()
{
char a[5];
int i=0;
char minchar;
printf("Enter characters->");
scanf("%s",a);
minchar=a[0];
for(i=1;i<=4;i++)
144
{
if(minchar>=a[i])
{
minchar=a[i];
}
}
printf("Minimum character = %c\n",minchar);
}
Summary
In this session we first discussed input and output of characters, strings and streams.
We also discussed how formatting options help to make the output more readable.
Learning Outcomes:
After reading this lesson you should be able to:
develop interactive programs using basic input and output operations.
use special formatting characters and white space in your programs.
145
Session 14
Functions in C
Contents
Introduction, p 146
14.1 What is a Function?, p 146
14.2 Declaring and Defining a Function, p 147
14.3 The „return‟ statement, p 150
14.4 Calling a function, p 150
14.5 The Execution of a Function, p 151
14.6 Assigning Default Values to Parameters, p 152
14.7 Local and Global Variables p 154
14.8 Arguments Passed by Value and by Reference, p 155
14.9 Special Functions, p 156
14.10 Advantages in Using Functions, p 157
Summary, p 158
Learning Outcomes: p 158
Introduction
As the standard of structured programming, any program is divided into a set of
modules arranged in a hierarchy defining their logical and execution-time
relationships. In a module, control must enter from its one entry point and must leave
the module from its one exit point, and must always be passed back to the invoking
module.
Program comments are used to define the overall program function and to introduce
each module by explaining its function, its data structures, and its relationship to other
modules in the program.
When writing a function, the first step is to know what tasks the function needs to
perform. In addition, a function has a specific format and it needs to be followed when
writing them.
146
A function can be called as a sub program which manipulates data and performs a
specific task in a program. Every program has at least a single function. For example
every program contains the function called main().
1 #include<stdio.h>
2 int addition (int no_of_bats, int no_of_balls);
3 void main ()
4 {
5 int answer;
6 answer = addition (5,15);
7 printf( "The result is %d”,,answer);
8 }
9
10 int addition (int no_of_bats, int no_of_balls)
11 {
12 int total;
13 total= no_of_bats + no_of_balls;
14 return total;
15 }
147
14.2.1. Declaring a function
There are three ways to declare a function: The declaration includes the function
return type, function name, and parameter list. This is also called the prototype of the
function.
1. Write the prototype into a separate file, and then use the #include
directive to include the function in the program.
Example 14.1: In the program given above, the functions like printf() (line 7) are
included in the „stdio.h‟ file and we include it in our program using #include (line 1).
2. Write the prototype at the beginning of the file (before the main method) in
which the function is used.
Example 14.2: In the above program the prototype of the function is given in line 2:
int addition (int no_of_bats, int no_of_balls);
3. Define the function before it is called by any other function. Here the
definition of the function acts as its own declaration.
In the above program the function can be included before the main() function. In a
situation like this there‟s no need of a prototype, but it is advisable to use a prototype
in programs for many reasons, such as;
If a prototype is not used, the functions need to be included in a particular order
making it difficult to maintain and change the program in the long run.
Sometimes a function may call another function and that function in return can call
the first function (function x calls function y and function y can call function x again)
In this kind of complex situations it is hard to decide which function should be
included first. Hence the function prototype needs to be declared.
Example 14.4: int addition (int no_of_bats, int no_of_balls) (line 10)
148
The function return can be a null value, which means there can be functions, which do
not return any value. These functions are declared using the keyword void.
The main function that is been used so far is a function, which does not return any
value. These functions are mostly used when we want to print a message on the screen.
Here no value needs to be returned in order to print a message. In addition, the
parameter list can be left blank if the function needs no parameters.
Example 14.5:Following function is a user defined function which prints the message
“This is a function!”
void message ()
{
Printf("This is a function!/n");
}
The void keyword can also be used in the function's parameter list to explicitly specify
that the function does not take any actual parameters when it is called.
Example 14.6: The function in example 14.5 could have been declared as:
void message (void)
{
Printf("This is a function!/n");
}
Even though some functions do not return any value, they can contain a parameter or
a list of parameters.
Example 14.7:
void PrintMessage(int messageSelect)
{
if (messageSelect == 0)
printf("Start of Programme.\n");
if (messageSelect == 1)
printf( "End of programme.\n");
}
The body of a function includes the statements (computation steps) inside the curly
braces {} which contains the instructions on how to perform a specific task.
Example 14.8: In the program given line 12 to 14 is the body of the function.
int total;
total= no_of_bats + no_of_balls;
return total;
149
14.3 The ‘return’ statement
In the example given above, in line 14, the return keyword has been used followed by
an expression. This is called the „return statement’. It should be declared inside the
function body. The return statement has a general format.
return expression;
The „expression’ is the value returned by the function. The type of this value should
be same as the return type of the function.
Example 14.9: In the program given above, the return type of the function is an
integer (int addition). Hence the return value „total‟ should also be an integer value.
For a function which the return type is void, expression should also be 0 or empty.
The main function can also be written as given below.
Note: In declaring the prototype of a function, it is not necessary to include the names
of the parameters. The type of the parameter list is also sufficient.
int calculate (int, int);
Example 14.11: The function called „int addition()‟ has only two parameters which is
int no_of_bats and int no_of_balls. In the calling function inside the call operator
brackets „()‟ there should be only two arguments which are 4 and 5.
Not only the number of parameters but also the type of the parameter should match
the function parameters.
150
Example 14.12: Both function parameters no_of_bats and no_of_balls are of type int
(line 10) Hence the argument values also should be of type int. (line 6). It cannot be a
floating point or other type of a value.
Consider the example program we examined first. First it declares the variable called
„answer‟ of type int. Then it branches to the prototype of the function called „addition‟
in line 2.
151
int addition (int no_of_bats, int no_of_balls);
When the function is identified by the program first, the above function prototype tells
the compiler that the program passes the value of two integers to the function so that
the „return value‟ must be assigned to an integer variable. Then the program execution
passes to the function definition which starts from line 10.
The arguments are evaluated and their resulting values are assigned to the
corresponding parameters. (The values 5 and 15 are passed to „int no_of_bats’ and int
no_of_balls respectively) The body of the function is then executed. (Add
no_of_balls and no_of_bats and store 20 in the variable called „total’). Finally if there
is a value to be returned (line 14), it is passed to the caller. (the value 20 is returned to
the variable called „answer’)
answer = addition ( 5, 15 );
After the last statement of the function has been processed (the return statement in
line 14), the execution resumes on the next line after the call to the function (return to
line 6) and prints the answer, “The result is 20”.
Activity 14.1
2. Write a program which takes an integer value between 1 and 10 as the input
and calculate its factorial and give the answer as the output.
Use the formula given below:
Factorial(0)=1
Factorial(n)=n*factorial(n-1)
Note: When the user enters a value out of the given range it should display an error message and
the program should again ask the user to input a valid integer.
A programmer can break the above rule by defining default parameter values in the
function declaration. Using the assignment operator (=), default values can be
152
assigned to the function parameters. Any or all of the function's parameters can be
assigned default values.
When sufficient number of arguments is not supplied for the function, the default
parameter values are being used but if a value is specified, this default value is
ignored and the passed value is used instead.
If any of the parameters do not have a default value, no previous parameters can have
a default value.
A default value to „x‟ can be assigned only after assigning default values to both „y‟
and „z‟. A default value to „y‟ can be assigned only after assigning a default value to
„z‟.
Use of default parameters
In the example given below, in line 3, for „b‟ and „c‟ default parameters have been
assigned. In the first function call in line 7, since the value 12 is passed as an
argument to the function, „a‟ is assigned to 8. Since there are no values passed for „b‟
and „c‟, it takes the default values which is b=9 and c=10. Then in the first average
calculation the result becomes 9 (Refer line 15: (8+9+10)/3 = 9).
1 #include<stdio.h>
2 //function prototype
3 int average (int a, int b=9, int c=10);
4 void main ()
5 {
6 //function call and result display
7 printf("First Average %d", average(8));
8 printf("Second Average %d", average(20,4,6));
9 printf("Third Average %d", average(1,4));
10 }
11 //function declaration
12 int average (int a, int b, int c)
13 {
14 int result;
15 result=(a+b+c)/3;
16 return result;
17 }
Output:
First average: 9
Second average: 10
Third average: 5
153
In the second function call in line 8, since all the values have been passed as an
argument the compiler ignores the default values and the answer becomes 9 (Refer
line 15: (20+4+6)/3 = 10).
In the third function call in line 9, values 1 and 4 are assigned to „a‟ and „b‟
respectively and the default value of 10 is assigned to „c‟. Here also the default value
of „b‟ is ignored since a value has been passed by the function call. Hence the answer
is 5 (Refer line 15: (1+4+10)/3 = 5).
Activity 14.2
Write a function which calculates a volume of a cube. Assign default parameters only to its width
and length.
Call the function 3 times inside the main method.
1. Pass only one argument (both default parameters will be called)
2. Pass two arguments (only one default parameter will be called)
3. Pass all three arguments
Write a separate function which prints the message “Volume of the cube:”
Variables declared outside the body of any other function is considered as global
variables and can be accessed inside any function in the program. These variables
said to have „global scope’.
However,
if a function has a variable with the same name as a global variable, the
name refers to the local variable (not the global variable) when used
within the function.
154
the program exit its scope. The memory space for global variables is
reserved prior to commencing of the program execution, whereas
memory space for local variables is allocated only for the time that the
variables are being used.
Output:
Total (inside main function): 9
Total (inside add function): 24
In line 4, two global variables called „x‟ and „y‟ are declared and initialized to 4 and 5
respectively. Inside the function called „addFunction’, a variable called „y‟ is
declared again and initialized to 20. This is a local variable, which is local to the
scope of the „addFunction‟. In line 7, in adding „x‟ and „y‟, the program refers to the
global variables and the answer is 9 (4+5).
In the function call (line 8), „y‟ variable refers to the local variable, which is equal to
10 (refer line 12). Since there is no variable called „x‟, which is defined inside the
function, „x‟ refers to the global variable as they can be accessed inside any function
in the program. Hence in the function call, the answer is 24 (4+20).
155
Example 14.16:
int x=10, y=20;
addition(x,y); //function call
Example 14.16 shows part of a program. During the function call, values 10 and 20
are passed into the function arguments „value1‟ and „value2‟ respectively. If we make
changes to the function arguments („value1‟ and „value2‟) inside the function, it does
not affect the variables „x‟ and „y „which are defined outside the function because „x‟
and „y‟ variables are not passed into the function but only their values are passed.
In passing values as references to a function, ampersand (&) sign is used before the
function arguments that need to be passed as references. When passing by reference,
the variable itself is passed into the function and not the copies of their values. Hence
all the changes that have been made to the function arguments inside the function
straight away affect the variables that have been passed to the function. Consider the
example given below.
Example 14.7:
int x=10, y=20;
counter (x, y);
void counter(int &value1,int &value2)
{
++value1;
++value2;
}
In the example given above, the ampersand (&) mark has been used before the
function arguments („&value1‟ and „&value2‟). It specifies that the arguments need to
be passed into the function by reference instead of by value. Inside the function, both
function arguments „value1‟ and „value2‟ has been incremented. Those increments
affect the variables „x‟ and „y‟ which is defined outside the function.
156
14.9.1 Recursion
Recursion is the ability that the function has, which could call itself. In the function
definition there is a point where the function calls to that very same function and
repeats the same code. In programming this method is useful in many tasks like
sorting and calculating.
For this purpose the C library has a standard string class. In order to use the functions
provided with it, the standard header file called the „string‟ needs to be included in the
program. Some of the string handling functions are strlen – find length of a string,
strcpy – copy a string, strcmp – compare two strings, strcat – concatenate two strings,
etc.
157
Summary
A function can be called as a sub program which manipulates data and
performs a specific task in a program.
There are two types of functions. They are user-defined functions and built in
functions.
There is a general format for a function. This includes function name, return
data type, parameters and a set of statements which is the body of a function.
Some functions do not contain any parameters and every function doesn‟t
return a value.
Before using functions, they need to be declared and defined. The definition of
a function includes the header and its body.
There are three ways to declare a function. They are, writing the prototype at
the beginning the file, defining the function before it is called by any other
function and using the #include directive.
Function call consists of function name followed by the call operator brackets
„()‟.
The execution of every C program starts from the main function.
The programmer can define default parameter values in the function
declaration.
Learning Outcomes:
After reading this lesson you should be able to:
declare and define functions
pass parameters into functions
return a value from a function
158
Session 15
Data Structures
Contents
Introduction, p 159
15.1 Abstract Data Types and arrays, p 159
15.2 Declaring and Accessing Arrays, p 160
15.3 Data Structures, p 162
15.4 Important General Characteristics Relating to Data Structures, p 166
Summary, p 167
Learning Outcomes, p 167
Introduction
By now you are very familiar with data types such as integer, which is built into the C
language. Its definition comprises of two parts.
Firstly, the set of all possible values a variable or a constant of that type may
take
Secondly, the operations that can be performed on such values (For example
operations such as multiplication, division, assignment, various forms of
comparison, etc).
If we are to write programs that need to use data types that are not defined within the
language, we must define these types ourselves. To make sure that our programs will
do what we want, we should make such definitions rigorous.
Therefore, when we define any data type, we have to describe what values it may hold,
and what operation are available to operate with it. In this session we will discuss how
to define such new data types with possible applications.
159
Thus when we define any data type, we will describe what values it may hold and
what operation are available to deal with them.
Figure 15- 1 shows a char array called myArray. Assume that this array contains 10
elements. Any one of these elements may be referred to by giving the name of the
array followed by the position number of the particular element in square brackets - [].
The first element in every array is the zeroth element. Thus, the first element of
myArra is referred to as myArray [0], the second element of myArray is referred to as
myArray [1], and, in general, the ith element of myArray is referred to as myArray [i
- 1].
Array names, like other variable names, can contain only letters, digits and
underscores. Array names cannot begin with a digit.
The position number contained within square brackets is more formally called a
subscript (or index). A subscript must be an integer or an integer expression.
To tell the computer to reserve 10 elements for integer myArray, the definition
Char myArray[10]
is used.
The following definition reserves 100 elements for characters for myArray.
Char myArray[100]
160
/* initializing an array */
#include <stdio.h>
/* function main begins program execution */
int main( void )
{
int numberArray[ 10 ]; /* array of 10 integers called numberArray */
int count; /*counter */
/* initialize elements of array called numberArray to 0 */
for ( count = 0; count < 10; count++ )
{
numberArray[count] = 0; /* set element at location i to 0 */
} /* end for */
printf( "%s%13s\n", "Location", "Value" );
/* output contents of numberArray as a table */
for ( count = 0; count < 10; count++ )
{
printf( "%7d%13d\n", count, numberArray[ count ] );
}
return 0; /* indicates successful termination */
} /* end main */
If the array size is omitted from a definition with an initialized list, the number of
elements in the array will be the number of elements in the initialized list.
Activity 15.1
Ten integers should be entered into an array named myFirstArray by the user and then find the
number of zeros stored in myFirstArray.
1) Draw a flow chart indicating begin, end, inputs, iterations and conditional control structures.
2) Write a C program for the flow chart including header files, main function, inputs, outputs,
iterations and conditional control structures. Write the program with a fewest number of lines in the
program.
161
This idea can be extended to multi dimensional arrays. Here we restrict our attention
to 2-D arrays. A two dimensional array of integers can be declared in C as;
int DataArray [3][4] ;
Column 1 Column 2 Column 3 Column 4
Row 1 [0][0] [0][1] [0][2] [0][3]
Row 2 [1][0] [1][1] [1][2] [1][3]
Row 3 [2][0] [2][1] [2][2] [2][3]
The above array has 3 rows and 4 columns and can hold maximum of 12 elements.
Since Arrays have a fixed size after declaring it, it is important that array size needs to
be specified in advance.
As another example, in a C array of char, the data elements are relatively simple –
characters – although a character has a bit structure.
At the highest-level, we prefer to deal with abstract data structures. This means that
we are not interested in how the structures are to be stored and handled in the
computer, but concerned only with the user‟s view of the structure. The users‟ view
should in fact be shielded from any implementation details. He/she should think of the
structures as a container for his/her data items, together with operations available to
him/her to access the items.
In addition to the operations on one set, we may decide to include in our abstract
definition operations between sets such as union, intersection difference for example.
162
15.3.1 Definition of the Data Structure
A data structure is a collection of related information nodes (elements, components,
entries, items, members, fields) which may themselves be (internally) structured.
Common data structures include arrays, records, lists, queues, stacks, sets, strings.
As with scalar data (integer, real, char, Boolean) each type of structure has an
associated set of operations.
e.g. Joining and leaving queues.
Element use (access) and change (update) for arrays.
Initialisation, push, pops for stacks.
Example 15.1:
enum workingDay {Monday, Tuesday, Wednesday, Thursday, Friday};
Every enumeration has an integer value. The default starts with 0 and the rest will
count up from there. Monday has a value of 0, Tuesday has the value 1, Wednesday
has the value 2 etc.
A value can also be initialized to an enumeration.
Example 15.2:
enum workingDay { Monday=50, Tuesday, Wednesday=88, Thursday, Friday=900 };
163
printf("\n Clubs value: %d", clubs);
printf("\n Diamonds value %d:", diamonds);
printf("\n ");
}
Output
Spades value 5
Hearts value: 6
Clubs value: 10
Diamonds value: 11
In the above program, when the variable „spades‟ is assigned to 5, the next value is
automatically assigned to 6. When clubs is assigned to 10, Diamonds will be
automatically assigned to 11.
Activity 15.2
Write a program that use „enumeration‟ type to hold values for months of the year.
15.3.3 Structures in C
Say that you want to store information about a student: his/her name, NIC number,
year of birth, and email address.
For this, you can create different variables; name, NIC number, year of birth, and
email address to store these information separately.
But if you need to store information of more than one student, you will have to create
different variables for each information per student like: name1, NIC number1, year
of birth1, email address1, name2, NIC number2and, year of birth2, email address2 etc.
164
Syntax of structure
struct structure_name { data_type variable_1; data_type varaiable_2; . .
data_type varaiable_n; };
Example 15.3:
struct Student{char name[55]; char NIC_number[10]; int year_of_birth; char email
_address[15]; };
To access a part of the structure, for example students‟s name, we use the format
student1.name
struct Student
{
char name[55];
char NIC_number[10];
int year_of_birth;
char email_address[15];
};
int main()
{
struct Student student1 = {0}; //Initializing to null
165
Activity 15.3
The keyword typedef is used to create an alias or a new name for an existing type or a
user defined type. It is an advance feature in C language.
#include<stdio.h>
main()
{
typedef unsigned short int USHORT;
USHORT val1 = 4;
USHORT val2 = 688;
USHORT val3 = 34;
USHORT total = val1+val2+val3;
printf("\n Total of the values : %d", total);
printf("\n ");
}
In the above example total of three values are being calculated. Here, USHORT
creates a synonym for „unsigned short int‟. This has reduced the tedious, repetitious
writing „unsigned short int‟ in rest of the program. This also reduces the user errors
that can happen in writing the same words over again in the programme.
166
If the nodes are of different types then the structures are called heterogeneous
structures
e.g. Structs
In the case of homogeneous structures, associated operations often apply to the each
element of the structure in tern or even potentially, in parallel, whereas such repetition
is not possible in the heterogeneous context. It should be noted that (heterogeneous)
records may be use to build structures such as lists, and trees which are collectively
homogeneous.
Some data structures are built into programming languages, whilst others are not,
depending on the language. C for example has built in arrays, strings, etc. Where
structures are built into a language, the compiler must be designed to map them to the
language in which it is written e.g. machine code. The data structures which are not
built into the programming languages have to be programmed by devising a suitable
storage scheme in term of the structures which are built in implementing the
operations as procedures and functions.
Summary
User defined data types are called Abstract Data Types (ADT)s. Two such examples
are enumeration type and struct.
Typedef keyword is used to create an alias or a new name for an existing type or a
user defined type.
An array is a set of elements, each of which holds the same type of data. These data
elements are stored in consecutive places in the memory and must be declared before
it is used. When declaring arrays there are two things that need to be taken into
consideration. That is:
The type of data items that are required
The number of data items required
Some data structures can contain values of only one data type, which are called
homogenous where as some other can contain values of different types.
Learning Outcomes
After studying this session you should be able to,
briefly explain the concept of a data structure
define and apply arrays in programs
apply enumeration data type in programs
apply struct data type in programs
use typedef function in programs
167
Session 16
Dynamic Data Structures
Contents
Introduction, p 168
16.1 Data Structure Storage Schemes, p 168
16.2 Pointer Concept in C, p 169
16.3 Linked List, p 172
Summary, p 177
Learning Outcomes, p 177
Introduction
The most important characteristic of any data structure is its capacity for structural
change. Some structures remain structurally fixed throughout their existence. i.e. they
are not permitted to grow or shrink between initial creation and eventual destruction.
These structures are called STATIC structures. Those structures which may be
changed are called DYNAMIC structures. In this session we will discuss how to
define DYNAMIC data structures.
168
Figure 16- 1 Sequential representation
The value of the linked method is in representing structures whose shape and size may
vary arbitrarily during their lifetime (dynamic structures), particularly when several
structures have to share and area of store. The sequential method is appropriate for
static structures.
It is not practical for a general purpose language to provide a range of data types
covering each possible class of linked data structure. So, C provides the user with a
mechanism called pointers with which he/she can program linked structures and
operations applicable to them.
A pointer contains the address of a data construct. Therefore, pointers are of the same
size regardless of what they are pointing to.
169
In declaring pointers, the pointer type needs to be declared first (int, char, float etc),
followed by the name of the pointer. Before the pointer name, an asterisk (*) is used
to denote that this is a pointer and not a variable. This asterisk mark is also called the
„value of operator‟.
Number of pointers and variables can also be declared at the same time.
Example 16.2: int *p1, *p2, result;
In the example given above, first an integer type pointer (*p1) and a variable called
„result‟ are declared ((a) and (b) of Figure 16- 3. Then the variable is assigned the
value 10 and the address of the variable (&result) is assigned to the pointer „p1‟((c)
and (d) of Figure 16- 3. This is further explained using the diagram given below and
using the concepts on how the pointers are arranged in the computer memory.
Figure 16- 3 Declare pointer and result next -assigning result to pointer
#include <stdio.h>
int main( void )
170
{
int result; /* result is an integer */
int *p1; /* p1 is a pointer to an integer */
result=10;
p1 = &result; /* p1 set to address of result */
printf( "The address of result is %p",&result);
printf("\nThe value of p1 is %p",p1 );
printf( "\nThe address of p1 %p\n",&p1 );
return 0; /* indicates successful termination */
}
output
The value of result is 10
The address of result is 0x7ffc46a9fcec
The value of p1 is 0x7ffc46a9fcec
The address of p1 0x7ffc46a9fcf0
Graphical representation of the above program is shown in Figure 16- 4. Value of the
variable “result” is 10 and its address is 0x7ffc46a9fcec. The value of the pointer “p1”
is 0x7ffc46a9fcec and it is the address of the variable “result”. Address of the pointer
“p1” is 0x7ffc46a9fcf0.
#include <stdio.h>
a = 7;
aPtr = &a; /* aPtr set to address of a */
171
printf( "The address of a is %p" "\nThe value of aPtr is %p",&a ,aPtr );
printf( "\n\nThe value of a is %d" "\nThe value of aPtr is %d",&a ,aPtr
printf( "\n\nShowing that * and & are complements of "
"each other\n&*aPtr = %p"
"\n*&aPtr = %p\n",&*aPtr ,*&aPtr );
Output
The address of a is 0012FF7C
The value of aPtr is 0012FF7C
The value of a is 7
The value of *aPtr is 7
Though arrays can be used to store linear data of similar types, but arrays have
following limitations.
172
1) The size of the arrays is fixed: So we must know the upper limit on the
number of elements in advance. Also, generally, the allocated memory is equal
to the upper limit irrespective of the usage. In a linked list there is no need to
define the total requirement of nodes required at the beginning. Nodes can be
added as and when needed.
This will effectively create a new head to the list with a new value, and keep the rest
of the list linked to it.
173
Traversing a list
Let us write a function that prints out all the items of a list. To do this, we need to
traverse the list from start to the end and also need to use a current pointer that will
keep track of the node we are currently printing.
That is,
1. Print the value of the first node
2. set the current pointer to the next node
3. print the value pointed by the current pointer and set the pointer to the following
node.
4. print again, and repeat the process until we reach the end of the list (the next node
is NULL).
Activity 16.1
Write a program to create linked list called myList and add 3 integer numbers.
If you master the art of declaring a linked list and traversing a linked list, then you can write
programs for any other operation to do with one. To understand how to define few more functions,
let us declare a list which has a key as well as a data part.
To find the length of the list we will have to traverse the whole list counting the nodes.
When remove the first data element from the list we need to change the location of the
next node to be pointed by the head carefully as to not to lose the list.
174
A complete C program to do few operations on a list
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
struct node
{
int value;
int key;
struct node *next;
};
while(ptr != NULL)
{
printf("(%d,%d) ",ptr->key,ptr->value);
ptr = ptr->next;
}
printf(" ]");
}
void main()
{
insertFirstNode(1,5);
insertFirstNode(2,10);
insertFirstNode(3,15);
insertFirstNode(4,100);
insertFirstNode(5,150);
while(!isEmpty()) {
struct node *temp = deleteFirst();
printf("\nDeleted value:");
printf("(%d,%d) ",temp->key,temp->value);
}
printf("\nList after deleting all items: "); //print list after deleting all values
printList();
176
Activity 16.2
Write a program to search for „a‟ in a linked list which has values „d, e, c, a, h,i‟ .
Hint: To remove a specific item from the list, either by its position or by its value, we will need to go
over all the items, to find out whether we reached the node before the element that we wish to
remove. This is because we need to change the location to where the previous node points to as
well.
Summary
A pointer is a reference whose value refers to another value stored somewhere in the
computer memory. They do not store values directly like normal variables but stores a
reference of another value. Thus, a pointer contains the address of a data construct.
A linked list is a linear data structure that can be created with pointers. To manipulate
a linked list a special set of operations must be defined.
Learning Outcomes
After studying this session you should be able to,
define Pointer data type in C
declare, initialize and use pointers in programs
declare a linked list and perform basic operations such as inserting, deleting
values, printing the list and finding the length
177