C++ Lecture All in One
C++ Lecture All in One
Chapter One
Introduction
What is programming?
Programming is a skill that can be acquired by a computer professional
that gives him/her the knowledge of making the computer perform
the required operation or task.
In every programming Language there are sets of rules that govern the symbols
used in a programming language. These set of rules determine how the
programmer can make the computer hardware to perform a specific operation.
These sets of rules are called syntax.
Memory unit: it retains information that has been entered through the
input unit, so the information may be made immediately available for
processing when it is needed. The memory unit also retains processed
information until that information can be placed on output devices by
the output unit.
Central Processing Unit (CPU): it is the computers coordinator and is
responsible for supervising the operations of the other sections. CPU tells
the input unit when information should be read into memory, tells ALU
when information from the memory should be used in calculation and
tells output unit when to send information from the memory to certain
output devices.
Arithmetic and Logic unit: is a part found inside the Central Processing
Unit and is responsible for performing calculations such as addition,
subtraction, multiplication and division. It also performs comparisons.
Secondary Storage device: Programs or data used by other units normally
are placed on secondary storage devices (such as disks) until they are
needed, possibly hours, days, months, or even years later.
1.7. Algorithm designing and modeling the logic (using flow chart).
A digital computer is a useful tool for solving a great variety of
problems. A solution to a problem is called an algorithm; it describes
the sequence of steps to be performed for the problem to be solved.
Generally, an algorithm is a finite set of well-defined instructions for
accomplishing some task which, given an initial state, will terminate in a
corresponding recognizable end-state.
The algorithm should be:
Precise and unambiguous
Simple
Correct
Efficient
Terminal point
Decision
Process
Input/Output
Flow line
Inter-page connector
On-page connector
start
Enter
number
num/2==0?
Display Display odd
even
end
In practice all these steps are usually invoked by a single command and the
user will not even see the intermediate files generated.
Worksheet 1
Course Title: Introduction to Programming / Fundamentals of Programming
Course No : Comp 271 / CSCE 232
Chapter Two
Basics of C++
#include<iostream.h>
#include<conio.h>
void main()
{
cout<<\n Hello World!;
getch();
}
Any C++ program file should be saved with file name extension
.CPP
Type the program directly into the editor, and save the file as
hello.cpp, compile it and then run it. It will print the words Hello
World! on the computer screen.
The first character is the #. This character is a signal to the
preprocessor. Each time you start your compiler, the preprocessor
runs through the program and looks for the pound (#) symbols and
act on those lines before the compiler runs.
The include instruction is a preprocessor instruction that directs the
compiler to include a copy of the file specified in the angle brackets
in the source code.
If the path of the file is not specified, the preprocessor looks for the
file under c:\tc\include\ folder or in include folder of the location
where the editor is stored.
The effects of line 1, i.e. include<iostream.h> is to include the file
iostream.h into the program as if the programmer had actually typed
it.
When the program starts, main() is called automatically.
Every C++ program has a main() function.
The return value type for main() here is void, which means main
function will not return a value to the caller (which is the operating
system).
The main function can be made to return a value to the operating
system.
The Left French brace {signals the beginning of the main function
body and the corresponding Right French Brace } signals the end
of the main function body. Every Left French Brace needs to have a
corresponding Right French Brace.
The lines we find between the braces are statements or said to be the
body of the function.
A statement is a computation step which may produce a value or
interact with input and output streams.
The end of a single statement ends with semicolon (;).
The statement in the above example causes the sting Hello World!
to be sent to the cout stream which will display it on the computer
screen.
void demoFunction()
{
cout<<\n demoFunction;
}
Data Types
Type Length Range
unsigned char 8 bits 0 to 255
char 8 bits -128 to 127
enum 6 bits -32,768 to 32,767
unsigned int 16 bits 0 to 65,535
short int 16 bits -32,768 to 32,767
int 16 bits -32,768 to 32,767
unsigned long 32 bits 0 to 4,294,967,295
long 32 bits -2,147,483,648 to 2,147,483,647
float 32 bits -3.4x10-38 to 3.4x10+38
double 64 bits -1.7x10-308 to 1.7x10+308
long double 80 bits -3.4x10-4932 to 1.1x10+4932
bool 8 bits true or false (top 7 bits are ignored)
Unsigned Signed
Binary Decimal Binary Decimal
0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 1 1
0 0 1 0 2 0 0 1 0 2
0 0 1 1 3 0 0 1 1 3
0 1 0 0 4 0 1 0 0 4
0 1 0 1 5 0 1 0 1 5
0 1 1 0 6 0 1 1 0 6
0 1 1 1 7 0 1 1 1 7
1 0 0 0 8 1 0 0 0 0
1 0 0 1 9 1 0 0 1 -1
1 0 1 0 10 1 0 1 0 -2
1 0 1 1 11 1 0 1 1 -3
1 1 0 0 12 1 1 0 0 -4
1 1 0 1 13 1 1 0 1 -5
1 1 1 0 14 1 1 1 0 -6
1 1 1 1 15 1 1 1 1 -7
In the above example, in case of unsigned, since all the 4 bits
can be used to represent the magnitude of the number the
maximum magnitude that can be represented will be 15 as
shown in the example.
If we use signed, we can use the first bit to represent the sign
where if the value of the first bit is 0 the number is positive if
the value is 1 the number is negative. In this case we will be
left with only three bits to represent the magnitude of the
number. Where the maximum magnitude will be 7.
Identifiers
A valid identifier is a sequence of one or more letters,
digits or underlined symbols. The length of an identifier
is not limited.
Neither space nor marked letters can be part of an
identifier.
Only letters, digits and underlined characters are valid.
Variable identifiers should always begin with a letter or
an underscore. By any means they should begin with a
digit.
Key words should not be used as names for identifiers.
C++ is not case sensitive. Small letter and capital letters
are different for C++. Eg: variable Age is not identical
with variable age
E.g.:
#include<iostream.h>
typedef unsigned short int USHORT;
void main()
{
USHORT width = 9;
}
Immediately after the second line, whenever the compiler
encounters the word USHORT it will substitute is with
unsigned short int.
\ single quote
\? Question mark
\\ backslash
2.5.2. Constants.
A constant is any expression that has a fixed value.
Like variables, constants are data storage locations in the computer
memory. But, constants, unlike variables their content can not be
changed after the declaration.
Constants must be initialized when they are created by the program,
and the programmer cant assign a new value to a constant later.
C++ provides two types of constants: literal and symbolic constants.
Literal constant: is a value typed directly into the program wherever
it is needed.
E.g.: int num = 43;
43 is a literal constant in this statement:
Symbolic constant: is a constant that is represented by a name,
similar to that of a variable. But unlike a variable, its value cant be
changed after initialization.
E.g.:
Int studentPerClass =15;
students = classes * studentPerClass;
studentPerClass is a symbolic constant having a value of 15.
And 15 is a literal constant directly typed in the program.
In C++, we have two ways to declare a symbolic constant. These are
using the #define and the const key word.
The enum type can not take any other data type than integer
enum types can be used to set up collections of named integer
constants. (The keyword enum is short for ``enumerated''.)
The traditional way of doing this was something like this:
#define SPRING 0
#define SUMMER 1
#define FALL 2
An alternate approach using enum would be
enum { SPRING, SUMMER, FALL, WINTER };
You can declare COLOR to be an enumeration, and then you can
define five possible values for COLOR: RED, BLUE, GREEN, WHITE
and BLACK.
E.g.: enum COLOR {RED,BLUE,GREEN,WHITE,BLACK};
Every enumerated constant has an integer value. If the programmer
does not specify otherwise, the first constant will have the value 0,
and the values for the remaining constants will count up from the
initial value by 1. thus in our previous example RED=0, BLUE=1,
GREEN=3, WHITE=4 and BLACK=5
But one can also assign different numbers for each.
E.g.: enum COLOR{RED=100,BLUE,GREEN=500,WHITE,BLACK};
Where RED will have 100 and BLUE will have 101 while GREEN will have
500, WHITE 501 and BLACK 502.
Byte address
1 1 0 1 0 0 0 1
bit
Compiled by: Mahder Alemayehu and Wondwossen Mulugeta 11
Addis Ababa University, Faculty of Informatics
Introduction to Programming in C ++
2.8. Operators.
An operator is a symbol that makes the machine to take an action.
Different Operators act on one or more operands and can also have
different kinds of operators.
C++ provides several categories of operators, including the
following:
Assignment operator
Arithmetic operator
Relational operator
Logical operator
Increment/decrement operator
Compiled by: Mahder Alemayehu and Wondwossen Mulugeta 12
Addis Ababa University, Faculty of Informatics
Introduction to Programming in C ++
Conditional operator
Comma operator
The size of operator
Explicit type casting operators, etc
2.8.1.1.Compound assignment operators (+=, -=, *=, /=, %=, >>=, <<=,
&=, ^=).
Compound assignment operator is the combination of the
assignment operator with other operators like arithmetic and bit
wise operators.
The assignment operator has a number of variants, obtained by
combining it with other operators.
E.g.:
value += increase; is equivalent to value = value + increase;
a -= 5; is equivalent to a = a 5;
a /= b; is equivalent to a = a / b;
price *= units + 1 is equivalent to price = price * (units + 1);
And the same is true for the rest.
E.g.
int k = 5;
(auto increment prefix) y= ++k + 10; //gives 16 for y
(auto increment postfix) y= k++ + 10; //gives 15 for y
(auto decrement prefix) y= --k + 10; //gives 14 for y
(auto decrement postfix) y= k-- + 10; //gives 15 for y
E.g.:
int m=1,n=2,min;
min = (m < n ? m : n);
The value stored in min is 1.
E.g.:
(7 = = 5 ? 4: 3) returns 3 since 7 is not equal to 5
2.8.7. Comma Operator (,).
Multiple expressions can be combined into one expression using
the comma operator.
The comma operator takes two operands. Operand1,Operand2
The comma operator can be used during multiple declaration,
for the condition operator and for function declaration, etc
It the first evaluates the left operand and then the right operand,
and returns the value of the latter as the final outcome.
E.g.
int m,n,min;
int mCount = 0, nCount = 0;
Precedence Table:
E.g.
a==b+c*d
c * d is evaluated first because * has a higher precedence than + and = =.
Worksheet 2
Course Title: Introduction to Programming / Fundamentals of Programming
Course No : Comp 271 / CSCE 232
For each of the problems write a C++ code to perform the required task. Your
program should be based on the flow chart you drawn in the first worksheet.
Chapter Three
Program Control Constructs.
A running program spends all of its time executing instructions or statements
in that program.
The order in which statements in a program are executed is called flow of
that program.
Programmers can control which instruction to be executed in a program,
which is called flow control.
This term reflects the fact that the currently executing statement has the
control of the CPU, which when completed will be handed over (flow) to
another statement.
Flow control in a program is typically sequential, from one statement to the
next.
But we cal also have execution that might be divided to other paths by
branching statements. Or perform a block of statement repeatedly until a
condition fails by Repetition or looping.
Flow control is an important concept in programming because it will give all
the power to the programmer to decide what to do to execute during a run
and what is not, therefore, affecting the overall outcome of the program.
3. Sequential Statements
Such kind of statements are instruction in a program which will executed
one after the other in the order scripted in the program. In sequential
statements, the order will be determined during program development
and can not be changed.
4. Selection Statements
Selection statements are statements in a program where there are points at
which the program will decide at runtime whether some part of the code
should or should not be executed.
There are two types of selection statements in C++, which are the if
statement and the switch statement
E.g.:
if(balance > 0)
{
interest = balance * creditRate;
balance += interest;
}
Most of the time expression will have relational expressions
testing whether something is equal, greater, less, or different from
something else.
It should be noted that the output of a relational expression is
either True (represented by anything different from zero) or False
(represented by Zero).
Thus any expression, whose final result is either zero or none zero
can be used in expression
E.g.:
int x;
cin>>x;
if(x)
cout<<you are an adult;
In the above example, the value of variable x will be an input from
the user. The if statement will be true if the user gives anything
different from zero, which means the message you are an adult
will be displayed on the screen. If the user gives zero value for x,
which will be interpreted as False, nothing will be done as the if
statement is not satisfied.
Thus, expression and be:
9 Relational expression,
9 A variable,
9 A literal constant, or
9 Assignment operation, as the final result is whatever we
have at the right hand side and the one at the left hand side
is a variable.
The If else statement
Another form of the if is the if else statement.
The if else if statement allows us to specify two alternative
statements:
9 One which will be executed if a condition is satisfied and
9 Another which will be executed if the condition is not
satisfied.
The General Syntax is:
if (expression)
statements1;
else
statements2;
First expression is evaluated and if the outcome is none zero
(true), then statements1 will be executed. Otherwise, which means
the expression is false statements2 will be executed.
E.g.:
if(balance > 0)
{
interest = balance * creditRate;
balance += interest;
}
else
{
interest = balance * debitRate;
balance += interest;
}
Compiled by: Mahder Alemayehu and Wondwossen Mulugeta 3
Addis Ababa University, Faculty of Informatics
Introduction to Programming in C ++
E.g.1:
if(age>18)
cout<<you are an adult;
else
cout<<You are a kid;
E.g.2:
int x;
cout<<Enter a number: ;
cin>>x;
if(x%2==0)
cout<<The Number is Even;
else
cout<<The Number is Odd;
E.g.3:
int x;
cout<<Enter a number: ;
cin>>x;
if(x%2)
cout<<The Number is Odd;
else
cout<<The Number is Even;
e.g2. #include<iostream.h>
#include<conio.h>
int main()
{
int testScore;
cout<<\nEnter your test score:;
cin>>testScore;
False True
testScore >=70?
True
False False
True
cout<</;you didnt pass; age < 10?
Expression is called the switch tag and the constants preceding each case
are called the case labels.
The out put of expression should always be a constant value.
First expression is evaluated, and the outcome, which is a constant value,
will compared to each of the numeric constants in the case labels, in the
order they appear, until a match is found.
Note, however, that the evaluation of the switch tag with the case labels is
only for equality
The statements following the matching case are then executed. Note the
plural: each case may be followed by zero or more statements (not just one
statement).
After one case is satisfied, execution continues until either a break
statement is encountered or all intervening statements are executed,
which means until the execution reaches the right French bracket of the
switch statement.
The final default case is optional and is exercised if none of the earlier
cases provide a match. This means that, if the value of the expression is
not equal to any of the case labels, then the statements under default will
be executed.
Now let us see the effect of including a break statement in the switch
statement.
true
true N==1? x = 10
N==1? x = 10
false break
false
true true
N==2? x =20 N==2? x = 20
N==3?
true x = 30 N==3?
true tru e
x = 30
The break terminates the switch statement by jumping to the very end of
it.
There are, however, situations in which it makes sense to have a case
without a break. For instance:
E.g.:
switch(operator)
{
case +: result = operand1 + operand2;
break;
case - : result = operand1 operand2;
break;
case x:
case *: result = operand1 * operand2;
break;
case /: result = operand1 / operand2;
break;
default: cout<< unknown operator:<<operator<<\n;
}
Because case x has no break statement (in fact no statement at all!), when
this case satisfied, execution proceeds to the statements of the next case
and the multiplication is performed.
Switch evaluates expression and compares the result to each of the case
values.
Relational and Boolean operators can be used in switch tag if and only if
the expected output is either 0 to represent False or 1 to represent True as
that is the only possible output from such operators.
Eg:2
//the following for statement adds the even numbers between 0 and n
int Sum=0;
for(int i=0; i<=n;)
{
Sum=Sum+i;
i+=2;
}
Eg:3
//the following for statement adds the even numbers between 0 and n
//where all the three expressions are null.
int Sum=0;
int i=0;
for( ; ; )
{
If(i<=n)
break;
else
{
Sum=Sum+i;
i++;
}
}
In the above example, the initialization is at the top before the
looping starts, the condition is put in if statement before the
instructions are executed and the increment is found immediately
after the statements to be executed in the loop.
NB: even though there is the option of making all the three
expressions null in a for loop, it is not recommended to make the
condition to take null statement.
age=-1;
do
{
cout<<\n enter your valid age [between 0 and 130]:;
cin>>age;
}
while(age < 0 || age > 130);
E.g.2:
//Do you know why the following is an infinite loop?
int counter = 1;
while(counter != 10)
counter += 2;
In the first example, since product is initialized with zero, the
expression product*=5 will always give us zero which will
always be less than 50.
In the second example, the variable counter is initialized to 1 and
increment is 2, counter will never be equal to 10 as the counter only
assumes odd values. In theory, this while loop is an infinite loop,
but in practice, this loop eventually terminates because of an
overflow error as counter is an integer it will have a maximum limit.
E.g.:2
count = 0;
while(count <= 10)
{
count++;
}
No this time the loop body is executed eleven times. The correct is
E.g.:3
count = 0;
while(count < 10)
{
count++;
}
OR
count = 1;
while(count <= 10)
{
count++;
}
8. Using the ASCII table numbers, write a program to print the following output, using a
nested for loop. (Hint: the outer loop should loop from 1 to 5, and the inner loops
start variable should be 65, the value of ASCII A).
A
AB
ABC
ABCD
ABCDE
9. Write a C++ program that displays the following output using their ASCII values.
a
bc
def
gehi
jklmn
opqrst
10. Write a C++ program that will print the following shapes.
A. B. C. D.
*
* ***** *
***
** **** ***
*****
*** *** *****
***
**** ** *******
*
***** * *********
11. Write a weather-calculator program that asks for a list of the previous 10 days
temperatures, computes the average, and prints the results. You have to compute the
total as the input occurs, then divide that total by 10 to find the average. Use a while
loop for the 10 repetitions.
12. Write a C++ program using for loop that can compute the following summation:
[( i 3 )* 2]
30
i =1
13. Write a C++ program that accepts marks of five students and then displays their
average. The program should not accept mark which is less than 0 and mark greater
than 100.
Compiled by: Mahder Alemayehu and Wondwossen Mulugeta 22
Addis Ababa University, Faculty of Informatics
Introduction to Programming in C ++
14. Develop a calculator program that computes and displays the result of a single
requested operation.
E.g. if the input is
15 * 20, then the program should display 15 * 20 equals 300
If the operator is not legal, as in the following example
24 ~ 25 then the program displays ~ is unrecognized operator
As a final example, if the denominator for a division is 0, as in the following
input: 23 / 0 then the program should display the following:
23 / 0 cant be computed: denominator is 0.
15. Use either a switch or an if-else statement and display whether a vowel or a
consonant character is entered by the user. The program should work for both lower
case and upper case letters.
16. Write a C++ code to display only even numbers found between 0 and 20.
17. Write a C++ application that extracts a day, month and year and determine whether
the date is valid. If the program is given a valid date, an appropriate message is
displayed. If instead the program is given an invalid date, an explanatory message is
given. Note: to recognize whether the date is valid, we must be able to determine
whether the year is a leap year or not.
An example of the expected input/output behavior for a valid date follows
If the year is a leap year, then February will have total of 29 days. Otherwise, it
will have 28 days. If the year is not a century year and is evenly divisible by 4,
then the year is a leap year. If the year is a century year (years whose last digits
are 00) and is evenly divisible by 400, then the year is a leap year.
Chapter Four
Functions
4. What is a function?
A function provides a convenient way of packaging a computational
recipe, so that it can be used as often as required.
Therefore, a function is a block of code designed to tackle a specific
problem.
void main()
{ no return type as it is void in the definition.
---------------
func1(); function call (notice the semicolon)
---------------
}
Return type is void
void func1() no semicolon. Decelerator
{
-------------- function body definition
--------------
} no semicolon.
void starLine()
{
for(int j=0;j<45;j++) definition of the function
with a
cout<< *; name starLine
cout<<endl;
}
Given the next program, which function is the calling function and
which is the called function?
#include<iostream.h>
#include<conio.h>
void nextMsg()
int main()
{
cout<< Hello!\n;
nextMsg();
return 0;
}
void nextMsg()
{
cout<< GoodBye!\n;
return;
}
the function. When the function is called and x passed to it, num
receives a copy of the value of x. As a result, although num is set to
0 by the function, this does not affect x. the program produces the
following output:
Num = 0
x = 10
o Passing arguments in this way, where the function creates copies of
the arguments passed to it is called passing by value.
o Suppose you have pairs of numbers in your program and you want
to be sure that the smaller one always precedes the larger one. To
do this, you call a function, order(), which checks two numbers
#.......
#.......
void order(int &, int &);
int main()
{
int n1 = 99, n2=11;
int n3 = 22, n4=88;
order(n1,n2);
order(n3,n4);
cout<< n1=<<n1<<endl;
cout<< n2=<<n2<<endl;
cout<< n3=<<n3<<endl;
cout<< n4=<<n4<<endl;
return 0;
}
o In the order() function the first variable is called num1 and the
second is num2. If num1 is greater than num2, the function stores
num1 in temp, puts num2 in num1, and finally puts temp back in
num2.
Eg
int num1;
void fun1(int num1)
{
//
}
The global num1 is inaccessible inside fun1(), because it is overridden
by the local num1 parameter.
This problem is overcome using the scope operator :: which takes a
global entity as argument.
int num1 = 2;
void fun1(int num1)
{
//
num1=33;
cout<<num1; // the out put will be 33
cout<<::num1; //the out put will be 2 which is the global
if(::num1 != 0)//refers to global num1
//
}
Static variables can be declared and initialized within the function, but
the initialization will be executed only once during the first call.
If static variables are not declared explicitly, they will be declared to 0
automatically.
Eg. void my_fun()
{
static int num;
static int count = 2;
count=count*5;
num=num+4;
}
{
Return n > 0 ? n : -n;
}
The effect of this is that when Abs is called, the compiler, instead of
generating code to call Abs, expands the program body and substitutes
the body of Abs in place of the call. While essentially the same
computation is performed, no function call is involved and hence no
stack frame is allocated.
The "inline" keyword is merely a hint to the compiler or development
environment.
Not every function can be inlined. Some typical reasons why inlining
is sometimes not done include:
the function calls itself, that is, is recursive
the function contains loops such as for(;;) or while()
the function size is too large
Another good reason to inline is that you can sometimes speed up
your program by inlining the right function. Instead of calling the
function every time it is invoked, the compiler will replace the function
call with a copy of the function body. If it's a small function which gets
called a lot, this can sometimes speed things up.
Most of the advantage of inline functions comes from avoiding the
overhead of calling an actual function. Such overhead includes saving
registers, setting up stack frames, and so on. But with large functions
the overhead becomes less important.
Concerning inline functions, the compiler is free to decide whether a
function qualifies to be an inline function. If the inline function is
found to have larger chunk (amount) of code, it will not be treated as
an inline function, but as like other normal functions.
Then, Why not inline everything? :Since the compiler will copy the
entire function body every time the function is called, if it is a large
function (more than three or four lines), inlining can increase the size
of your executable program significantly.
void main()
{
int a=40, b=50, c=60;
Add_Display(a,b,c); //will print 150 (ie 40+50+60)
Add_Display(a,b); //will print 120 (ie 40+50+30)
Add_Display(a); //will print 90 (ie 40+20+30)
Add_Display(); //will print 60 (ie 10+20+30)
Mult_Display(a,b) //will print 2000 (40*50)
Mult_Display(a) //will print 2800 (40*70)
//Mult_Display() //is invalid as there is no default for x
getch();
}
//the following function definition is invalid as z is
//a parameter without a default and written after y
//parameters with default should always be at the
//right side of function declaration
void Mult_Dispaly (int x, int y=70, int z)
{
cout<< (x*y*z);
}
float fabs(float x)
{ if(x<0.0)
Return (x * -1.0);
else
Return (x);
}
Without using overloading, you have to call the function as:
int ans = iabs(weight);//for int arguments
float ans = fabs(weight);//for float arguments
But with overloading, the above code can be used as:
float abs(flaot x)
{
if(x<0.0)
Return x*-1.0;
else
Return x;
}
N.B: if two or more functions differ only in their return types, C++
cant overload them. Two or more functions that differ only in their
return types must have different names and cant be overloaded
4.10. Recursion
A function which calls itself is said to be recursive. Recursion is a
general programming technique applicable to problems which can be
defined interms of themselves. Take the factorial problem, for instance
which is defined as:
- factorial of 0 is 1
- factorial of a positive number n is n time the factorial of n-
1.
The second line clearly indicates that factorial is defined in terms of
itself and hence can be expressed as a recursive function.
int Factorial(unsigned int n )
{
return n = = 0 ? 1 : n * factrial(n-1);
}
For n set to 4, the following figure shows the recursive call:
Factorial(4)
24
4 * Factorial(3)
6 3 * Factorial(2)
2 2* Factorial(1)
1 1
The stack frames for these calls appear sequentially on the runtime
stack, one after the other.
A recursive function must have at least one termination condition
which can be satisfied. Otherwise, the function will call itself
indefinitely until the runtime stack overflows.
Try to use a recursive function call to solve the Fibonacci series. The
Fibonacci series is :
0,1,1,2,3,5,8,13,21,
the recursive definition of the Fibonacci series is as follows:
Fibonacci (0) =0
Fibonacci (1) =1
Fibonacci (n) =Fibonacci (n-1) +Fibonacci (n-2);
Chapter Five
Arrays and Structures
5. What is An Array
9 A collection of identical data objects, which are stored in consecutive memory
locations under a common heading or a variable name. In other words, an
array is a group or a table of values referred to by the same name. The
individual values in array are called elements. Array elements are also variables.
9 Set of values of the same type, which have a single name followed by an index.
In C++, square brackets appear around the index right after the name
9 A block of memory representing a collection of many simple data variables stored
in a separate array element, and the computer stores all the elements of an array
consecutively in memory.
9 Arrays in C++ are zero-bounded; that is the index of the first element in the
array is 0 and the last element is N-1, where N is the size of the array.
9 It is illegal to refer to an element outside of the array bounds, and your program
will crash or have unexpected results, depending on the compiler.
9 Array can only hold values of one type
9 Declaring the name and type of an array and setting the number of elements in
an array is called dimensioning the array. The array must be declared before
one uses in like other variables. In the array declaration one must define:
1. The type of the array (i.e. integer, floating point, char etc.)
2. Name of the array,
3. The total number of memory locations to be allocated or the maximum value of each
subscript. i.e. the number of elements in the array.
9 The expression array size, which is the number of elements, must be a constant
such as 10 or a symbolic constant declared before the array declaration, or a
constant expression such as 10*sizeof (int), for which the values are known at the
time compilation takes place.
Note: array size cannot be a variable whose value is set while the program is running.
9 That means, we can store 10 values of type int without having to declare 10
different variables each one with a different identifier. Instead of that, using an
array we can store 10 different values of the same type, int for example, with a
unique identifier.
9 The above declaration would have created an array like the following one:
9 For example, in the example of the day array we have declared that it had
5 elements and in the list of initial values within curly brackets { } we
have set 5 different values, one for each element. If we ignore the last
initial value (12071) in the above initialization, 0 will be taken
automatically for the last array element.
9 Because this can be considered as useless repetition, C++ allows the
possibility of leaving empty the brackets [ ], where the number of items in
the initialization bracket will be counted to set the size of the array.
9 The compiler will count the number of initialization items which is 6 and set the
size of the array day to 6 (i.e.: day[6])
9 You can use the initialization form only when defining the array. You
cannot use it later, and cannot assign one array to another once. I.e.
9 Note: when initializing an array, we can provide fewer values than the
array elements. E.g. int a [10] = {10, 2, 3}; in this case the compiler sets the
remaining elements to zero.
9 In any point of the program in which the array is visible we can access
individually anyone of its elements for reading or modifying it as if it was
a normal variable. To access individual elements, index or subscript is
used. The format is the following:
name [ index ]
9 In c++ the first element has an index of 0 and the last element has an
index, which is one less the size of the array (i.e. arraysize-1). Thus, from
the above declaration, day[0] is the first element and day[4] is the last
element.
9 Following the previous examples where day had 5 elements and each
element is of type int, the name, which we can use to refer to each
element, is the following one:
9 For example, to store the value 75 in the third element of the array
variable day a suitable sentence would be:
9 And, for example, to pass the value of the third element of the array
variable day to the variable a , we could write:
a = day[2];
9 Therefore, for all the effects, the expression day[2] is like any variable of
type int with the same properties. Thus an array declaration enables us to
create a lot of variables of the same type with a single declaration and we
can use an index to identify individual elements.
9 Notice that the third element of day is specified day[2] , since first is
day[0] , second day[1] , and therefore, third is day[2] . By this same
reason, its last element is day [4]. Since if we wrote day [5], we would be
acceding to the sixth element of day and therefore exceeding the size of
the array. This might give you either error or unexpected value
depending on the compiler.
9 In C++ it is perfectly valid to exceed the valid range of indices for an
Array, which can cause certain detectable problems, since they do not
cause compilation errors but they can cause unexpected results or serious
errors during execution. The reason why this is allowed will be seen
ahead when we begin to use pointers.
9 At this point it is important to be able to clearly distinguish between the
two uses the square brackets [ ] have for arrays.
o One is to set the size of arrays during declaration
o The other is to specify indices for a specific array element when
accessing the elements of the array
9 We must take care of not confusing these two possible uses of brackets [ ]
with arrays:
Eg: int day[5]; // declaration of a new Array (begins with a type name)
day[2] = 75; // access to an element of the Array.
Other valid operations with arrays in accessing and assigning:
int a=1;
day [0] = a;
day[a] = 5;
b = day [a+2];
day [day[a]] = day [2] + 5;
day [day[a]] = day[2] + 5;
Compiled by: Mahder Alemayehu and Wondwossen Mulugeta 4
Addis Ababa University, Faculty of Informatics
Introduction to Programming in C ++
Eg: Arrays example ,display the sum of the numbers in the array
#include <iostream.h>
int day [ ] = {16, 2, 77, 40, 12071};
int n, result=0;
void main ()
{
for ( n=0 ; n<5 ; n++ )
{
result += day[n];
}
cout << result;
getch();
9 admits a parameter of type "Array of int " called arg . In order to pass to this
function an array declared as:
procedure (myarray);
#include <iostream.h>
#include <conio.h>
void printarray (int arg[], int length)
{
for (int n=0; n<length; n++)
cout << arg[n] << " ";
cout << "\n";
}
void main ()
{
int firstarray[] = {5, 10, 15};
int secondarray[] = {2, 4, 6, 8, 10};
printarray (firstarray,3);
printarray (secondarray,5);
mult(firstarray,3);
cout<<first array after being doubled is\n;
printarray (firstarray,3);
getch()
}
9 As you can see, the first argument (int arg[] ) admits any array of type int ,
whatever its length is, for that reason we have included a second parameter
that informs the function the length of each array that we pass to it as the first
parameter so that the for loop that prints out the array can have the
information about the size we are interested about. The function mult
doubles the value of each element and the firstarray is passed to it. After that
the display function is called. The output is modified showing that arrays are
passed by reference.
9 To pass an array by value, pass each element to the function
9 In all programs and concepts we have seen so far, we have used only
numerical variables, used to express numbers exclusively. But in addition to
numerical variables there also exist strings of characters that allow us to
represent successive characters, like words, sentences, names, texts, etc. Until
now we have only used them as constants, but we have never considered
variables able to contain them.
9 In C++ there is no specific elementary variable type to store string of
characters. In order to fulfill this feature we can use arrays of type char,
which are successions of char elements. Remember that this data type (char)
is the one used to store a single character, for that reason arrays of them are
generally used to make strings of single characters.
9 For example, the following array (or string of characters) can store a string up
to 20 characters long. You may imagine it thus:
name
H e l l 0 \0
S t u d y i n g C + + \0
9 Notice how after the valid content it is included a null character ('\0') in order
to indicate the end of string. The empty cells (elements) represent
indeterminate values.
9 Unlike single quotes ( ' ) which allow to specify single character constants,
double quotes ( " ) are constants that specify a succession of characters. These
strings enclosed between double quotes have always a null character ( '\0' )
automatically appended at the end.
9 Therefore we could initialize the string mystring with values by any of these
two ways:
9 In both cases the Array or string of characters mystring is declared with a size
of 6 characters (elements of type char ): the 5 characters that compose Hello
plus a final null character ( '\0' ) which specifies the end of the string and
that, in the second case, when using double quotes ( " ) it is automatically
appended.
9 Before going further, you should note that the assignation of multiple
constants like double-quoted constants ( " ) to arrays are only valid when
initializing the array, that is, at the moment when declared.
9 The following expressions within a code are not valid for arrays
mystring="Hello";
mystring[] = "Hello";
9 neither would be: mystring = { 'H', 'e', 'l', 'l', 'o', '\0' };
9 Look how we have needed to include <string.h> header in order to be able to use
function strcpy.
9 Although we can always write a simple function like the following setstring with the
same operating than cstring's strcpy :
// setting value to string
#include <iostream.h>
#include<conio.h>
#include <iostream.h>
#include<conio.h>
int main ()
{
char mybuffer [100];
cout << "What's your name? ";
cin.getline (mybuffer,100);
cout << "Hello " << mybuffer << ".\n";
cout << "Which is your favourite team? ";
cin.getline (mybuffer,100);
cout << "I like " << mybuffer << " too.\n";
getch();
return 0;
}
9 Notice how in both calls to cin.getline we used the same string identifier (
mybuffer ). What the program does in the second call is simply step on the
previous content of buffer by the new one that is introduced.
9 If you remember the section about communication through console, you will
remember that we used the extraction operator ( >> ) to receive data directly
from the standard input. This method can also be used instead of cin.getline
with strings of characters. For example, in our program, when we requested
an input from the user we could have written:
9 this would work, but this method has the following limitations that
cin.getline has not:
It can only receive single words (no complete sentences) since this method
uses as delimiter any occurrence of a blank character, including spaces,
tabulators, newlines and carriage returns.
It is not allowed to specify a size for the buffer. What makes your program
unstable in case that the user input is longer than the array that will host
it.
9 All of these functions admit one parameter and return a value of the
requested type ( int , long or float ). These functions combined with getline
method of cin are a more reliable way to get the user input when requesting a
number than the classic cin>> method:
// cin and ato* functions
#include <iostream.h>
#include <stdlib.h>
#include<conio.h>
int main()
{ clrscr();
char mybuffer[100];
float price;
int quantity;
cout << "Enter price: ";
cin.getline (mybuffer,100);
price = atof (mybuffer);
cout << "Enter quantity: ";
cin.getline (mybuffer,100);
quantity = atoi (mybuffer);
cout<<"\nafter conversion :\n";
cout<<"\nprice is : "<<price;
cout<<"\nquantity is : "<<quantity;
cout << "\nTotal price: " << price*quantity;
getch();
return 0;
}
Multidimensional Arrays
9 Multidimensional arrays can be described as arrays of arrays. For example, a
bi-dimensional array can be imagined as a bi-dimensional table of a uniform
concrete data type.
int matrix[3][5];
9 For example, the way to reference the second element vertically and fourth
horizontally in an expression would be:
matrix[1][3]
9 Multidimensional arrays are not limited to two indices (two dimensions). They
can contain so many indices as needed, although it is rare to have to represent
more than 3 dimensions. Just consider the amount of memory that an array
with many indices may need. For example:
9 Assigns a char for each second contained in a century, that is more than 3
billion chars ! What would consume about 3000 megabytes of RAM memory if
we could declare it?
9 Multidimensional arrays are nothing else than an abstraction, since we can
simply obtain the same results with a simple array by putting a factor
between its indices:
9 With the only difference that the compiler remembers for us the depth of each
imaginary dimension. Serve as example these two pieces of code, with exactly
the same result, one using bi-dimensional arrays and the other using only
simple arrays:
// multidimensional array
#include <iostream.h>
#define WIDTH 5
#define HEIGHT 3
int matrix [HEIGHT][WIDTH];
int n,m;
int main ()
{
for (n=0;n<HEIGHT;n++)
for (m=0;m<WIDTH;m++)
{
matrix [n][m]=(n+1)*(m+1);
}
return 0;
}
9 None of the programs above produce any output on the screen, but both
assign values to the memory block called matrix in the following way:
Structures
9 A structure is a collection of one or more variable types grouped together that
can be referred using a single name (group name) and a member name.
9 You can refer to a structure as a single variable, and you also can initialize,
read and change the parts of a structure (the individual variables that make it
up).
9 Each element (called a member) in a structure can be of different data type.
9 The General Syntax of structures is:
Struct [structure tag]
{
Member definition;
Member definition;
Member definition;
}[one or more structure variables];
9 Structure tag is not a variable name. Unlike array names, which reference the
array as variables, a structure tag is simply a label for the structures format.
9 The structure tag Inventory informs C++ that the tag called Inventory looks
like two character arrays followed by one integer and one float variables.
9 A structure tag is actually a newly defined data type that you, the
programmer, defined.
struct Student Stud; //declaring Stud to have the property of the Student structure
strcpy(Stud.FName,Abebe); //assigned Abebe as First Name
Stud.CGPA=3.21; //assignes 3.21 as CGPA value of Abebe
sout<<Stud.FName; //display the name
sout<<Stud.CGPA; // display the CGPA of Abebe
9 A better approach to initialize structures is to use the dot operator(.). the dot
operator is one way to initialize individual members of a structure variable in
the body of your program. The syntax of the dot operator is :
structureVariableName.memberName
here is an example:
#include<iostream.h>
#include<conio.h>
#include<string.h>
void main()
{
clrscr();
struct cd_collection{
char title[25];
char artist[20];
int num_songs;
float price;
char date_purchased[9];
}cd1;
//initialize members here
strcpy(cd1.title,"Red Moon Men");
strcpy(cd1.artist,"Sams");
cd1.num_songs= 12;
cd1.price = 11.95f;
strcpy(cd1.date_purchased,"22/12/02");
//print the data
cout<<"\nHere is the info"<<endl;
cout<<"Title : "<<cd1.title<<endl;
cout<<"Artist : "<<cd1.artist<<endl;
cout<<"Songs : "<<cd1.num_songs<<endl;
cout<<"Price : "<<cd1.price<<endl;
cout<<"Date purchased : "<<cd1.date_purchased;
getch();
}
Arrays of Structures
9 Arrays of structures are good for storing a complete employee file, inventory
file, or any other set of data that fits in the structure format.
9 Consider the following structure declaration:
struct Company
{
int employees;
int registers;
double sales;
}store[1000];
Compiled by: Mahder Alemayehu and Wondwossen Mulugeta 18
Addis Ababa University, Faculty of Informatics
Introduction to Programming in C ++
9 In one quick declaration, this code creates 1,000 store structures with the
definition of the Company structure, each one containing three members.
9 NB. Be sure that your computer does not run out of memory when you create
a large number of structures. Arrays of structures quickly consume valuable
information.
9 You can also define the array of structures after the declaration of the
structure.
struct Company
{
int employees;
int registers;
double sales;
}; // no structure variables defined yet
#include<iostream.h>
void main()
{
struct Company store[1000]; //the variable store is array of the structure Company
}
9 Here is a complete C++ code that shows you how to use array of structures,
and how to pass and return structures to functions.
#include<iostream.h>
#include<conio.h>
#include<stdio.h>
#include<iomanip.h>
struct inventory
{
long storage;
int accesstime;
char vendorcode;
float cost;
float price;
};
void disp_menu(void);
struct inventory enter_data();
void see_data(inventory disk[125],int num_items);
void main()
{ clrscr();
inventory disk[125];
int ans;
int num_items = 0; //total number of items in the inventory
do{
do{
disp_menu();
cin>>ans;
}while(ans<1 || ans>3);
switch(ans)
{ case 1:
disk[num_items] = enter_data();
num_items++;
break;
case 2:
see_data(disk,num_items);
break;
default :
break;
}
}while(ans != 3);
return;
}//end main
void disp_menu()
{
cout<<"\n\n*** Disk Drive Inventory System ***\n\n";
cout<<"Do you want to : \n\n";
cout<<"\t1. Enter new item in inventory\n\n";
cout<<"\t2. See inventory data\n\n";
cout<<"\t3. Exit the program\n\n";
cout<<"What is your choice ? ";
return;
}
inventory enter_data()
{
inventory disk_item;//local variable to fill with input
cout<<"\n\nWhat is the next drive's storage in bytes? ";
cin>>disk_item.storage;
cout<<"\nWhat is the drive's access time in ms ? ";
cin>>disk_item.accesstime;
cout<<"What is the drive's vendor code (A, B, C, or D)? ";
disk_item.vendorcode = getchar();
cout<<"\nWhat is the drive's cost? ";
cin>>disk_item.cost;
cout<<"\nWhat is the drive's price? ";
cin>>disk_item.price;
return (disk_item);
}
Chapter Six
Pointers
6. Introduction
We have already seen how variables are memory cells that we can access by
an identifier. But these variables are stored in concrete places of the computer
memory. For our programs, the computer memory is only a succession of 1
byte cells (the minimum size for a datum), each one with a unique address.
A pointer is a variable which stores the address of another variable. The only
difference between pointer variable and regular variable is the data they hold.
There are two pointer operators in C++:
& the address of operator
* the dereference operator
Whenever you see the & used with pointers, think of the words address of.
The & operator always produces the memory address of whatever it
precedes. The * operator, when used with pointers, either declares a pointer
or dereferences the pointers value. The dereference operator can be literally
translated to "value pointed by" .
A pointer is simply the address of an object in memory. Generally, objects can
be accessed in two ways: directly by their symbolic name, or indirectly
through a pointer. The act of getting to an object via a pointer to it, is called
dereferencing the pointer. Pointer variables are defined to point to objects of
a specific type so that when the pointer is dereferenced, a typed object is
obtained.
At the moment in which we declare a variable this one must be stored in a
concrete location in this succession of cells (the memory). We generally do not
decide where the variable is to be placed - fortunately that is something
automatically done by the compiler and the operating system on runtime, but
once the operating system has assigned an address there are some cases in
which we may be interested in knowing where the variable is stored.
This can be done by preceding the variable identifier by an ampersand sign (&), which
literally means, "address of. For example:
ptr= &var;
This would assign to variable ptr the address of variable var , since when
preceding the name of the variable var with the ampersand ( & ) character we
are no longer talking about the content of the variable, but about its address
in memory.
We are going to suppose that var has been placed in the memory address
1776 and that we write the following:
var=25;
x=var;
ptr = &var;
#...
#...
void main()
{
int num = 123; // a regular integer variable
int *p_num; //declares an integer pointer
cout<< num is <<num<<endl;
cout<< the address of num is <<&num<<endl;
p_num = #// puts address of num in p_num;
cout<< *p_num is <<*p_num<<endl; //prints value of num
cout<< p_num is <<p_num<<endl; //prints value of P_num
getch();
}
type then we cant assign the address of variable to pointer variable but this is
also possible in C++ by declaring pointer variable as a void as follows:
void *p;
Let us see an example:
void *p;
int x;
float y;
p = &x; //valid assignment
p = &y; //valid assignment
The difficulty on void pointers is that, void pointers can not be de referenced.
They are aimed only to store address and the dereference operator is not
allowed for void pointers.
.
.
.
.
.
.
.
.
.
.
p = numbers;
At this point p and numbers are equivalent and they have the same
properties, with the only difference that we could assign another value to the
pointer p whereas numbers will always point to the first of the 20 integer
numbers of type int with which it was defined. So, unlike p, that is an
ordinary variable pointer, numbers is a constant pointer (indeed that is an
Array: a constant pointer). Therefore, although the previous expression was
valid, the following allocation is not:
numbers = p;
Unlike arrays, you can change a pointer variable. By changing pointers, you
can make them point to different values in memory. Have a look at the
following code:
#...
#...
void main()
{
clrscr();
float v1 = 679.54;
float v2 = 900.18;
float * p_v;
p_v = &v1;
cout<< \nthe first value is <<*p_v;
p_v = &v2;
cout<< \nthe second value is <<*p_v;
getch();
}
You can use pointer notation and reference pointers as arrays with array
notation. Study the following program carefully. It shows the inner workings
of arrays and pointer notation.
void main()
{
clrscr();
int ctr;
int iara[5] = {10,20,30,40,50};
int *iptr;
iptr = iara; //makes iprt point to arrays first element. Or iprt = &iara[0]
cout<< using array subscripts:\n
cout<< iara\tiptr\n;
for(ctr=0;ctr<5;ctr++)
{
cout<<iara[ctr]<< \t<< iptr[ctr]<< \n;
}
Suppose that you want to store a persons name and print it. Rather than
using arrays, you can use a character pointer. The following program does
just that.
void main()
{
clrscr();
char *c = Meseret Belete;
cout<< your name is : <<c;
}
Suppose that you must change a string pointed to by a character pointer, if
the persons name in the above code is changed to Meseter Alemu: look at the
following code:
void main()
{
char *c = Meseret Belete;
cout<< youe name is : <<c;
c = Meseret Alemu;
cout<< \nnew person name is : <<c;
getch();
}
If c were a character array, you could never assign it directly because an array
name cant be changed.
When we saw the different data types that exist, we saw that some occupy
more or less space than others in the memory. For example, in the case of
integer numbers, char occupies 1 byte, short occupies 2 bytes and long
occupies 4.
Let's suppose that we have 3 pointers:
char *mychar;
short *myshort;
long *mylong;
And that we know that they point to memory locations 1000 , 2000 and 3000
respectively. So if we write:
mychar++;
myshort++;
mylong++;
mychar , as you may expect, would contain the value 1001 . Nevertheless,
myshort would contain the value 2002 , and mylong would contain 3004 . The
reason is that when adding 1 to a pointer we are making it to point to the
following element of the same type with which it has been defined, and
therefore the size in bytes of the type pointed is added to the pointer.
This is applicable both when adding and subtracting any number to a pointer.
It is important to warn you that both increase ( ++ ) and decrease ( -- )
operators have a greater priority than the reference operator asterisk ( * ),
therefore the following expressions may lead to confusion:
*p++;
*p++ = *q++;
The first one is equivalent to *(p++) and what it does is to increase p (the
address where it points to - not the value that contains).
The second, because both increase operators ( ++ ) are after the expressions to
be evaluated and not before, first the value of *q is assigned to *p and then
they are both q and p increased by one. It is equivalent to:
*p = *q;
p++;
q++;
Now let us have a look at a code that shows increments through an integer
array:
void main()
{
int iara[] = {10,20,30,40,50};
int * ip = iara;
cout<<*ip<<endl;
ip++;
cout<<*ip<<endl;
ip++;
cout<<*ip<<endl;
ip++;
cout<<*ip<<endl;
}
G e o r g e \0
M e s f i n \0
J o h n \0
K i m \0
B a r b a r a \0
Notice that much of the table is waster space. Each row takes 20 characters,
even though the data in each row takes far fewer characters.
To fix the memory-wasting problem of fully justified tables, you should
declare a single-dimensional array of character pointers. Each pointer points
to a string in memory and the strings do not have to be the same length.
Here is the definition for such an array:
This array is a single-dimension array. The asterisk before names makes this
array an array of pointers. Each string takes only as much memory as is
needed by the string and its terminating zero. At this time, we will have this
structure in memory:
E.g.:
char a;
char * b;
char ** c;
a = 'z';
b = &a;
c = &b;
This, supposing the randomly chosen memory locations of 7230 , 8092 and
10502 , could be described thus:
(inside the cells there is the content of the variable; under the cells its location)
int * ptr3;
ptr3 = new int [5];
In this case, the operating system has assigned space for 5 elements of
type int in the heap and it has returned a pointer to its beginning that
has been assigned to ptr3 . Therefore, now, ptr3 points to a valid block
of memory with space for 5 int elements.
You could ask what is the difference between declaring a normal array
and assigning memory to a pointer as we have just done. The most
important one is that the size of an array must be a constant value,
which limits its size to what we decide at the moment of designing the
program before its execution, whereas the dynamic memory allocation
allows assigning memory during the execution of the program using
any variable, constant or combination of both as size.
int * ptr3;
ptr3 = new int [5];
if (ptr3 == NULL) {
// error assigning memory. Take measures.
};
b) Operator delete
Since the necessity of dynamic memory is usually limited to concrete
moments within a program, once this one is no longer needed it shall
be freed so that it become available for future requests of dynamic
memory. For this exists the operator delete , whose form is:
delete pointer ;
or
delete [] pointer ;
The first expression should be used to delete memory allocated for a
single element, and the second one for memory allocated for multiple
elements (arrays).
In most compilers both expressions are equivalent and can be used
without distinction, although indeed they are two different operators
and so must be considered for operator overloading.
In the following simple example, a program that memorizes numbers,
does not have a limited amount of numbers that can be introduced,
thanks to the concept and power of pointer that we request to the
#include <iostream.h>
#include <stdlib.h>
#include<conio.h>
int main ()
{
char input [100];
int i,n;
long * num;// total = 0;
cout << "How many numbers do you want to type in? ";
cin.getline (input,100);
i=atoi (input);
num= new long[i];
if (num == NULL)
{
cout<<"\nno enough memory!";
getch();
exit (1);
}
for (n=0; n<i; n++)
{
cout << "Enter number: ";
cin.getline (input,100);
num[n]=atol (input);
}
cout << "You have entered: ";
for (n=0; n<i; n++)
cout << num[n] << ", ";
delete[] num;
getch();
return 0;
}
Chapter Seven
File Operations (File I/O)
7. Introduction
- The data created by the user and assigned to variables with an assignment
statement is sufficient for some applications. With large volume of data
most real-world applications use a better way of storing that data. For this,
disk files offer the solution.
- When working with disk files, C++ does not have to access much RAM
because C++ reads data from your disk drive and processes the data only
parts at a time.
7.2 Stream
- Stream is a general name given to flow of data. In C++, there are different
types of streams. Each stream is associated with a particular class, which
contains member function and definition for dealing with file. Lets have a
look at the figure:
ios
istream ostream
iostream
ifstream ofstream
fstream
- According to the above hierarchy, the class iostream is derived from the
two classes istream and ostream and both istream and ostream are
derived from ios. Similarly the class fstream is derived from iostream.
Compiled by: Mahder Alemayehu and Wondwossen Mulugeta 1
Addis Ababa University, Faculty of Informatics
Introduction to Programming in C ++
Generally two main header files are used iostream.h and fstream.h. The
classes used for input and output to the video display and key board are
declared in the header file iostream.h and the classes used for disk file
input output are declared in fstream.h.
- Note that when we include the header file fstream.h in our program then
there is no need to include iostream.h header file. Because all the classes
which are in fstream.h they are derived from classes which are in
iostream.h therefore, we can use all the functions of iostream class.
close a file, C++ writes any remaining data to the file, releases the file from
the program, and updates the file directory to reflect the files new size.
- You can use either of the two methods to open a file in C++:
using a Constructor or
using the open function
- The following C++ statement will create an object with the name fout of
ofstream class and this object will be associated with file name hello.txt.
ofstream fout;
fout.open(hello.txt);
- If you open a file for writing (out access mode), C++ creates the file. If a
file by that name already exists, C++ overwrite the old file with no
warning. You must be careful when opening files not to overwrite existing
data that you want.
- If an error occurs during opening of a file, C++ does not create a valid file
pointer (file object). Instead, C++ creates a file pointer (object) equal to
zero. For example if you open a file for output, but use an invalid disk
name, C++ cant open the file and therefore makes the file object equal to
zero.
- You can also determine the file access mode when creating a file in C++. If
you want to use the open function to open a file then the syntax is:
fileobject.open(filename,accessmode);
File name is a string containing a valid file name for your computer.
Accessmode is the sought operation to be taken on the file and must be
one of the values in the following table.
Mode Description
app Opens file for appending
ate Seeks to the end of file while opening the file
in Opens the file for reading
out Opens the file for writing
binary Opens the file in binary mode
- You should always check for the successful opening of a file before
starting file manipulation on it. You use the fail() function to do the task:
Compiled by: Mahder Alemayehu and Wondwossen Mulugeta 3
Addis Ababa University, Faculty of Informatics
Introduction to Programming in C ++
if(outfile.fail())
{
cerr<< \nError opening test.txt;
getch();
exit(1);
}
for(int i=1;i<=15;i++)
{
cout<< \nEnter a character : ;
cin>>c;
outfile.put(c);
}
output.close();
}//end main
- The following program adds three more names to the names.txt file
created in the earlier program.
#include<fstream.h>
#include<stdlib.h>
void main()
{
ofstream outdata;
outdata.open(c:\\names.txt,ios::app);
if(outdata.fail())
{
cerr<< \nError opening names.txt;
getch();
exit(1);
}
outdata<< Berhanu Teka<<endl;
outdata<< Zelalem Assefa<<endl;
outdata<< Dagim Sheferaw<<endl;
outdata.close();
}//end main
- If the file names.txt does not exist, C++ creates it and stores the three names
to the file.
- Basically, you have to change only the open() functions access mode to
turn a file-creation program into a file-appending program.
- The following code asks the user for a file name and displays the content
of the file to the screen.
#include<fstream.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
clrscr();
char name[20],filename[15];
ifstream indata;
cout<<"\nEnter the file name : ";
cin.getline(filename,15);
indata.open(filename,ios::in);
if(indata.fail())
{
cerr<<"\nError opening file : "<<filename;
getch();
exit(1);
}
while(!indata.eof())// checks for the end-of-file
{
indata>>name;
cout<<name<<endl;
}
indata.close();
getch();
}
cin.getline(filename,15);
indata.open(filename,ios::in);
if(indata.fail())// check id open succeeded
{
cerr<<"\nError opening file : "<<filename;
getch();
exit(1);
}
while(!indata.eof())// check for eof
{
indata.get(c);
cout<<c;
}
indata.close();
getch();
}
fileout.open(c:\\test.txt,ios::app);
int length = fileout.tellp();
- By the above statement in length, the total number bytes of the file are
assigned to the integer variable length. Because the file is opened in
append mode that means, the file pointer is the last part of the file.
- Now lets see the seekg() function in action
#include<fstream.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
clrscr();
fstream fileobj;
char ch; //holds A through Z
//open the file in both output and input mode
fileobj.open("c:\\alph.txt",ios::out|ios::in);
if(fileobj.fail())
{
cerr<<"\nError opening alph.txt";
getch();
exit(1);
}
//now write the characters to the file
for(ch = 'A'; ch <= 'Z'; ch++)
{
fileobj<<ch;
}
fileobj.seekg(8L,ios::beg);//skips eight letters, points to I
fileobj>>ch;
cout<<"\nThe 8th character is : "<<ch;
fileobj.seekg(16L,ios::beg);//skips 16 letters, points to Q
fileobj>>ch;
cout<<"\nThe 16th letter is : "<<ch;
fileobj.close();
getch();
}
- To point to the end of a data file, you can use the seekg() function to
position the file pointer at the last byte. This statement positions the file
pointer to the last byte in the file. Fileobj.seekg(0L,ios::end);
- This seekg() function literally reads move the file pointer 0 bytes from the
end of the file. The file pointer now points to the end-of-file marker, but
you can seekg() backwards to find other data in the file.
- The following program is supposed to read c:\alph.txt file backwards,
printing each character as it skips back in the file.
- Be sure that the seekg() in the program seeks two bytes backwards from
the current position, not from the beginning or the end as the previous
programs. The for loop towards the end of the program needs to perform
a skip-two-bytes-back, read-one-byte-forward method to skip through
the file backwards.
#include<fstream.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
clrscr();
ifstream indata;
int ctr=0;
char inchar;
indata.open("c:\\alph.txt",ios::in);
if(indata.fail())
{
cerr<<"\nError opening alph.txt";
getch();
exit(1);
}
indata.seekg(-1L,ios::end);//points to the last byte in the file
for(ctr=0;ctr<26;ctr++)
{
indata>>inchar;
indata.seekg(-2L,ios::cur);
cout<<inchar;
}
indata.close();
getch();
}
void main()
{
clrscr();
char filename[15];
ofstream outdata;
cout<<"\nenter file name : ";
cin>>filename;
outdata.open(filename,ios::out);
if(outdata.fail())
{
Compiled by: Mahder Alemayehu and Wondwossen Mulugeta 12
Addis Ababa University, Faculty of Informatics
Introduction to Programming in C ++
- The above code uses the combination of ostream function seekp and write
to store data at exact locations in the file.
- Function seekp sets the put file-position pointer to a specific position in
the file, then the write outputs the data.
- 1 is subtracted from the student id when calculating the byte location of
the record. Thus, for record 1, the file position pointer is set to the byte 0 of
the file.
- The istream function read inputs a specified number of bytes from the
current position in the specified stream into an object.
- The syntax of read : read((char*)&name of object, sizeof(name of object));
- Function read requires a first argument of type char *. The second
argument of write is an integer of type size specifying the number of bytes
to be read.
- Here is a code that shows how to read a random access record from a file.
#include<fstream.h>
#include<conio.h>
#include<stdlib.h>
struct stud_info{
int studid;
char name[20];
char fname[20];
float CGPA;
};
void main()
{
clrscr();
ifstream indata;
char filename[15];
cout<<"\nEnter the file name : ";
cin>>filename;
indata.open(filename,ios::in);
if(indata.fail())
{
cerr<<"\nError opening "<<filename;
getch();
exit(1);
}
stud_info student;
cout<<"\nEnter the id no of the student : ";
int sid;
cin>>sid;
indata.seekg((sid-1) * sizeof(student));
indata.read((char*) &student, sizeof(student));
cout<<"\nhere is the information";
cout<<"\nstudent id : "<<student.studid;
cout<<"\nstudent name : "<<student.name;
cout<<"\nstudent fname : "<<student.fname;
cout<<"\nstudent CGPA : "<<student.CGPA;
indata.close();
getch();
}
{
ofstream outdata;
ifstream indata;
outdata.open(argv[2],ios::out);
if(outdata.fail())
{
cerr<<"\nlow disk space to create file : "<<argv[2];
getch();
exit(1);
}
indata.open(argv[1],ios::in);
if(indata.fail())
{
cerr<<"\nfile : "<<argv[1]<<" does not exist";
getch();
exit(1);
}
//now start copying the file
while(!indata.eof())
{
indata.get(ch);
outdata.put(ch);
}
indata.close();
outdata.close();
cout<<"\nfinished copying";
}
}