Nuk
Nuk
COMPUTER PROGRAMMING
& NUMERICAL METHODS
UE 261
Lecture Notes
Addis Ababa
Ethiopia
June 12
Ethiopian Civil Service College Computer Programming & Numerical Methods
Evaluation
Evaluation: Instructor
Assignment (5x2%) 10 % Name: Shimelis Behailu (M.Sc.)
Project (3x10%) 30 % E-mail: shimelisbehailu@yahoo.com
Mid-Exam 20 % sbehailu@nilebasin.org
Final Exam 40 % Tel. +251-911-411357 [Mob]
Total 100 % +251-116-267552 [Res.]
Text Book:
References:
Computer Programming
Numerical Methods
Numerical Methods for Engineers, S.C. Chapra, and R.P. Canale
Numerical Methods for Engineers and Scientists, A.C. Bajpai, I.M. Calus and
J.A. Fairley
Elementary Numerical Analysis, S.D. Conte and C. de Boor
Numerical Recipes, by W. H. Press et al
Numerical Analysis – Schaum’s Outline Series
Web URL
http://www.bestsamplequestions.com/technical-questions/cpp-sample-questions/cpp-
sample-questions.html
http://www.csse.monash.edu.au/~jonmc/CSE2305/index.html
Table of Contents
PART ONE: COMPUTER PROGRAMING ..................................................................... 1
1. Introduction to Computer Programming ..................................................................... 1
1.1. Introduction ......................................................................................................... 1
1.2. Information/Data Transfer .................................................................................. 1
1.3. Computer Organization ....................................................................................... 2
1.4. What is programming? ........................................................................................ 3
1.5. Why do we learn programming?......................................................................... 6
1.6. Algorithm and Program ...................................................................................... 6
1.7. Classification of Programming Languages ......................................................... 7
1.7.1. Machine Languages .................................................................................... 7
1.7.2. Low-level Languages .................................................................................. 8
1.7.3. High-Level Languages ................................................................................ 8
1.8. Program Process................................................................................................ 10
1.9. Running a computer program ........................................................................... 11
1.10. Program Development .................................................................................. 12
1.10.1. Qualities of a good program ..................................................................... 12
1.10.2. Program development stages .................................................................... 14
1.11. Representation of Algorithms ....................................................................... 17
1.11.1. Representation Algorithms using Step form ............................................. 17
Example: ............................................................................................................... 17
1.11.2. Representing Algorithms using Pseudo-code ........................................... 17
Examples:.............................................................................................................. 20
1.11.3. Representing Algorithms using Flowchart ............................................... 24
Examples:.............................................................................................................. 26
1.12. Review Exercise and Assignment ................................................................. 29
2. Introduction to C++ .................................................................................................. 30
2.1. History of C++ .................................................................................................. 30
2.2. C++ Program Structure ..................................................................................... 31
2.3. Basic Elements of C++ Program ...................................................................... 33
2.4. Names ............................................................................................................... 34
2.4.1. Identifiers .................................................................................................. 34
2.4.2. Keywords .................................................................................................. 34
2.5. Comments ......................................................................................................... 35
2.6. Input/Output, I/O............................................................................................... 35
2.6.1. Input Statement ......................................................................................... 35
2.6.2. Output Statement ...................................................................................... 35
2.6.3. I/O manipulation ....................................................................................... 36
2.7. Variables ........................................................................................................... 37
2.7.1. Data types.................................................................................................. 37
2.7.2. Declaration of Variables ........................................................................... 37
Integers .................................................................................................................. 38
Real Numbers: ...................................................................................................... 39
Characters: ............................................................................................................ 40
String ..................................................................................................................... 41
2.7.3. Scope ......................................................................................................... 41
2.8. Constants ........................................................................................................... 42
2.9. Special characters (Escape sequences) ............................................................. 43
2.10. Review Exercise............................................................................................ 44
List of Tables
Table 2-1 List of some C++ keywords ............................................................................. 34
Table 2-2 Data types and their value range ...................................................................... 37
Table 2-3 List of Escape sequences in C++ (Special characters) ..................................... 43
Table 3-1 C++ Arithmetic operators ................................................................................. 45
Table 3-2 Relational operators .......................................................................................... 46
Table 3-3 Logical operators .............................................................................................. 46
Table 3-4 Bitwise operators .............................................................................................. 47
Table 3-5 How the bits are calculated in 8-bit machine ................................................... 48
Table 3-6 Increment and decrement operators.................................................................. 48
Table 3-7 Compound Assignment operators .................................................................... 49
Table 3-8 Operator precedence levels............................................................................... 51
List of Figures
As an end user, one can buy a PC, Personal Computer, and use it by loading the
necessary software. We have been using sophisticated word processing programs,
spreadsheet software, engineering design software and many more. We’ve been enjoying
all the pleasant features of these programs. But today, let’s think about one question.
Who is behind these programs?
In this regard, some people give all the thanks to the computer itself. These people feel
that computer is a magic box sensing its environment and capable of performing anything
by itself once it is constructed and be a computer. They think that the most venerable
people are the people that construct the hardware part of the computer system. They are
not able to see that software is also playing a significant role in making the computer a
computer. Of course, we couldn’t blame them since they should see what they could see.
But what is the realty?
The answer to the previously raised question is very simple. It is the programmer who is
behind these sophisticated programs. Programmers are people who prepare and write set
of instructions to solve a given problem. Unless these people prepare the set of
instructions which will be followed by the computer to solve every individual problem,
no one could use the computer to perform any of the tasks.
things that you are saying may not tell to the other party the correct message. In short,
man-to-man communication is contextual. It depends on the current situation and
understanding of the other party.
But if we consider the information transfer between man and the machine (computer),
then it is more consistent and less ambiguous. The tools used in this case are
programming languages. Programming languages have limited number of words and
rules. To instruct the computer, you need to use one of the existing programming
languages correctly. ‘Correctly’ implies by following the keywords and the rules strictly.
Example of programming languages are BASIC, ForTran, Pascal, C, C++, Visual Basic,
C#, etc.
External
Memory
Internal
memory
Input Output
Processing unit
ALU
CPU
The processing unit or processor is the part of the computer that controls all the other
parts. The processor accepts input values and stores them in the memory. It also interprets
the instructions in a computer program. If we want to add two values, the processor will
retrieve them from the memory and send them to the arithmetic logic unit or ALU. The
ALU performs the desired addition, and the processor then stores the result in the
memory. If we desire, we may also direct the processor to print the result on paper. The
processing unit and the ALU use a small amount of memory, the internal memory, in
their processing; most data is stored in external memory. The processor, internal memory,
and ALU are collectively called the central processing unit or CPU. Thus, a
microprocessor is a CPU, but a microcomputer is a CPU with input and output
capabilities.
The following are few of the software that are in common circulation:
o Word processors: MS Word, WordPerfect
o Spreadsheets: MS Excel, Lotus123
o Computer aided design: AutoCAD, SAP
o Geographic Information System: ArcInfo, ArcView, IDRISI
Programs are written and fed into the computer in a certain specific rules. These rules,
which must be followed in writing a program make up the programming language. Read
and understand the following analogy example:
Example 1:
Suppose that there is a boy named Bob. Bob can understand only some instructions, but
amazingly Bob can do anything if you can instruct him using only those instructional
words. Assume that Bob also knows some other common descriptive English words.
Note that each job should be disintegrated into instructions, which can be described using
only these words. The instructions with their meanings (for Bob) are the following:
Instruction Meaning/description
Ask Inquire the stated thing.
Record Put (save) it in your mind.
Add Add the given two numbers.
Subtract Subtract two given numbers.
Multiply Multiply the given numbers.
Divide Divide the given numbers.
Speak out Speak the mentioned thing.
Job 1: Say Bob should add two numbers for your friend. Instruct him (tell him the right
things to do, in their right order with only the words he can understand) to perform this
job.
Instructions:
What shall you tell him to do first?
He must get the numbers to be added. Where can he get this information? It is just from
your friend and to have these numbers, he has to ask your friend to tell him. How? By
which word can you instruct him? Ask is the word used to tell Bob to ask something.
Therefore, the first instruction has to be:
Ask like ‘Tell me the two numbers’.
As your friend tells him the numbers, Bob should be able to record the numbers in his
mind to add them later. So for Bob you have to tell him to record the numbers. And the
second instruction will be the following:
Record the two numbers.
And the other instruction can be followed as the following:
Ask like ‘Tell me the two numbers”.
Record the two numbers.
Add the numbers.
Record the sum.
Speak out the sum.
Job 2: I need this: Bob will take from me two numbers and tell me the sum of the
numbers, the result when the second number is subtracted from the first one, the product
of the numbers and the quotient found when the first number is divided by the second
one.
Instructions:
You may instruct Bob as the following:
Ask her two numbers
Record the numbers
Add the numbers
Record the sum
Subtract the second number from the first one.
Record the difference
Multiply the numbers
Record the product
Divide the first number by the second one
Record the quotient
Speak out sum
Speak out the difference
Speak out the product
Speak out the quotient
OR
Both set of instructions have the same final output, but their approach is different. So, one
can have another approach to get the same output. This shows us problems (jobs) can be
solved using different methods. We will discuss the significance of this truth later.
Here Bob is the computer, you (who tells (prepare and store) him the instruction in their
right order) are the programmer, and the one who initiate Bob with the help of some
action is the end user of the program. The process of telling him the instructions is
programming.
From Bob Instructions to Computer Programs
Computers are just like Bob (may be primitive than him) but obedient enough to listen to
instructions and perform them with a great speed and accuracy. Because of their speed
and accuracy, they seem to be special (of course they are). If the output of a certain
computer program has an error, then 99% the problem should be from you, either from
the instructions stored or the entered user’s data. If you instruct Bob to ask the question,
‘kick me once’, to the user and expects Bob to say, ‘Enter the first number’, then that is
your problem. Laugh at yourself and edit the instructions or if you are the end user then
edit your input. Bob is always volunteer and ready. So, as a programmer, all your
instructions should be clear and unambiguous.
So, we learn programming because it is still our job to solve problems and present the
solutions in a form which is completely understandable for the computer. Actually,
solving problems is the most difficult part. But it is also necessary to present solutions
using instructions written in programming languages.
You might say
“Why, in the world, we trouble ourselves to solve our problems, then again to
write instructions in programming languages and ask (may be beg) the
computer to carry out the instructions, after we have been through much to
solve the problems?”
It is because computers are fast, accurate, and efficient than us. Once problems are solved
and presented for the computer, the computer can repeatedly work on it efficiently, with
high speed and accuracy. The other reason is that all people cannot be programmers. The
available programmers must solve problems and prepare instructions for the computer to
solve problems for large number of end users. Definitely, the number of end users will be
greater than the number of programmers. Hence, programmers are responsible for the
preparation of programs for the end users.
You need to know something. Programming is very interesting but it has also challenges.
When you program, you will fight to hide the ‘pseudo intelligence’ of the computers by
making them to speak, listen, communicate and react with a very good user-interface.
But programs are set of instructions which are presented using one of the programming
languages using the keywords and following the rules.
A machine instruction usually has got two parts namely the opcode (operation code) and
the operand addresses. The opcode specifies the thing that should be done and the
operand addresses will lead to the operands needed to the function specified in the
opecode.
Example: 11000001
This is an eight-bit machine instruction. The first three digits (110) represent the opcode
which is the code for the move function in this particular case. The move function
instructs the computer to move some data from one place to another. Since moving needs
the specification of two places (source and destination of the data to be moved), we
expect to have two operands. Consequently the next two digits (00) represent the first
operand and the other remaining three bits (001) represents the second operand. In this
case, both operands are registers, which are very small memory cells found within the
CPU. 00 is the code for the register named AX and 001 is for BX. Finally when this
instruction is translated and practiced, data which was saved in BX will be moved to AX.
Obviously, machine languages are not completely pleasant. Some of the limitations and
problems of machine languages are given below:
1. Programming with machine languages is very boring.To write a program that can add
two integers using machine language, you might sit, bend your head and scan the
opcodes and operands used in each instruction. It is a must to remember the
opcode of the different limited number of functions and you have to keep track
of the storage locations of data.
2. It is an error-prone process. No one blames for frequent errors when you are writing
programs in machine languages. If you simply forget a 0 or a 1, then that is going
to be a big bug.
It is very clear that remembering this code is more difficult and unpleasant than the
previously given low level language instruction (Add Ax,Bx). Therefore, the main
difference between low-level languages and machine languages is that machine
languages use binary codes (0’s and 1’s) where as low-level languages use symbolic
language.
But it doesn’t mean that the computers started to understand directly low-level language.
They still understand directly only machine language. Therefore, there will be a
translation process from low-level instructions to machine instructions. This translation is
done by using a special translation program.
Limitations of low-level language include:
1. It is machine dependant. Assembly language is a very good example of low-level
languages. It is totally machine dependant meaning that it works only on machines of
particular type. As an example, take Assembly 8088/86 which works only on machines
having microprocessor of the 8088/86 family.
2. Even if the instructions are easier to work with (relative to machine language), many
instructions are still needed to perform a very simple task. This is because the
correspondence between machine languages instructions and low-level
languages instructions is one-to-one.
1.7.3. High-Level Languages
Because of the limitations of low-level languages, programming was still a very tough
task. Eventually, low-level languages had to be replaced by other convenient languages.
What we said happened and the languages are called High-level programming languages.
languages, you will have set of keywords which look like English words. In addition to
that, there will be different rules to use the available commands (keywords).
Example:
Pascal is one of the high-level programming languages. Try to see the following small
program written in Pascal to observe that the keywords used have similarity with English
words.
Program First
Begin
Writeln (“This is my first program”);
Write (“Thank you”);
End.
The first line of this program shows the name of the program. The next line remarks the
beginning of the program. The third and the fourth lines will print the texts specified on
the screen, i.e. what ‘write’ or ‘writeln’ (read as write line) means in Pascal. The last line
shows the end of the program. Additionally, this program consumes only five lines where
as if the same program is rewritten in Assembly, it might take more than 10 lines
(instructions).
2. In most cases, it does not allow to program system software such as operating
system. This is because when using high - level language the programmer has no
direct control over the memory locations, which is required in system software
development. In case of machine languages (or low-level languages) you can
easily keep track of the RAM of the system. For example Mov [1000],ax will copy
the data in the register Ax to the memory location 0004. When using high-level
languages and when copying and moving data, it is the operating system that
tracks the memory for your program.
Machine Dependent
Machine Independent
+ other object
+ test data
+ Libraries
OS loads
Assembler
Compilers
modules
Links
Source
Object Executable
code Output
Code file
Link Runtime
Syntax error
errors errors
+ Warnings
ii. Compiler: compilers translate high-level language source code into their equivalent
object code. Compilers translate all the source code into an object code before loading the
program into RAM so that it can be executed.
iii. Interpreter: this one has the same function as compilers. The difference here is the
way the translation is handled. The translation will be instruction by instruction. A single
instruction will be taken and translated into an object code instruction and automatically
loaded into the RAM. Then, the next instruction will continue.
b. Loading and Linking: The translated object program will be loaded into the RAM so
that it could be available for the CPU. If there are any separate program units (like the
different built in header files of C++), they will also be linked in this stage to form a
single complete executable program.
Source
Program
Assembler or
Compiler
Object
Code
Note: In C++, the source code will be saved with extension .cpp. Then when the
compiler compiles the source code, it will produce a file with same filename but with
different extension which is .obj. This is the object code file. Then the linker will load
and link the object code to create a file with the same name but with extension .exe. This
is the executable file which means the file containing the code which is ready to run. It is
the executable file which will be executed (processed) by the CPU.
Once you have compiled your program without errors, a linkage editor program performs
the final preparations so that it can be submitted to the execution step. It is in the
execution step that the statements are actually performed. Errors can also arise in the
execution step; these are called logic errors, run-time errors, or execution errors. These
errors (also called "bugs") are not in the statement syntax but are errors in the logic of the
statements, which are detected only when the computer attempts to execute the statement
In short, programmers should develop programs. But all programs are not good enough.
Therefore, programmers should follow certain steps, procedures and strategies to produce
best programs as much as they can. A computer stream that studies about these
techniques of developing programs is called software engineering.
c. Portable: Sometimes programs running correctly in one type of computers might not
be able to run in other systems. As much as possible, the program must be easily portable
with a little modification.
d. Efficient: The resources we have in a computer system are scarce. The available
memory space and the CPU time are some examples of resources which are inadequate.
Your program should not waste memory space by reserving memory space for unused
values. Moreover, the program must not waste the CPU time by executing unnecessary
instructions. It has to avoid needless repetitions.
Example (on efficiency of programs):
Let’s go back to the former example about Bob. Consider the first job given to
Bob which was adding two numbers for your friend.
Ask like ‘Tell me the two numbers’. This was the set of instructions which we
Record the answer of my friend. were convinced to tell Bob for getting done
Add the numbers. the given task
Record the sum.
Consider that your friend gave the two numbers as 9 and 6 and their exact conversation
was as the following:
Bob: “Tell me the two numbers” {According to the first instruction}
Your friend: “Thank you very much Bob. My numbers are 9 and 6”
The first instruction in both set of instructions is the same. But the other instructions
differ. So, we better execute them separately as follows:
The First Set The Second Set
nd nd
2 Inst: Record the two numbers 2 Inst: Record the answer of my friend
Bob will keep in his mind only the Bob will keep in his mind all the word of your
numbers 9 and 6. friend’s reply. This constitutes 9 words and 2
numbers (9 and 6).
3rd Inst: Add the numbers
3rd Inst: Add the numbers
Bob will add 9 and 6.
Bob will add 9 and 6.
4th Inst: Record the sum
th
4 Inst: Record the sum
Bob will keep in his mind the sum
which is 15. Bob will keep in his mind the sum which is 15.
5th Inst: speak out the sum 5th Inst: Multiply the sum by 1
Bob will tell your friend the Bob will multiply 15 by 1.
number 15. And that is the final th
6 Inst: Record the product
answer.
Bob will record in his mind the product, i.e. is 15.
7th Inst: Speak out the product
Bob will tell your friend the number 15. And that
is the final answer.
Both set of instructions yield the same output which is the expected one. But the second
set is not efficient. To be sure of this idea, take the second instruction. Is it really
necessary to store all the words that your friend replies? This really doesn’t have any
advantage but wastes space in Bob’s mind. The only data that Bob needs are the numbers
9 and 6.
And take the 5th and 6th instructions. Why do you need to multiply the sum by 1 and to
record the product? These are unnecessary instructions. Even if these instructions don’t
have any harm and affect the final output, they take the time of Bob which he can use to
do other things.
Therefore, this program is inefficient. Put side by side the space of Bob’s mind and the
memory space of the computer system. Since both have a limited size, they should be
used efficiently. Similarly the time of Bob and the CPU time can be interrelated since
time is another precious resource in every case. Using time effectively implies end users
get a response with in a short period of time.
Problem
Definition
& analysis
Test &
Debugging Coding &
Documentatio
n
In this stage, the main thing to do is to understand the given problem. Problem
identification simply means understanding what to be done. Ask yourself this question:
What must I do?
What is needed or expected?
Specifically, the things that should be known at the end of this stage are:
i. Identifying input data to the problem
ii. Identifying output data from the problem
iii. Identifying procedures needed to achieve the result.
Note: in this stage the thing that must be worked out is what must be done not how to do
it.
2. Algorithm Design
When you pass to this stage, you have all the information about what to be done. But you
still don’t think about how to do the specified thing. This is the purpose of this step.
Programs are the children of algorithms. If the algorithm is not correct or not efficient,
then the program will also be inefficient and incorrect since programs are the direct
translation of algorithms in programming languages.
Therefore, to make your program of good quality, you must design the algorithm
carefully. And it is advisable to test the algorithm (instead of the program) to check for
reliability, maintainability and efficiency.
Since an algorithm is set of steps to perform the thing that is defined in the previous
stage, it should be represented in one way or another to be available and be a program in
the next step. Algorithms could be represented in different ways. You might use the
narrative way (writing the steps in English), pseudo-code (‘false code’) or flowcharts. We
will discuss about the representation of algorithms in another section of the same chapter.
3. Coding or Implementation
Right now, the algorithm is available. You know how to achieve the goal specified in the
problem identification stage. But the steps represented in the previous phase are not still
in the form understandable for the computer. Therefore, it is necessary to rewrite the
steps of your algorithm by using instructions in the selected programming language. This
process is called coding.
4. Testing and Debugging
You must be very lucky if your program works perfect at its first completion. But it is not
also fair to complain about the unlucky situation of a program’s fail at its first
completion, because it is a usual thing to happen.
Therefore, it is more than necessary to test a program for all possible inputs including
invalid and extreme cases. If a program cannot perform as expected, then the program is
said to have errors. Errors in programs are usually called bugs. Whenever, there is a bug,
you need to remove it until your program is error free. Removing bugs is called
debugging.
There are three types of errors that probably be encountered in a program:
Syntax errors (compilation errors): Syntax is the general format of writing a command
(statement) in programming languages. Syntax errors are errors created due to the
violation of the syntax of a command or a statement.
If there are any syntax errors in C++, then they will be detected and notified in the
compilation time. Therefore, a program having a syntax error could not be run without
removing the errors. Generally, there are three sorts of syntax/compiler errors:
Ordinary errors - the compiler will attempt to continue compilation after one or more
of these errors has occurred, e.g. Missing ENDIF statements
Fatal errors - the compiler will not attempt further compilation after detecting a fatal
error, e.g. Program too complicated -too many strings
Warnings - these are not strictly errors, but are intended to inform you that you have
done something unusual which might cause problems later, e.g. Expression in IF
construct is constant
Example: In C++, at the end of each statement (command), there should be a semicolon.
This is one of the grammatical rules in C++. If you miss a semicolon at the
end of a statement in C++ program, then it will be a syntax error.
Run-time errors: These types of errors are errors that will appear when the program is
allowed to run†.
Example: division by zero. If there is any place (instruction) which attempts to divide any
number by zero, then this error will not be syntax error instead run time error.
When the computer reaches and executes this instruction, it will find out that
this is invalid and the execution will be interrupted by announcing the error.
Logical Errors: These are the most dangerous errors. These errors are errors which cause
the program to produce a wrong output. Logical errors cannot be detected in the
compilation time as well as in the run time. It is the programmer’s job to test the program
for such types of errors by providing all the possible inputs and check whether the
outputs are the expected ones.
Debugging (particularly for logical errors) can be done in different ways:
Manually: Before entering the program instruction into the computer, the programmer
can trace the program by checking each and every instruction and by recording the
values (outputs) of each instruction.
Tools included in the compiler: most compilers have got debugging tools which show
you how each instruction after being executed affects the values of your variables
and outputs.
At times a program will give numerical answers to a problem which appear inexplicably
different from what we know to be the correct mathematical solution. This can be due to
rounding error, which results from the finite precision available on the computer.
5. Maintenance
Writing program for a given problem is an endless task. At the end of the day, you might
find undiscovered errors in the above phases or otherwise users may come up with a new
need. Therefore modification is expected even after finishing and implementing the
program. Modifying programs to make them error free (more!), to satisfy user’s need, or
to expand the capability of the program is called maintenance.
To make programs easier to modify, documentation play a major role. Starting from the
first step, documentation should be done. A typical document may contain the following
about a developed program:
A statement of the problem
A description of the system, which involves the description of program functions
and the system specifications
†
Running programs means executing them.
Example:
1. Prepare an algorithm for making a cup of tea using the step form representation.
1. Prepare a kettle and a tea cup
2. If the kettle doesn’t have water, then fill it
3. Plug the kettle into the power point
4. If the tea cup is not empty, then empty the cup
5. Place tea leaves in the tea cup
6. If the water in the kettle is not boiling, then wait till it boils
7. Switch the power off
8. Pour the water from the kettle into the tea cup.
2. Develop an algorithm in step form that counts all vowels on a given page of text.
Assume n is the number of letters on that page.
1. Set current to 1
2. Set last to n
3. Set count to 0
4. Read letter at current
5. If letter is vowel, then increment count by 1
6. Increment current
7. If current <= last, then go to step 4
When designing an algorithm for a given problem, the designer is advised to use a
pseudo-code so that he/she could be able to focus on the algorithm or the method of
solving the problem instead of worrying to write instructions in the correct syntax of a
particular programming language. Moreover, once an algorithm is represented, coding
will be translating the steps written in the pseudo-code in one of the programming
language. We can say if a well-written algorithm is prepared, the challenge of
programming is defeated.
There is no standard for pseudo-code writing. You may see different ways of pseudo-
code representations in different books. Even you can develop your own way of writing
pseudo-cde for an algorithm. But, there are some useful points that you have to know to
start writing pseudo-code. There are three basic constructs for flow of control from which
any algorithm is implemented. Therefore a pseudo-code may be made up of these three
logic structures. They are:
1. Sequence: Sequence structures show the processing of steps one after the other
sequentially. Whenever there are any series of steps, they will be represented in
pseudo-cde by writing one after the other in their right order just like the
following illustration:
Step 1
Step 2 A sequence can consist of only one
Step 3 instruction. But if the steps are more that
. one, then they are usually enclosed
. between begin….and …end.
.
step n
2. Selection: Selection happens whenever there are things to be done based on the being
true of a certain condition. There will be usually two or more choices. This one
is illustrated as:
If condition1 then
Sequence 1
Else if condition2 then
Sequence 2 This part is optional,
.
. i.e, it may appear or
. not.
Else
Sequence n
End if
3. Iteration (Loop): This condition refers to a situation in which there are one or more
instructions which should be performed several times depending on some
condition. This is what we call loop. Loop is implemented in pseudo-code like
the following (i.e. of course one way)
While condition
Sequence
End while
Additionally, the following keywords are common:
a) To show the beginning and the end of the algorithm: Begin, End
Note: indentation will also play a major role in making the represented algorithm
readable and easily modifiable. When you start a different sequence, indent the
steps to differentiate the set of the steps in this sequence from the previous one.
Examples:
Design an algorithm for solving the following problems. Represent the algorithm in
pseudo-code.
1. Add two given numbers.
Pseudo-code can be completely formed from only English phrases or alternatively
English phrases and code like statements can be mixed in a pseudo-code. For this
problem both types are shown below. But for the other examples, the second form is used
to implement the pseudo-code.
Begin
Read the two numbers Completely described
Compute the sum by adding the numbers in English phrases
Display the sum
End
Begin
Read a,b The second style consisting of keywords,
sum a+b operators and sometimes English phrases
Display sum
End
Try to see how the steps are clear. For this problem, the only thing that is left is to rewrite
the steps in the selected programming language. In C++, the following program could be
produced from the above pseudo-code:
#include <iostream.h>
main()
{
int a,b,sum;
cout<<”Please enter the two numbers”; //To ask the user for the two
numbers
cin>>a>>b; //To read the numbers
sum=a+b; //To add the numbers
cout<<sum; //To display the sum
}
Don’t worry if you don’t really understand the above program since it is not the right
time to complain. This program is just here to show you how a program in one
programming language could be produced from a pseudo-code.
2. Produce the result of the following computation for four given numbers a, b, c and d
Result=(a-b-c)+d
Begin
Read a, b, c, d
Result (a-b-c) + d
Display result
End
4. Find the average mark of a student for given four subject marks.
This is not really a different question than Q.No.4. Therefore it will be done like the
following:
Begin
Read mark1,mark2,mark3,mark4
sum mark1+mark2+mark3+mark4
Average sum/4
Display Average
End
5. Obtain average marks for five students for given four subject marks.
This problem and the above one are basically the same. The only difference between the
two is that in the first case, we had only one student where as in this problem we have
five students for whom the same task to be done. What are we going to do to treat this
problem?
One way (may be foolish way) is to repeat the instructions for all of the five students
resulting to have 20 steps (later to be instructions) in the algorithm. What if we have 100
students? Is this method really feasible?
Therefore we use a loop for such cases. A loop refers to set of instructions, which will be
repeated for a number of times based on some condition. Since we have five students
here, the loop should run for five times. How can we implement this?
‘While loop’ is going to be used in implementing the above algorithm. How do I tell the
‘while loop’ that there are five students and it should run exhaustively for five times?
Even how will I stop the ‘while loop’? To continue or to stop, you need to count the
students naturally.
‘While loop’ needs an initialization in which the condition is going to be based on. A
certain variable will be initialized to count the number of times the loop is run. Usually
the counter must be initialized to 1 to start counting the loop from 1.
The first step is to assign the value 1 to a variable called ‘counter’. This is the
initialization process. The value of ‘counter’ is going to be used for counting the loop.
The loop is started now. All loops have a certain condition to be tested. In our case, the
condition is set to check whether the current value of the variable ‘counter’ is less than or
equal to 5. If this condition is evaluated to true, then the instructions found within the
loop will be executed for one more time. If the evaluation of the condition is false, then
the loop will be stopped and the very next instruction after ‘end while’ will be executed.
Once a loop is stopped, it will never be returned back.
Success to start
the loop once
Begin again because
Checking
the
counter 1 the condition
possibility while counter<=5 stated is true
to add one Read mark1,mark2,mark3,mark4
more loop sum
mark1+mark2+mark3+mark4
Average sum/4
Display Average
Otherwise, when
counter counter+1 the condition is
end while false, all the
End instructions will
be jumped.
First round:
Counter=1
Since 1<5, the loop will be entered and as a result the average for the first student will be
computed by reading his/her marks. Then after displaying the computed average, the
statement counter counter+1 will be processed. According to this instruction, the sum
of the current value of the variable counter and 1 will replace the previous value of
counter. So after the execution of this instruction, the value of counter is 2.
Second round:
Counter=2
One more execution of the loop will be carried out and the value of counter will be
incremented.
The same will happen to the third, fourth and fifth round. At the end of the fifth round,
the value of counter becomes 6. Right now, it is not possible for the ‘while loop’ to
continue since the logical comparison counter<=5 (which is 6<=5) yields false.
6. Compute the following: 20+21+22+……..+29
Begin
sum 0
i 0
while i<=9
sum sum+2i
i i+1
end while
Display sum
End
The list of the standard symbols and their meaning is shown below:
Terminal
Decision
Connectors
Input / Output
Any flowchart can be built from the above standard symbols. Below is explanation of the
standard symbols.
Terminal: This standard symbol is used to show the beginning and the end of the
algorithm. You usually write ‘start’ and ‘stop’ in the terminal symbols at the beginning
and end of the flowchart.
Start
The body of
the algorithm
Stop
Read a
Display sum
Processing: operations to be done will be expressed using this symbol. These operations
are of two types: arithmetic operations (addition, subtraction, multiplication and division)
and data movement instructions (copying some data from a variable to another one).
sum a+b
x y
x 4
Decision: we know that there are two types of operations that can be done by the
computer. The first types are arithmetic operations where as the other type is logical
operation. Logical operation consists of the evaluation of logical expressions. Logical
expressions are expressions which are built from logical operators (like <,>,=,<=,>=) and
evaluated only to the values true or false. Therefore, sometimes decisions can be made
based on the value of a logical operation. A good example for this is the statement ‘if a>b
then max a’. When you have such conditions to be tested, then you could use the
decision symbol to represent the situation.
To implement the above if clause using the decision symbol, you could do the following:
No Is Yes
max b max a
a>b
The decision standard symbol will have one entry point and at least two exits.
Flow line: shows the direction of logical flow. This arrow connects standard symbols
used to represent sequence of steps.
Connectors: There are two types: on-page connector and off-page (Interpage) connector
respectively as shown above in the figure.
...On-page: is used for connecting two points in a program (algorithm) without
drawing flow lines. A pair of identically labeled connector symbols denotes
that the indicated points of the flowchart are connected.
A labeled on-page
1 connector connecting
one point from the
flow chart to another
1 one
Stop
There are some guidelines that you have to follow when drawing flowcharts:
a) A flowchart should start and end with the terminal symbol having ‘start’ or
‘begin’ and ‘stop’ or ‘end’ respectively.
b) Crossing flow lines should be avoided. And to avoid this, you need to use
connectors.
Before seeing the examples that we have, let’s list some of the advantages of flowcharts:
a) They can be used by both programmers and non-programmers alike to illustrate
the entire process graphically in a smart manner.
b) While drawing a flowchart one is not concerned with the details of the elements
in programming language. Hence, it facilitates program writing.
c) Since it shows the flow of operations in pictorial form, it allows to easily detect
logical errors in the algorithm.
d) Since it is independent of programming languages, it can be translated into more
than one language.
We will draw flow charts for some of the same examples given before (in the pseudo-
code section).
Examples:
1. Find the largest of three given numbers. Take the assumption that the numbers
entered will never be equal.
Start
Begin
Read a,b,c 1.1.1. S
max a Read a,b,c t
if max<b then a
max b r
max a t
end if
if max<c then
max c
max b max<
end if
b
Display max
No
End
display
max
Stop
Stop Stop
3. Design and represent an algorithm to obtain the sum of the first 50 counting numbers.
Start
Begin
number 1
while number<=50 number 1
sum sum+number sum 0
number number+1 1
end while No number<
Display sum
=50
End
Display Yes
sum
sum sum+number
Stop 1
number number+
1
Start
Read number
Yes
Display message
‘ n is odd’
Stop
5. Suppose that Birr 1000 is deposited in a savings account in 1993 and the bank pays 10
percent interest, compounded annually. Draw a flowchart of an algorithm which
prints the year and the amount in the account, until amount first exceeds Birr 10,000
and which also finds the number of years it takes for amount to reach Birr 10,000 or
more. {From ‘Introduction to computer Science’ by Dr. Dida Midekso}
Develop your own algorithm after understanding the problem. Write the pseudo-code
form of your algorithm and draw the flowchart. The following is an algorithm presented
here:
Start
amnt 1000
year 1993
cnt 1
amnt amnt+0.10*amnt
2. Introduction to C++
We have been writing algorithms in pseudo-code from in the last chapter. And we have
said many times that these are only algorithms not real programs which implies the
algorithms have to be rewritten in a program form by using a certain programming
language that is completely understood by the computer.
Our language in this course is C++. Since its introduction about a decade ago, C++ has
experienced a growing acceptance as a practical object-oriented programming language
suitable for teaching, research, and commercial software development. The language has
also rapidly evolved during this period and acquired a number of new features (e.g.,
templates and exception handling) which have added to its richness.
C++ programming language has got its name from C programming language. The ++
sign is derived from the ++ operator which is found both in C and C++ languages. It tells
us that C++ includes all features of C and many more.
C language was derived, in turn, from the B programming language which again derived
from BCPL. The languages BCPL and B are earlier versions of the C language; hence
they do not concern us. The C programming language developed, by Dennis Ritchie, at
AT&T Bell Laboratories in the 1970s. It was first used for writing the UNIX operating
system and later its use was extended to write any sort of program. Hence C is general-
purpose language. But the popularity of C language is highly tied with the UNIX
operating system. If someone wanted to maintain his UNIX, he had to know C language.
C language is unique in that it is a high-level language with many of the features of low-
level language. It is between the two extremes. Like low-level C language programs can
directly manipulate the computers’ memory. On the other hand, it is easier to read and
write programs in C language than Assembly, which is feature of high-level languages.
This has made C an excellent choice for writing system programs. But for other programs
C is not as easy to understand as other high- level languages.
To overcome this and other shortcomings of C, in the early 1980s a new language known
as C++ was developed, by Bjarne Stroustrip, at AT&T Bell Laboratories. C++ was
designed to be a better C. In other word C is a subset of C++. Unlike C, C++ has features
to do Object-Oriented Programming (OOP).
#include <iostream.h>
main()
{
variable declaration; #include <iostream.h>
statement 1; main()
statement 2; {
. cout<<”Hello World”;
. return 0;
. }
statement n;
return 0;
}
To understand the general structure given above, let's discuss about each line separately:
Line 1: The Preprocessor Directive: #include <iostream.h>
“iostream.h” is one of the several header files available in C++ compilers. Header
files are files which are external and saved in a certain path. These files contain the code
for different functions and operators used in your C++ program.
You have heard about compilers of C++. You can have a different kind of them. But
there is another program called preprocessor which always run before the compiler each
time one starts the compiler. The function of the preprocessor program is to look for all
lines which begin with the pound symbol (#) through out the program. And having
these lines of the program, the preprocessor will ‘read in’ or copy the content of the
header files specified after include into the program to make the program ready to be
compiled. It is after this time the compiler starts acting on the program (translating and
checking for syntax errors).
Example 1: #include <iostream.h> is used to copy and insert all the content of
the mentioned header file which is iostream.h into the source program (our own
program).
You might be thinking about one thing right now! Why do we need to include the code
written in an external file to our own programs while we believe that our program files
are complete? The answer is straightforward. It is because your program needs the copied
code. Since you will use predefined (pre-coded) operators and functions in your program,
the code written for each of these has to be included in your program. Otherwise, the
compiler will not recognize the operators and the functions used and will refuse to
compile the program.
Example 2: Look at the statement in line 4 of the C++ program given as example right to
the general format above. It is cout<<”Hello World”; ‘cout<<’ is an operator
whose code is written in the iostream.h header file. If the content of the header file is
not included prior to the compilation process, the compiler will not recognize this
statement at all.
Therefore, this line of the program (as well as all include directives) is used to include
header files. Note that there are a number of header files with their own content and it is
possible to include multiple header files. If you intend to use one of the operators or
functions defined in one of these files, include them at the beginning of your program.
Given a big problem, divide it into smaller sub-problems. Then prepare programs (code)
for each smaller problem. Finally combine and integrate the small programs to build a big
software. The small programs which are here used as a building block to form a larger
program are called functions. Functions in a program will communicate to each other.
This communication technically is called calling. Therefore you could say one function
call another one. The output of one function can be used as an input to another one etc.
In this sense, a C++ program can be defined as set of functions. And one of these
functions is the function to be executed first when the program is run automatically. This
function is known as the main function.
The main function in a C++ program is entitled as main() so that execution will be
started from the first instruction of this main function. Even if in our simple C++
programs in this course we will not have multiple functions, we will give the title
main() as the header of our only and main function.
As a wise beginner programmer, try to declare all your variables which will be used in
your program at the beginning of your program. And note that variable declaration may
contain multiple lines.
If you omit this statement from the main function, then the compiler will not refuse to run
the program but at least will give you a warning telling you that any function should
return a value. If you want to omit the return statement without any warning, add void
before main as:
void main()
2.4.1. Identifiers
Identifiers are names given to a variable. A variable has a unique name in a program and
there are some restrictions when naming variables. C++ imposes the following rules for
creating a valid identifier
Should consist of sequence of letters, numbers and underscore;
Could not begin with a number,
Should not use keywords (eg. Void = 2 can not be valid since Void has specific
meaning for the compiler),
Identifiers in C++ are case sensitive and sometimes their size is limited.
C++ imposes no limit on the number of characters in an identifier. However, most
implementations do. But the limit is usually so large that it should not cause a concern
(e.g., 255 characters).
2.4.2. Keywords
Certain words are reserved by C++ for specific purposes and may not be used as
identifiers. These are called keywords or reserved words and are summarized Table 2-1.
2.5. Comments
A comment is a piece of descriptive text which explains some aspect of a program.
Program comments are totally ignored by the compiler and are only intended for human
readers. C++ provides two types of comment delimiters:
2.7. Variables
In programs, data is needed to be stored in memory. This is to store input values to
retrieve it for later use, or to assign a certain value (either the result of a computation or a
constant value) and in the mean time track intermediate results.
Therefore, variables will give an easy and flexible way to access the RAM in your
program. The value of variables can be changed in any part of the program as a result of
your program instructions. The kind of value a variable can assume depends on its type.
A variable has to be declared before using it. The declaration is to tell the compiler the
name of your variable with its data type so that a memory space is allocated for your
variable. The syntax of a variable declaration is:
<Type> <identifier/ variable name>;
Multiple variables of the same type can also be declared like the following:
Type varname 1, varname 2, …, varname n;
Example: int a;
float x,y,z;
Initialization is assigning of a variable for the first time. The syntax is:
Example: int a = 5;
float x = 9.5;
Integers
An integer variable may be defined to be of type short, int, or long. The only
difference is that an int uses more or at least the same number of bytes as a short, and
a long uses more or at least the same number of bytes as an int.
Just like unsigned int, Turbo C++ will allocate 2 bytes for each variable declared as
int or signed int. Note that int and signed int are the same. The 16 bits
given for such a variable will possibly be used to store one of the signed numbers within
the following interval:
-2n-1 to +2n-1 –1
-216-1 to +216-1 –1
-32768 to +32767
The same type of the previous problem that is exhibited in the case of unsigned int
will occur if a signed number out of this range is tried to be assigned to this variable.
Since 32768 is a positive signed number which is out of the range and which is found
next to the right boundary number, it makes the compiler to loop back to the left
boundary (to the first and the smallest number of the interval). Similarly the assignment
of the value –32769 to the variable x in the above example makes the compiler to loop
back to the last number because it is found just before the first number of the interval.
In all the cases when a value out of the interval of its type is assigned to a variable, it will
wrap around and start over forming a cycle.
2. signed short int (or short int)
The short int (unsigned short int) and int (signed int) are the same
in the compiler that we are using.
3. signed long int (or long int)
Probably, you yourself can see easily that 4 bytes will be reserved in memory for long
int variable just in the case of unsigned long int. The difference comes when
we consider the interval of numbers to be stored in the variable.
And before leaving the discussion about integers, look at the following examples:
int x; int x; int x;
x = 12.0; x = 12.3; x = 12.6;
cout<<x; cout<<x; cout<<x;
Output is 12 Output is 12 Output is 12
Even if the declared variable is an integer, we assign real numbers (numbers with a
decimal point and a fractional part) in all the three cases. But as shown, the output from
all code fragments is 12.
What does this indicate? An integer variable (whatever the integer type is) when assigned
a real number will truncate (not round) the fractional part and store only the integer part.
Truncating is cutting the fractional part.
Real Numbers:
Real numbers are numbers having both integer and fractional part. Whenever there is a
need to declare a variable for storing real numbers, one of the following data types could
be used:
1. float
float variablename;
Turbo C++ compiler will allocate 4 bytes for a variable of type float. These bytes can be
used to represent one of the floating-point numbers in the following interval: -3.4 10-38
to 3.4 10+38
2. double
double variablename;
‘double’ is also a floating point data type but be capable of storing very large or very
small numbers than float. The compiler will allocate 8 bytes for a double variable type.
The interval is: –1.7 10-308 to 1.7 10+308.
Characters:
A character variable occupies a single byte which contains the code for the character.
This code is a numeric value and depends on the character coding system being used (i.e.,
is machine dependant). The most common system is ASCII (American Standard Code for
Information Interchange). For example, the character A has the ASCII code of 65, and the
character a has the ASCII code 97. When a character variable is declared, one byte (8
bits) will be given in memory. The data type that is usually used to declare a character
variable is char.
char variablename;
All variables declared as ‘char’ are represented in their ASCII number code. A total of
256 printable and non-printable characters are possibly represented using the one byte
allocated.
may mean unsigned char. A signed character variable can hold numeric values in
the range -128 through 127. An unsigned character variable can hold numeric values in
the range 0 through 255. As a result, both are often used to represent small integers in
programs (and can be assigned numeric values like integers).
Due to the aforementioned relation, an int value can be assigned to a char variable and
a character value can be assigned to an int variable. This is because the representation
of characters is internally in numbers specifically unsigned integers. Therefore, a
character variable assigned an integer will store the corresponding ASCII character
instead of taken as incompatibility (mismatch) type problem. The following two
examples illustrate variables of type int being assigned a character so that they can store
the ASCII value of the character:
char ch; int y;
ch=97; y=’a’;
cout<<ch; cout<<y;
output is a. output is 97.
Example:
String
A common programming error results from confusing a single-character string (e.g., “A”)
with a single character (e.g., ‘A’). These two are not equivalent. The former consists of
two bytes (the character ‘A’ followed by the character ‘\0’), whereas the latter consists of
a single byte. The shortest possible string is the null string (“”) which simply consists of
the null character.
2.7.3. Scope
Scope of an identifier is part of the program where it can be used. The scope of a variable
begins at its declaration and ends at closing brace in which the variable was declared. A
variable defined at the program scope level (Beginning of the program) is said to be
global variable. Each block in a program defines a local scope. Variables defined within a
local scope are visible to that scope only and are called local variables. Local scopes may
be nested, in which case the inner scopes override the outer scopes.
Generally, global variables last for the duration of program execution, while local
variables are created when their scope is entered and destroyed when their scope is
exited. The memory space for global variable sis reserved prior to program execution
commencing, whereas the memory space for local variables is allocated on the fly during
program execution.
2.8. Constants
A constant could either be defined or declared. A constant could be defined as:
# define x 35
# define y 390
Preceding a variable definition by the keyword const declares that variable as a
constant and read-only (i.e. a symbolic constant). A constant must be initialized to some
value when it is defined. For example:
const int maxsize = 128;
const float PI = 3.14;
i. Integers:
Decimal: int x = 1776, y = 364, z = 0, w = -342;
Octal (Base 8): int x = o113 // (113)8
Hexadecimal: int x = ox4b; // (4b)16 = 4x1b + 11
ii. Floating Point numbers
float pi = 3.141593;
float av = 6.02e23;
float ec = 1.6e-19
iii. Character and strings
char x = ‘a’
char y = “the” // illegal!
Example:
main()
{ a = 3; // Error: it has not been declared yet.
int a; // Scope(life) of a begins here
{ a = 17; // Now it is okay
b = 34; // Error because b is not yet declared
int b; // Scope(life) of b begins here
b = 36; // Now it is okay
} // Scope(life) of b ends here
b = 4; // Error: it has not been declared yet.
}
Assignment
1. Write a simple calculator program which displays the sum, difference, product
and quotient of two integers entered by the user.
2. Develop algorithm in both pseudo-code and flow chart format:
a. To calculate the LCM and GCF/GCD of two numbers,
b. To check whether a number is prime or not.
3. Expressions in C++
This section introduces the built-in C++ operators for composing expressions. An
expression is any computation which yields a value.
When discussing expressions, we often use the term evaluation. For example, we say that
an expression evaluates to a certain value. Usually the final value is the only reason for
evaluating the expression. However, in some cases, the expression may also produce
side-effects. These are permanent changes in the program state. In this sense, C++
expressions are different from mathematical expressions.
C++ provides operations for composing arithmetic, relational, logical, bitwise, and
conditional expressions. It also provides operators which produce useful side effects,
such as assignment, increment, and decrement.
When both operands of the division operator (/) are integers then the division is
performed as an integer division and not the normal division we are used to. Integer
division always results in an integer outcome (i.e., the result is always rounded down).
Example: 9 / 2 // gives 4, not 4.5!;
-9 / 2 // gives -5, not -4!;
Unintended integer divisions are a common source of programming errors. To obtain a
real division when both operands are integers, you should cast one of the operands to be
real: int a = 100;
int b = 80;
double c = a / (double) b; // gives 1.25;
It is possible for the outcome of an arithmetic operation to be too large for storing in a
designated variable. This situation is called an overflow. The outcome of and overflow is
machine-dependant and therefore undefined. For example:
Unsigned char k = 10 * 92; // overflow: 920 > 255;
C++ provides library functions (e.g., strcmp) for the lexicographic comparison of strings.
Note that here we talk of zero and nonzero operands (not zero and 1). In general, any
nonzero value can be used to represent the logical true, whereas only zero represents the
logical false. The following are, therefore, all valid logical expressions:
!20 // gives 0;
10 && 5 // gives 1;
10 || 5.5 // gives 1;
10 && 0 // gives 0;
C++ does not have a built-in Boolean type. It is customary to use the type int for this
purpose instead. For example:
int sorted = 0; // false;
int balanced = 1; // true;
3.4. Bitwise Operators
C++ provides six bitwise operators for manipulating the individual bits in an integer
quantity as listed in Table 3-4.
Table 3-4 Bitwise operators
Operator Name Example
~ Bitwise Negation ~’\011’ // gives ‘\366’
& Bitwise And ‘\011’ & ‘\027’ // gives ‘\001’
| Bitwise Or ‘\011’ | ‘\027’ // gives ‘\037’
^ Bitwise Exclusive Or ‘\011’ ^ ‘\027’ // gives ‘\036’
<< Bitwise Left Shift ‘\011’ << 2 // gives ‘\044’
>> Bitwise Right Shift ‘\011’ >> 2 // gives ‘\002’
Bitwise operators expect their operands to be integer quantities and treat them as bit
sequences. Bitwise negation is a unary operator which reverses the bits in its operands.
Bitwise and compares the corresponding bits of its operands and produces a 1 when both
its bits are 1, and 0 otherwise. Bitwise or compares the corresponding of its operands and
produces a 0 when both bits are 0, and 1 otherwise. Bitwise exclusive or compares the
corresponding bits of its operands and produces a 0 when both bits are 1 or both bits are
0, and 1 otherwise.
Bitwise left shift operator and bitwise right shift operator both take a bit sequence as their
left operand and a positive integer quantity n as their right operand. The former produces
a bit sequence equal to the left operand but which has been shifted n bit positions to the
left. The latter produces a bit sequence equal to the left operand but which has been
shifted n bit positions to the right. Vacant bits at either end are set to 0.
Table 3-5 illustrates bit sequences for the sample operands and results in Table 3-4. to
avoid worrying about the sign bit (which is machine dependent), it is common to declare
a bit sequence as an unsigned quantity:
Unsigned char x = ’\011’;
Unsigned char y = ‘\027’;
Bjarne Stroutstrup initially named C++ “C with Classes.” However, at the suggestion of
Rick Mascitti, Stroutstrup later changed the name to C++. While the new language was
already destined for success, the adoption of the name C++ virtually guaranteed its place
in history because it was a name that every C programmer would instantly recognize.
m is incremented because m++ is evaluated but n is not incremented because n++ is not
evaluated.
Because a conditional operation is itself and expression, it may be used as an operand of
another conditional operation, i.e., conditional expression may be nested. For example:
int m = 1, n = 2, p = 3;
int min = (m < n ? (m < p ? m : n): (m < p ? n : p);
// min receives m;
3.9. Comma Operator
Multiple expressions can be combined into one expression using the comma operator.
The comma operator takes two operands. It first evaluates the left operand and then the
right operand, and returns the value of the latter as the final outcome. For example:
int m, n, min;
int mcount = 0, ncount = 0; // …
min = (m < n ? mcount++, m : ncount++, n) ;
Here when m is less than n, mcount++ is evaluated and the value of m is stored in min.
Otherwise, ncount++ is evaluated and the value of n is stored in min.
3.10. sizeof Operator
Sizeof is a useful operator for calculating the size of any data item or type. It takes a
single operand which may be a type name (e.g., int) or an expression (e.g., 100) and
returns the size of the specified entity in bytes. The outcome is totally machine-
dependent.
#include <iostream.h>
As shown by these examples, the built-in type identifiers can be used as type operators.
Type operators are unary (i.e., take one operand) and appear inside brackets to the left of
their operand. This is called explicit type conversion. When the type name is just one
word, an alternate notation may be used in which the brackets appear around the operand:
int (3.14) //same as: (int) 3.14
In some cases, C++ also performs implicit type conversion. This happens when values of
different types are mixed in an expression. For example:
double d = 1; // d receives 1.0
int i = 10.5 // i receives 10
i = i + d; //means: i = int(double(i) + d)
In the last example, i+d involves mismatching types, so i is first converted to double
(promoted) and then added to d. The result is a double which does not match the type of
i on the left side of the assignment, so it is converted to int (demoted) before being
assigned to i.
3. What will be the value of each of the following variables after its initialization:
double d = 2 * int (3.14);
long k = 3.14 – 3;
char c = ‘a’ + 2;
char c = ‘p’ + ‘A’ – ‘a’;
4. Write a program which inputs a positive integer n and outputs 2 raised to the
power of n.
A running program spends all of its time executing statements. The order in which
statements are executed is called flow control (or control flow), reflecting the fact that the
currently executing statement has the control of the CPU which when completed will be
handed over (flow) to the next, but may be diverted to other paths by branch statements.
Flow control is an important consideration because it determines what is executed during
a run and what is not, therefore affecting the overall outcome of the program.
Like many other procedural languages, C++ provides different forms of statements for
different purposes. Declaration statements are used for defining variables. Assignment-
like statements are used for simple, algebraic computations. Branching statements are
used for specifying alternate paths of execution, depending on the outcome of a logical
condition. Loop statements are used for specifying computations which need to be
repeated until a certain logical condition is satisfied. Flow control statements are used to
divert the execution path to another part of the program. We will discuss these in turn.
4.2.1. If statement
It is sometimes desirable to make the execution of a statement dependant upon a
condition being satisfied. If statement provides a way of expressing this, the general
syntax is:
if (Logical_Expression)
statement;
Where Logical_Expression is an integer expression and statement is any executable
statement. If the test of condition is evaluated to 1 (true), then the statement is executed.
When the expression is evaluated to 0, it is considered as false value; in which case the
statement is skipped. Any non-zero value is taken to be true. For example:
#include <iostream.h>
main ()
{
int num1, num2;
cout << “ Enter the two numbers: “;
cin >> num1 >> num2;
if (num1%num2 = = 0)
cout << num1 << “ is divisible by “ << num2 << endl;
return 0;
}
This program gets two numbers from the keyboard and checks if the condition,
num1 % num2 == 0, is true. If it is true then the output statement is executed. Otherwise,
it skips over the output statement.
If … else statement:
If … else is a variant form of the if statement to specify two alternative statements: one
which is executed if a condition is satisfied and one which is excited if the condition is
not satisfied. The syntax is:
if (Logical_Expresson)
Yes_Statement;
else
No_statement;
If the Logical_Expression evaluates to true then the statement after if, Yes_Statement, is
executed; otherwise the statement after else, No_Statement, is executed.
Using if… else the above program can be rewritten in more complete sense:
#include <iostream.h>
main ()
{
int num1, num2;
cout << “ Enter the two numbers: \n “;
cin >> num1 >> num2;
if (num1%num2 == 0)
cout << num1 << “ is divisible by “ << num2 << endl;
else
cout << num1 << “ is not divisible by “ << num2 << endl;
return 0;
}
Any expression that results in a zero or non-zero value can be used to control the if. For
example the following program reads two integers from the keyboard and displays the
quotient.
// divide the first number by the second
#include <iostream.h>
int main ()
{
int num1, num2;
cout << “ Enter the two numbers: “;
cin >> num1 >> num2;
if (num2) cout << num1/num2 << ‘\n’;
else cout << “ can not divide by zero. \n“;
return 0;
}
Note: it is not necessary (and would be considered as bad programming style) to write
this if as:
It is possible to make test for multiple conditions using more than one if statements. In
which case it is called nested if statement. Two or more conditions are connected using
conditional connectors. && for and, || for or.
because by that point in the code the switch block was ending, and there is no need of
using an explicit command to exit the switch.
It should be obvious that any switch statement can also be written as multiple if-else
statements. However, preference should be given to the switch version whenever
possible. The if-else approach should be reserved for situations where a switch cannot
do the job (e.g., when the conditions involved are not simple equality expressions, or
when the case labels are not numeric constants).
The while statement (also called while loop) provides a way of repeating a statement
while a condition holds. The test condition for the loop is made at the top. Its syntax is:
while (<condition>)
<statement>;
First condition (also called the loop condition) is evaluated. If the outcome is nonzero the
statement (called the loop body) is executed and the whole process is repeated.
Otherwise, the loop is terminated. For example:
While (1)
; // Loops forever
*****************************************************************
i = n;
while ( n >= 1)
i *= --n; // Computes n factorial
It is not unusual for a while loop to have an empty body (i.e., a null statement). The
following loop, for example, sets n to its greatest odd factor.
While ((n % 2 = = 0) && (n /= 2))
;
Here the loop condition provides all the necessary computation, so there is no real need
for a body. The loop condition not only tests that n is even, it also divides n by 2 and
ensures that the loop will terminate should n be zero.
The do…while statement (also called do loop) is similar to the while statement,
except that its body is executed first and then the loop condition is examined. The general
syntax is:
do
<statement>;
while (<condition>);
First statement is executed and then condition is evaluated. If the outcome of the latter is
nonzero then the whole process is repeated. Otherwise, the loop is terminated.
Example: i = n;
do
i *= --n;
while (n>1);
The do loop is less frequently used than the while loop. It is useful for situations where
we need the loop body to be executed at least once, regardless of the loop condition.
Unlike the while loop, the do loop is never used in situations where it would have a
null body. Although a do loop with a null body would be equivalent to a similar while
loop, the latter is always preferred for its superior readability.
The for statement (also called for loop) is similar to the while statement, but has two
additional components: an expression which is evaluated only once before everything
else, and an expression which is evaluated once at the end of each iteration. The general
form of the for statement is:
for (<initialize> ; <exit_ test> ; <update>)
<statement>;
Using braces we can have more than one statement to iterate. The for loop localizes
initialization, test for exit, and update - the variable to test, in one general syntactic
construct.
Contrary to what may appear, the scope for i is not the body of the loop, but the loop
itself. Scope wise, the above is equivalent to:
int i
for (i = n; n>2; n--)
i *= (n-1);
However, the three loop headers are optional. For example, removing the initialize and
update expressions:
for (; i != 0;) // is equivalent to: while (i != 0)
something;
Similarly, removing all the expressions gives us an infinite loop. This loop’s condition is
assumed to be always true:
for (;;) // loops forever
Something;
Because loops are statements, they can appear inside other loops. In other words, loops
can be nested. For example:
for (int i = 1; i <= 3; ++i)
for (int j = 1; j <= 3; ++j)
cout << ‘(‘ << i << ‘,’ << j << “) , ”;
produces the products of the set {1, 2, 3} with itself, giving the output:
(1,1) , (1,2) , (1,3) , (2,1) , (2,2) , (2,3) , (3,1) , (3,2) , (3,3) ,
Of course, it is not always easy to write all of your for, while and do…while loops
so that they are easy to read and yet the loops terminate on exactly the right pass through
the loop. C++ makes it easier to jump out of loops and to control other areas of program
flow with its break and continue statements.
The continue statement terminates the current iteration of a loop and instead forces
program control to go to the next iteration. In while and do loops, the next iteration
commences from the loop condition. In a for loop, the next iteration commences from
the loop expression. It is an error to use the continue statement outside a loop. For
example, a loop which repeatedly reads in a number, processes it but ignores negative
numbers, and terminates when the number is zero, may be expressed as:
Is Equivalent to
do { do {
cin >> num; cin >> num;
if (num < 0) continue; if (num < 0) {
// process num here … // process num here…
} while (num != 0); } while (num != 0);
A variant of this loop which reads in a number exactly n times (rather than until the
number is zero) may be expressed as:
for (i = 0; i < n; ++i) {
cin >> num;
if (num < 0) { // causes a jump to: ++i
// process num here …
}
When the continue statement appears inside nested loops, it applies to the loop
immediately enclosing, and not to the outer loops. For example, in the following set of
nested loops, the continue applies to the for loop, and not the while loop:
While (more) {
for (i = 0; i < n; ++i) {
cin >> num continue;
if (num < 0) { // causes a jump to: ++i
// process num here …
}
//etc…
}
4.4.2. break Statement
Just as the continue statement, a break statement is used to move program control to
immediately after the end of a loop. A break statement may appear inside a loop
(while, do, or for) or a switch statement. It causes a jump out of these constructs,
and hence terminates them. Earlier in this chapter, you saw how the break statement is
used to exit a switch statement. A break statement only applies to the loop or switch
immediately enclosing it. It is an error to use the break statement outside a loop or a
switch.
For example, suppose we wish to read in a user password, but would like to allow the
user a limited number of attempts:
for (i = 0; i < attempts; ++i) {
cout << “please enter your password: “;
cin >> password;
if (Verify(password)) //check password for correctness
break; // drop out of the loop
cout << “incorrect!\n”;
}
Her we have assumed that there is a function called Verify which checks a password
and returns true if it is correct, and false otherwise. Rewriting the loop without a break
statement is always possible by using additional logical variable (verified) and adding
it to the loop condition:
verified = 0;
for (i = 0; i < attempts && !verified; ++i) {
cout << “please enter your password: “;
cin >> password;
verified = Verify(password);
if (!verified) //check password for correctness
The goto statement provides the lowest-level of jumping. Using goto (for local
jumping) program control can be sent to anywhere inside the body of the program to
repeat execution of the statement(s).It has the general form:
goto label;
Where label is an identifier which marks the jump destination of goto. The label should
be followed by a colon and appear before a statement within the same function as the
goto statement itself. For example, the role of break statement in the for loop in the
previous section can be emulated by a goto:
for (i = 0; i < attempts; ++i) {
cout << “please enter your password: “;
cin >> password;
if (Verify(password)) //check password for correctness
goto out; // drop out of the loop
cout << “incorrect!\n”;
}
out:
//etc…
Because goto provides a free and unstructured form of jumping (unlike break and
continue), it can be easily misused.
The return statement enables a function to return a value to its caller. It has the general
form: return expression;
where expression denotes the value returned by the function. The type of this value
should match the return type of the function. For a function whose return type is void,
expression should be empty: return;
The only function we have discussed so far is main, whose return type is always int. the
return value of main is what the program returns to the operating system when it
completes its execution.
When a function has a non-void return value (as in the following example), failing to
return a value will result in a compiler warning. The actual return value will be undefined
in this case (i.e., it will be whatever value which happens to be in its corresponding
memory location at the time.)
int main (void)
{
cout << Hello World\n”;
return 0;
}
3. Assume that n is 20, what will the following code fragment output when
executed?
if (n >= 0)
if (n < 10)
cout << “n is small\n”;
else
cout << “n is negative\n”;
4. Write a program which inputs an integer value, checks that it is positive, and
outputs its factorial. Use the formula:
factorial (0) = 1
factorial (n) = n * factorial (n – 1)
5. Write a program for the Magic Number game. The program generates a random
number, prompts for your guess, and prints the message ** Right ** if you guess
the magic number. Include the header <cstdlib.h>.
5. Array
This section introduces the array and illustrates their use for defining their use for
defining variables.
An array consists of a set of objects (called its elements), all of which are of the same
type and are arranged contiguously in memory. It can also be considered as a variable
that can hold more than one value. Array is a series of elements of the same data type
(homogenous elements) placed consecutively in memory that can be individually
referenced by adding an index to a unique name. When you first studied variables, you
learned that a variable is like a box in memory that holds a single value. Now, if you take
a bunch of these boxes and put them together, you get an array.
Example: data Int Int Int Int contains 4 integer elements
In general, only the array itself has a symbolic name, not its elements. Each element is
identified by an index which denotes the position of the elements in the array. The
number of elements in an array is called its dimension. The dimension of an array is fixed
and predetermined; it cannot be changed during program execution.
Arrays are suitable for representing composite data which consist of many similar,
individual items. Examples include: a list of names, a table of world cities and their
current temperatures, or the monthly transaction for a bank account.
Fifty blocks are reserved in memory for this array. The size of each block is
determined by the data type; four bytes in this case.
Elements (values) of an array are accessed by using indexes with array name. If
the size of an array is n, then its n blocks are addressed using indexes from 0 to n-
1. For example, the first element of the above array is named by myarray[0], the
second one by myarray[1], ..., and the last element(block) by myarray[49].
The values to store in the above array should all be of data type integer.
If an array is defined as a global variable it will be automatically initialized to zero,
otherwise all the elements will be garbage values.
Arrays can be initialized during declaration with a single initializer list. In this case, its
size specifier may be omitted from its declaration. Consider the following declaration,
double a[5] = {15.5, 25.5, 35.5, 45.5, 55.5};
is equivalent to the declaration,
double a[] = {15.5, 25.5, 35.5, 45.5, 55.5};
In the later case the size is determined to be the number of values in the initializer list. If
the array has more elements than values listed in the initializer list, then the remaining
elements are initialized to zero. Un-initialized values in a list will be set to zero as:
double a[5] = {15.5, 25.5}; //means a[5] = {15.5, 25.5, 0, 0, 0}
double a[5] = {0}; //is equivalent to a[5] = {0, 0, 0, 0, 0}
Example 1.
/* The following program initializes an array and displays its elements in the reverse
order.*/
main ( )
{int b[5] = {10, 20, 30, 40, 50};
for (int i = 4; i >= 0; i--)
cout << " a[" << i << "] = " << a[i];}
Running this program, displays the numbers in reverse order.
N.B. This has not changed the physical allocation of the data in the memory.
Example 2.
/* The following program rearranges values in the array in increasing order. It uses
the bubble sort algorithm that proceeds through a sequence of iterations, each time
moving the next largest item into its correct position. On each iteration,
consecutive elements are compared, pushing the larger element forward.*/
main ( )
{
int a[20],tmp,k;
// The maximum number of values that you can store
//in the array a is 20
clrscr();
cout << "Enter the size and your data: \n";
cin >> k;
for (int i = 0;i < k;i++)
cin >> a[i];
Example 3.
/* The following program searches for a value and tells the location of the value, if it is
found in the array. It uses the linear search algorithm that starts at the beginning of
an array and inspect each element, one after another, until the object is found or the list
is exhausted.*/
main ( )
{
int a[]={50,100,2,70,40,30,79,1,10,7,8,25},target, found, loc;
clrscr();
cout << "The value to search: ";
cin >> target;
found = loc = 0;
while(!found && loc < 8)
found = (a[loc++] == target);
if(found)
cout << target << " is at a[" << --loc << "]\n";
else
cout << target << " is not in the list. \n";
5.1.2. Multidimensional Arrays
The arrays we have seen so far are all one - dimensional. An array may have more than
one dimension (i.e., two, three, or higher). Multidimensional array is an array of arrays.
The organization of the array in memory is still the same (a contiguous sequence of
elements), but the programmer’s perceived organization of the elements is different.
Data Type Identifier [Dim_1][Dim_2]…[Dim_n]
For example,
int a[10][5]; //two dimensional (10 & 5) integer array
char x[3][5][4]; // three dimensional character array
In the first array each block of the first ten blocks points to an array of five blocks. To
access a certain element, indices corresponding to each dimension should be supplied.
Example:
/* The following program inputs names of twenty students in a two-dimensional array
and then displays their names. */
main ()
{
char name[20][25];
for(int i = 0;i < 20;i++)
cin.getline(ch[i],15);
for(int i = 0;i < 20;i++)
cout << ch[i] << endl;
}
Assignment:
1. Write a program that multiplies two matrices, entered by the user.
2. Write a program that calculates the determinant of n x n matrix.
6. Functions
This section describes functions as one of the main building blocks of C++ program.
Functions are sub programs in C++. It is a very good technique to approach big problems
by dividing them into sub-problems.
Using a function involves ‘calling’ it. A function call consists of the function name
followed by the call operator brackets ‘( )’, inside which zero or more comma-separated
arguments appear. The number of arguments should match the number of function
parameters. Each argument is an expression whose type should match the type of the
corresponding parameter in the function interface.
When a function is executed, the arguments are first evaluated and their resulting values
are assigned to the corresponding parameters. The function body is then executed.
Finally, the function return value (if any) is passed to the caller.
Since a call to a function whose return type is non-void yields a return value, the call is
an expression and may be used in other expressions. By contrast, a call to a function
whose return type is void is a statement.
6.1. Modularization
To see how modularization makes things easy, take a look at the following code:
Example 1.
#include <iostream.h>
#include <conio.h>
main()
{
int A[3],B[3],C[3],sum[3],diff[3];
clrscr();
cout<<”Enter the elements of the arrays:\n”;
cout<<”The first array(A)”;
for (int i=0; i<3; i++)
cin>>A[i];
cout<<”The second array(B)”;
for (i=0; i<3; i++)
cin>>B[i];
cout<<”The third array(C)”;
for (i=0; i<3; i++)
cin>>C[i];
for (i=0; i<3; i++)
{
sum[i] = A[i]+B[i]+C[i];
diff[i] = A[i]-B[i]-C[i];
}
cout<<”Here is the sum of the elements of the three
arrays\n”;
for (i=0; i<3; i++)
cout<<sum[i]<<endl;
cout<<”Here is the difference of the elements of the
three arrays\n”;
for (i=0; i<3; i++)
cout<<diff[i]<<endl;
getch();
return 0;
}
The above code (program) is designed to read elements of three given arrays from the
user and then display the sum and the difference of the elements of the arrays
respectively. The program is actually doing what it intends to do. But there are some
‘ugly’ points that are visible if you have the eyes to do so. Can you see any ugly point?
You might say there are no ‘ugly’ points seen. You may feel that this is a very organized
and structured program. But unfortunately, it is not! We can show this by explaining
about modularization.
Programming in its general view refers to writing programs (which are set of
instructions) for solving a certain problem. We have been discussing in the previous
sections that the problems should be well defined and understood before writing any
programs to solve them.
This all is right except missing one important explanation about modular (structured)
programming which is one of the techniques of programming. Structured programming
refers to the way of writing programs as a group of modules instead of a very long block.
A module is a sub program which will be probably used by other sub programs and
which will probably use other modules.
It is always advisable to divide a given big problem into sub problems. It is again wise to
approach each sub problems separately. In effect, small problems which could be easily
solved will be left in hand. Then write the sub programs for the sub problems and finally
integrate them to form a bigger software.
In C++, sub programs are called functions. You will find different names for sub
programs in different programming languages (like procedures in Pascal).
So far, we have seen (written) programs consisting of only one function (which is the
main function and is mandatory). But after all, what is the need for modularization? Some
of the quite obvious reasons are:
a) Programs will be easily manageable: Attacking a problem in this way makes things
easy. Once you divide the problem into sub problems, it is possible to think of
the smaller problems separately with full attention and potential. Complexity is
one of the main reasons why writing programs is so difficult and eventually
complexity will be much less when using modularization.
#include <iostream.h>
#include <conio.h>
#include <math.h>
void main()
{
float a = sqrt (4);
cout<<a;
getch();
}
Sit and try to write a module to calculate the square-root of a given number
from scratch and see how much time you will spend.
d) Easy testing and maintenance: Testing is included as one of the steps when
developing programs. People (especially beginners) may underestimate testing
but it is very basic. To test a certain program, different test values (inputs) and
the corresponding expected outputs would be prepared and then provided
(entered) for the program observing the result and determine whether it is the
expected one or not.
It would be good to have a program which is used to do one main well defined
task instead of multiple tasks for the testing process. The same holds true for
maintaining programs. Obviously, after testing if you realize that there is an
error, it will be simple to identify and correct problems when the code is
compact and stand for the same task.
In summary, to correct mistakes, problems should first be identified. Identification of
problems is easier if the program is to be developed as set of functions instead of being a
very long block.
In the previous example, we may criticize points like the following in relation to
modularization:
a) So many tasks but only one block: As can easily be seen, there exist several tasks
included in the code. Here is how the code is organized:
i) Read array A,
ii) Read array B,
iii) Read array C,
iv) Add the elements of the arrays,
{ {
… …
} }
SubtractArrays() main()
{ {
…
ReadArray();//for array a
}
ReadArray();//for array b
DisplaySum()
ReadArray();//for array c
{
… AddArrays();
} SubtractArrays();
DisplayDiif() Display();// for the sum
{ Display(); //for the difference
… }
}
main()
{
ReadArrayA();
ReadArrayB();
ReadArrayC();
AddArrays();
SubtractArrays();
DisplaySum();
DisplayDiff();
}
In the first skeleton, we mapped each task to one function. It is not always appropriate to
do so from efficiency point of view. Before mapping each task to one function, look for
similar tasks. For example ReadArrayA(), ReadArrayB(), ReadArrayC()
are very similar and can be made to be accommodated in one function. A function named
ReadArray() could be defined and the main() function could call it three times for
each array. The same is true for displaying the sum and difference. We could have one
generic function name Display() and call it two times. As a result, we will have a
compact skeleton like the second one.
Avoid any confusion which could be created as a result of calling the same function for a
little bit different tasks by believing that there is a way to make the ‘callings’ different. I
assure you there is!
int a=2,b=3,c;
c = pow(a,b);
cout<<c;
getch();
return 0;
}
The pow(a,b) function is used to calculate ab (a the power of b). This function is not
part of the C++ language itself. Instead it is written and be ready for use by the producers
of the compilers. These kinds of functions which are readily available are called pre-
defined functions.
But where are these functions defined? The answer is straightforward. They are defined
in header files which are included at the beginning of the program. In actual terms,
header files contain built-in (pre-defined) function prototypes.
The direct implication of the above statement forces us to include the header file
<math.h> to use the pow function. Several built in functions exist and it is a good habit
to dig into header files to put the functions in mind so that you will be able to explore the
vast ocean of functions in C++.
A function definition consists of the interface (also called head) and the body of the
function. The interface of the function includes important information about the function
which are listed below:
i. The function’s name: Any function must have a name so that it can be referenced.
The rules which we rely on to name variables could directly be applied to function
names.
Example 3: Read_Input()
ii. The function’s return type: Even if there are functions which do not return any thing,
most functions do return a certain value to their calling functions. If a function
returns a value, then the value should be one of the data types in C++. This type is
needed to be stated explicitly in the head of the function.
iii. Parameters: Parameters are zero or more identifiers which are used to pass
information between functions in different ways.
The body of the function will contain all the C++ statements used for accomplishing the
task of the function. Pair of braces ‘( )’ is used to enclose the body of the function.
Example 4:
int add (int num1, int num2)
{
int s;
s = num1+num2;
return s;
}
Note: the above is not a complete C++ program.
Let’s discuss about the above function. The first line is the head of the function:
int add (int num1, int num2)
Return name parameters
type
If you feel that there is nothing to be returned, the function’s return value could be called
‘void’. This implies void functions do not need a return statement.
If a function doesn’t have any parameters, put two brackets ‘(())’ at the end of the
function’s name. It is not correct to leave a function name without brackets. If the worst
comes, the brackets might be empty.
A function call simply consists of the function’s name followed by brackets in which zero
or more arguments are included. Arguments are values which will be sent to the function
and later copied to parameters. The number of parameters and arguments must be equal.
Note that arguments are directly mapped to parameters based on their order.
Moreover, void functions and functions having return values are called a little bit
differently. The value that is returned from a function should be (it is not actually must
be) used in an expression in the calling function’s side. But, void functions will be simply
called as a C++ statement.
The third point regarding function calling is that any function can call any other function
if the function to be called is declared or defined prior to its usage. Finally, in C++, it is
not possible to define a function within the body of another function.
int add (int num1, int num2) int add (int num1, int num2)
{ {
int s; int s;
s = num1+num2; s = num1+num2;
return s; return s;
} }
//********************** //**********************
void main() void main()
{ {
int sum; int a,b,sum;
sum = add(2,5); cout<<”Enter two numbers:”;
cout<<sum; cin>>a>>b;
} sum = add(a,b);
cout<<”The sum of the
numbers is “<<sum;
}
In the above examples, observe the following points:
The function add (its definition) comes before the main() function is defined. The
reason is that the main function will call the add function and at the time of calling,
the function has to be defined or declared. If you rearrange the functions (main first
and add second), without adding anything, then the compiler will report an error
message. Particularly Turbo C++ compiler displays the following error message
whenever such a problem exists:
Function ‘function name’ should have a prototype.
(Function add should have a prototype.)
This implies: because of the rearrangement, something else is needed which the
compiler called it ‘prototype’. We are going to discuss about prototypes later on. But
for the time being let’s adhere to the assumption that to be called functions should be
placed before the caller function.
In Example 5, arguments are numbers which are sent to the function. Let’s study the
statement at which the function is called.
sum = add(2,5);
This is actually an assignment statement which assigns the value returned by the
expression add(2,3) to the variable sum. When this statement is processed, control
will automatically be taken to the function add. The arguments 2 and 3 are copied to
the parameters num1 and num2 respectively. Then the sum of the numbers is
calculated and is stored in the local variable s inside the body of the function.
The same happens in Example 6 except arguments are obtained from users and are
sent through variables.
sum = add(a,b);
The values of the variables a and b will be copied to the parameters num1 and num2
respectively and their sum will be returned.
Example 7:
#include <iostream.h>
#include <conio.h>
//-----Display_Menu----------------------------
void Display_Menu()
{
cout<<”*******MENU*******”);
cout<<”\n\t1. Add Numbers”;
cout<<”\n\t1. Subtract Numbers”;
cout<<”********************”);
}
//--------add----------------------------------
int add (int num1, int num2)
{
int s;
s = num1+num2;
return s;
}
//--------subtract---------------------------------
int subtract(int num1, int num2);
{
return num1-num2;
}
//--------main--------------------------------------
void main()
{
int n1,n2,choice;
Display_Menu();
cin>>choice;
cout<<”Enter two numbers:”;
cin>>n1>>n2;
if (choice==1)
cout<<”The sum of the numbers is “<<add(n1,n2);
else
cout<<”The difference between the numbers is
“<<subtract(n1,n2);
}
The function Display_Menu() is called as a statement because we do not expect any
return value from this function. Void functions may do an action like displaying
something, changing the values of variables, and etc. In the other side, the values returned
from the remaining two functions (add and subtract) are used in the cout statements. But
this doesn’t mean that the following call is invalid:
add(n1,n2);
This is a valid call causing the numbers to be added and their sum is returned. But the
value returned is simply lost and logically this is not all right.
Note: If a return value is not specified for a function, then it will be assumed that the
function has an int return type and eventually a return statement is expected.
Generally, we may define the following types of functions (commonly) when practicing
functions in writing programs:
a. Void functions: These functions will be included whenever some action has to be done.
The names of these functions are usually verb phrases like Display_Menu();
b. Input/Output functions: Functions used for reading input and producing output will
also be included most of the time.
c. Boolean functions: These kinds of functions are used to determine whether something
is true or false. They return a Boolean value (true(1) OR false(0)). Boolean
functions are usually used with selection statements like ‘if’. It is also a common
practice to give a name which starts with “Is...” for such types of functions. (like
IsMax(int m)…this can be a good name to refer to a function which
determines whether the argument is the largest number from a certain reference
list).
The prototype of a function is simply a declaration of the function which consists of the
return type, the name of the function and the parameters (if there are any).
Look at the Example 8 which is given below. Lines 4-7 indicate how function prototypes
are specified. If all the functions are declared like this, the compiler will not bother about
the order of the functions. In other words, the functions’ declarations make them global.
return ch;
}
//--------add----------------------------------
int add (int num1, int num2)
{
return num1+num2;
}
//--------subtract------------------------------
int subtract(int num1, int num2);
{
return num1-num2;
}
//-------Read_Numbers---------------------------
void Read_Numbers()
{
cout<<”Enter two numbers:”;
cin>>num1>>num2;
}
Example 9:
Write a program which will find the value of y for a given value of x using the following
mathematical function:
x3 5 x 5
y *
2 x 3
Solution:
Observing the given function, we can easily come up with a set of functions needed to
solve this problem. Study the mathematical function. The operations involved are:
Square root
Exponentiation Subtraction
x3 5 x 5
y *
2 x 3
Multiplication
Division Addition
Therefore we need to use five functions. We are going to write a function for each
operation and test it using a test driver. Let’s proceed:
a. Exponentiation:
The following is a function which returns xy by taking x and y as parameters:
int expo(int x, int y)
{
int result=1;
for (int i=1;i<=y;i++)
result=result * x;
return result;
}
The next step is to test the function by writing a test driver. But before that let’s talk
about one more point. In the mathematical function given in the problem, we need to
calculate only x3. But here we developed a generic function which could be used to
calculate xy for any given positive integers x and y. This is a good idea because we may
need a similar function in another time and can simply reuse this one if we make it to
work for general case. Therefore, it is always better to write generic functions except in
cases where you might face more problems when trying to do it. Anyways, it is still your
decision.
But, is this the end of the test? The answer is no since we need to try more numbers like 4
and 5 (by expecting 1024) or 1 and 3 (by expecting 1). You will do this by inserting the
numbers in the function call found in the main function. Still, the function is working
well.
Are we satisfied? If you say yes, you are really wrong. Previously, we tried only positive
numbers. What about other cases where negative numbers involve? What about x 0? You
must also see these cases since we are making the function generic and we may reuse it in
the future without any hesitation.
Try 2 and 0. The expected value is 1. Luckily, this test is also successful. As we have
already discovered, we are left with one case which is when one of the parameters are
negative.
Try -2 and 3. The expected value is -8. It again works. The other case is when the
exponent is negative like 2 and –3. We expect to see 0.125 on the screen. Unfortunately
or fortunately, we will see 1 which is not the expected answer. This implies the function
has a defect. What is the cause of this defect?
You will automatically find out that the function is unable to handle negative exponents
since the for loop doesn’t have any chance of execution when the exponent (which is the
boundary value for the for loop) is negative. Even if you find a way to execute the for
loop, it is still needed to return the reciprocal of the number. The function can be
corrected as follows:
#include <iostream.h>
#include <conio.h>
//prototype………………………………
float expo(int x, int y);
//--main----------------------------------------------
void main()
{
cout<<expo(2,3);
getch();
return 0;
}
//--expo----------------------------------------------
float expo(int x, int y)
{
float result=1.0;
if (y>0) // if y is positive
for (int i=1;i<=y;i++)
result=result * x;
else //if y is negative
{
for (int i=1;i<=-y;i++)
result=result * x;
result = 1/result; //take the reciprocal
}
return result;
}
After modification, the function is tested and it returns 0.125.
In a similar way, develop the other functions one by one and build the program.
Therefore, the following could be the complete program:
#include <iostream.h>
#include <conio.h>
#include <math.h>
//prototypes………………………………
float expo(int x, int y);
float difference(float x, float y);
float sum(float x, float y);
float quotient(float x, float y);
float product(float x, float y);
float computeY (float x);
//------main------------------------------------
void main()
{
float x, y;
cout<<”\n\n\t This program will help you to evaluate the
function”;
cout<<”\n\ty =[(x3+5)/2]*[(sqrt(x)-5)/(x+3)] for a given
value of x.”;
cout<<”\n\n\t\t Please provide the value of x:”;
cin>>x;
y = computeY(x);
cout<<”For x=”<<x<<” y=”<<y;
getch();
return 0;
}
//------expo-----------------------------------
float expo(int x, int y)
{
float result=1.0;
if (y>0) // if y is positive
for (int i=1;i<=y;i++)
result=result * x;
else //if y is negative
{
for (int i = 1;I <= -y; i++)
result=result * x;
result = 1/result; //take the reciprocal
}
return result;
}
//--sum---------------------------------------
float sum(float x, float y)
{
return (x+y);
}
//--difference-------------------------------
float difference(float x, float y)
{
return (x-y);
}
//--quotient----------------------------------
The scope of variables determines how long it is available to the program and where it
can be accessed. Generally to understand this in more detail, pay attention to the
following simple example:
Example 10:
#include <iostream.h>
#include <conio.h>
int DoubleValue(int a);
void main()
{
int x=5;
int y=DoubleValue(x);
cout<<”When the number “<<x<<” is doubled, “<<”it
will be “<<y;
getch();
return 0;
}
//-- DoubleValue -----------------------------
int DoubleValue (int a)
{
int s=2*a;
return s;
}
In the above program, different variables are declared and used in different places. The
variables x and y are declared in the main function. Since x is declared in the first line
within the block of the main function, it is visible and usable (accessible) through out the
main function (note that it is not stated as ‘through out the program’). Concerning the
second variable y, it is declared in the second line and accessible after that point. There is
no way to legally use the variable y before its declaration even in the main function. It is
quite obvious that these variables are not known in the function DoubleValue. Similarly,
variables like a and s are declared and used in the function DoubleValue which implies
they are local to this function.
Discussing about the scope of variables is very important here as we do have more than
one function in a program. The existence of several functions in a program makes the
scope of the variables different as to where they are declared.
Based on the scope of variables, it is likely to divide the type of variables into two
namely Local Variables and Global Variables. We will discuss about these two types of
variables in the next few topics:
Parameters of functions are also considered as local variables which directly implies that
parameters can be used as any local variables as if they had been declared in the body of
the function.
//----main----------------------------------------
void main()
{
int choice=Display_Menu();
Read_Numbers();
if (choice==1)
cout<<add(num1,num2);
else
cout<<subtract(num1,num2);
}
//---Display_Menu----------------------------------
int Display_Menu()
{
int ch;
cout<<”*******MENU*******”);
cout<<”\n\t1. Add Numbers”;
cout<<”\n\t1. Subtract Numbers”;
cout<<”********************”);
cout<<”\nEnter your choice:”;
cin>>ch;
return ch;
}
//--------add--------------------------------------
int add (int n1, int n)
{
return (n1+n2);
}
//--------subtract-----------------------------------
int subtract(int n1, int n2);
{
return (n1-n2);
}
//-------Read_Numbers--------------------------------
void Read_Numbers()
{
cout<<”Enter two numbers:”;
cin>>num1>>num2;
}
Example 12:
Consider the following program: a is a global variable
which is visible to all the
#include <iostream.h> functions in the program,
#include <conio.h>
int a=6; sum is a local
int add(int x, int y); variable to the
void main() main function.
{ ch is a global variable
int sum = add(a,a);
which is global to all
cout<<”Sum=”<<<<sum;
} the functions after its
char ch=’A’; declaration (add).
int add(int x, int y) x and y are local
{ variables to the
cout<<”ch=”<<ch; function add.
int s=x+y; s is a local
return s; variable to the
}
function add.
Example 13:
Predict the output of the following program:
1 #include <iostream.h> Observe that there exist three local variables.
2 #include <conio.h> All these variables are the same by name (num),
3 void fun1(int num); but they are completely separated and different
4 int func2(int num); variables. In other words, there is num of the
5 void main() main function, num of func1, and num of func2.
6 { Therefore, the four lines will be displayed.
7 int num=6;
8 cout<<”num=”<<num<<endl; In line 8, num=6 will be displayed. In line 9,
9 func1(num); func1 is called causing the body of the function
10 cout<<”num=”<<num<<endl; to be executed. The variable num is specified as
11 num = func2(num); an argument in this call. Recall that the value of
12 cout<<”num=”<<num<<endl; the variable (not the variable itself) is sent to the
13 } function. This value which is brought to the
14 void func1(int num) function will be copied to the parameter (local
15 { variable) num of func1. func1 increments the
16 num++; local parameter num and display it in line 16
17 cout<<”num=”<<num; and 17 respectively. The end of the function is
18 } marked by the closing brace in line 18 and
19 int func2(int num) execution will be continued back in the main
20 { function from line 10 printing line 3 of the
21 num=num+2; output. Here the same local num to the main
22 return num; function is referred (Hence num=6). Line 11
23 } consists of another function call. func2 is called
by specifying the value of num as an argument.
The output of the program shown will be func2 copies the argument to its local num. In
as indicated below: line 21, the local num is updated to 8 and this
num = 6 (in the main function) same value is returned. The returned value is
num = 7 (in the function func1) assigned to the local num of main because of the
num = 6 (in the main function) assignment operator in line 11. and finally,
num = 8 (in the main function) num=8 will be printed since the local num of
main is already modified in line 11.
In the second program, the variable n is declared as static. Because of this reason, the
value of n in the previous call is preserved. Therefore, after the call of MyFunc for the
first time, the value of n will be 3. This value will be saved. In the next call, the value of
n will again be incremented. This time the value of n becomes 4. When the third call is
executed, the value of n will be 5.
Of course by using global variables you will not worry about the visibility of the variable
to any given function. It might seem this way simplifies things. However, the truth is it
may create a very complex problem because one function may unconsciously modify the
variable and hence logical error. But if you have a good reason to make variables global
(if several functions share a variable), it might be acceptable. Still, the surprising thing is
that anything that can be done using global variables can also be performed using local
variables and that is why global variables are not encouraged.
Static variables are used when you want to preserve intermediate values. The following
might be a good example:
Example 15:
The following program will compute the value of y for a given value of x using the
following mathematical equation:
y = x3+x2+x+5
Solution:
#include <iostream.h>
#include <conio.h>
#include <math.h>
int sum(int currval);
void main()
{
int x,y;
cout<<”\nEnter the value of x”;
cin>>x;
y=sum(pow(x,3));//to add x3 to the initial value of static
variable s which is 0.
y=sum(pow(x,2));//to add x2 to x3
y=sum(x);//to add x to the sum of x3 and x2
y=sum(5);//to add 5 to the total sum of x3,x2 and x
cout<<”\nThe value of y is “<<y;
}
int sum(int currval)
{ Enter the value of x:
static int s=0; 2
s=s+currval;
The value of y is 15
return s;
}
The possibility that we have is to assign a default value for parameters and it is allowed
to omit the parameters which have a default value when the function is called. The logic
is simple: if you don’t provide a value for the default parameter, then the default value
will be used within the function (if needed).
Default parameters are given default values when the function is declared (in the
prototype). In addition to this, default parameters must be placed to the right of the other
parameters. This implies it is not possible to mix up default parameters with the others.
Example 16:
#include <iostream.h>
#include <conio.h>
void f1(int x, int y=0);
void main()
{
x=2
f1(2,3);
y=3
f1(9);
getch(); x=9
} y=0
void f1(int x)
{
cout<<”x=”<<x<<endl;
cout<<”y=”<<y<<endl;
}
The function f1 is called two times. In the first call, two arguments are sent to the
function and x=2 and y=3 are printed. The second call to the same function has got only
one argument and it is valid as the second parameter is a default parameter. As a result of
this call, x=9 and y=0 (which is the default value) will be displayed.
Example 17:
The prototype int f1(int a, int b, int c=3, int d=2) is valid because all the default
parameters are accumulated to the right side. But the prototype void f2(int a, int b=4, int
c, int d=45); is invalid as the default parameters are mixed up with the others.
Example 18:
Write a C++ program which will be used to evaluate polynomial functions with various
degrees. Suppose it is required that the program should be able to work for up to degree 4
polynomials. The user will be prompted to enter the degree of the polynomial, the
polynomial itself and the value of x. In the end, the program is expected to display the
value of y.
Solution:
There could be two possibilities to write a program for the given problem.
Possibility 1:
Define separate function to evaluate polynomials of degree 0,1,2,3, and 4 and call them
based on the given degree (obtained from the user)
Possibility 2:
Define only a single function that could be called for all the stated degrees flexibly. The
function would have arguments for the coefficients of the polynomial and the value of x.
Since the value of the degree of the polynomial depends on the user’s input, there is no
way to know it in advance. Therefore, we could make the parameters for the coefficients
default parameters by assigning them a default value 0 like the following:
int computeY (int valueofx, int c0,int c1=0,int c2=0,int c3=0,int c4=0);
//c0 refers to the constant value, c1 refers to the coefficient of x1, c2 refers
//to the coefficient of x2, c3 refers to the coefficient of x3,c4 refers to the coefficient
of x4
For instance if the user wants the program to evaluate a polynomial of degree 2, then it is
expected that coefficients exist for x2, and probably for x1. In this particular case, the
function will be called by providing valueofx,c0,c1 and c2. The last two parameters will
be omitted and their default value (which is 0) will be taken in the calculation within the
body of the function. The following could be a call to this function to evaluate the
function y=2x2+3x+5 when the value of x is 3.
int y=computeY(3,5,3,2);
The following program is provided as to make you see how this feature is useful. The
program uses graphics mode and has a very good interface. I believe it will be a good
opportunity for you to explore these built in graphics functions as well. Try to understand
it by reading about each of the functions and learn more (optional).
#include <iostream.h>
#include <conio.h>
#include<math.h>
#include <graphics.h>
#include <stdlib.h>
#include <dos.h> //global variables
int c[5];
int ValueOfX,deg; //function prototypes
void DisplayHomePage(int color);
void CollectInformation(int color);
void AcceptEquation(int deg);
int computeY(int ValueOfX,int c0,int c1=0,int c2=0,int c3=0,int
c4=0);
//--------main function------------------------------------------
void main()
{
int gdriver = DETECT, gmode, errorcode;
int left, top, right, bottom;
/*initialize graphics and local variables */
/*C:\\tc\\bgi is the path of the graphics driver and
it is to be changed if a differnt driver path exists
in the pc that you are working*/
initgraph(&gdriver, &gmode, "C:\\tc\\bgi");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
cout<<"Graphics error: %s\n"<<grapherrormsg(errorcode);
cout<<"Press any key to halt:";
getch();
exit(1); /* terminate with an error code */
}
int ValueOfY;
DisplayHomePage(4);
sleep(1);
DisplayHomePage (0);
CollectInformation(5);
if (deg==0)
ValueOfY=computeY(ValueOfX,c[0]);
else if (deg==1)
ValueOfY=computeY(ValueOfX,c[0],c[1]);
else if (deg==2)
ValueOfY=computeY(ValueOfX,c[0],c[1],c[2]);
else if (deg==3)
ValueOfY=computeY(ValueOfX,c[0],c[1],c[2],c[3]);
else if (deg==4)
ValueOfY=computeY(ValueOfX,c[0],c[1],c[2],c[3],c[4]);
setcolor(4);
outtextxy(100,150+15*(deg+9),"The value of y is ");
gotoxy(28,11+(deg+9));
cout<<"y = "<<ValueOfY;
getch();
}
//---------DisplayHomePage -------------------------------------
void DisplayHomePage (int color)
{
setcolor(color);
setlinestyle(2,3,3);
/*draws an ellipse of center(290,220)
and horizontal radius of 220 and vertical
radius of 120*/
ellipse(290,220,0,360,220,120);
if (color==0)
setcolor(color);
else
setcolor(2);
settextstyle(5,0,3);
delay(500);
outtextxy(130,130,"Dear User,");
delay(500);
outtextxy(150,150,"It is a pleasure to help you!");
delay(500);
settextstyle(4,0,3);
if (color==0)
setcolor(color);
else
setcolor(15);
outtextxy(150,190," WELCOME");
settextstyle(3,0,2);
if (color==0)
setcolor(color);
else
setcolor(9);
delay(500);
outtextxy(150,220,"This program will help you to");
delay(500);
outtextxy(150,250,"evaluate a polynomial equation");
delay(500);
outtextxy(150,280," of degree 0,1,2,3,4");
}
//---------CollectInformation------------------------------------
void CollectInformation(int color)
{
setcolor(color);
rectangle(80,80,500,400);
setcolor(15);
settextstyle(11,0,3);
outtextxy(100,100,"Enter the degree of the polynomial:");
gotoxy(49,7);
cout<<"_\b";
cin>>deg;
outtextxy(100,130,"Now, enter the equation:");
AcceptEquation(deg);
}
//---------AcceptEquation--------------------------------
void AcceptEquation(int deg)
{
for(int i=deg;i>0;i--)
{
int j=deg-i;
outtextxy(120,150+15*j,"Coefficient of ");
gotoxy(31,10+j);
cout<<"x^"<<i<<": _\b";
cin>>c[i];
}
outtextxy(120,150+15*deg,"Constant value:");
gotoxy(31,10+deg);
cout<<"_\b";
cin>>c[0];
setcolor(4);
int r=deg+2;
outtextxy(100,150+(15*r),"Your equation is");
gotoxy(30,11+r);
cout<<"y = ";
for (i=deg;i>0;i--)
{
if (c[i]!=0)
if(i==1)
cout<<c[i]<<"x+";
else
cout<<c[i]<<"x^"<<i<<"+";
}
cout<<c[0];
r=r+3;
setcolor(15);
outtextxy(100,155+(15*r),"Enter the value of x:");
gotoxy(35,11+(r-1));
cout<<"_\b";
cin>>ValueOfX;
}
//---------computeY----------------------------------
int computeY(int ValueOfX,int c0,int c1,int c2,int c3,int c4)
{
int
y=c4*(pow(ValueOfX,4))+c3*(pow(ValueOfX,3))+c2*(pow(ValueOf
X,2))+c1*(pow(ValueOfX,1))+c0;
return y;
}
The variables that are listed in the function’s parameter list are known as formal
parameters (arguments). Formal arguments are local to a function. They are also
called dummy arguments.
The expressions that are listed as parameter in the function call are called actual
parameters (arguments). During function call each of these expressions should be
evaluated to give a result which is compatible to the corresponding formal parameter.
When passing information through parameters, there are two different ways to do it:
i) Pass by value (by copy)
If parameters are said to be passed by value, then only their values (not themselves)
are passed to the function. As a result, any change which is done within the function
body on the formal parameters will not affect the actual parameters sent. To
understand this idea well, look at the examples given below:
Example 19:
Predict the output of the following program: Enter the length of the rectangle: 11.5
#include <iostream.h> Enter the width of the rectangle 12
#include <conio.h> The perimeter of the rectangle is 23.5
float perimeter(float length, float width);
void main()
{
float l,w;
cout<<”Enter the length of the rectangle:”;
cin>>l;
cout<<”\nEnter the width of the rectangle:”;
cin>>w;
cout<<”\nThe perimeter of the rectangle is
”<<perimeter(l,w);
getch();
}
float perimeter(float length, float width)
{
return (2*length+2*width);
}
Four local variables are defined in the above program namely l,w (actual arguments
and local to main) and length, width(dummy parameters and local to perimeter).
During the function call (line 6 of the main function), the variables l and w are
specified as arguments. In this call, the arguments are passed by value, which is
exactly to mean the values of l and w are brought to the function and copied to the
parameters length and width respectively.
Parameters passed by value are referred as read-only.
Example 20:
Consider the following program and predict the output:
#include <iostream.h>
#include <conio.h>
void fun1(int i, int j); a=2
void main() b=3
{ int a=2,b=3; a=2
cout<<”\na =”<<a; b=3
cout<<”\nb =”<<b;
fun1(a , b);
cout<<”\na =”<<a;
cout<<”\nb =”<<b;
getch();
}
void fun1(int i, int j)
{
i++;
j=j+2;
}
The output will be as shown in the box. When the function is called (in line 4 of the
main function), the arguments are passed by value. The values of a and b are sent and
copied to i and j. The two statements with in the body of the function will change the
value of i and j but this will not be propagated to the variables a and b because only
their values are brought there.
Example 21:
The program given in the previous example is a little bit changed at some points.
Changes are shown in bold font. Determine whether the same output will be
generated than the previous one.
#include <iostream.h>
#include <conio.h>
void fun1(int i, int j);
void main()
{
int i=2,j=3;
cout<<”\ni =”<<i;
cout<<”\nj =”<<j;
fun1(i , j);
cout<<”\ni =”<<i;
cout<<”\nj =”<<j;
getch();
}
void fun1(int i, int j)
{
i++;
j=j+2;
}
We are ready to bet that exactly the same output will be generated. We have still four
distinct local variables namely i, j (local to main) and other i, j (local to fun1).
Therefore, no change will be exhibited even if we replaced the variables a and b by i
and j in the main function. Still the variables are passed by value.
To make a parameter passed by reference, put an ampersand (&) symbol before the
identifier of the parameter or after the data type of the parameter. All the following
prototypes are valid considering compilation as well as execution:
void f1(int &a);
void f1(int& a);
void f1(int&a);
Example 22:
Trace the following simple program and predict the output:
#include <iostream.h>
#include <conio.h>
void fun2(int &x);
void main()
{
int myvar=3;
cout<<”\nBefore the call…….\n”;
cout<<”myvar = “<<myvar;
func2(myvar); Before the call……….
cout<<”\\nAfter the call…….\n”; myvar = 3;
cout<<”myvar = “<<myvar; After the call……….
getch(); myvar = 5;
}
void func2(int &x)
{
x = x+2;
}
The modification being made to x is propagated to myvar because the argument is now
passed by reference.
Parameters are passed by reference because of different reasons. Some of the frequently
happened cases which make the program to use pass by reference could be:
Example 23:
Suppose we want to develop a function which accepts the value of the radius of a circle
and calculates both the area and circumference of the circle. The following
implementation is not the right solution:
The function call passes the variables area and circum to the function compute by
reference. In the parameter listing of the function compute, the variables A and C will
replace them. In other words, A and C are local names to represent Area and circum with
in the body of the compute function. The two assignment statements in the function
compute will assign the computed value to A and C and eventually to Area and circum in
the main function.
#include <iostream.h>
#include <conio.h>
void compute(float radius, float &A, float &C);
void main()
{
float area, circum,radius;
cout<<”\nEnter the radius of the circle”);
cin>>radius;
compute(radius, area, circum); Enter the radius of the circle: 3
cout<<”\n\tArea = “<<area; Area = 28.26
cout<<”\n\tcircumference = “<<circum; Circumference =
getch(); 18.84
}
void compute(float radius, float &A, float &C)
{
A=3.14*radius*radius;
C=2*3.14*radius;
}
b. When writing Input functions reading multiple values:
A function that is used to prompt the user for input data (multiple values) could
possibly have parameters passed by reference. These parameters will be used to pass
the values of the input parameters.
Example 24:
In the following program, three functions exist: Get_Values(), Calc_Avg() and
main(). Understand the program and see how parameters passed by reference are
useful in writing functions like Get_Values().
#include <iostream.h>
#include <conio.h>
void Get_Values(int &a, int &b, int &c);
float Calc_Avg(float a, float b, float c);
void main()
{
int a,b,c; Enter the values of the
three numbers:
Get_Values(a,b,c);
3, 4, 6
The average of
Last Update: Jun. 23, 12
the numbers is 4.33
95
Circumference = 18.84
Ethiopian Civil Service College Computer Programming & Numerical Methods
Note: It is possible to add the keyword const before parameters passed by reference to
make sure that no change will affect the actual argument.
There is one exceptional case:
When arrays are passed as arguments, they are passed by reference by default. The reason
is that the pointer to the initial element of the array is passed when arrays are passed as
arguments. Therefore, any modification is directly applied to the memory space reserved
for the array as the function statements are executed.
Example 25:
#include <iostream.h>
#include <conio.h>
void Change(int a[3]);
void main()
{
int b[3] = {2,3,5};
cout<<”Before the call…….”;
for (int i=0;i<3;i++)
cout<<”b[“<<i<<”]=”<<b[i]<<endl;
Change(b);
cout<<”After the call…….”;
for (int i=0;i<3;i++) Before the call…………..
b[0]=2
cout<<”b[“<<i<<”]=”<<b[i]<<endl;
b[1]=3
getch(); b[2]=5
} After the call…………..
void Change(int a[3]) b[0]=3
{ b[1]=4
for(int i=0;i<3;i++) b[2]=6
a[i]++;
}
Example 26:
Write a program which will double a given number. If the user enters a character (instead
of a number), the program should display the character two times (funny doubling).
Solution:
‘Number’ may refer to integers or float type numbers. Considering both cases is essential.
Since we will give a chance for the user to enter integers, floats and characters, we need
three different functions to double them. Based on this conclusion, the program given on
the next page (page 29) could be a good candidate to achieve the goal stated in the
problem.
The three functions that are used to double the items are DoubleInt, DoubleFloat and
DoubleChar. Observing these functions lead us to the conclusion that they are used to
perform the same thing but on different types of data. For such kinds of situations,
overloading functions is very helpful and comfortable.
In C++, overloading functions is possible which means more than one functions can be
defined with the same name but with different parameters. Parameters may differ in their
number or their data type. It is possible to define the following functions in a single
program:
}
else if (choice==2)
{
cin>>FloatVal;
cout<<"When the value "<< FloatVal <<" is doubled,
it will be "
<< DoubleFloat (FloatVal);
}
else
{
cin>>CharVal;
cout<<"When the character "<<CharVal<<" is double,
it will be ";
DoubleChar (CharVal);
cout<<". Funny! Isn't it?";
}
getch();
}
The three functions that are developed for similar actions to be applied on different items
(in the above program) can be declared and defined using the same name. Overloading
these functions is useful because you will not bother to create and use different functions
for each type of data. Therefore, these functions could be declared and defined using the
same name but with different parameters and return type. The programmer is not to
worry about which one to call. When passing arguments, the right function will be called
automatically. The above program could be rewritten like the following applying
overloading:
Going here and there might result in poor efficiency (speed). Specifically, if the functions
are very small (having two or three instructions), it will not be reasonable to jump into
these instructions as the functions are called. If these small functions are called twenty
times in your program, it is an obligation to move from the current execution point to the
copy of the instructions of the function and come back again for twenty times.
In C++, there is one solution for this problem which is making functions inline. If
functions are made to be inline, then the compiler will not create an independent copy of
the instructions but will directly insert the instructions in the place of the function call to
prevent jumping from one point to another one. No jump is made; it is just as if you had
written the statements of the function right into the calling function.
But sometimes making functions inline may not help or may result in another problem
which is also related to efficiency. The program becomes very long if (especially) large
functions are declared as inline functions. Therefore, the only candidate functions to be
inline are very small functions and are called many times in the program.
On page 32, a funny program is presented in which I believe using an inline function is
reasonable. An array of string(of size 14) is declared and initialized in the main function.
The elements of the array are sent to the function named PrintMessage so that each
message is displayed on the screen. Consequently, the program prints 14 messages turn
by turn by making a delay of two seconds between each message. The bottom line is the
small function PrintMessage is called 14 times.
Example 27:
#include <iostream.h>
#include <conio.h>
#include <dos.h>
inline void PrintMessage(char* msg);
void main()
{
char* greetings[14]={"Hello Dear User", "Welcome to this game",
"Here we have the funs", "You will be happy to be here",
"Sooner or later you will get the dearest thing in the world",
"That is OUR GREETING and WELCOME", "Are you angry?",
"We have another fun which makes you cheerful",
"Wait please………..",
"Fire!Fire!Fire",
"All your files are being deleted from your harddisk",
"..........................",
"You better shut down the system",
"No,no,no! Ha,Ha,Ha………… don't do that! we are kidding" };
clrscr();
for (int i=0;i<14;i++)
{
if (i==11)
for(int j=1;j<=5;j++)
{
PrintMessage(greetings[i]);
delay(400);
}
else
{
PrintMessage(greetings[i]);
sleep(2);
}
}
getch();
}
void PrintMessage(char* msg)
{
cout<<msg<<endl;
}
The relative error is sometimes important to get a feeling on how 'significant' an error is.
Thus for a number A, if a is its approximation, then:
Ea = A - a
In reality, however, we seldom know the true value of a quantity. Hence to talk about the
correct value of the error might not make sense. Therefore, it is a usual practice to talk
about the upper bound of the error rather than the true magnitude of the error, it is
written:
Ea /A - a/
Or
A = a Ea
Thus the error is taken as the smallest number that is greater than or equal to the
difference between the true value and the approximate value.
In the same way the definition for the relative error is somewhat modified to reflect the
fact that the true value is not known,
A a
Er , a 0
a
and the true value can be written as
A = a (1 Er)
Still in some applications, the solution of a given problem is obtained through successive
approximation. In such cases the value at the end of any iteration apart from the last one
is an approximation of the final (approximate) solution. Hence in such cases an estimate
of the error, at the end of any iteration, is made based on approximate values of the
present and previous iteration. Hence,
Ea = present approximation - previous approximation,
and
Er = (present approximation - previous approximation)/ present approximation
Note: in all the above definitions of errors same symbols are used for simplicity.
Whichever of the definitions is used in a particular case should be clear from the context.
1.3. Number Representation in the Computer
Since there is a fixed space of memory in the computer, a given real number in a certain
base must be represented in a finite space in the memory of the machine. This means that
not all real numbers can be represented in the memory. The numbers that can be
represented in the memory of the computer are called machine numbers. Numbers
outside these cannot be represented. There are two conventional ways of representation.
1.3.1. Fixed Point Representation:
Suppose: the number to be represented has t digits. In the fixed point representation
system, the t digits are subdivided into t1 and t2 , where t1 is reserved for the integer part
and t2 is reserved for the fractional part of the number. Here, whatever the value of the
number is, the numbers t1 and t2 are fixed a priori, i.e. the decimal point is fixed.
Example
Suppose: a = (0111)2 is the number to be represented. Then:
if t1 = t2 = 2, then a = (01.11)2.
Bit number 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Sign Bit Bit pattern representing the integer
0 positive number
Note: Sign bit
1 negative number
Example
Suppose we want to represent the decimal number 21.
The binary equivalent of 21 is 10101, i.e., (21)10 = (10101)2.
We observe that the bit pattern for 21 has only 5 bits.
To store it in a 16-bit word, we have to expand it into an equivalent 16-bit pattern. This
can be done by adding as many zeros as are necessary to the left of the bit pattern 10101.
i.e., (10101)2 = (0000000000010101)2
Thus the representation of 21, in a 16 bit word computer will be:
0 000000000010101
Example
Consider a = 0.556712 with N = 10 and t = 3
Here the mantissa is 0.556712
Now, 1/2 N-t = 1/2 x 10-3 = 0.5 x 10-3 = 0.0005
Adding this to the mantissa, we have:
p + 1/2 N-t = 0.556712 + 0.0005 = 0.557 212
chopped here
a = 0.557
Note:
1. The difference between x and fl(x) is called the round off error.
2. IBM computers use the “chopping” type of rounding off while the PDP11 uses the
symmetrical rounding off.
3. In a floating-point representation, if the exponent q > M, we have what we call
overflow and if q m, we have underflow.
p1 p p2
p1 p p2
-t
Locate the point: p1 + 1/2 N between p1 and p2 as shown below.
p1 p1 + 1/2N-t p2
Example
Let p = 0.5561.
We observe that p lies in the left interval (p1, p1+1/2 N-t)
i.e. 0.5561 + 1/2 N-t = 0.5561 + 0.0005
= 0.556 6
p
p = p = p1
0.556 + 1/2 x10-3
p1 = 0.556 p = 0.5565 p2= 0.557
-3
Thus, p - p = 0.5561 - 0.556 = 0.0001 1/2.10 = 0.0005
-t
If instead p = 0.5567, then: 0.5567 + 1/2N = 0.5567 + 0.0005 = 0.557 2
p= 0.557 = p2
-3
Again, p - p = 0.557 - 0.5567 = 0.0003 1/2 x10 = 0.0005
Conclusion:
t
N forchopping
p-p t
1
2 N forsymmetrical roundingoff
In general, if a = pNq and a = pNq, then:
N qN t
Nq t
forchopping
a - a = pNq - pNq = Nq p - p
N q 12 N t 1
2 Nq t
for symmetrical roundingoff
Definition: Let be the exact value and be the approximation.
Then we say: ( - ) is the absolute error and ( - )/ is the relative error.
x1
i.e. in the relation : y = f(x) , x x2 input and y output
.
.
xn
x f y
f(x) = f( x + x) = f( x ) + f/ x1 x . x1 + f/ x2 x . x2 + .......... + f/ xn x .
xn +
+ 2nd order terms (1.10)
y = f(x) - f( x ) = f( x + x) - f( x )
= f/ x1 x . x1 + f/ x2 x . x2 +...........+ f/ xn x . xn +
+ 2nd order terms (1.11)
Considering the relative error, we have:
yy f/ x1 x . x1 y . x1 x1 + ...........+ f/ xn x . xn y . xn xn +
+ 2nd order terms (1.13)
[Eqn. (1.13) results from Eqn. (1.12) because for any real number a, if a = a1 + a2 +
......+an ,
then : a a1 + a2 + .... + an ]
Note that
f/ xi x . xi y represents the amplification coefficient of the relative error xi / xi .
猠捵桴瑡›††††††††–⁄
EMBED Equation
(2.3)
Hence, the convergence of this sequence is essential. Therefore, the problems to be
considered are:
1. Convergence problem and
2. Stopping criteria. i.e. when should we stop the sequence and give an
approximation to the procedure.
2.2. Methods Used in Root Finding
The idea of successive approximation (Iterative method) is widely used. It starts with one
or more initial approximation to the root and produces a sequence: x0, x1, x2,..............xn
which presumably converges to the root.
To obtain the initial approximation, some methods need a pre-assigned interval [a,b];
others need a close approximation of the root itself. The later methods converge more
rapidly. The approximations can be obtained:
a) by graphical method or
b) by analytical method
Illustrations: y
a) The graphical method:
›††††††††††††††††††††††††††愉
桔牧灡楨慣敭桴摯›††††††††††††††††††††
†††††††ഠ ഈ††††不 桔
b) By analytical method:
x x1 x2 x3 x4
††††††††††††††††砉ㄉ砲㌉破††††ഈ ††††††††††††††
f(x) - - + +
Table 2.1
Here, the solution lies between x2 and x3.
f(x) = x3 - x2 - 1 = 0 (2.4)
We find out that f(1) = -1 and f(2) = 3. This means that since f(x) is a continuous
function, it must vanish somewhere in the interval [1,2]. This is by the Intermediate-value
Theorem.
If f(x) were to vanish at two or more points in the interval [1,2], i.e. has more than one
root in the interval, then f((x) must vanish somewhere in [1,2]. This is by Rolles’
Theorem.
This is an example of bracketing methods which requires an interval within which the
root lies. The procedure in this method consists of continuously halving the interval that
contains the root. The convergence can be checked by determining the error as defined
below.
Let (2 = tolerance of f(x) i.e f(x) < (2
(1 = tolerance between two successive approximations.
i.e. (x k+1 - xk( ( (1 /(xk+1(
where, x0 : initial approximation , and x1 : next approximation
Algorithm
1. Input { x0, x1, (1, (2}
2. fo ( f(x0) ; f1 ( f(x1)
3. While ( f0 (> (2 and ( f1 ( > (2
3.1 If ( x1 - x0( < (1 ( x1( :
Then
3.1.1 output { x0, x1}, stop
3.2 x2 (
EMBED Equation
3.3 f2 ( f(x2)
x1: y1=P1
P12
x2 : y2=P2 P123
x3 : y3=P3 P234
P34
x4: y4=P4
Neville's algorithm is recursive way of filling in the numbers in the tableau a column at a
time, from left to right. It is based on the relationship between a " daughter" P and its
two "parents,"
Cm,i=Pi...(i+m)-Pi...(i+m-1)
Dm,i=Pi...(i+m)-P(i+1)...(i+m) Eq 2.4
( xi x)(Cm,i 1 Dm,i )
Cm 1,i
xi xi m 1
Eq 2.5
( xi m 1 x)(Cm,i 1 Dm,i )
Dm 1,i
xi xi m 1
1. The data value of the closest pointy to the desired point is selected by successive
comparison of their distance from the point of interest and the value will be assigned
ass an initial guess to the point desired.
Distance = / x – xi /
Hence initial guess f(2) = f(3) = 28
2. The difference between each successive data values will be used to obtain the small
incremental modifications ( C ij, D ij ), needed to arrive at the desired point.
From Eq 2.5, the initial values ( C0i, D0i ) are the differences between each
successive data value obtained by going backward and forward, i.e.,
D01 = f( x1 ) - f(x2)
= -4-2.375
= -6.375
Similarly,
C02 = 6.375
D02 = -25.625
C03 = 25.625
D03 = -33.0
C04 = 33.0
D04 = 61.0
Applying equations 2.5
( x1
x )(C02 D01 )
C11
x1 x2
3(6.375 ( 6.375)
C11
1.5
= 12.75
= 6.375
C12 = 15.375
D12 = -10.25
C13 = -33.0
D13 = -66.0
By the same talking the next small increments will be
( x3 x)(C12 D11 )
D21
x1 x3
= -2.25
( x2 x )(C13 D12 )
C22
x2 x4
= -9.75
D22 = 13
Following the family tree, one end up at D31, hence the final correction, D31, is
( x4 x )(C22 D21 )
D31
x2 x4
=3
Finally the incremental values will systematically be added /the computer adds at each
step/ and the final value is the interpolation result
x1 f(x1) = P1
P12
x2 f(x2) = P2 P123
P23 P1234
X3 f(x3) = P3 P234
P34
X4 f(x4) = p4
This recurrence generates the rational function through m+1 points form the ones through
m and (second term in the denominator of equation 3.3) m-1 points. It started with
Ri=yi Eq 3.4
and with
[
R= Ri(i+1)...(i+m) with ]
m=-1 = 0 Eq 3.5
Now, exactly as in the polynomial case equations (2.4) and (2.5) above, we can convert
the recurrence (3.3) to one involving only the small differences
Cm,i = Ri...(i+m)-(i+m-1)
Dm,i = Ri...(i+m)-R(i+1)...(i+)...(i+m) Eq. 3.6
These satisfies the relation
Cm+1,I - Dm+1,I = Cm,i+1 - Dm,i Eq. 3.7
which is useful in proving the recurrences
Cm, i 1(Cm, i 1 - Dm, i)
Dm 1, i
x - xi
Dm, i (Cm, i 1 - Dm, i)
x - xi m 1
x - xi
Dm, i (C m, i 1 - Dm, i)
x - xi m 1
Cm 1, i Eq. 3.8
x - xi
Dm, i - Cm, i 1
x - xi m 1
This recurrence is implemented in the subroutine of the computer program, whose use is
analogous in every way to the subroutine of the polynomial interpolation.
Illustrative example
The rational function interpolation also follows same procedure as polynomial function
Interpolation. The basic difference is the way one obtained the incremental correction of
each step.
Sample data were generated from the explicit analytic function
x
.
f ( x) 2
x 1
The degree of numerator and the denominator is added to yield three; hence the four data
points will be necessary for the interpolation.
Data points and their respective distance from x=4.5
X 2.0 3.0 5.0 6.0
f(x) 0.667 0.375 0.208 0.171
Distance 2.500 1.500 0.500 1.500
The initial guess is f(4.5) = 0.208
Successive correction to this guess are obtained using equation 3.8
Similar procedure as the case of polynomial will end up with the following values of (C,
D)
D11 = 0.219
C12 = -0.521
D12 = -0.167
C13 = -0.019
D21 = 0.181
C22 = 0.133
D22 = 0.030
D31 = 0.015
Adding corrections by walking through the family tree
F(2) = f(x3) + C13 + D22 + D3
= 0.208 + (-0.019) + (0.030) + (0.015) = 11.0
= 0.234.
Hence the error is zero, i.e., the interpolation function is polynomial of same degree and
coefficient as that of the analytic.
polynomials used. Unfortunately, this is not generally true. Indeed, for various functions.
and more
between nodes as n increases. Hence we need to see a method of spline.
Spline interpolation is a piecewise polynomial interpolation. This means that a function
f(x) is given on an interval a< x <b, and we want approximate f(x) on this interval by a
function g(x) that is obtained as follows. We partition a< x <b; that is, we subdivide it
into subintervals with common endpoints
a =x0 <x1 < . . .< xn = b.
We now require that g(x) = f(x), . . . ,g(x) = f (x), and that in these subinterval g(x) be
given by polynomials, one polynomial per subinterval, such that at those endpoints, g(x)
is several times differentiable . Hence, instead of approximating f(x) by a single
polynomial on the entire interval a < x < b, we now approximate f(x) by n polynomials.
In this way we may obtain approximating functions g(x) that are more suitable on many
problems of interpolation and approximation. In particular, this method will in general
be numerically stable; these g(x) will not be as oscillatory between nodes as a single
polynomial on a < x < b often is. Function thus obtained are called Spline.
The simplest continuous piecewise polynomial approximation would be by piecewise
linear function. But the graph of such a function has corners and would be of little
practical interest. Hence it is preferable to use functions that have a certain number of
derivatives everywhere on the interval a < x < b.
We shall consider cubic splines, which are perhaps the most important ones from a
practical point of view. By definition, a cubic spline g(x) on a < x < b is a continuous
function g(x) that has continuous first and second derivatives everywhere in that interval
and , in each subinterval of that partition, is represented by a polynomial of degree not
exceeding three. Hence g(x) consists of cubic polynomials, one in each subinterval.
Illustrative example
Data from cubic polynomial of Y= -3/4(x-1) + 3/2(x-1) 2 – 3/4(x-1) 3
4 3
X2 (K+1)
(X1, x2)
D2
1 2
X2 (K)
D1
X1 (J) X1 (J+1)
Bicubic Spline
The other common technique for obtaining smoothness in two-dimensional interpolations
is the bicubic interpolation. To interpolate one functional value, one performs one-
dimensional splines across the rows of the table, followed by one additional one-
dimensional spline evaluations for the M rows; one must still do a constriction and an
evaluation for the final column spline.
Illustrative example
Consider the function, f (x1, x2) were,
f ( X 1, X 2) ( X 1X 2) eX1X2
Consider the grid lines
X1=0, X1=0.2, X1=0.4, & X1=0.6
X2=0, X2=0.2 X2=0.4 & X2=0.4
X2
0.8
0.1064 0.1888 0.2512
0.6
0.0738 0.1363 0.1888
0.4
0.0384 0.0738 0.1064
0.2
X1
0 0.2 0.4 0.6 0.8
Consider the grid line X2 = 0.2 with X1 = 0.2, X1 = 0.2, X1 = 0.4, X = 0.6 and X1 = 0
As can be seen this a one-dimensional problem. Hence using Newton’s divide difference
and third degree polynomials.
f3 (X1) = b0 + b1 (X-0) + b2 (X-0)(X-0.2) + b3(X-0)(X-0.2)(X-0.4)
b0 = f (X10) = 0
b1 = f [X1, X10] = 0.1920
b2 = f [X2, X1, X0] = -0.0375
b3 = f [X3, X2, X1, X0] = 0.0042
Hence,
f3(X)=0.1920X-0.0375X(X-0.2)+0.0042X(X-0.2)(X-0.4)
Similarly interpolation functions are constructed along X2=0 and X2=0.4
The next step is evaluation step, in our case the functional values for f(0.3,0), f(0.3,0.2)
and f(0.3,0.4) ,from the already constructed functions.
The last step is construction of one interpolating function along the newly created
column.
Here in our case, the desired interpolation point is f(o.3,0.2)
f (0.3,0.2) = 0.1920(0.3) - 0.0375(0.3)(0.3-0.2) + 0.0042(0.3)(0.3-0.2)(0.3-0.4)
f (0.3,0.2)= 0.0565
Using Bicubic Spline
X2 = 0.2
X1 = 0.2, X1 = 0.4 and X1 = 0.6
For one-dimensional interpolation
f '' ( x i 1 ) f '' ( x)
f i ( xi ) ( xi x) 3 ( xi x) 3
6( x i x i 1 ) 6( x i x i 1 )
f ( xi 1 ) f '' ( xi 1 ) f ( xi ) f '' ( xi )( xi xi 1 )
( xi xi 1 ) ( xi x) (x xi 1 )
( xi xi 1 ) 6 ( xi xi 1 ) 6
…Eq5.3
In our case for X2 =0.2 constant the problem reduces to a one dimensional problem with
the pointes X1=0,X2=0.2, X1=0.4 and X1=0.6
Using Eq. 5.4 for each interval.
0.2f”(0)+0.8f”(0.2)+0.2f’’(0.4)=-0.09 …(a)
’’
0.2f”(0.2)+0.8f”(0.4)+0.2f (0.6)=-0.09 …(b)
Assuming natural spline
f”(0)=f”(0.6)=0
Solving (a) and (b)
f’(0.2)=-0.092
f”(0.4)=-0.082
Using Eq. 5.4 the interpolating functions are determined for each interval.
For the interval (0,0.2)
f (X)=0.0767X3+0.1951X
For the interval (0.2,0.4)
f (X)=-0.0767(0.4-X)3 –0.0683(X-0.2)3+0.1951(0.4-X)+0.3717(X-0.2)
For the interval (0.4,0.6)
f (X)=-0.0683(0.6-X)3 +0.3717(0.6-X)+0.5320(X-0.4)
From the above functions f(0.3,0.2) can be computed as
f (X)=-0.0767(0.1)3 –o.0683(0.1)3+0.1951(0.1)+0.3717(0.1)
=0.0565
START
INTERPOLATION OPTION
1 POLYNOMIAL/RATIONAL
2. BICUBIC, CUBIC, BICYBUC SPLINE
OPTION = 1/2
SPECIFIC INTERPOLATION
FROM GROUP.
END
References
8. G
Annex
I. Solution to Review Exercises & Assignments
I.1. Introduction to Programming
Exercise:
1. Write an algorithm in step form for making a cup of tea.
a. Prepare a kettle and a tea cup
b. If the kettle doesn’t have water, then fill it
c. Plug the kettle into the power point
d. If the tea cup is not empty, then empty the cup
e. Place tea leaves in the tea cup
f. Wait the water in the kettle till it boils
g. If the water in the kettle is not boiling, then go to step 6
h. Switch the power off
i. Pour the water from the kettle into the tea cup.
2. Develop an algorithm that counts all vowels on a given page of text. (assume n is
the number of letters on that page)
Step form Pseudo-code form
1. Set current to 1 Begin
2. Set last to n Current = 1
3. Set count to 0 Last = n
4. Read letter at current Count = 0
5. If letter is vowel, then increment Repeat
count by 1 Read letter
6. Increment current If letter is vowel, then
7. If current <= last, then go to step 4 Count = Count + 1
Current = Current + 1
End if
Until Current > Last
End
3. Write an algorithm in step form that sums all even numbers between 1 & 20
inclusive and displays the sum.
Begin
Sum = 0
Count = 2
Repeat
Sum = Sum + Count
Count = Count + 2
Until Count > 20
Print Sum
End
4. Develop an algorithm in pseudo-code & flow chart format to find the roots of a
quadratic equation.
Assignment:
Develop an algorithm (both pseudo-code and flow chart) for the following problems:
1. Calculate the average of the first n whole numbers and display the average
Begin
Read n
Sum = 0
Current = 1
Repeat
Sum = Sum + Current
Current = Current + 2
Until current > n
Average = Sum / n
Display Average
End
3. Generate the Fibonacci sequence, where the user enters the value of n.
F1 = F2 = 1
Fn = Fn-1 + Fn-2
#include <iostream.h>
int main (void)
{
Double fahrenhait, celsius;
cout << “Temperature in Fahrenhait: “;
cin >> fahrenhait;
Celsius = 5 * (fahrenhait – 32) / 9;
cout << fahrenhait << “ degrees Fahrenheit = “ <<
celsius << “ degree Celsius\n”;
return 0;
}
Assignment
1. Write a simple calculator program which displays the sum, difference, product
and quotient of two integers entered by the user.
#include <iostream.h>
void main ()
{
int x, y;
int sum, dif, prd, qtn;
char a ;
clrscr () ;
cout << "Enter the Operator \n";
cin >> a
cout << " + for If statement \n";
cout << " - for Subtraction \n";
cout << " * for multiplication \n";
cout << " / for division \n";
cout << "Enter the two numbers:\n " ;
cin >> x >> y;
switch (a)
{
case ‘+’:
sum = x + y;
cout << x << " + " << y << " = " << sum << endl;
break;
case '-' :
dif = x - y;
cout << x << " - " << y << " = " << dif << endl;
break;
case '*' :
prd = x - y;
cout << x << " * " << y << " = " << prd << endl;
break;
case '/' :
if (y !=0)
qtn = x / y;
cout << x << " / " << y << " = " << qtn << endl;
else
cout << “ Stop! Division by zero \n” ;
break;
}
getch ();
}
7. What will be the value of each of the following variables after its initialization:
double d = 2 * int (3.14);
long k = 3.14 – 3;
char c = ‘a’ + 2;
char c = ‘p’ + ‘A’ – ‘a’;
8. Write a program which inputs a positive integer n and outputs 2 raised to the
power of n.
case '2':
cout<<"Compare two numbers using If...else\n ";
cout<<"Enter the two numbers: " ;
cin>>num1>>num2;
if (num1%num2 == 0)
cout <<num1<<" is divisible by "<<num2<<endl ;
else
cout <<num1<<" is not divisible by "<<num2<<endl;
break;
case '3':
cout<<"Compare two numbers using the Conditional
statement "<<endl;
cout<<"Enter the two numbers: " ;
cin>>num1>>num2;
max = num1 > num2 ? num1 : num2;
cout<<"Maximum of "<<num1<<" & "<<num2<<" is
"<<max<<endl;
case '4':
cout<<"n! using while statement. "<<endl;
cout <<"Enter the number n"<<endl;
cin>>b ;
cout<<" using i *= --n"<<endl ;
n = b;
i = n ;
while (n>=1)
{
cout<<"n = "<< n<<" f = "<<i<<endl;
i *= --n;
}
break;
case '5':
cout<<"n! using do while statement. "<<endl;
cout <<"Enter the number n"<<endl;
cin>>b ;
cout<<" using i *= --n"<<endl ;
n = b ;
i = b ;
do
{
i *= --n;
cout<<"n = "<< n<<" f = "<<i<<endl;
}
while (n>1);
break;
case '6':
cout<<"n! using for statement. "<<endl;
cout <<"Enter the number n"<<endl;
cin>>b ;
default:
break ;
}
getch () ;
}
Exercises:
1. Write a program to solve a quadratic equation.
2. Write a program which inputs a person’s height (in cm) and weight (in kg) and
outputs one of the messages: underweight, normal, or overweight, using the
criteria:
Underweight: weight < height / 2.5
Normal: height / 2.4 <= weight <= height / 2.3
Overweight: height / 2.3 < weight
3. Assume that n is 20, what will the following code fragment output when
executed?
if (n >= 0)
if (n < 10)
cout << “n is small\n”;
else
cout << “n is negative\n”;
4. Write a program which inputs an integer value, checks that it is positive, and
outputs its factorial. Use the formula:
factorial (0) = 1
factorial (n) = n * factorial (n – 1)
5. Write a program for the Magic Number game. The program generates a random
number, prompts for your guess, and prints the message ** Right ** if you guess
the magic number. Include the header <cstdlib.h>.
#include <iostream.h>
#include <conio.h>
void main ()
{
Long x, y, r, p, LCM, GCF ;
cout << “Enter the two Positive Integers \n” ;
cin >> x >> y ;
P = x * y ;
If ( x > y)
{
r = x % y ;
while ( r > 0 )
{ x = y ;
y = r ;
r = x % y ;
}
GCF = y ;
LCM = P / y ;
cout <<” GCF = “ << GCF << endl;
cout << “ LCM = “ << LCM << endl ;
}
Else if ( x < y)
{
r = y % x ;
while ( r > 0 )
{ y = x ;
x = r ;
r = y % x ;
}
GCF = x
LCM = P / x
cout <<” GCF = “ << GCF << endl;
cout << “ LCM = “ << LCM << endl ;
}
Else
cout <<” Check input number! “ << endl;
}
#include <iostream.h>
#include <conio.h>
void main ()
{
Long x, y, z;
cout << “Enter the two Positive Integers \n” ;
cin >> x ;
If ((x != 2) && a (x % 2 = 0 )
cout << x << “ is not prime number \n”;
else
{ y = 3 ;
z = x ;
While (z > y)
{ If (x % y = 0)
cout << "Divisible by " << y
z = x / y ;
y = y + 2 ;
}
}
cout << x << “is a Prime number \n” ;
}
#include <iostream.h>
#include <conio.h>
void main ()
{
long m, d, n = 0;
cout << “Enter a Positive Integer \n” ;
cin >> m ;
while (m > 0)
{
d = m % 10 ;
m /= 10 ;
n = 10 * n + d ;
}
cout << “ The reverse is “ << n << endl;
}
I.5. Arrays
Exercises:
1. Write a program that calculates the sum and average of maximum of 20 numbers
to be entered by the user.
2. Write a program that adds two matrices, entered by the user. What is the address
of the ith and jth element stored in column
Assignment:
1. Write a program that multiplies two matrices, entered by the user.
2. Write a program that calculates the determinant of n x n matrix.
Begin
Read ValueInkm
ValueInm ValueInkm*1000
Display ValueInm
End
b. Find the largest of three given numbers. Take the assumption that the numbers entered
will never be equal.
A number of algorithms can be designed for this problem. Please try to design your own
algorithm before going through the next one.
Begin
Read a,b,c
max a
if max<b then
max b
end if
if max<c then
max c
end if
Display max
End
c. Design and represent an algorithm to obtain the sum of the first 50 counting numbers.
Looping structure is needed and the algorithm is presented below.
Begin
number 1
while number<=50
sum sum+number
number number+1
end while
Display sum
End
Hand trace (process the instructions yourself) the above algorithm. It seems to be perfect.
But it is not. The problem is that sum is not initialized. When we reserve space for ‘sum’
in memory, we don’t know the value stored there. Therefore we have to initialize ‘sum’
to be zero. The edited algorithm will be:
Begin
sum 0
number 1
while number<=50
sum sum+number
number number+1
end while
Display sum
End
d. Find the maximum (largest) from a given list of numbers.
In this case, the number of data in the list should be known in advance. Therefore you
need to ask for this number first.
Begin
Read n
Read number //the first number
max number
counter 1
while counter<=n
read number
if max < number then
max number
end if
counter counter+1
end while
display max
End
Begin
cnt 0 //cnt is to say counter. Even you can use a different name for the
variable.
index 1
while index<=10
read number
if number<0 then
cnt cnt+1
end if
index index+1
end while
Display cnt
End
g. Find the largest of three given numbers. Assume there is a probability that three equal
numbers be entered.
Begin
Read a,b,c
If a=b and b=c then
Display message as to tell the user the numbers are all equal
else
max a
if max<b then
max b
end if
if max<c then
max c
end if
Display max
End if
End
h. Compute ab without using the exponential operator.
Begin
Read a,b
result 1
i 1
while i<=b
result result*a
i i+1
end while
Display result
End
2. Design an algorithm for solving the following problems. Represent the algorithm in
pseudo-code and flowchart.
a. Find the largest from two given numbers. Take the assumption that the numbers
entered will never be equal.
Start
Begin
Read a,b
Read a,b
if a>b then
max a
else
Is Yes
max b max a
a>b
end if
Display max No
End
max b
display max
Stop
b. Obtain average marks for five students for given four subject’s marks.
Start
Begin
counter 1
while counter<=5 counter 1
Read mark1,mark2,mark3,mark4 1
sum mark1+mark2+mark3+mark4
Average sum/4 No counter<=5
Display Average
counter counter+1
Stop Yes
end while
End
Read mark1, mark2,
mark3, mark4
Avg (mark1+mark2+mark3+mark4)/4
Display avg
counter counter+1 1
Begin Start
Read n
Read number
Read n
max number Read
counter 1 number
while counter<=n max
read number number
if max < number then cnt 1 1
max number
end if No cnt<=n
counter counter+1
end while Display Yes
display max max
End Read
Stop number
No max<nu
mber
Yes
max number
cnt cnt+1 1
d. A university employs students on a part time basis. It pays a first year student 2 Birr
per hour, a second year 3 Birr per hour, a third year 4 Birr per hour and 5 Birr per
hour to the 4th year students. Draw the flow chart of the algorithm that will accept the
name of the student, year, and the number of hours and calculate his/her total
payment. {From ‘Introduction to computer Science’ by Dr. Dida Midekso}
The pseudocode for this problem can be written like the following:
Begin
Read name,year,hour
If year=1 then
Totalpayment=hour*2
else of year=2 then
Totalpayment=hour*3
else if year=3 then
Totalpayment=hour*4
else if year=4 then
Totalpayment=hour*5
else
Display message as “Invalid year value”
Endif
Display totalpayment
end
Start
Read
name
Read year
Read hour
yes Year=1
Totalpayment hour*2 No
1
yes
Year=2
Display
Totalpayment
2
No Totalpayment hour*3 1
Stop
yes
Year=3
No Totalpayment hour*4 1
yes
Year=4
No Totalpayment hour*5 1
2 Display message
INVALID DATA
2. What will be the value of each of the following variables after its initialization:
Declaration Output
Unsigned int x = - 3.14; x = ***** //error! X should be non-negative
double d = 2*int (3.14); d = 6 // d = 2 * 3 = 6
long k = 3.14 – 3; k = 0 // k = (0.14)L = 0
char c = ‘a’ - 32; c = A // c = 97 – 32 = 65 = ‘A’
char* b = “Love”; b = Love // b is string variable
4. Write the output of the following program for input numbers -1, 0, 2, 8 and 13.
// PROGRAM TO CHECK WHETHER A POSITIVE INTEGER IS PRIME OR NOT.
#include <iostream.h>
void main ()
{
long i,x, y, z;
cout << "Enter the number \n";
cin >> x ;
if ((x ==2) || (x == 3))
cout << x << " is a Prime number \n";
else if ((x <= 0) || (x % 2 == 0 ))
cout << x << " is not a Prime number \n";
else
{
y = 3 ;
z = x ;
while (z > y)
{
if (x % y != 0)
{
y += 2;
if(z <= y)cout << x << " is a Prime number \n";
}
else
{cout <<x << " is not a prime number" <<endl;
break;
}
}
}
}
int main(void)
{
cout << max(1,2.2);
}
4. List the advantages and drawbacks of the use of function overloading. [5 marks]
5. Suggest two or more guidelines for when overloaded functions should and
shouldn't be used. [6 marks]
6. Explain why operator overloading is often not a good idea. [5 marks]
7. List the three C++ operators which are most usually overloaded and explain why
your answer to the previous question does not apply to these three operators. [5
marks]
8. Write a overloaded operator function that allows the code:
MyClass mc;
cout << mc;
to behave identically to the code: [8 marks]
MyClass mc;
mc.PrintMeTo(cout);
9. Modify the following class declaration:
class String
{
public:
String(void)
: myStr(0) {}
String(char* str)
{ myStr = new char[strlen(str)];
strcpy(myStr,str);
}
private:
char* myStr;
};
so that the code:
String s ("a string");
s[1] = 'z';
cout << s[1] << endl;
correctly allows access to individual characters in the
string. [8 marks]
Dymanically-allocated memory
1. Explain the diference between the new and new[] operators. [4 marks]
2. Explain the diference between the delete and delete[] operators. [4 marks]
3. Write a single C++ statement that dynamically allocates a single int and initializes
it to 42. [3 marks]
4. Write one or more C++ statements that dynamically allocates an array of 42 ints
and initializes each one to zero. [3 marks]
Constructors and destructors
1. Write a declaration for a constructor for the class Annotation. Your constructor
should take two arguments: number (of type int), and ref (of type TextRef). [2
marks]
Score play(void)
{
Score s;
while (!match())
{
while (!game())
{
s = set();
}
}
return s;
}
int main(void)
{
while (globalval< 2)
{
globalval *= 2;
}
else if (globalval > 8)
{
globalval -= 2;
}
else
{
globalval = 10-globalval;
}
}
for (int i=0; i<globalval; i++)
{
cout << i << endl;
}
}
class Derived
{
public:
virtual void PrintMe(void)
{
Base::PrintMe();
cout << "Derived!" << endl;
}
};
int main(void)
{
Base b;
Derived d;
12. Draw a class diagram for a system to solve the following problem. Include key
attributes and behaviours.
The El Cheapo video store needs a computerized database system to record
borrowed videos, CDs, and video games. Videos are categorized as new release,
weekly, or five-for-five-dollars. video games may be either PlayStation,
MegaDrive, or Saturn.
They also want to generate lists of customers secting by various criteria: most
prolific borrowers, inactive (no borrowing for a month or more), who owes the
most on overdue books.
[20 marks]
13. Draw a class diagram for a system to solve the following problem. Include key
attributes and behaviours.
We are creating a symbolic mathematics package. We want to be able to
specify functions of X, Y, and Z. Each function will consist of a left- and right-
hand expression, and each expression will consist of one or more terms, with
addition or subtraction operators between them.
Each term may be either a constant (a numerical value or the special constant
C) or a product (a numerical coefficient followed by one ore more of the
variables X, Y, and Z, each raised to some power).
public:
int bval;
base(){ bval=0;}
};
int main()
{
base BaseArr[5];
SomeFunc(BaseArr,5);
deri DeriArr[5];
SomeFunc(DeriArr,5);
}
Answer:
00000
01010
Explanation:
The function SomeFunc expects two arguments. The first one is a pointer to an array of
base class objects and the second one is the size of the array. The first call of someFunc
calls it with an array of bae objects, so it works correctly and prints the bval of all the
objects. When Somefunc is called the second time the argument passed is the pointeer to
an array of derived class objects and not the array of base class objects. But that is what the
function expects to be sent. So the derived class pointer is promoted to base class pointer
and the address is sent to the function. SomeFunc() knows nothing about this and just
treats the pointer as an array of base class objects. So when arr++ is met, the size of base
class object is taken into consideration and is incremented by sizeof(int) bytes for bval (the
deri class objects have bval and dval as members and so is of size ›=
sizeof(int)+sizeof(int) ).
Question
For this assignment you are required to design and code a simple Train management
system. The Piedmont Railway Company (P.R.C.) maintains a simple railway transport
system. There are several different classes of rolling stock used by P.R.C.: Engines,
carriages, wagons and cabooses. Carriages are normally fitted with seating and come in a
number of different varieties: 1st class, 2nd class and diner cars. Wagons are used for the
transport of general materials (e.g. timbre, livestock, etc.) P.R.C. uses two main types of
engine: diesel and electric. Electric engines require overhead power on the train lines they
travel on, where as Diesel engines do not (although they can run on lines with overhead
power). Engines have a total load carrying capacity (measured in metric tonnes) which is
the total weight the engine can move (including its own weight). The weight of carriages
depends on the base carriage weight (different for each type of carriage - see table below)
plus a "PAX load" equal to 100kg x the number of people on board. For dining cars the
PAX load is 20% of the total passenger PAX transported up to a maximum of 5,000kg.
Carriages also have a maximum carrying capacity. A Wagon's weight depends on the
stock transported.
Base Weight Max carrying
Stock Max Load Journey Cost
(kg) capacity
Diesel Engine 16,000kg N/A 500 Metric Tonnes $100/km
Electric Engine 12,000kg N/A 300 Metric Tonnes $150/km
1st Class $20/km +
4,000kg 40 PAX N/A
Carriage $180/passenger
2nd Class $10/km +
3,000kg 60 PAX N/A
Carriage $100/passenger
Dinner Carriage 5,000kg 50 PAX N/A $8/km
Caboose 1,500kg N/A N/A $4/km
30 Metric
Wagon 2,200kg N/A $18/km + $300/tonne
Tonnes
P.R.C. maintains a fleet of rolling stock. Items of rolling stock are assembled into a train
which makes a journey. Each train requires at least one engine (at the front) and a
caboose (at the back). Any number of carriages, wagons and engines may be added, up to
the total carrying capacity of the engines. It is anticipated that new stock may have
different parameters than those shown in the table, so the figures should not be hard
coded into any system.
Given a particular fleet configuration we are interested in a system that allows us to build
trains suitable for a specified journey. The journey is specified with the following
parameters:
Distance
Number of passengers
Amount of freight
Group Activity I:
s