0% found this document useful (0 votes)
202 views88 pages

MIAE 215 Entire Course Package

This document provides an overview of key concepts in the C programming language including: 1. Data types like int, char, float, boolean, and struct are discussed along with their sizes and ranges. 2. Operators for arithmetic, assignment, comparison, increment/decrement are introduced. 3. Variables, literals, and expressions are defined. 4. Concepts like I/O streams, file handling, escape sequences, and data structures are covered at a high level. 5. The sizeof operator and type casting are explained briefly. 6. Control flow structures like if/else and enums are mentioned.

Uploaded by

Nicholas Franco
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
202 views88 pages

MIAE 215 Entire Course Package

This document provides an overview of key concepts in the C programming language including: 1. Data types like int, char, float, boolean, and struct are discussed along with their sizes and ranges. 2. Operators for arithmetic, assignment, comparison, increment/decrement are introduced. 3. Variables, literals, and expressions are defined. 4. Concepts like I/O streams, file handling, escape sequences, and data structures are covered at a high level. 5. The sizeof operator and type casting are explained briefly. 6. Control flow structures like if/else and enums are mentioned.

Uploaded by

Nicholas Franco
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 88

Good idea to make more templateC to have a base for a program

have 4 in front of them disregarded


Comments
bycomputer left parenthesis
Then there are compiler directives library rightparenthesis
Then theint main
Then our code
And finally return O
output operator shootsout cont stream in ett it is connected to monitor
inputoperatorallowstoshootin endl identifier will print a new line
compiler is a translator using human text and the library translating to machine
code
filestries to determine thetype of file
rm s remove

o s rename usually name it filename without C


diff r compares two files no output if same

I long format

compile time error program won'tcompile will tellyou what's wrong


run tim error program won't run will still compile
int x a variable declaration int integer datatype
ADDRESS Byte o
Bit 1111111 1 Byte 8 Bits a variable must be on the left ofthe
2
assignment operator
3
u x 5 what's on theright is a literal
value that we chose

iffy
6
X x ti is an expression in thiscase
the 5 will get overwritten with
each variable x takes up 4 bytes a 6

Xt I is same as X t

Cin is a stream connected tothe keyboard


short x uses 2 bytes of memory int x usesu

of things we can count using binary is 2 n of boxes

Range of representable integers D 2h I l bit is usedfor o


Possible bit patters
o o o o to range of unsigned short is o 065535 2 1
00 i t tt
o 0 2 te If you exceed therange you get the
0 1 I 3 3 consequence of NEB not enough bits goes to o
I 00 4 y
5 3 signed short is 32768 32767
range ofexceed
I 0 1
I I o 2 If you the
therange you get
I I t t consequence of NEB not enough bits goes to 32768
unsigned signed
range is on rangeis y as

sizeof function gives of bites in main memoryneeded to hold data


UL unsigned long U unsigned olet'sto
explicitly stateyourtype

gtt o file name file name C to compile


data types ASCII American Standard Code for
Information Interchange
short unsignedshort
int signed unsigned int unsigned ASCII table turnsall characters into
long unsignedlong numbers o 0127

characters char take up I byte computer converts ascii number into


binary code
A this specifies a character character literal 5 integer literal
In a new line 5 acharacter literal

escape sequences l specific letter represent integers

Integral data types integers characters integers come in chunks of


characters come in chunks of
Need to represent the Reals

I box for sign I bit for float anddouble

iii
I box for exponent 8 bits for float 10 for double controls
range
I float 4 bytes 6 decimalplaceaccuracy

in
untderflow
is potsitive overflow overflows cannot be represented NEB
positive
boolean data type a bool true
bool false O

ID unsigned int
student no negative all wholenumbers large range
GPA float or double

name variables so we know what they represent

struct structure ocreates new data type

ex struct student a unsigned int ID bites for Mick ID mick Id


float GPA 4 bytes for MickGPA mick GPA

student o mick Keith


mick ID
Mick ID 5 to store 5 as ID
Mick GPA 4.3 to store 4.3 as ID
pic
mickGPA
Nested struct a structinside another struct

compiler directive D define set a const for a


variable or symbol
define
pi 3.1415926used as a
nestedinside shortcut

gt
if
I const set constatuame to a
a
variable cannot change later

Enum Enumerated datatype


enum days sun mon tues wed thur fri sat
days today 08 10 28 35
day mon
will spit out 1 not mon
or
enum days sun l mon 2 tues 3
I can choose to notlet it flow logically

Mixing data types


int x

x 4.56 should be float


it will chop off the 56 and spitout 4

can put a short into an int without issues but can't do the
you without a error
possible
opposite

int Keith 5
int Keef Keith variable Keef is a reference variable to variable Keith
a reference is a nickname

Kget

J
intKeith int Keef Keith
5 is stored at 1 location but you can get it by calling for 2 names

Keef 10 D rewrites 5 as 10

When we study pointer variables I will fully and completely understand


reference variables 17 January
login info loginenes concordia.ca

Is view directory

mkdir make new folder

ed enter the folder

ed leave folder

rm rf a delete folder y yes

nano txt create text editor file open existing file


cat txt show text
add
sub
malt
I division
remainder 5 2 1

i itt it r.tt
lsanfitt
increment tt D post increment Itt
pre increment ti
decrement n post decrement i
pre decrement i
k i jtt t does i j then tt to j
ish i m t does to m the it new m
m u

doing t to a char will bring it tothe next letter or next ascii


float i 0.2 c out cc i is ccitt Lendl L is 0.2 shows i then
c out cc i is a ice endL 5 c is 1z does tf
k it 2 will spit out 2 0.5 will be trunched

fix this k 2 Of
by doing it j
says it's a float notsupernecessary
or
K feat it j 12
applying a cast to i

i t
j 2 boolean expression icj a true or false
D not equal
Dequal evaluates if LHS and pits are equal

is
just assignment
IF statement if boolean expression var relation ops var

true stuff
31 booleandexpressionFI
evaluate

next statement False Truestaff


Nextstatement
IF Else statement
if Iboolean expression

True stuff I
Faisestuff
I
ftp.fednateexpression
n
Traetstuff
1
y
Nextstatement
else

falsest False stuff Always use for equality


falsesta
setprecision n when doing cout will show n decimals

if tabs number 0.3 2 0.001

coat cc number is close enough to 0.3 cc endl


else

coatLinumber is not close enough to 0.3 cc endi Fthis instead


NEVER NEVER NEVER COMPARE FLOATS FOR DIRECT EQUALITY
If and If Else can be nested nested If flow chart

is compmand u
T And T T na ra
is comemand
d
F
ii iii is comemand
I D
F or F is cogmand
r

Not q
Next

Switch Statement
switch var

case n coutee result wanted cc endl


break breaks out of switch statement goes to next statement
case d coutee result wanted
break

out cc game over cand


no break will run every statement
under selected one until there are
no more

Loops

nai Édgwi getcommente

Next statement once boolean statement is met


int counter
counter 0

while counter 1000


ofbody of loop
Contcc Keith e end
countertt need a statement which eventuallymakes the condition FALSE

next statement
Flow Chart
counter 0

no counterciooo F

se T
contackeithccendl

countertt

Next
pwd s tells which directory I'm in

rm f a delete file make sure to include filetype


to get to Mech215 folder directory home E ted PUBLIC MECHE's

clear cleans up previous commands

send a file I email address


by emailtmpack s subject

to write a ctt file a nano app


to compile a ctt file a o namegiven copfile name
get
to run a code to name given
Use while loop to find sum of 5000 values entered by keyboard
at counter 0
float sum o
float u

while counter 5000

cin u

Efisatiienal
countertt a placement doesn'tmatter

next statement

FORLoop
at sumo
nt v var onlyaccessiblewithinloop

for intMounter o counter 5000 counter tt


initialization booleanexp condition
post

Cin Vi
sum sum tr i
Coutee the counter is cc counterccendl a will show counter after each value entered
g
coutcesumcendl
d
nt v
nt counter 0 initialization

or counter 5000 counter tt booleanexpr e


Tu
Cin Vi n
sum sumtri
Coutee The counter is cc counterccendl
y
coutcesumcendl
county counterccendl a will show counter after showing sum Next
initialization is performed upon loopentry
2 boolean expression is evaluated
if true body of loop is executed postexpression is executed
ya
boolean
expr is evaluated
Do while loop
floats 1034
BodyofLoop

booleanexpr F
n
VT
www.m

Éo
many rabbits will you have after K months
to start with 1 pair of rabbits one male I female that were just born
2 rabbits are mature after I month
3 gestation period is 1 month
4 rabbits don't die
int prevel curren
month i r I pair for int month 3 month2 12 month
month 2 D pair
month 3 2 sum prev t curr
pair
month 4 o 3 coutcesumccendl
month 5 o s prevaurr
month 6 s 8 curr sum
month 7 13 sum preutcurr
month 8 b 21 coutcesumccendl
month 9 D 34 prev
month 10 s 55 curr sum
month it 89
month 12 0 My me ends
piet
curr sum
phigoldenratio sum preutcurr continues to loop
dingy coutcesumccendl
nano asst txt to view the assignment I description
Use visual studio towrite code the compile with putty
communityversion

EEisatttp
write using namespace std under includeCio
stream

local windows debugger to run code

variable name can'tstart with a number can't have a space can't have a specialcharacter
Finding smaller of 2 numbers plugged in
if num c name
smaller numl
else
smaller num 2

looking for greatest common diviser of 2 numbers


will stop looking when it hits smallest number

mod will figure out if a number is divisible evenly or with a remainder


if i 0 i is a divisor of

library function smath is a


library with abs as a function absolute
value
int float x int results in float
mostprecise var

float res
res I 1.5 will be a floateventhough rightside is only int
22
casting
res float a a

greaterthan ex if a b
greater than or equal while ac b
if Ca b
Ésiuathat or equal while la b

not equal
11 OR
AND
Not
User defined functions for arduino Global space before
go in anycode
ex print Keith void
no inputneeded
void print Keithvoid doesn't return a value
can now use function in program
ARDUINO
Arduino is a small CPUmicro with 32768bytes offlash memory doesntgetlostwith no power
Sram has 2000 bytes for all variables
constants can be stored in another storageroughly 1000byte

