Vous êtes sur la page 1sur 115

CSCI124

Applied Programming

Lesson 1
C++ Revision
Objectives

The objective of this lecture is to provide students with a


reminder of where they are at with C++.

It will look at aspects of the language such as;

Types (basic and complex).


Arrays.
Functions & Functional decomposition.
Control Structures in C++

There are a number of different control structures in


C++.

Control structures fall into two generic groups;

Conditional
Iteration
The If Control Structure

The syntax for such a structure in C++ and most other


languages is;

if (condition)
{
statement(s)
}
condition
false
true

statement

Diagrammatically it looks like this.


The if-else control structure

The if-else condition is effectively a binary choice


dependent upon the result of the condition;

if (condition)
{
statement(s)
}
else
{
statement(s)
}
condition
false
true
statement
statement

Diagrammatically it looks like this.


The while loop

The while loop allows you to repeat statements till a


condition is meet.

while (condition)
{
statements
}
condition
false
true

statement

Above is an illustration of a while loop.


The do-while loop.

The do-while loop is the converse of the while loop.

It can be written as;

do
{
statement
} while (condition);
statement

condition
false
true

Diagrammatically it looks like this.


The for loop.

The for loop is a loop that should be used when the


exact number of iterations is known, it has the
following syntax;

for (init; cond; post)


{
statement(s);
}
init

condition
false
true
statements

post

It has the above form.


Data types and Structure in C++.

C++ has a number of basic data types. These types are;

int
char
float
Data types and Structure in C++.

There are variations of these basic data types which effect


precision/ maximum value.

For example;
long; // a long integer
short; // a short integer
double; // a large floating point
number
Data types and Structure in C++.

It is also common to see variable declaration prefixed with


the keyword unsigned. This means to create a variable
that can only store positive numbers.

This is used to influence the precision/maximum value of


the variable.
Data types and Structure in C++.
Each type consumes a portion of the computers memory.
We can use the sizeof() function to tell us how many
bytes are associated with a declarations. For example;
int main()
{
int myint;
char mychar;
float myfloat;

cout << myint consumes << sizeof(myint) <<


bytes << endl;
cout << mychar consumes << sizeof(mychar) <<
bytes << endl;
cout << myfloat consumes << sizeof(myfloat) <<
bytes << endl;
return 0;
}
Data types and Structure in C++.

On different computers you will get different output. But


normally a integer is 4 bytes, a char is 1 bytes and a float
is 4 bytes.

Again it will differ upon the architecture.


Data types and Structure in C++.
Sometimes though you will have data which can be grouped
together like marks for an assignment.
Would it make sense to have each student mark occupy a
unique variable in a program?

int main()
{
int student1_mark;
int student2_mark;
...
}

Probably not because there would be a number of


difficulties in referencing the data.
Data types and Structure in C++.

The word const also has special meaning depending on


its usage - remember this.
Type Casting

Sometimes we want to convert a data type to another.


C++ supports implicit conversion on a number of types:

short a=1000;
int b = 0;
b = a;

Here the value a has been promoted to type int.


Type Casting

A more common way to do this is:

short a=1000;
int b = 0;
b = (int) a;

These are explicit conversions with the above being the


c-like casting notation.
Type Casting

ANSI C++ has got several casting operators these being -


static_cast and reinterpret_cast.

For the most part in this class you should use static_cast
- the reason will be clearer later when we talk about
classes. It is safer then the other.
Type Casting
Here is a simple example;
#include <iostream>
using namespace std;
int main()
{
float a = 2000.0;
int b = static_cast<int>(a);
cout << b << endl;
return 0;
}
Arrays

Arrays are a construct in most programming languages


which allow programmers to group variables into one
large variable called an array.

The array consists of elements. Each element of the array


is of the same type.
Arrays

Each element of the array is treated as if it were a single


variable.

The elements of the array are accessed using an index.

In C++ the convention for accessing elements in an array


is from index 0 to n - 1, where n is the number of
elements in the array.
Arrays

array0 array[0]
array1 array[1]
array2 array[2]
array3 array[3]
array4 array[4]
array5 array[5]

