MIAE 215 Entire Course Package
MIAE 215 Entire Course Package
I long format
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
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
gt
if
I const set constatuame to a
a
variable cannot change later
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
Is view directory
ed leave folder
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
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
True stuff I
Faisestuff
I
ftp.fednateexpression
n
Traetstuff
1
y
Nextstatement
else
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
Loops
next statement
Flow Chart
counter 0
no counterciooo F
se T
contackeithccendl
countertt
Next
pwd s tells which directory I'm in
cin u
Efisatiienal
countertt a placement doesn'tmatter
next statement
FORLoop
at sumo
nt v var onlyaccessiblewithinloop
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
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
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
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
g
uv u v u w u
DoDI
digitalports
ÉfM
function will do
pinMode port mark as input or output marks what pin
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
float a
Switch
int ai
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
g if 1 10 0
coutccendl
Do while
int ai
do
coat cc enter a pos number Lendl
Cin a
while a o
For loop
int i
for i s it 8 i tt
cont cc ice ends
iii iii
Ask user how many numbers to generate
if count I 2 largest
largest counts
if count 22 largest
largest count 2
coutee ccend
E axis
User defined functions
argest Max A B A 5 B to
largest Max C D
largest Max E F
t t
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
return 0
int my functionCinta int b
return at bi
int main I
int xyi
int output
contact
g void printmessage
couth hi
intr
int maine
Eiti
g
nt maine gy tellscompiler all
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
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
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
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
Cin x r cc
7Tumnsneeded
Void print matrix int argc 5
for intro remick tt
coutccargerscc
Couteeends
Arrays
int myNum 33 10 20 30
Volvo
cout Lc cars o
Volvo
Ferrari
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
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
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
1000
ptr outa canal
Ptr x 10
10 1002 out c ptracendl
ptr 1000
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
Up byte Ii p
emp char up
char up char up 1 i
char up ti temp
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 r col c 42
0 83 OXFE
int var 1 3
0057 FER
ptr 1
5
0057FE C Coutee ptrzcendl
route varccendli
5
I
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
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
cin
Fa bad coat In
Ciostream
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
infileopen IN 2 dat
badversion outfileopenOUT2 dat
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
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:
/*
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.
CONSTANTS
---------
In general, the method C++ uses for constants is:
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(){
keith = 5;
cout << keith << " " << good_guitar_player << endl;
good_guitar_player = 7;
return 0;
}
The program output is: 5 5
77
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.
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:
int day;
day = Mon;
if ( day == Sat)
cout << "Yahooo it is the weekend time for windsurfing" << endl;
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_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 };
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;
};
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;
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.
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:
struct a_simple_struct
{
int a_number;
char a_letter;
bool a_boolean;
};
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;}
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 )
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.
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;
cout << setprecision(15) << "number is equal to " << number << endl;
return 0;
}
The IF STATEMENT
---------------
Form 1: if (expression)
{ statement;
}
Form 2: if (expression)
{ statement;
}
Else
{
another statement;
}
CAVEAT
-------
ALWAYS USE == FOR COMPARISON IN IF STATEMENTS!!!!!
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;
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;
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;
}
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(){
char a_letter;
int how_many_ts = 0;
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;
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;
ones = number;
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".
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)
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>
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:
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.
EVERY time that we run the above program it will produce the values:
16838
5758
10113
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:
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
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)
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:
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
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()
{
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();
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.
where:
base_type_of_elements: the type of each array element like char, int, float, double, struct, etc...
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.
int my_array[10] = {12, 234, 23, 1, -7, 55, 18, 67, 99, 100};
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] ;
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
cout << my_name << endl; // will print out all characters in the array up to null character
int main(){
int array[5] = {100, 100, 100, 100, 100};
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.
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
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)
int main(){
int unsorted_array[10] = {12, 234, 23, 1, -7, 55, 18, 67, 99, 100};
int sorted_array[10];
print_array(unsorted_array, 10);
int main(){
int unsorted_array[10] = {12, 234, 23, 1, -7, 55, 18, 67, 99, 100};
print_array(unsorted_array, 10);
NOTES 6a
How arrays are passed by reference to a function (change values from 0 to 5)
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
some_function(an_array , 2);
The some_array[index] expression is translated into a address in main memory using the
following "1 dimensional array address translation formula" :
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 ;
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
// 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
*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;
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
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.
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;
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 * ptr;
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:
int x;
int* const ptr = &x;
int x;
int* const ptr;
ptr = &x ; // wrong...
int x;
int y;
int* const ptr = &x; // this is ok
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
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".
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
const int x = 5;
const int * const y = &x ;
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 };
return 0; }
char * s = "ABC";
and
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
#include <iostream>
#include <string>
int string1_end = 0;
for( ; s1[string1_end] != '\0' ; string1_end++);
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(){
reverse_string(string1, string2);
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
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)
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 ).
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
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:
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
delete [] pointer; // once we're done with the memory, give it back
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;
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:
unlike the 1-d dynamic array, we do NOT have the option of using good old array square bracket
notation such as:
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
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:
ifstream infile("myinput.dat"); // associate the file myinput.dat with infile object of class ifstream
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.
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() {
int number;
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:
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;
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");
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() {
float number;
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;
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):
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");
double number;
We are invoking a method called 'write' belonging to the object outfile which is of type ofstream.
This method has 2 arguments:
We can make use of the sizeof(double) operator to specify the second argument.
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() {
double number;
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
The read method expects two arguments : a pointer to a char and an integer specifying the
number of bytes to read.
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.