Arduino
programs end with ino
serial begin9600 considered a library function that links pc to arduino
9600 bits persecond

serial printInc like the cont

Digital us Analog signals


d
low false in Ctt hightrue I
Digital D
qq.FI
high True in ett

g
uv u v u w u
DoDI
digitalports
ÉfM
function will do
pinMode port mark as input or output marks what pin

function digitalWrite port value portmust produce nwrites value to port


function digitalRead port reads input from port gives o Clow or high as answer

light sensor outputs analog signal


Ex using bit Ex using 2 bits
10 bit DAC

I
coloss as output
am
IFI it
digital
NEB
My 100 microseconds to sampleonce
Read port
function analog tells which analog port to turn into ADC
int u
float voltage
read s
U analog
max voltage
voltage v iozzo g

Duty cycle
D on time us cycle time pulse width modulation
function analogWrite port dutycycle value between 0 255 o or
255 1007

clock speed
350kt something Iokspeed
higher clockspeed faster operations
Jr
happens
at everyrisingedge
Arduino has 32 bit counter can count up to 2374 billion

Arduino data types

Name Boot int long Float


Size of bytes I
Byte Gr 2 y y
If else

float a

coat cc enter a number Lendl


Cin s ai
if ca a
conf cc the number is greater than one Lendl
else
a a x2
cont cc a i

Switch
int ai

coat cc enter a number 4,2 3 a endl If else if


Cin z ai

switch a also use

case 1
ut the number is one en rout cc the number is one c e
break
Else if Ca 2
case z cont c
the number is two renal
break

gift m
break

11 1 all code here will


be commented out
I
For loop

for int i o i cio itt for int i o icao itt


coat cc ice endl cout a c

g if 1 10 0
coutccendl

Do while
int ai
do
coat cc enter a pos number Lendl
Cin a
while a o

cont cc end cc end

For loop
int i
for i s it 8 i tt
cont cc ice ends

contcc loop finished end


Dice problem
count1 1
3 count2
7

iii iii
Ask user how many numbers to generate

For int i o is how many itt


me
Keep track of of times each of 7 numbers appear switch random value
print out 7 bar charts a
break
How to print star bar chart case 1 count Itt
Ex break
counto 5
Count1 8 1 txstaggibritrary
count 2 Y 0 518 of 40
A default cont wtf end
count 3 4 2 48 of 40
count 4 a wantedone
count 5 6 Scale count i x 40stars largest
count 6 3
For int j 0 jescale jtt
findlargest couth i prints out bar chart
count 8 has to be copypasted 7 times
assumelargest count 0

if count I 2 largest
largest counts
if count 22 largest
largest count 2

using sin function


012 yaxis80g
Y i 52 For int x
rad
o xc 360 xtt
it 180 x 11convert deg to rad
g sincrad scale ynew x 80 2
grew y
scaledynew x80112 gives ofleadingblank
For int blank o blankscaleblanket ynew y scale
coatcc o i o

coutee ccend
E axis
User defined functions

MAX int Mick int Keith


giftype
If Mick Keith
EiseTURN Mick
RETURN Keith

argest Max A B A 5 B to
largest Max C D
largest Max E F
t t

Yid inclint Keith


Keith Keithtfrigermeti
g Keith Keitht

int mainc
int a s int maine
inc a
a inc a
a is still 5

int Keith 5
int mick 10

a inters

If
int temp
temp
a bi
ai

int main c

swap mick Keith


Coutee mick cc Keith c endl

return 0
int my functionCinta int b
return at bi

int main I
int xyi
int output

contcc enter first and secondnumber ccendl


in x y
output my function x y
out cc sum is cc outputccenal
int subtraction int a int b int subtraction int a int b
intr intr
r a b r a bi
return i return ri
s s f

int maine int maine


iggy
int x 5 y 3 Zi
route subtraction 7,2
Z subtraction 7,2

contact

g void printmessage
couth hi
intr
int maine
Eiti
g
nt maine gy tellscompiler all

int x 5 y 3 Zi Gallows detsoffunctionstobe


put
anywhere
n in abt
int maine
int x 5 y 3 Zi
void duplicate intra int b int c
jawn
a 2
bt contact
I
int subtraction int a int b
int main i intr

int x 1 y3 Z 7
cont u x cc
y cczccendl 5
duplicate x yZ
cont Cxc cycle
g
I 3 7
You can count how times a user defined function is called with a counter
many
built in to the function mustinitialize outside the function or using static
If youwant more than oneoutput a return statement must be usedafter other
statements return acts as a break any

mick address
of mick willshowwhere in main memory thatvariable is in hexadecimal

a nested blocks

wi out
fÉÉuti
conf i 11 will coat 2
out i n will coat
coat ill will cont o

var accesses the global variable of name var scope resolution operator
int max of three int a int b inte void swaplintta into b
int gre int temp a
if a b a e a b

gre ai b temp

elseit b add b c
gre bi Int
maine in

int a bi
gre c
iii
return gre

int maine a b b a
int a b c di
Cin a b c
const constant value for
variable won'tchange

return 0

void funce void funce


static int num l int num l
coutcenumccenal coutanumccenal
num tt num tt

imma
fund
fund
fund
fund
funce
returnOi

I 2 3 4 1 11 I
Callgraphfornested functions
maine

2 Hello from y

s
s
fa Y returning to f2
s
terminating

A nested functionloopwon't run foreverduetolimited amount of memory in stack space


a.k.a segmentation fault

ARRAYS
Find Max normalway FindMax arrayway
int resize
int w i
in w
int maxi
i
uz uz uz
int vesjarras
t
for inti o ics itt
f
Va g g g g
g
this is g
also allowed

max voi at compiletime so can't


if v max a samethings choosehow
manyvariables
g Max VCO while running
else if vz maxi for int i t ics itt
max ve if Vci Max if each boxholds t int each box
else ifcuz max max Vci will be 4 bites address 1 1000
us address 2 1004 et
Sg max
address 3 1008
coatcc maxi behind
pinfrontor
going out of bounds beyond the array will produce weird results for any array numbers
not defined but will compile produces no compiletime bound checking

name of an array is the same as thestarting address of the array arrayciso will go to starting
address andsetvalue to o
for int
i starting address i up void how array int parames intsize
for int i o i size itt
paramciso
need to put
arrays are always passed
by reference no
Sorting is green less than pink yes swap no move arrow
I
28 z É 2 z z
z f swap z N 28
no
28 É swap 28
É no
8 8 8 8
15 15 E 15 is 53

z
s 94 less than act if yes swap usingtemp etc
If y Dont
z swap
is s

2D is c
array woo
grows

O
Fd Epe
int 3 s wgbox XC C3 xHr 3 c
re
howthese 3 o box
arestored o
for intro re 3 rtt

for int c o res att

Cin x r cc

7Tumnsneeded
Void print matrix int argc 5
for intro remick tt

for int c o cckeith Ctt

coutccargerscc

Couteeends
Arrays

int myNum 33 10 20 30

cars y Volvo BMW Ford Mazda


string o c 3
coat Le cars o

Volvo

cars y Volvo BMW Ford Mazda


string o n z z
i
coat cc cars core endl
cars o Ferrari

cout Lc cars o

Volvo
Ferrari

not needed will default to ofelements


cars y Volvo BMW Ford Mazda
string
for int i o i y it
cout cars i cc endl

Volvo
BMW
Ford
Mazda

int myNum 3 10 20 30

cout cc size of
myNum Lendl
12 of bytes used
byarray
2D array 3D array
string letters 23233
0 I Bl É A B
I D E F C D

g
E F
Coutee letters 03123 G H
c 3

swap numbers in
array
int
array 33 1,2 33
int inv 33 0,0 03
int j 2

for int i o i 3 i tt

inv 53 arrayCi
J i
3
void F int I ang

arg 23 52 11memory address uses formula

At Li f Fudgefactor
In 2D Ali j rows j
for nx3 matrix
Void printmatrix int 3233 arg int mick int Keith
for int r o remick rtt
for int c o cckeith Ctt

E
cont agha

int mess i

coutcc m a Imco this will print out the same thing twice starting address

Coutee unsigned long m will print theaddress using numbers only

char name I Keith


cont a name this prints Keith not theaddress char arraysare the exception
must be added as an outputtoendthecoat
char name263 A B ie 3,740 weird ASCIIcode
Coutee name 2 this prints ABC
1 2 3 3D array
4 5 6 slice o A 2 3 3
7 slice row cot
8 g
for int so see Stt
10 11 12 for int r o re rtt
for int c o c 3 att
13 14 15 Slice I
16 17 18
don't havetogive first dimension
Void F int 3233233 ang
Tin 3D address translation formula
Box 5 5 CUTEY 3
binders t t t t
t sections
folders tabs groups

BoxCo Boxer Boxes Boxes Boxes


2D array

nt x 33223 0,13 2.33 4,533


for int i o i 3 itt

for int j o
jez j tt
contcc element at x cc ice ccj cc
Coat a x i j acendli
3
3
element at Oslo O
element at co i I
element at 1 o 2

3D array

int x 23223223 0 13 2,333 9,53 6.7333

how too keep an ongoing sum

forcint i o i size itt


sum t arr Ci

one sum size


Talked about pointer variables last class
int x 5 ptr
P 5

1000
ptr outa canal
Ptr x 10
10 1002 out c ptracendl
ptr 1000

charci this willnot compile


that pic this is ok int ptrz
ptrz c ptrz c

void pointers
X 5 x 5
10oz 1002
void up 1003 thestpfiniter too

int x 5 char up B
up zoo Up 2000
char c A
2000 zoo
up Ici c A 2001
C B 2001
2002 zoo

usingned short intx uzoix.gg o


char temp
void Pi Ptr 1000

Up byte Ii p

emp char up

char up char up 1 i

char up ti temp

compiler treats reference variables as a constant pointer


int Acs jinns
Ali j expression

starting address offset 2D array address translation formula

void print void A int rows int cols char type c


i
arrayof char
array of int
for int ro i r crows rtt f array of float
for int c o cc cols att