As you can see the left hand diagram illustrates arrays and indices. It
right hand side demonstrates how these indices relate to index number
(elements).
Each element can house its own data of a particular type.
Each element is as if it were a single variable.

The diagram above illustrates subscripts and indices/


elements in an array.
Arrays
In C++ we declare an array using the following syntax;

type array_name[size];

The type of the array could be any C++ basic type or user
defined type (struct, class, enum, typedef).

The name of the array can be anything so long as it meets


the rules for identifiers in C++.

The size of the array defines how many elements of that


particular type make up the array.
Arrays

For example;

int marks[5];

Creates an array of 5 integers called marks. The


elements of the array are not initialised.

mark[0] mark[1] marks[2] marks[3] marks[4]


Arrays

The statement;

marks[0] = 0;

Will set the 0th element to the value 0.

0 ? ? ? ?
mark[0] mark[1] marks[2] marks[3] marks[4]

Please note the other elements were not initalised and


hence would have any value in them.
Arrays
The following fragment sets each element of the
array to 0;

for (int i = 0; i < 5; i++)


{
marks[i] = 0;
}

Diagrammatically it looks like this.

0 0 0 0 0
mark[0] mark[1] marks[2] marks[3] marks[4]
Arrays
Outputting an element of an array is the same as
outputting a normal variable;

cout << marks[0];

OR

for (int i = 0; i < 5; i++)


{
cout << marks[i] << endl;
}

The difference in the above fragment is one only outputs


the first element and the other output all.
Arrays
As a matter of style, when you declare an array you should
define its size as a constant.

const int MAX = 5;


int marks[MAX];

This therefore means loops can be rewritten using the


constant.

for (int i = 0; i < MAX; i++)


{
cout << marks[i] << endl;
}
Arrays

This is important because if the size of the array needs to


change then it needs to change in one place.

As you saw one of the easiest ways to initalise an array is


by using a counter and a loop.
Arrays
Here is a declaration of an array except this time
we are going to initialise the elements upon
creation.

int marks[5] = { 1, 2, 3, 4, 5};

The element will have the following data;

1 2 3 4 5

marks[0] marks[1] marks[2] marks[3] marks[4]


Arrays

If we did this;

int marks[5] = { 4, 5 };

We would get an array with five elements. The first two


would be initialised to the values 4 and 5. The remainder
would be 0.

4 5 0 0 0
mark[0] mark[1] marks[2] marks[3] marks[4]
Arrays

If we omit the size and did the following;

int marks[] = { 1, 2, 3, 4, 5};

In memory our array would look like this;

1 2 3 4 5

mark[0] mark[1] marks[2] marks[3] marks[4]


Arrays

When it comes to functions arrays are always passed by


reference.

When you pass an array to a function the parameter list


need not have an &.

Remember an array can be of any type.


Arrays
Here is an example; Possibly makes more
sense to make this
#include <iostream> variable global.
using namespace std;

void squares(int[], const int);

int main()
{
const int MAX=5;
int numbers[MAX] = {2, 4, 6, 8, 10};
squares(numbers, MAX);
for (int i = 0; i < MAX; i++)
{
cout << squares[i] << endl;
}
return 0;
}

void squares(int square[], const int MAX)


{
for (int i = 0; i < MAX; i++)
{
square[i] = square[i] * square[i];
}
}
Arrays

This piece of code defines an array and initialises it to a set


of values.

The array is then passed to a function and the function


computes the square of each element. The result is placed
in the same element.

If you do not want the function to be able to change the


contents of the array then you would prefix the parameter
with the modifier const.
Arrays

You can also have multi-dimensional arrays.

That is an array which has rows and columns.

A multi dimensional array is declared using this syntax;

type name[no of rows][no of columns]


Arrays
So the declaration;

int table[4][5];

Would create an multidimensional array with 20


elements. The array would comprise of 4 rows with 5
integer elements per row.

So;

table[0][0] = 100;

Would access the first element of the first row to 100;


Arrays

Where as;

table[3][4] = 10000;

Would set the fifth element of the fourth row to 10000.


Arrays

Again multidimensional arrays are passed by reference.

You should think of such array as a table.


Arrays

1 2 3 4 5
table[0][0] table[0][1] table[0][2] table[0][3] table[0][4]

1 2 3 4 5
table[1][0] table[1][1] table[1][2] table[1][3] table[1][4]

1 2 3 4 5
table[2][0] table[2][1] table[2][2] table[2][3] table[2][4]

1 2 3 4 5
table[3][0] table[3][1] table[3][2] table[3][3] table[3][4]

table[4][5] array
Above diagram illustrates this concept of multidimensional
tables.
Arrays

The problem with arrays is they are fixed sizes, so how


can we create arrays where the size can change or we do
not know the size?
C String

C++ uses C strings to store string however this is


becoming less and less common with the STRING class
being made part of the standard.

A C string is an array of characters terminated by a null


character (null byte)- often denoted by \0.
C String

A C string is just like a normal array except it is of type


char;

char name[100];

Can hold 100 characters. A C string actually means it can


hold 99 characters plus the NULL terminating character.

The NULL character is necessary because it indicates the


end of the string.
C String

Just like arrays, C strings can be multidimensional and


initialised at creation.

They are also always passed by reference.


C String

There are also a number of routines in the string header


which are part of the standard library.

To use these routines to manipulate C strings we #include


<cstring> assuming we are using the standard namespace.

Such functions include strcpy(), strcmp(), strstr() etc.

There are also character manipulation routines found in


the header <ctype>.
Structures

Sometimes however a programmer may want to group the


basic data types together to form a complex data type.

Such an occasion may be the modeling of a record, whether


it be a student or a patient. Such a record would have a
number of fields.
Structures

C and C++ both have the concept of structures which are


identified by the keyword struct.

A struct defines a collection of data which for all intents


and purposes is treated as one.
Structures

Here are two examples of where structures may be used:

To store the components of a student record;

The student number


The students name
The students age

To store the components of a fraction as one.

The numerator
The denominator
Structures

Notice how a structure allows us to group together data.


Structures

The syntax for defining a structure is as follows;

struct nameofstruct
{
member declarations;
...
};
Structures

The keyword struct instructs the C++ compiler that a


structure is about to be defined.

Remember that the rules pertaining to scope apply.

Inside the structure we can have declarations for


members. A member can be any basic of complex type.

That means we can embed structures within


structures!
Structures
Examples of this would include;

const int MAX = 256;


struct student{
int studentno;
char name[MAX];
int age;
};

struct fraction{
int numerator;
int denominator;
};
Structures

Now we have the definition of what a structure looks like,


we can now create instances of these structures using the
conventional syntax for creating a variable;

student mystudent;

Would create a variable mystudent of type student.


Structures
Because mystudent is of type student we can access the
members of student by using the . operator.
Here is an example;
#include <iostream>
using namespace std;

struct student{
int studentno;
char name[256]; // should be a CONST
int age;
};

int main()
{
student mystudent;
cout << Enter name of student: ;
cin >> mystudent.name;
cout << Enter student no of student: ;
cin >> mystudent.studentno;
cout << Enter age of student: ;
cin >> mystudent.age;
return 0;
}
Structures
Effectively the structure is placed in memory. The
structure is composed of the components specified
in the structures definition.

Student Structure
Integer for student
Integer for age
Number

Array of characters for name

You can do sizeof(student) to tell you how much


space an instance of this structure will consume in
memory.
Structures
You can initialise a structure using the same syntax as an
array. Here is a piece of code that initialises a structure to
hold a fraction;
#include <iostream>
using namespace std;

struct fraction{
int numerator;
int denominator;
};

int main()
{
fraction myfraction = { 0 , 0 };
cout << member are: << endl;
cout << numerator: << myfraction.numerator
<< endl;
cout << denominator: << myfraction.denominator
<< endl;
return 0;
}
Structures
Arrays of structures can also be made:
#include <iostream>
using namespace std;
struct student{
int studentno;
char name[256]; // should be a const
int age;
};
int main()
{
const int MAX=10;
student mystudent[MAX];
int i = 0;
cout << -1 to terminate input << endl;
while (i < MAX)
{
cout << Enter student number: ;
cin >> mystudent[i].studentno;
if (mystudent[i].studentno == -1)
break;
cout << Enter student name: ;
cin >> mystudent[i].name;
cout << Enter student age: ;
cin >> mystudent[i].age;
i++;
}
Structures

Continued from previous slide;

for (int j = 0; j < i; j++)


{
cout << Record << j << endl;
cout << mystudent[j].studentno << endl;
cout << mystudent[j].name << endl;
cout << mystudent[j].age << endl;
}

return 0;
}
Structures