switch type

catechin
cont x int A tr cols to cc endli

cafe
iii cont cc x float A t r cols to cc end l

Dynamic Memory
int ptri Ptr 2000
New int
Ptr datatype
6 gap
ptr 5
5
contact ptr ccendl
DELETE Ptr memory is now free again dangling don't write
ptr o to or readfrom
Ptr 0 i
heap
int ptr ptr zooo int ptri ptr zooo
new int 5 i
ptr Cin size
datatype
piniw inte
5
gyeap datatype Toohey
for inti ni ie

int
Cin
Ptr i
row coli
ptr i

DELETE ptri
ptr
42
i 42
III
of arraychosen
time

ptr new inflow d


2D array
for intro re row i r tt
g
for int c o carol Ctt

ptr r col c 42

Everycall to new has to be matched with a call to delete


int vats Ptr is value val is value
int ptr int ptr vat
ptr dual ptr val ptr is address oval isaddress

0 83 OXFE

int var 1 3

contccaddress of vari Le variccendl

0057 FER

int ptr var


var 5 var 5

ptr Ivar ptr Ivar


Coutee ptracendt contcc ptrcendl

ptr 1
5
0057FE C Coutee ptrzcendl
route varccendli
5
I

int v23 1 2,33


int ptr

ptr vi
for int i o i 3 itt
contcc address at ptr Leptrocenal
cont c valueat ptr a ptracendl

OOAFFA80
GO
AFFA8.4
AFFA8.8
OJO
int num 53
int pi
p num
p lo

ptt
p 20
p numC2
p 30
p num 3
poi
p num
ptu 50

forfintnoinesintt
couth numen cc

10 20 30 40 50
Servo mymotor
variable object
datatype

struct circle
won't compile can'taccess rad this is default for class
frigate
p this isdefault for struct frigate

Fifa'tareas return 3.14 rad rad Fifa't areac return 3.14 rad rad

circle mick Keith circle mick Keith

mick rad 1.0 Micksetrad 1.0 mick rad 1.0 Micksetrad 1.0
Keith rad 2.0 Keith Keith rad 2.0 Keithsetrad 2.0
cont cc mick areaccenal cont cc mick areaccenal
cont cc Keith area cc endl cont cc Keith area cc endl

File input output

wintered.int niigenjboolean expression


performsinput
it inputoperation succeeds expression evaluates to True
court a numberwendy

ctrl d will endthis loop

cin
Fa bad coat In
Ciostream

include Lfstream class


Istream inputs
OFstream outputs fstream version
includeciostream
infile
usingnamespace std
inputdot outputdot number

Ii
int mainc
g
I
coxut a number Lendl
IFstream IN FILE
OFStream outFILE infile Dputdot outfile put.de
infileopen inputdot

infileclose
outfile close Ii tocloses files
Exercise
Inadat Ina dat
I variable oftype IFstream include If streams

I I variable oftype ofstream u


include Ciostreams

OUTIdat out2dat int maine Int da


popens
ifstream infile CINIdat
streaminfile
ofstream outfile

cafe end of file outfileopenCOUTI dat


returnstrue when end offile is reached
returns false when still in file
for asciifile
infiles number while ingyes tamper
good version
whileCinfileeofc outfile cc numberccenal
Couteenumberccenali
in files number infile close I
outfilecloseC

infileopen IN 2 dat
badversion outfileopenOUT2 dat

whileC infileeofc while infile 7 number


infiles number outfile cc numberccenali
Couteenumberccendl

infileclose l
outfileclosed

Couteesetprecision
tochoose how many decimal places you ant as output
make output file binary
ofstream outfile myoutput float precision binary writedat ios binary1 ios out

while infiles number copies on a byte bybyte


startingaddress
basis not charby char
outfile write char number sizeof double
Least as pointer to a char always

how to read binary file


ifstream infile myoutput float precision binary writedat ios binary1 ios in

infileread char number sizeof doubles


while infileeofc
contcc number cendli
infile read char number sizeof doubles

To avoid scrambling bytes you can tell the computer to swap the bytes or
unscramble them learned lastclass
NOTES 0
Comment pairs do not nest:
/*

float pi = 3.14 ; /* pi is used in math */


float x, r ;

x = pi * r* r ;

*/
The compiler will not recognize pi in the line x = pi * r* r since its declaration has been
commented out. Furthermore, the last */ will cause a compile time error.

IDENTIFIERS
----------
An identifier is a sequence of LETTERS, DIGITS, and the underscore (_) character.
An identifier CANNOT begin with a digit. C++ is case-sensitive which means upper and
lower case letters are treated as being different.

C++ BUILT-IN DATA TYPES


----------------------
1 is size of char
2 is size of short
4 is size of int
4 is size of long
1 is size of unsigned char
2 is size of unsigned short
4 is size of unsigned int
4 is size of unsigned long
4 is size of float
8 is size of double
16 is size of long double
4 is size of void *

Range of built-in data types


----------------------------
These are the ranges for the integral data types:

unsigned char: 0 to 255 char : -128 to 127


unsigned short: 0 to 65535 short : -32768 to 32767

unsigned int : 0 to 4294967295 int : -2147483648 to 2147483647

unsigned long: 0 to 4294967295 long: -2147483648 to 2147483647


float: 1.175494351E-38F to 3.402823466E+38F (6 digits of precision)

double: 2.2250738585072014E-308 to 1.7976931348623157E+308 (15 digits of precision)

CONSTANTS
---------
In general, the method C++ uses for constants is:

const data_type identifier initialization;

Attempting to define a constant without giving it an initial value will result in a compile time error:

const float pi ;

The use of the keyword const allows the creation of an object in main memory whose
CONTENTS CANNOT BE CHANGED.

REFERENCES
----------
int main(){

int keith ; // declare an integer variable called keith

int & good_guitar_player = keith ; // declare and initialize a reference to keith

keith = 5;

cout << keith << " " << good_guitar_player << endl;

good_guitar_player = 7;

cout << keith << " " << good_guitar_player <<endl;

return 0;
}
The program output is: 5 5
77

A reference must be initialized to the variable to which it is referring


to when it is being declared:

int x;
int & a ; // error must always initialize a reference to some variable
A reference can only refer to one thing; once it has been initialized IT CANNOT BE LATER
CHANGED TO REFER TO SOMETHING ELSE.

USER DEFINED DATA TYPES: ENUM AND STRUCT


-----------------------------------------

C++ allows for a programmer to declare and use their own data types. The enum and struct
constructs are used for this purpose:

Suppose we want to associate special meanings to certain integer values. We can use symbolic
integer constants such as:

const int Mon = 1;


const int Tue = 2;
const int Wed = 3;
const int Thur = 4;
const int Fri = 5;
const int Sat = 6;
const int Sun = 7;

Once we have declared these days, we can do things like:

int day;

day = Mon;

if ( day == Sat)
cout << "Yahooo it is the weekend time for windsurfing" << endl;

Of course, we could have done the same thing using:

int day;
day = 1;
if ( day == 6)
cout << "Yahooo it is the weekend time for windsurfing" << endl;

Writing {Mon=1, Tue, Wed, Thur, Fri, Sat, Sun} instead of {Mon, Tue, Wed, Thur, Fri, Sat, Sun}
allows the symbolic constant Mon to be associated with the value 1, Tue with 2, etc., as
opposed to Mon has the value 0, Tue has 1, etc.
Struct
------

C++ has a struct declaration which is useful to hold information of different data types pertaining
to a certain object or thing.

struct student
{
int ID;
float gpa;
}

student student_x, student_y;

student_x.ID = 9999999;
student_x.gpa = 0.00 // this person is in serious trouble

student_y.ID = 1234567;
student_y.gpa = 4.30 // this person wins a medal at convocation

We say that ID and gpa are the two FIELDS of the struct student. We declare two variables
student_x and student_y to be of type student.

The dot (.) notation is used to access the individual fields of a struct variable.

Structs may be NESTED, meaning that the field of a certain struct can be a previously declared
STRUCT as in the following example:

int main(){

enum months {Jan = 1, Feb, Mar, Apr, May, Jun, July, Aug, Sept, Oct, Nov, Dec };

enum days_of_the_week {Sun, Mon, Tue, Wed, Thur, Fri, Sat };

struct time
{
int hour;
int minute;
int second;
bool pm ;
};
struct date
{
int year;
months month;
int day_of_month;
days_of_the_week day_of_week;
time time_now;
};

date today, yesterday, tomorrow;

today.year = 2022;
today.month = Apr;
today.day_of_month = 28;
today.day_of_week = Thur;
today.time_now.hour = 10;
today.time_now.minute = 12;
today.time_now.second = 35;
today.time_now.pm = true;

cout << "today's date is " << today.day_of_week << " " << today.month << " " <<
today.day_of_month << " " << today.year << endl;

cout << "time now is " << today.time_now.hour << " " << today.time_now.minute << " " <<
today.time_now.second ;

if (today.time_now.pm == true )
cout << " pm" << endl;
else
cout << " am" << endl;

return 0;
}

NOTES 1
Assignment operator in C++
--------------------------
variable = expression ;

int main()
{
short mick;
int keith;
keith = 234456;
mick = keith;

cout << "Keith = " << keith << endl;


cout << "Mick = " << mick << endl;

return 0;
}

This code compiles with no warnings or errors. It produces the following output: Keith = 234456
Mick = -27688
This is because Mick is a short, which has a max of 32767, after that it loops to -32767

Compound Operators
-----------------
i = i + 1; —---------- i += 1; —-------- (i++;) —-------- (++i;)
j = j - 5; —----------- j -= 5; —--------- (j--;) —--------- (--j;)
k = k * 4; —--------- k*= 4;
l = l / 2; —----------- l /= 2;
m = m % 2; —----- m %= 2;

Increment (++) and decrement (--) operators can be applied to float, double, and long double.
They add or subtract 1.0 from a floating point variable.

They can also be applied to char variables as well with the expected results that the result is
equal to the next (or previous) character in the ASCII collating sequence.

The cast operator:


-----------------
int i, j ; // numbers to be read in from keyboard
cout << "Input an integer number " ;
cin >> i;
cout << "Input a second integer number ";
cin >> j;
float k ;
k = (i+j) / 2.0; // now the division will keep the fractional part (it has been casted)
or k = ( (float) i+j) / 2 // now the division will keep the fractional part (it has been casted)
cout << " The average value is " << k << endl;
return 0;}

The result is now: Input an integer number 3


Input a second integer number 2
The average value is 2.5
NOTES 2
The Boolean type
---------------

C++ now has the built-in BOOLEAN logical data type which is named bool. The bool data type
can take on one of two possible symbolic constants: true (1), false (0).

Relational Operators
--------------------
The equality operators are:

== returns true if both of the operands are equal to each other


!= returns true if the two operands are not equal to each other

struct a_simple_struct
{
int a_number;
char a_letter;
bool a_boolean;
};

a_simple_struct first_struct, second_struct, third_struct;

first_struct.a_number = 1;
first_struct.a_letter = 'a';
first_struct.a_boolean = true;

second_struct.a_number = 1;
second_struct.a_letter = 'a';
second_struct.a_boolean = true;

third_struct.a_number = 5;
third_struct.a_letter = 'a';
third_struct.a_boolean = true;

if (first_struct == second_struct)
cout << "first and second structs are equal" << endl;
else
cout << "first and second structs are not equal" << endl;
return 0;}

The answer is nothing! The program DOES NOT EVEN COMPILE :


If you want to compare structs, then the comparison must be done on a field-by-field basis. For
example, the above program can be fixed by simply replacing the if statement with something
along the lines of:

if ((first_struct.a_number == second_struct.a_number) &&


(first_struct.a_letter == second_struct.a_letter) &&
(first_struct.a_boolean == second_struct.a_boolean) )
cout << "first and second structs are equal" << endl;
else
cout << "first and second structs are not equal" << endl;

Ordering Operators
------------------
< less than
> greater than
<= less than or equal
>= greater than or equal

Boolean Operators
-----------------
&& : used to perform a logical AND of two boolean expressions. ex: (i < 3 ) && (k < 56 )

|| : used to perform a logical OR of two expressions. ex: (i < 2 ) || ( k > 45)

! : used to perform a logical NEGATION. ex: ! (i < 2)

SHORT-CIRCUIT EVALUATION
------------------------
( i != 0) && ( (k/i) < 2 )

the ( i != 0) will be equal to false only when i is equal to 0, since the boolean && operator
requires both its operands to be true in order for the entire to be expression to be true, it is not
even necessary to evaluate the right-hand side ( (k/i) < 2 ) in the case of i being equal to 0. By
virtue of short-circuit evaluation, we can guarantee that division by zero will NEVER occur.

Comparing floating point numbers


-------------------------------

Round-off errors can cause some problems when comparing floating point numbers for equality.
It is better to check if 2 numbers are close enough to each other.

float number;
const float epsilon = 0.001;
number = 0.0000001 + 0.0000001 + 0.0000001 + 0.0000001 + 0.0000001 + 0.0000001 +
0.0000001 + 0.0000001 + 0.0000001 + 0.0000001;

if ( fabs( (number - 0.000001) <= epsilon ) )


cout << " number is equal to 0.000001" << endl;
else
cout << " number is not equal to 0.000001" << endl;

cout << setprecision(15) << "number is equal to " << number << endl;

return 0;
}

number is equal to 0.000001


number is equal to 9.99999997475243e-07

The IF STATEMENT
---------------
Form 1: if (expression)
{ statement;
}
Form 2: if (expression)
{ statement;
}
Else
{
another statement;
}

CAVEAT
-------
ALWAYS USE == FOR COMPARISON IN IF STATEMENTS!!!!!

Nested if-else-if statements:


----------------------------
if (command == 'u' || ‘U’) //the U allows “u” and “U” to give the same output (fallthrough)
cout << "Move up command was received" << endl;
else if (command == 'd' || ‘D’)
cout << "Move down command was received" << endl;
else if (command == 'l' || ‘L’)
cout << "Move left command was received" << endl;
else if (command == 'r' || ‘R’)
cout << "Move right command was received" << endl;
else cout<< "Invalid command" << endl;
The switch statement
-------------------
switch (command)
{
case 'u': case ‘U’ cout << "Move up command was received" << endl;
break; //the U allows “u” and “U” to give the same output (fallthrough)
case 'd': case ‘D’ cout << "Move down command was received" << endl;
break; //the break is very crucial here, without it, all cout functions will be done
case 'l': case ‘L’ cout << "Move left command was received" << endl;
break;
case 'r': case ‘R’ cout << "Move right command was received" << endl;
break;
default : cout << "Invalid command" << endl;
}

return 0; }

LOOPING CONSTRUCTS
-----------------
Suppose we had to find the sum and average of a list of 10 000 values? The brute force
approach is not very convenient to use. We can use a while loop to control the number of times
a portion of program code is to be executed.

int main(){
float sum;
float average;
const int size_of_list= 10000;
float number;
int number_of_items_processed;
sum = 0.0;
number_of_items_processed = 0;

while (number_of_items_processed < size_of_list)


{
cout << "Please enter a number " << endl;
cin >> number;
sum = sum + number; // update running sum
number_of_items_processed++; // increment number of items processed so far
}
average = sum / size_of_list;
cout << "The sum is " << sum << endl;
cout << "The average is " << average << endl;

return 0; }
A version that allows the user to end with the CRTL+D key would be:

int main(){
float sum;
float average;
float number;
int number_of_items_processed;
sum = 0.0;
number_of_items_processed = 0;

cout << "Please enter a number " << endl;

while ( cin >> number )


{
sum = sum + number; // update running sum
number_of_items_processed++; // increment number of items processed so far
cout << "Please enter a number " << endl;
}

if (number_of_items_processed != 0)
{
average = sum / number_of_items_processed;
cout << "The sum is " << sum << endl;
cout << "The average is " << average << endl;
}
else
{
cout << " No numbers were entered " << endl;
cout << " Sum is " << sum << endl;
cout << " Impossible to compute average... sorry " << endl;
}
return 0;
}

The for loop


-----------
The general form of a for loop is the following:

for ( initialization ; test_expression ; post_expression )


{
action1;
action2; //etc.
}
Another example:
---------------
We can rewrite our while loop program to use a for loop:
int main(){
float sum;
float average;
const int size_of_list= 10000;
float number;
int number_of_items_processed;
sum = 0.0;
number_of_items_processed = 0;

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


{
cout << "Please enter a number " << endl;
cin >> number;
sum = sum + number; // update running sum
}

average = sum / size_of_list;


cout << "The sum is " << sum << endl;
cout << "The average is " << average << endl;
return 0;
}

In a for loop, any of the initialization, test_expression, post_expression, may not be included
(infinite loop)

Note that in the case that the test_expression evaluates to false right away, the body of the for
loop is never executed:

Nested loops:
------------
Loops may be nested. For example;
int main(){

for(int out = 1 ; out <= 3; out++)


for (int in = 1 ; in <= 3 ; in++)
{
cout << "out = " << out << " in = " << in << " " ;
if (in % 5 == 0 )
cout << endl; }
The program output is:

out = 1 in = 1 out = 1 in = 2 out = 1 in = 3 out = 1


out = 2 in = 1 out = 2 in = 2 out = 2 in = 3 out = 2
out = 3 in = 1 out = 3 in = 2 out = 3 in = 3 out = 3

The break statement:


-------------------
A BREAK STATEMENT MAY ONLY APPEAR IN A SWITCH STATEMENT OR IN
ANY OF THE LOOP STATEMENTS. IT MAY NOT APPEAR ANYWHERE ELSE!

The continue statement:


-----------------------
The continue statement is used ONLY IN LOOPS. When a continue statement is encountered
in the body of a loop, the REMAINING statements in the body of the loop are SKIPPED OVER,
and a new LOOP ITERATION commences. Note that while a continue statement causes the
program to skip any remaining body statements, it does not skip the loop test_expression.

char a_letter;
int how_many_ts = 0;

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


{
cout << "Please enter a letter " ;
cin >> a_letter;
if ( a_letter != 't' )
continue;
cout << "Ahhhh... the t was entered!" << endl;
how_many_ts++;
}

cout << "The total number of t's entered was " << how_many_ts << endl;

return 0;
}

If the letter entered is not equal to 't', then the program goes to the i++ part of the for (int i = 0; i
< 5; i++) part and evaluates if the condition i < 5 is true or not. Based on this evaluation either
the loop continues or terminates. If the letter entered is equal to 't', then the two statements
following the continue are executed and loop execution carries on in the normal manner (when it
gets to the } the i++ is executed and the condition is evaluated).
The do-while loop
-----------------

C++ has another loop construct called the do-while loop which is used in situations where a
certain action is to be performed AT LEAST ONCE. The general form is:

do
{
statement 1;
statement 2;
...
last_statement_to_do;
} while (some_condition);

ex:
const int Keiths_age = 58;
int num_of_guesses = 0;
int user_guess;

do
{
cout << "Please enter a guess between 1 and 100" << endl;
cin >> user_guess;
num_of_guesses++;
} while (user_guess != 58);

cout << "Congratulations. It took you " << num_of_guesses << " to guess Keith's age." << endl;

Some more examples of loops:


----------------------------
Here is a program which uses while loops to "decompose" an integer value into thousands, etc.

int hundred_thousands_counter = 0;
int ten_thousands_counter = 0;
int thousands_counter = 0;
int hundreds_counter = 0;
int tens_counter = 0;
int ones = 0;

int number;
cout << "Please enter a number less than a million" << endl;
cin >> number;

while (number >= 100000)


{
hundred_thousands_counter++;
number = number - 100000;
}

while (number >= 10000)


{
ten_thousands_counter++;
number = number - 10000;
}

while (number >= 1000)


{
thousands_counter++;
number = number - 1000;
}

while (number >= 100)


{
hundreds_counter++;
number = number - 100;
}

while (number >= 10)


{
tens_counter++;
number = number - 10;
}

ones = number;

cout << "hundreds of thousands = " << hundred_thousands_counter << endl;