That code is pretty awful, because it is one blob called


main, so lets make it a number of functions;

Firstly lets make the variables i and MAX global.

There are two functions in this program. One is the


function that gets the data and the other is the one that
outputs the data.
Structures

They would have the following prototypes;

void getdata(student[]);

void printdata(student[]);

The implementations would be as follows;


Structures
This is the getdata() function;
void getdata(student fmystudent[])
{
cout << -1 to terminate input << endl;
while (i < MAX)
{
cout << Enter student number: ;
cin >> fmystudent[i].studentno;
if (fmystudent[i].studentno == -1)
break;
cout << Enter student name: ;
cin >> fmystudent[i].name;
cout << Enter student age: ;
cin >> fmystudent[i].age;
i++;
}
}
Structures

The printdata() functions looks like this;


void printdata(student fmystudent[])
{
for (int j = 0; j < i; j++)
{
cout << Record << j << endl;
cout << fmystudent[j].studentno << endl;
cout << fmystudent[j].name << endl;
cout << fmystudent[j].age << endl;
}
}
Structures
As a consequence of this our main function changes;

#include <iostream>
using namespace std;

struct student{
int studentno;
char name[256];
int age;
};

void getdata(student[]);
void printdata(student[]);

const int MAX=10;


int i = 0;

int main()
{
student mystudent[MAX];
getdata(mystudent);
printdata(mystudent);
return 0;
}
Structures

The previous piece of code allows a user to enter a


number of student entries.

These entries are held in an array of structures.

The input is terminated using a sentinel (-1) value.


Structures

As you saw previously we can also pass structures to


functions.

Again they follow the same semantics as other types.


Structures
Here is a simple example where a structure is defined and
passed by reference to a function which populates it.
#include <iostream>
using namespace std;

struct fraction{
int numerator;
int denominator;
};

void getfraction(fraction& fmyfraction);


int main()
{
fraction myfraction = { 0 , 0 };
getfraction(myfraction);
cout << member are: << endl;
cout << numerator: << myfraction.numerator
<< endl;
cout << denominator: << myfraction.denominator
<< endl;
return 0;
}
Structures
Here is the functions implementation;
void getfraction(fraction& fmyfraction)
{
cout << Enter the numerator: ;
cin >> fmyfraction.numerator;
cout << Enter the denominator: ;
cin >> myfraction.denominator;
}

As you can see the function takes the structure by


reference and populates it.

If it were passed by value a copy of the structure would be


given to the function. This incurs more overhead.
Structures

Arrays of structures are always passed by reference but


please be warned as to there usage - you will see why
later.
Other types in C++.

In CSCI114 you were introduced to other types in C++,


specifically enum.

Enum allows you to associate symbolics with an actual


data type e.g.

enum radiation { ALPHA, BETA, GAMMA };

ALPHA etc, are what are known as enum constants - they


have value which starts from zero and goes upwards.
Other types in C++.

You can assign your own value;

enum size {SMALL = 10, MED=100,


LARGE=1000};
Other types in C++.

To create an instance of said enumerated type we would


go;

enum size {SMALL = 10, MED=100,


LARGE=1000};
size y;

Once done, we can assign the constants to y.

Y = LARGE;
Other types in C++.

It should be noted that there is an implicit conversion from


any enum type to int.

enum radiation { ALPHA, BETA, GAMMA };

int temp = BETA;

The value for temp would be 1.


Other types in C++.

You should note that it does not work in reverse.

radiation foobar;
foobar = 10;

This will not compile.


Typedef in C++

A typedef is a data type which is synomous with another.


Many great uses:

typedef char name[128];


name people[256];

Can you guess what this does? How would you be sure?
Functions

A function typically has the following form;

return-type function-name( parameter list )


{
// local declarations

// statements
}
Functions

The return type of the function denotes the return


value of the function.

The parameter list defines what parameters the


function will take from the caller.