cout << "tens of thousands = " << ten_thousands_counter << endl;
cout << "thousands = " << thousands_counter << endl;
cout << "hundreds = " << hundreds_counter << endl;
cout << "tens = " << tens_counter << endl;
cout << "ones = " << ones << endl;

NOTES 3
Library Functions
----------------
C++ contains many different libraries. In order to access a function within a particular library it is
necessary to #include <library_name> in your C++ code.
sqrt function
------------
In programming terminology, we see that there is an "invocation" of the square root function
which "returns" a value back to the "calling program".

The prototype for the sqrt function is: double sqrt(double) ;

This means the function is called sqrt, it expects a single (formal) parameter of type double.
(the parameter list is the part enclosed in () after the function name). The function returns a
single value of type double.

The type of the parameter passed to the function should MATCH the type of parameter returned
by the function. If not, the compiler will try to change it.
ex:
cout << sqrt(2) << endl; ; // the int 2 will be changed to a double and a double will be returned
int four = 4;
cout << sqrt(four) << endl ; // legal
cout << sqrt(-2.0) << endl ; // believe it or not this will display NaN (Not A Number)

Some Common C++ libraries


-------------------------
The standard C libraries are those with a .h suffix in their library name. They would be included
as : #include <stdlib.h>

C++ libraries do not require the .h suffix and are included by simply specifying the name of the
library within the <> brackets as in: #include <iostream>

Some C++ libraries are derived from the standard C libraries and have a “c” as the prefix as in:
#include <cassert>
#include <cmath>

The stdlib library


------------------
Some of the commonly used functions found in stdlib are:

int abs(int) : returns the absolute value of the integer argument passed

void exit(int) : causes the calling program to terminate with a return value equal to the parameter
passed to the function:

exit(0); // terminate program with a return value of 0


exit(1); // terminate program with a return value of 1

int rand(): returns a (somewhat) random number between 0 and RAND_MAX (32767) Seed is 1
void srand(unsigned int val) : Sets the seed value used by the rand function to the value given in
the formal parameter.

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


cout << rand() << endl; // print out 3 random numbers between 0 and 32767
return 0;
}

EVERY time that we run the above program it will produce the values:
16838
5758
10113

Use seed to change these numbers.

int seed_value;
cout << "Please enter a seed value" ;
cin >> seed_value;
srand(seed_value);
for(int i = 0 ; i <= 3 ; i++)
cout << rand() << endl; // print out 3 random numbers between 0 and 32767

The program's output when we run it two times with different initial seed values
is:

Please enter a seed value 3 Please enter a seed value 890


17747 11116
7107 32040
10365 23590

We can modify the above program to display random numbers between 0 and 6
by simply changing the : cout << rand() % 7 <<” “; // print random numbers between 0 and 6

The output is now: 0 1 3 0 3 6 4 6 6 5 0 2 0 1 2 4 5 4 6 6 2

NOTES 4
The time library:
----------------
You can use the time function (time(0)) in the <time.h> library to give the current time, this can
then be used as a seed value for the srand()
User-Defined Functions
-----------------------
The general form of a function prototype is:
return_type function_name(type argument1_name, type argument2, ...)

Where return_type can be any of the following: char, short, int long, float, double, enum, struct,
class, int& (actually can be a reference to any of the above types), double * (a pointer to any of
the above type), void (signifies the absence of a return type)

NEITHER AN ARRAY NOR A FUNCTION CAN BE SPECIFIED AS A RETURN TYPE OF A


FUNCTION. IN THESE CASES, A POINTER TO EITHER AN ARRAY OR A FUNCTION CAN
BE SPECIFIED AS THE RETURN TYPE.

Call-by-value versus Call-by-reference


--------------------------------------
They ARE NOT PRESERVED ACROSS FUNCTION CALLS. A special place in main memory
called the STACK is used to hold copies of call-by-value parameters and only local variables
used by a function. Call-by-value is the default parameter passing mechanism in C++.

We can pass a REFERENCE to an integer, and not the actual value of the integer. If we pass a
reference, then the function manipulates the actual variable and not a copy of it.

void inc(int& a)
{
a = a + 1; // increment the value of the passed parameter by 1
}

int main(){

int a = 5;
cout << "The value of a before we call the function is " << a << endl;
inc(a) ; // call the function and pass the value a = 5 to it
cout << "Hello, I'm back from the function, this is the value of a " << a << endl;

return 0;
}

The program now produces :The value of a before we call the function is 5
Hello, I'm back from the function, this is the value of a 6
Swap Example:

void swap(int& num1, int& num2)


{
int temp ; // a local variable to temporarily hold the value
temp = num1;
num1 = num2;
num2 = temp;
}