It explains what the types of the parameters are, how


many there are and theyre locality.

A function normally has a return value.


Functions
Inside the body of the function there are
statements.

int getage() Statements


{
int age;
cout << Enter your age:;
cin >> age;
return age;
}

The above code fragment illustrates how inside a


function there can be an infinite number of
statements.
Functions

Within the body of a function a programmer can define


variables.

These variables are only visible within the function. This is


called scope.

Remember a variable can have either local scope or global


scope. This is dependent upon where it is declared.

A special keyword called static allows a variable declared


in a function to maintain values between calls.
Functions
Below is a function;

int counter()
{
int count = 0;
char a;
while (cin >> a)
{
count++;
}
return count;
}

When the function is called a variable count is created on


the stack. It is only visible within the function. An attempt
to access this variable outside will yield an error.
Functions

Sometimes you will need to give a function information.


Information can be given to function in the form of a
parameter list.

float rectarea(float width, float


length);

Above is a simple function called rectarea. The function


requires two parameters of type float. The return value of
the function is of type float.
Functions

The function can access these parameters inside the body of


the function.
float rectarea(float width, float length)
{
if (width <= 0 || length <= 0)
{
return 0;
}
return (width * length);
}
width and length can be accessed
within the function as if they are locals.
Functions

The call to this function would be:


int main()
{
float width, length, area;
cout << Enter width:;
cin >> width;
cout << Enter length:;
cin >> length;
area = rectarea(width, length);
cout << Area is: << area << endl;
return 0;
}

The call to rectarea is passed the values of width and


length. The function performs its task and returns a value.
Functions

The previous function is not entirely correct. Infact it


would not compile.

Before a program can be compiled in C++ you need to


include the appropriate header and devise the appropriate
prototypes for your functions.
Functions
prototypes describe to the C++ compiler the look of
functions.

A prototype is necessary because it allows the compiler to


perform extensive checking on how a programmer uses a
function.

A prototype normally describes the following;

the return type of a function.


the name of a function.
the type and even the name of arguments in the parameter list.
Functions
So our code would look like this
#include <iostream>
using namespace std;
This is the prototype
float rectarea(float, float); for the function rectarea.

int main()
{
float width, length, area;
cout << Enter width:;
cin >> width;
cout << Enter length:;
cin >> length;
area = rectarea(width, length);
cout << Area is: << area << endl;
return 0;
}
Functions

Any function in C++ can only return one value.

If your function requires to return more then one value,


you need to consider putting the return value in a
structure of some kind or exploit the parameter list.

The return value is copied from the function because


once the function terminates the scoping rules normally
destroy the variable.
Functions
Here is an example;
struct point{
int x;
int y;
};

point getpoint()
{
point mypoint;
cout << Enter the x coordinate:;
cin >> mypoint.x;
cout << Enter the y coordinate:;
cin >> mypoint.y;
return mypoint;
}
Functions

When the function getpoint() is executed a structure of


type point is created locally within the function.

The function prompts the user to enter the point


coordinates and it places them in the appropriate
members of the structure.

The function now needs to return this data - so it returns


the structure.

The function returns a copy of the structure mypoint to


the caller. The reason for this is mypoint is a local and
hence is destroyed upon termination.
Functions
The complete code fragment looks like this;
#include <iostream>
using namespace std; Function is implemented else
struct point
{ where, this is the prototype.
int x;
int y;
};
Make a structure of type
point getpoint(); point.
int main()
{
point z;
z = getpoint();
cout << z.x << : << z.y << endl;
return 0;
}

The function returns a copy of the structure. Remember the


return value of the function is a structure of type point.
Variations of Parameters

As you just discovered one of the problems with functions


is return values. A function by definition can not return
more then one value.

As a consequence we can use the parameter list to help us


with this problem.
Variations of Parameters

C++ supports two kinds of parameter list augments;

Pass by value
The function can not change the value of a variable in the
parameter list.

Pass by reference
The function can change the value of a variable in a parameter
list.
Variations of Parameters

A parameter list can have a mixture of pass by value or


pass by reference.

A variable is passed by reference if it is followed with a &


(ampersand) after the type.
Variations of Parameters
Assume we have the following prototypes of functions;