int main(){

int x, y;
x = 10;
y = 20;

cout << "x before the swap is " << x << endl; // will be 10
cout << "y before the swap is " << y << endl; // will be 20

swap(x,y);

cout << " x after the swap is " << x << endl; // will now be 20
cout << " y after the swap is " << y << endl; // will now be 10

Counting using Static Example:

int count_me_up(void)
{
static int counter = 0; // the local variable counter will be initialized once and its value will be
// remembered across function invocations
counter++;
return counter;
}

int main()
{

for(int tattoo_you = 0 ; tattoo_you <= 10000; tattoo_you++)


cout << count_me_up() << endl;
Counting using Global Variable Example:

int counter = 0; // This GLOBAL variable can be seen by all functions

void count_me_up(void)
{
counter++; // now this refers to the global variable
cout << "Value of counter is " << counter << endl;
}
int main(){
for(int tattoo_you = 0 ; tattoo_you <= 10000; tattoo_you++)
count_me_up();

SCOPE and STORAGE CLASSES


--------------------------
THIS DOES NOT COMPILE
void out_of_scope(int mick, int keith)
{
cout << "Hello from function out_of_scope" << endl;
cout << mick << keith << endl;
mick = 10;
keith= 20;
cout << mick << keith << endl;
int ron = 500;
cout << ron << endl;
}
int main(){

int a = 1;
int b = 2;

out_of_scope(a,b);
cout << mick << keith << endl; // mick and keith cannot be seen by int main(out of scope)
cout << ron << endl; // ron cannot be see by int main(out of scope)

Definition: In C++, a BLOCK is simply a list of statements enclosed within the curly braces {}.

Scope rule : A local object can only be used in the block and any other nested blocks of the
block in which it has been defined in.
GLOBAL SCOPE
------------
Objects not declared in any statement block are said to be of GLOBAL SCOPE. Objects of
global scope are visible by all functions.

When we are inside a function, the local of a variable definition HIDES the global one.

SCOPE RESOLUTION OPERATOR (::) allows for the GLOBAL variable to be referenced

NOTES 6 and 7
ARRAYS
-----
An array is simply a collection of similar items referred to by a single common name in which
every individual item or element in the collection can be individually referenced.

In general arrays are declared in the following manner:


base_type_of_elements name_of_the_array[ size_expression ]

where:

base_type_of_elements: the type of each array element like char, int, float, double, struct, etc...

name_of_the_array : is an identifier which specifies the name of the array

size_expression: is a constant or a constant expression which identifies the SIZE of the array.
The expression must be capable of being evaluated to integer value at COMPILE time.

Array elements are stored sequentially:

int my_array[10] = {12, 234, 23, 1, -7, 55, 18, 67, 99, 100};

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


cout << "my_array[" << i << "] = " << my_array[i] <<
" stored at address " <<( (unsigned long) &my_array[i]) << endl;

Using the &(address of) operator in front of the &my_array[i] returns the main memory address.
Casting to unsigned long will give the address as numbers, not hexadecimal

ARRAY BOUNDS
------------
C++ does not prevent the programmer from exceeding the boundaries of an array. This may
cause strange program behavior leading to incorrect results.
Max of 10 values using Arrays Example:

int my_array[10] ;

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


{
cout << "Enter an integer " ;
cin >> my_array[i];
}

int max = my_array[0];

for(int i = 1; i <= 9; i++)


if ( my_array[i] > max)
max = my_array[i];

cout << "Max is " << max << endl;

ARRAY INITIALIZATION
--------------------
int my_array[10] = {12, 234, 23, 1, -7, 55, 18, 67, 99, 100};
Gives: 12, 234, 23, 1, -7, 55, 18, 67, 99, 100

int array2[5] = {5};


Gives: 5, 0, 0, 0, 0

ARRAY INITIALIZATION WITHOUT SPECIFYING AN EXPLICIT ARRAY SIZE


--------------------------------------------------------------
int numbers[] = {0,1,2,3,4,5,6,7,8,9} ; //compiler sets size to # of elements (10)

char lower_case_vowels[] = {'a','e','i','o','u'} //compiler sets size to # of elements (5)

CHARACTER ARRAY STRING INITIALIZATION


-------------------------------------
C++ allows for an alternate initialization of character arrays which uses a character string
(enclosed in double quotes) to specify the individual initial values of the array elements. Ex:

char my_name[] = "Ted";

will create and initialize an array of FOUR elements:


my_name[0] = 'T'
my_name[1] = 'e'
my_name[2] = 'd'
my_name[3] = `\0` //the null character (indicates end of a string)
Can print in 2 ways:

char my_name[] = "Ted";

for(int i = 0; i <= 3; i++) // print out the array element by element


cout << my_name[i] ; // null character will cause nothing to be printed.

cout << endl;

cout << my_name << endl; // will print out all characters in the array up to null character

// four ways to initialize an array to the same values

char my_name1[] = "Ted";


char my_name2[4] = {'T','e','d','\0'};
char my_name3[] = {'T','e','d','\0'};
char my_name4[4] = "Ted";

// print out the array element by element

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


{cout << my_name1[i] ;} // null character will cause nothing to be printed.
cout << endl;

cout << my_name2 << endl ;

cout << &my_name1[0] << endl;

PASSING ARRAYS TO FUNCTIONS


----------------------------
void how_are_arrays_passed(int param[], int size_of_array)
{
for (int i = 0 ; i < size_of_array; i++)
param[i] = 0; // set all the elements to 0
}

int main(){
int array[5] = {100, 100, 100, 100, 100};

cout << "Before function : " << endl;

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


cout << "array[" << i << "] = " << array[i] << endl;
how_are_arrays_passed(array,5);

cout << "After function : " << endl;

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


cout << "array[" << i << "] = " << array[i] << endl;

This changes all values of 100 to 0 for every element of the array.

In C++ (and in good old C) ARRAYS ARE ALWAYS PASSED AS REFERENCE PARAMETERS.
NO & IS NEITHER NEEDED NOR EXPECTED IN THE ARRAY PARAMETER DEFINITION.

SEARCHING A NON-SORTED ARRAY (LINEAR SEARCH)


-----------------------------------------
Here is an implementation of the linear search in C++ to find a key value:

int main(){

int my_array[10] = {12, 234, 23, 1, -7, 55, 18, 67, 99, 100};

int key;
cout << "enter the key value to be searched for";
cin >> key;

int array_index; // define this outside the for loop since we want to know its value at the end

bool found = false;

for( array_index = 0 ; array_index <=9; array_index++)


{
if (my_array[array_index] == key)
{
found = true;
break;
}
}

if (found)
cout << "Key found in position " << array_index << " " << my_array[array_index] << endl;
else
cout << "Key is not in the array." << endl;
SORTING AN ARRAY LINEARLY
--------------------------
Arrays can also be sorted linearly (increasing/decreasing order)

void print_array(int some_array[], int size)


{
for(int i = 0 ; i < size ; i++)
cout << some_array[i] << endl;
}

int main(){

int unsorted_array[10] = {12, 234, 23, 1, -7, 55, 18, 67, 99, 100};

cout << "The unsorted array is: " << endl;


print_array(unsorted_array, 10);

int sorted_array[10];

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


{
int smallest = unsorted_array[i];
for(int j = i+1 ; j <10; j++)
{
if (unsorted_array[j] < smallest)
{
smallest = unsorted_array[j]; // found a new smallest value in array
int temp = unsorted_array[i]; // now swap the two array elements
unsorted_array[j] = temp;
unsorted_array[i] = smallest;
}
}
}

cout << "The sorted array is: " << endl;

print_array(unsorted_array, 10);

New and Improved sorting program


----------------------------------
void print_array(int some_array[], int size)
{
for(int i = 0 ; i < size ; i++)
cout << some_array[i] << endl; }
void swap_elements(int some_array[], int first, int second) //function swaps 2 elements of array
{
int temp;
temp = some_array[second];
some_array[second] = some_array[first];
some_array[first] = temp;
}

int main(){

int unsorted_array[10] = {12, 234, 23, 1, -7, 55, 18, 67, 99, 100};

cout << "The unsorted array is: " << endl;


print_array(unsorted_array, 10);

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


{
for(int j = i+1 ; j <10; j++)
{
if (unsorted_array[j] < unsorted_array[i])
{
swap_elements(unsorted_array, i,j); // can also do swap_elements(unsorted_array, j , i)
}
}
}

cout << "The sorted array is: " << endl;

print_array(unsorted_array, 10);

NOTES 6a
How arrays are passed by reference to a function (change values from 0 to 5)

void some_function(int some_array[], int stop_at )


{
for(int index = 0 ; index <= stop_at ; index++)
{
some_array[index] = 5;
}

cout << "The array which I received as an arg is" ;


cout << "stored in main memory at address: " << some_array << endl;
}
int main(){

int an_array[5] = {0,0,0,0,0};

cout << "Array stored starting at address: " ;


cout << &an_array[0] << endl; //print starting address (address of function)

// IMPORTANT: the NAME OF AN ARRAY IS SYNONYMOUS WITH THE STARTING


//ADDRESS OF THE FIRST ELEMENT OF THE ARRAY SO WE CAN SIMPLY DO :

cout << "The name of an array is the same as the starting address" << endl;
cout << "of the first element: " << an_array << endl; //prints starting address

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


{
cout << an_array[i] << “, “;
}

some_function(an_array , 2);

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


{
cout << an_array[i] << “, “;
}

Here is the output of the program:


Array stored starting at address: 0x7ffe5c2de210
The name of an array is the same as the starting address of the first element: 0x7ffe5c2de210
0, 0, 0, 0, 0
The array which I received as an arg is stored in main memory at address: 0x7ffe5c2de210
5, 5, 5, 0, 0 // only elements 0, 1, 2 are changed, because 2 was set as int stop_at

The some_array[index] expression is translated into a address in main memory using the
following "1 dimensional array address translation formula" :

some_array[index] = starting address + (index * sizeof(int) )

= value stored in argument some_array + (index * 4 ) //this 4 is size of


//data type in bytes
NOTES 6b
Swapping array elements Example:
//we compare a[i] with a[j] and swap the two array elements if a[j] < a[i]

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


{
for (int j = ( i + 1 ) ; j < 5 ; j++)
{
if ( a[j] < a[ i ] )
{
int temp = a[i];
a[i] = a[j] ;
a[j] = temp;
}
}
}

NOTES 7a
Print out 2D array Example:
for (int row = 0 ; ( row < 4 ) ; row++)
{
for(int col = 0 ; col < 3 ; col++)
{
cout << a[ ] [ ] << " " ;
}
cout << endl; // print out a new line for the next row
// and continue with the row outer loop
}

Storing 2D array
Each "box" of the array is 4 bytes in size since each element is an int.

There is a 2d array address translation formula the compiler uses when it encounters array
notation in the program code:
a[i][j] = a + [ ( (i * (# of cols ) + j ) * sizeof(int) ] // the # of cols is the only # that must be provided

the compiler translates a[1][2] into an address which contains the first byte of the integer
element stored in position a[1][2] of an array with 3 columns:
a + [ ( ( 1 * 3) + 2 ) * 4 ]
= 1000 + [ ( 3 + 2 ) * 4 ]
= 1000 + [ 5 * 4 ]
= 1020
NOTES 8
POINTERS
-------
C++ has a data type called a POINTER data type. The * symbol is used to define a pointer
data type. For example, suppose we have an integer variable called x, we would declare
it as follows:

int x ;

To declare a pointer to an integer would use:


int* some_pointer;

Pointer declarations are best understood if we 'read' them backwards as in:


"some_pointer is a pointer to an integer"

Pointers to other data types are declared in a similar fashion.

A variable which is declared to be a pointer simply holds the ADDRESS of some object.
Once we have declared a pointer, we can give it a value by using the address-of
(&) operator as in:

int x = 13;
int* some_pointer;

some_pointer = &x; // assign the address where x is stored to the pointer variable

Suppose memory location with address 1000 is used to store the integer variable x and memory
location with address 2000 is used to store the pointer variable some_pointer. This looks like:

contents address
----------
x 13 1000
----------
----------
----------
some_pointer 1000 2000
----------

We can change the value stored in this x variable by using the pointer dereferencing operator (*)

*some_pointer = 5 ;

This statement means "go to the memory location at address 1000 and store the value 5 in this
location". The situation in memory now looks like:
contents address
----------
x 5 1000
----------
----------
----------
some_pointer 1000 2000
----------

int main(){
int mick = 4 ; // declare an integer variable called mick and assign it value 4
int keith_richards = 23 ; // declare an int called keith_richards initialized to 23

int* mick_ptr = &mick; // now declare some pointers (mick_ptr is a pointer to address of mick)
int* keith_ptr = & keith_richards; // C++ doesn't care if you put a space between & and variable

cout << &keith_richards << endl;

// print out the addresses of the 2 variables and print out the values of their pointers
// the pointers will contain the addresses of the respective variables

cout << "Variable mick stored in location " << &mick


<< " Value stored in mick_ptr = " << mick_ptr << endl;

cout << "Variable keith_richards stored in location " << &keith_richards


<< " Value stored in keith_ptr = " << keith_ptr << endl;

*mick_ptr = 345; //now change the values stored in the 4 variables using pointer dereferencing
*keith_ptr = 222;

cout << "mick = " << *mick_ptr << endl;// print out the new values using pointer dereferencing
cout << "keith_richards = " << *keith_ptr << endl;

The program output is:

0xffbeea20
Variable mick stored in location 0xffbeea24 Value stored in mick_ptr = 0xffbeea24
Variable keith_richards stored in location 0xffbeea20 Value stored in keith_ptr = 0xffbeea20
mick = 345
keith_richards = 222
Some Dos and Don'ts for Pointers
-------------------------------
1) incorrect assignment of pointers

an int* may only receive the address of some int variable


a char* may only receive the address of some char variable
etc.

2) Attempting to dereference a non-initialized pointer

Attempting to dereference a non-initialized pointer variable will give undefined and unpredictable
results. Merely declaring a pointer variable does not give it an initial value.

SO ALWAYS REMEMBER TO GIVE AN ADDRESS TO A POINTER VARIABLE USING THE


ADDRESS OF OPERATOR (&) APPLIED TO SOME PREVIOUSLY DECLARED VARIABLE.

VOID POINTERS
-------------
C++ allows the programmer to declare a VOID POINTER. A VOID POINTER may be assigned
the address of any type. For example;

void* pointer_to_anything ;
int an_integer;

the following assignments of addresses to void pointers are legal:

pointer_to_anything = &an_integer;

Although void pointers may be assigned the address of any data type, VOID POINTERS MAY
NOT BE DEREFERENCED DIRECTLY!!!!!!!!!!!!!!!!!

The reason why it is forbidden to dereference a void pointer directly is that the compiler has no
information as to what the void pointer is pointing to.

Void pointers may be dereferenced PROVIDED THEY ARE CAST TO A POINTER OF THE
APPROPRIATE DATA TYPE BY USING THE CAST OPERATOR. Ex:

int an_integer = 5 ;
void* pointer_to_anything = &an_integer ;
cout << an_integer << endl; // this will cout 5
* (int*)pointer_to_anything = 67; // cast this pointer to an integer pointer
cout << an_integer << endl; // this will cout 67
POINTERS AND ARRAY NAMES
------------------------
In C++, the name of an array is the same as the starting address of the first element in the array.
We can use this fact to traverse the array using pointer notation :

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

int * ptr;

ptr = &array[0]; // same as doing ptr = array

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


{
cout << (*ptr) << ptr << endl;
ptr = ptr + 1;
}

The program output is:


0 0xffbeea00
1 0xffbeea04
2 0xffbeea08

POINTER ARITHMETIC
-----------------
The above program illustrates the concept of what is referred to as POINTER ARITHMETIC in
C++. If we have an integer pointer (ptr), and we perform the assignment:

ptr = ptr + 1 ;

The actual value of ptr will be incremented by 4 (because it is pointing to an int) and not by 1.

When we write down something like: pointer_variable = pointer_variable + 1, the compiler really
translates this to:
pointer_variable = pointer_variable + (1*sizeof(thing that pointer_variable is pointing to)

This means that it is incorrect to add "1" to a void pointer since the compiler has no way of
determining how much to add to the void pointer since it does not know what it’s pointing to:

IT IS IMPORTANT TO NOTE THAT WE CANNOT DO SOMETHING LIKE array = array + 1 !!!!!


IN C++, the name of an array is treated as a constant address; once the compiler has allocated
memory to hold an array, this starting address cannot be changed!!!
CONSTANT POINTERS
-----------------
C++ allows for the declaration of constant pointers. A constant pointer must be assigned an
address when it is declared, and once it has been assigned this address it cannot be
subsequently changed to another address:

int x;
int* const ptr = &x;

4 3 2 1 // to be read as: 1: ptr is a, 2: constant, 3: pointer, 4: to an integer

It would be an error to attempt to assign the value of ptr after


its declaration:

int x;
int* const ptr;
ptr = &x ; // wrong...

It would also be an error to attempt to reassign the value of th constant pointer:

int x;
int y;
int* const ptr = &x; // this is ok

ptr = &y ; // INCORRECT !! assignment of read-only variable `ptr'

REFERENCES AND CONSTANT POINTERS


--------------------------------
The C++ compiler treats reference variables as CONSTANT POINTERS. The compiler performs
the dereferencing of these constant pointers for you automatically. For example:

int some_int;
int& some_reference = &some_int;

some_int = 5 ;
cout << some_int << endl ; // produces 5 as output

some_reference = 10;
cout << some_int << endl; // produces 10 as output

The compiler actually produces run -time code equivalent to the following:

int some_int;
int* const some_reference = &some_int
some_int = 5 ;
cout << some_int << endl ; // produces 5 as output

*some_reference = 10; // compiler does the dereferencing of reference variables


// for you automatically
cout << some_int << endl; // produces 10 as output

Consider the following declaration:

const int i = 5;
int* ptr;
ptr = &i;

ptr is a pointer to an integer constant. The compiler allows the integer to be read (directly and
indirectly through the pointer) but any attempt to dereference (change the value of) the pointer
ptr yields a compile time error stating "assignment of read-only location".

The address of a non-constant variable may be assigned to a pointer to a constant,


but the compiler will still not allow you to dereference the pointer:

int i = 5;
int const * ptr;
ptr = &i; // assign the address of a non-constant integer i to a pointer
// which points to an integer constant

Constant Pointers to Constant Data


----------------------------------
This is the most restrictive, neither the value of the pointer, nor the contents that it is pointing to
can be changed. A declaration of a constant pointer which points to an integer constant is:

const int x = 5;
const int * const y = &x ;

A generic Print_Matrix function which uses pointers


---------------------------------------------------
We are now in a position to write a generic Print_Matrix function which is capable of printing out
any sized two-dimensional array. It makes use of the address translation mechanism, pointer
arithmetic, and void pointers:
void Print_Matrix(void* a , int rows, int columns, char data_type)
{
for(int i = 0 ; i < rows ; i++)
for(int j =0 ; j < columns ; j++)
{
switch (data_type)
{
case 'i' : cout << *( (int *)a + (i * columns) + j) << " " ;
break;
case 'c' : cout << *( (char *)a + (i * columns) + j) << " " ;
break;
case 'f' : cout << *( (float *)a + (i * columns) + j) << " " ;
break;
default : cout << "Invalid data type" << endl;
return;
}

if ( j == columns - 1)
cout << endl;
}
cout << endl;
}

int main(){
int big_matrix[5][5] = { 10, 11, 12, 13, 14,
16, 17, 18, 19, 20,
22, 23, 24, 25, 26,
28, 29, 30, 31, 32,
34, 35, 36, 37, 38 };

cout << "The big_matrix is : " << endl;


Print_Matrix(&big_matrix[0][0], 5, 5, 'i');

return 0; }

The program output is: The big_matrix is : 10 11 12 13 14


16 17 18 19 20
22 23 24 25 26
28 29 30 31 32
34 35 36 37 38
STRINGS AND CHARACTER ARRAYS
---------------------------
There is a subtle difference between the two following declarations:

char * s = "ABC";

and

char s1[4] = {'A', 'B', 'C', '\0' );

The first creates a pointer to a character which is assigned the address of a CHARACTER
STRING LITERAL CONSTANT stored in a portion of memory which may only be read from
(the CHARACTER STRING LITERAL CONSTANT is terminated by the '\0' character).
*s = ‘Z’ will cause run-time error

The second declares and initializes a 4 element array of characters. The last element in the
array is the null character '\0'. The elements of the array s1 may both be read from and
written to at will.
*s = ‘Z’ will give ZBC

A string reverse function


------------------------
Here is a nice function which joins two character arrays but the second array is copied
BACKWARDS. It makes use of pointers.

// Author: Ted Obuchowicz


// March. 13, 2002
// example program illustrating use of

#include <iostream>
#include <string>

using namespace std;

void reverse_string(char s1[], char s2[])


{
// find the end of the first string designated by the '/0' character

int string1_end = 0;
for( ; s1[string1_end] != '\0' ; string1_end++);

// the above for loop is a sneaky way of writing


// for( ; s1[string1_end] != '\0' ; string1_end++)
// { }
// the ; in the original for loop terminates the statement consisting of the for loop with no body...

int string2_end = 0;
for( ; s2[string2_end] != '\0' ; string2_end++);

string2_end--;

int i;
for( i = string2_end ; i >= 0; i--)
s1[ string1_end++] = s2[i];

string1_end++;
s1[string1_end] = '\0'; // now add the '\0' character to s1
}

int main(){

char string1[50] = "Keith";


char string2[50] = "Richards";

cout << string1 << endl;


cout << string2 << endl;

reverse_string(string1, string2);

cout << string1 << endl;

return 0;
}

ARRAY OF POINTERS
----------------
C++ lets a programmer declare and use an array of pointers:

int main(){
char* rolling_stones[4] ; // declare an array of 4 character pointers

// initialize the 4 pointers to chars to some string literal constants. note, we may only READ
these string constants and cannot write to them..
rolling_stones[0] = "Keith";
rolling_stones[1] = "Mick";
rolling_stones[2] = "Charlie";
rolling_stones[3] = "Ron"; // this will set the values of the 4 pointers to point to the starting
// address of the 4 strings

// rolling_stones[0] -------> |'K'|'e'|'i'|'t'|'h'|'\0'|


--------------------------
// rolling_stones[1] -------> |'M'|'i'|'c'|'k'|'\0'|
----------------------
// rolling_stones[2] -------> |'C'|'h'|'a'|'r'|'l'|'i'|'e'|'\0'|
---------------------------------
// rolling_stones[3] -------> |'R'|'o'|'n'|'\0'|

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


cout << rolling_stones[i] << endl; // print out the strings
return 0; }

The line: char* rolling_stones[4] ; declares the variable named rolling_stones to be a 4 element
array of pointers to characters (i.e. each element of the array is a pointer to a character)

the lines: rolling_stones[0] = "Keith"; rolling_stones[1] = "Mick"; rolling_stones[2] = "Charlie";


rolling_stones[3] = "Ron";

initializes the 4 pointers to characters stored in the elements of the array rolling_stones to 4
different string literal constants (which may only be READ FROM ).

The 4 strings may be printed out by using the loop:

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


cout << rolling_stones[i] << endl;

DYNAMIC MEMORY ALLOCATION WITH NEW AND DELETE


---------------------------------------------
C++ has another method of assigning a value to a pointer variable.This method makes use of
the new operator to DYNAMICALLY ALLOCATE MEMORY.

Here is a simple program which dynamically allocates enough room for an integer:

int* integer_pointer ;

integer_pointer = new int; // request enough memory from the heap to hold an integer, if the
// request is successful, new returns the address,if there is no more
// memory, new returns the value 0.
// the bits in the dynamically allocated memory are random 1's and 0s..

// the following will print out some garbage number since we did not initialize the allocated
// memory with any value

cout << *integer_pointer << endl;


// before assigning a value to this dynamically and newly allocated
// memory space, we should check that the call to new was successful

if ( integer_pointer != 0 )
*integer_pointer = 10 ; // assign the value 10 to this memory location

cout << "Address of newly allocated memory = " << integer_pointer << endl;
cout << "value stored at this address = " << *integer_pointer << endl;

// once a program no longer needs the memory which it has asked for at run time, it should
//return it back to the heap. This is performed with the delete operator

delete integer_pointer ; // this returns the 4 bytes of memory which integer_pointer pointed to
// and was used to store the value of 10 in note that the pointer itself still
// exists and can be assigned another address (though a second call to
// new for example).
The program output is:
261944
Address of newly allocated memory = 0x3ff30
value stored at this address = 10

There is a variation of the new operator which initializes the memory allocated from the heap
with some user-specified value. Ex: same code but integer_pointer = new int (55)

Rather than space to hold a single variable, new may be asked to dynamically allocate a
contiguous sequence of memory locations (i.e. an array) this is done with:

new <data_type> [size]

Here is a program which dynamically allocates an array of integers. The size of the array is
specified by the user as input at run-time:

int size;

int* pointer ; // this pointer will be set to the starting address of an array of integers. This array
// will be dynamically allocated at run time through a call to the new operator we will
// pass the requested size as to new
cout << "enter the size of the array you wish to create" << endl;
cin >> size;

pointer = new int [size] ; // request space to hold size integers and assign
// starting address of this space to pointer

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


{
*(pointer + i) = i; // assign some values to these integers
// same as doing pointer[i] = i;
// note: can only do this for 1 d arrays.. will not work for two dynamic arrays
}
for(int i = 0 ; i < size ; i++)
{
cout << *pointer << " " << pointer << endl; // now print out the array
pointer++;
}

cout << pointer << endl;

pointer = pointer -size ; // set pointer back to start of array

cout << pointer << endl;

delete [] pointer; // once we're done with the memory, give it back

The program output is:


enter the size of the array you wish to create
4
0 0x40018
1 0x4001c
2 0x40020
3 0x40024
0x40028
0x40018
A variation of the above program is to use new to dynamically allocate a two-dimensional array.
The program uses the address translation mechanism discussed earlier:

int rows;
int cols;

int* pointer ; // this pointer will be set to the starting address of an array of integers. This array
// will be dynamically allocated at run time through a call to the new operator we will
// pass the requested size as to new

int* pointer_backup ;

cout << "enter the number of rows of the array you wish to create" << endl;
cin >> rows;

cout << "enter the number of cols of the array you wish to create" << endl;
cin >> cols;

pointer = new int [rows*cols] ; // request space to hold a 2-d array rows x cols

pointer_backup = pointer;

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


for(int j = 0; j < cols; j++)
{
*(pointer + (i*cols + j)) = i+j; // assign some values to these integers
}

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


for(int j = 0; j < cols; j++)
{
cout << *(pointer + (i*cols + j)) << " " ; // now print out the array
if (j == cols - 1 )
cout << endl;
}

delete [] pointer_backup; // once we're done with the memory, give it back

Note that in the above example, we had no choice but to use the 2-address translation formula
together with the pointer dereference to pretend that the dynamically allocated 1-d array
consisting of enough contiguous bytes from the heap to store row*col number of integers is
organized as a 2d array of 'rows' rows and 'cols' columns: *(pointer + (i*cols + j))
if we want to treat the dynamically allocated array as 'cols' number of rows by 'rows' number of
columns we would have used the formula:

*(pointer + (i*rows + j))

unlike the 1-d dynamic array, we do NOT have the option of using good old array square bracket
notation such as:

pointer[i][j] = some_value ; // will result in compile time error

since the compiler does not know what value to "put in the box" when it converts the pointer[i][j]
notation into an address :
---
pointer + ( i* |? | + j)
---
Should the compiler put the number 'rows' in the box? Or should it put the number 'cols' in the
box ??? . It can't determine what to put in the box , so it gives a compile time error.

NOTES 11
FILE INPUT AND OUTPUT
--------------------
The C++ library <fstream> contains definitions of three STREAM class types:

ifstream - this class is used to create streams which are used to input values from
ofstream - this class is used to create streams which are used for output
fstream - used to create streams capable of both input and output

We will study the ifstream and ofstream classes only.

Here is a simple program which creates an input file and an output file and simply reads
integers from the input file and writes them to the output file:

#include <fstream> // fstream library defines stream classes ifstream


// ofstream and fstream
int main()
{

ifstream infile("myinput.dat"); // associate the file myinput.dat with infile object of class ifstream

ofstream outfile("myoutput.dat"); //associate file myoutput.dat w/ outfile object of class ofstream

int number;
while ( infile >> number ) // a simple while loop which reads numbers from the infile and writes
// them to the outfile object. Loop will terminate when the end of the
// infile object is reached
outfile << number << endl;

When this program is executed, the input will be taken from a disk file called myinput.dat, the
output will be written to a disk file called myoutput.dat.

For example, the contents of the disk file myinput.dat are: 1, 2, 3, 4, 5

After running the program, the file myoutput.dat will contain: 1, 2, 3, 4, 5

The following example shows a variation of the method used to associate a file name with an
object of type class ifstream or ofstream:

#include <fstream>
using namespace std;
int main() {

ifstream infile; // create an object called infile of type ifstream

ofstream outfile; // create an object called ofstream of type ofstream

infile.open("myinput.dat"); // associate the diskfile called myinput.dat with object infile

outfile.open("myoutput.dat"); // associate the diskfile called myoutput.dat with object outfile

int number;

while ( infile >> number )


outfile << number << endl;

File modes
----------
The default mode for output to a stream object is to OVERWRITE the file every time the
program is invoked. If we wish to ADD to the end of the existing output file, then the file must be
opened in a slightly different fashion with an extra parameter:

ofstream outfile("myoutput.dat", (ios_base::out | ios_base::app));


-----------------------------
This expression specifies that the file "myoutput.dat" is to be opened for output
and that any writing to the file is to be ADDED to the current end of the file.

g++ compiler doesn’t support the ios_base::out | ios_base::app


Opening and closing files
-------------------------
Let us see some examples of closing files. Objects of type ifstream or ofstream also have the
member function close() - this is typically used to break a current association of a physical file
with a file stream object. The program can then make a new association between a new disk file
and the given stream object.

The following program reads from two different disk files and write the output to different disk
files using only two file stream objects : infile and outfile:

#include <fstream>
using namespace std;

int main() {

ifstream infile;

ofstream outfile;

infile.open("input1.dat") ;
outfile.open("output1.dat");

int number;

while ( infile >> number )


outfile << number << endl;

infile.close(); // close the files and associate the file streams infile and outfile with new disk files
outfile.close();

infile.open("input2.dat") ;
outfile.open("output2.dat");

while ( infile >> number )


outfile << number << endl;

infile.close(); // "input2.dat" will be closed (this is good practice, but not necessary)
outfile.close(); // "output2.dat" will be closed

Binary files
------------
Consider the following program:

#include <fstream>
using namespace std;
int main() {

ifstream infile("myinput_float.dat"); // associate the file myinput.dat with infile


// object of class ifstream

ofstream outfile("myoutput_float.dat"); // associate the file myoutput.dat with the


// outfile object of class ofstream

float number;

while ( infile >> number )


outfile << number << endl;
return 0; }

If the contents of the input disk file "myinput_float.dat" are:

1.234567899999999
2.222222229999999
3.333333333333333
4.444444443333333
5.555555553333333
6.666666663333333
7.777777773333333
8.888888883333333
9.999999999999999

What do you think the output file will contain??? The answer may surprise you:

1.23457
2.22222
3.33333
4.44444
5.55556
6.66667
7.77778
8.88889
10

We can note that only 5 digits of precision are used when writing to the output. If we want more
digits after the decimal place, we have to explicitly tell the << operator by making use of
MANIPULATORS contained in the <iomanip> header file:
#include <fstream>
#include <iomanip> // needed for the setprecision manipulator
using namespace std;

int main() {

ifstream infile("myinput_float.dat");

ofstream outfile("myoutput_float_precision.dat");

double number;

outfile << setprecision(16); // print floats with 16 decimal place precision

while ( infile >> number )


outfile << number << endl;
return 0; }

Now, the contents of the two files are identical:

ted@brownsugar Programs 8:17pm >more myinput_float.dat


1.234567899999999
2.222222229999999
3.333333333333333
4.444444443333333
etc.

Note, that both of these files are ASCII text files, and note the file sizes (in number of bytes of
disk storage that they occupy):

ted@brownsugar Programs 8:17pm >ls -al myinput_float.dat myoutput_float_precision.dat


-rw------- 1 ted ted 162 Mar 26 20:09 myinput_float.dat
-rw------- 1 ted ted 162 Mar 26 20:15 myoutput_float_precision.dat
|
|--------> each file occupies 162 bytes, 17 characters per number, newline
character at end of every line and 1 end of file character at the end
= (9 x 18) = 162

Instead of using 1 ASCII character (which equals 1 byte of disk storage) to represent every digit
of the number, the number can be stored in its binary floating point representation (using the
IEEE 754 floating point format which uses 4 bytes for a float and 8 bytes for a double) to
represent each number. To specify that we want to use BINARY representation instead of ASCII
text, we must open the file and specify ios::binary and we must also use an explicit function
called write() to perform the output instead of the outfile << number as in the earlier example.

#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;

int main() {

ifstream infile("myinput_float.dat");

ofstream outfile("myoutput_float_precision_binary_write.dat", ios::binary | ios::out);;

double number;

outfile << setprecision(16);

while ( infile >> number )


outfile.write((char *) &number, sizeof(double));
return 0; }

Let us examine the details of the :

outfile.write((char *) &number, sizeof(double))

We are invoking a method called 'write' belonging to the object outfile which is of type ofstream.
This method has 2 arguments:

a pointer to character ( actually a pointer to a character constant), an integer specifying the


number of bytes to write.

We can make use of the sizeof(double) operator to specify the second argument.

When we run this program, a binary file with filename


"myoutput_float_precision_binary_write.dat" will be created and it will contain the 9 numbers
stored in binary format (each number is presented in 8 bytes of binary information) :

Binary files have the advantage of being small in size , so that large amounts of information may
be stored in disk files which do not occupy much room on your hard drive.

The next example, opens the binary file created earlier for input and simply reads
in every number and displays it on the screen. It makes use of the read() method.
#include <iostream>
#include <fstream>
#include <iomanip> // needed for the setprecision manipulator
using namespace std;

int main() {

ifstream infile("myoutput_float_precision_binary_write.dat", ios::binary | ios::in);


// associate the file myinput.dat with infile object of class ifstream

double number;

cout << setprecision(16);

infile.read((char *) &number, sizeof(double)); //read in a double from input file into var number

// infile.eof() will return true if reached the end of the file otherwise it will return false, so check //
it’s at end of file, and if not , then output the number and read the next number and check //
again if it’s at the end of file

while ( !infile.eof() ) // check to see that not end of file of infile


{
cout << number << endl; // print out the number to the monitor
infile.read((char *) &number, sizeof(double)); // read in number from file
}
return 0; }

The read method expects two arguments : a pointer to a char and an integer specifying the
number of bytes to read.

When we run this program, the following output is produced:


1.234567899999999
2.222222229999999
3.333333333333333
4.444444443333333
5.555555553333333
6.666666663333333
7.777777773333333
8.888888883333333
7.099499599999592

IMPORTANT: If a program is reading or writing binary files, it is very important that the file be
created on the same type of computer (operating system) as the program which reads the file
was compiled. Errors will occur otherwise.

You might also like