int foobar(int x);

Describe a function which takes as


an argument a variable of type int.
Inside the function the variable will
be referred to as x.

This is pass by value.


Variations of Parameters

In pass by value the function receives a copy of the


variable. Any alterations to the variable inside the
function (if the type permits this) are not visible outside.
Variations of Parameters
On the other hand the following prototype tells a
different tale;

int foobar(int& x);

This prototype describes a function which takes as an


argument an int. Inside the function this integer is
referred to as x.

However notice the & after the type definition?

This means pass by reference.


Variations of Parameters

In pass by reference the function receives a reference to


the variable.

A reference is effectively the address of the variable where


it resides in memory.

As a consequence the function can change the contents of


the variable and as such changes are visible outside the
function.
Variations of Parameters
Example code;
#include <iostream>
using namespace std;

void swap(int a, int b);

int main()
{
int val1, val2;
cin >> val1 >> val2;
swap(val1, val2);
cout << In main function << endl;
cout << val1 << << val2 << endl;
return 0;
}
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
cout << In swap function << endl;
cout << a << << b << endl;
}
Variations of Parameters
When the program is compiled and executed we get
the following if we enter the values 1 and 2 as input.

Inside swap function


21
Inside main function
12

Notice how inside the function the values change


however outside they do not.. It is because of pass by
value.
Variations of Parameters
main function swap function
int main()
{ void swap(int a, int b)
int val1, val2; {
cin >> val1 >> val2; int temp = a;
swap(val1, val2); a = b;
cout << In main function << endl; b = temp;
cout << val1 << << val2 << endl; cout << In swap function << endl;
return 0; cout << a << << b << endl;
} }

val1 a

val2 b
function main makes When the function is called
two variables the two variables
are copied for the function

Above is an illustration of how pass by value works.


Variations of Parameters
Same code but now modified to use pass by reference.
#include <iostream>
using namespace std;

void swap(int& a, int& b);

int main()
{
int val1, val2;
cin >> val1 >> val2;
swap(val1, val2);
cout << In main function << endl;
cout << val1 << << val2 << endl;
return 0;
}
void swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
cout << In swap function << endl;
cout << a << << b << endl;
}
Why functions?

When you program you should be aiming to write


modular code.

Modular code is code which has been broken down into


small tasks.

The process of writing modular code is called function


decomposition. This is the process of taking a problem
and breaking it down into smaller problems.
Why functions?

You will find functions can help reduce the amount of code
you write and maintain.
Inline functions in C++

In C++, a function which a programmer considers


simple enough can be made inline.

An inline function is where any call to the function is


actually replaced by code to perform the task.
Inline functions in C++
Because you are replacing the call of the function with
the code - you are avoiding the function call and the
overheads associated with it.

Consider this function:

double abs(double x)
{
if (x < 0)
return -x;
else
return x;
}
Inline functions in C++

The function we described could be rewritten as this:

double abs(double x){return (x<0)?-


x:x;};
Inline functions in C++

Now lets imagine we have this code;

y = abs(z);

Here we are making a call to the function. When this is


done, the function is called and then executed. In doing so
variables are passed into the function and returned.

This is very expensive considering it is a simple


function.
Inline functions in C++
Now lets make our function inline:

inline double abs(double x){return


(x<0)?-x:x;};

And now consider the call in our code:

y = abs(z);

Instead of calling the function and passing the variables,


the compiler does not make the call. Instead it substitutes
the call with the code of the function - hence avoiding a
function call.
I/O in C++

In CSCI114, you learnt about I/O in C++ using stream


extraction and stream insertion operations (<< and >>).

You learnt how to do I/O to standard device such as


Standard Input, Output and Error.
I/O in C++

In addition to this you learn about types such as fstream,


ifstream and ofstream - which allowed you to make
references to files.

Consider a text file that has the following data.

Daniel 65.9
Tom 80.2
Harry 76.3
Sandra 92.0
I/O in C++
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream ins;
const int MAX = 128;
char name[MAX];
float mark;
ins.open(data.txt);
if (ins.good())
{
while (ins.good())
{
ins >> name >> mark;
cout << name << mark <<
endl;
}
ins.close();
}
return 0;
}