Pointers to Structures

wackybabiesΛογισμικό & κατασκευή λογ/κού

14 Δεκ 2013 (πριν από 3 χρόνια και 6 μήνες)

63 εμφανίσεις

Data
Types and
Structures




C++ provides large collection of data types and structures








Fundamental data types, arrays, structs, and unions are provided both
in C and C++. But, other structured data types are available only in
C++.



ARRAYS



Are c
ollect
ion of data elements



Such that a
ll of

elements are

same type



Each
element is
accessed by specifying position



Static array



Compiler determines how memory allocated



Dynamic array



Allocation takes place at run time




One
-
dimensional Arrays



Syntax:


ElementTy
pe


arrayName [CAPACITY];


ElementType

a
rrayName [CAPACITY] =
{ initializer_list };



Example:




int b [10];





int a[]={1,2,10,30, 5};



Elements accessed by



name and [ ] operation


For example, cout << b[5];

yi
elds 55





Elements of an array may be of any type



Including characters



Example:



char name [NAME_CAPACITY] =
"John Doe";












Extra locations are
filled with null
characters are added !

Note
: NOT Always



We have s
aid elements accessed
by name and [ ] numList[5]



Consider the [ ] to be an operator



The subscript operator



Performs address
translation



Name of the array is a pointer
constant



The base address




























Note use of arrays as parameters



Must specify number of elem
ents of array being used

Accessing Array for Output

void display(int theArray[], int numValues)


/*
-
----
-------------------
---------------------------------


Display values in an array of integers.


Precondition: 0 <= numValues < capacity of theArray.


Postcondition: The first numValues integers stored in
theArray have been output to cout.

-
-----------------------------------
---------------------
*/

{


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




cout « theArray[
i] « “ “ ;


cout « endl;

}


Array Input Function


#include <cassert>


void read(IntArray theArray, int capacity, int numValues)


/*
----------------------------------
----------------------------------

Input values into an array of integers from the keyboard.


Preconditions: 0 <= numValues < capacity, which is the capacity of
theArray.

Postcondition: numValues integers entered from the keyboard


have been stored in
the first NumValues positions of theArray


---------------------------------------------------------------------
/*

{


assert (numValues >= 0 && numValues <= capacity);



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


cin » theArray[i] ;

}




Out of Range Errors



Most C++ compilers do not by default check indices for out of range



Results of out of range array access



Program can exceed allowed memory area



Program can give puzzling results



































*
-------------------------------
----------------------
--------



Demonstration of what can happen when array indices get out of bounds.


Input: Three arrays of integers


Output: The three arrays before and after modification using


out
-
of
-
range indices.


-------------------------------------------
-----------------
*/

#include <iostream>

using namespace std;


const int CAPACITY = 4;

typedef int IntArray[CAPACITY];


void read(IntArray theArray, int capacity, int numValues);

void display(IntArray theArray, int numValues);


int main(){


IntArray a, b,

c;




cout << "Enter " << CAPACITY << " integer values for:
\
n";


cout << "Array a: ";


read(a, CAPACITY, CAPACITY);


cout << "Array b: ";


read(b, CAPACITY, CAPACITY);


cout << "Array b: ";


read(c, CAPACITY, CAPACITY);



cout << "
\
n
----
--

Part I of the demonstration
-----
\
n
\
n"


"The arrays are:
\
n";


cout << "a: ";


display(a, CAPACITY);


cout << "b: ";


display(b, CAPACITY);


cout << "c: ";


display(c, CAPACITY);



//
---

Now change array elements in b, but using



//
---

some out
-
of
-
range indices.


int below =
-
3,


above = 6;


b[below] =
-
999;


b[above] = 999;


cout << "
\
n
------

Part II of the demonstration
-----
\
n
\
n"


"The arrays after out
-
of
-
range errors are:
\
n";


cout << "a: ";


displ
ay(a, CAPACITY);



cout << "b: ";


display(b, CAPACITY);


cout << "c: ";


display(c, CAPACITY);


cout << endl;


return 0
;

}





Problems with C
-
style Arrays



Capacity cannot change.



An array is not an object



(in the OOP sense)



Virtu
ally no predefined
operations
for

non
-
char arrays.



The Deeper Problem:




C
-
style arrays aren't self
-
contained




Data, functions, and size not encaps
ulated


Multidimensional Arrays



Consider a table of test scores for several different students






Two
-
dimensional array




Syntax:

ElementType arrayName [numRows][numCols]
;



Three Dimensional





Consider multiple pages of the student grade book



const int NUM_ROWS =

10, NUM_COLS = 5,

NU
M_RANKS = 10;

typedef double
ThreeDimArray[NUM_ROWS][NUM_COLS][NUM_RANKS]
;












Memory Allocation







Passing arrays in functions




One dimensional arrays;



void display( int table[], int N
);




Example: Is the following valid?



void display( int table[][], int rows, int cols );




You must fill the constant number of the column:



void display( int table[][COLS], int rows, int cols );




What about
3
-
D?



void display( int table[][COLS]
[RANKS]
, int
rows, int cols
, ranks

);



Dynamic Arrays


Recall:



What is a pointer variable? How to use it?



After declaring a pointer variable, assign an

address to it, how?



int i = 2;



int * p;



p = & i;



//
Note:
i
has been declared before



Elements stored
in
row
-
wise
order



Also called
column major
order


location [0][4] is
followed in memory
by loca
tion [1][0]




Static method (
i is

in a static memory:

assigned in compile time !)



By the way, program cannot assign address to

the pointer directly such as




p = 0X13eff860



Dynamic Memory Allocation



The
new
operation


Example




int * intPtr;




intPtr = new int;



New function returns

a memory address that can store “int” type data
operator and
release it with delete operator.




Usually, dynamic allocation is
done
with assignment or initiation:


type *p;


p = new type;


//or



type* p = new type;




Examples:





int* ip;


ip = new int;


*ip = 100;

// constant integer value


float* np = new float;


cin >> *np;

// read float


char* cp = new char;


*cp = 'X';

// char
acter



Operator Delete



When done using the memory, return it to

free store by using delete:



Example:



delete p;



Result of delete :

-

return the storage (deallocation)

-

p still exists, but the address stored in p is

meaningless,

-

Hence, set it to

NULL:



p
= NULL;



In sum, if we

don’t

need pointers to point to a

data

anymore, we should



delete ip;



delete np;



delete cp;








Dynamic Arrays




Recall: static array is fixed size at

compile time



Space wasted by unused cells



Program cannot adjust if size s
et too

small




Dynamic (run time) allocation provided



Acquire memory as needed



Release memory when no longer

needed



The new operator



Syntax for arrays



new Type [capacity]



This command issues a run
-
time request for a block of memory

of




S
i
ze

=

type *
capacity




Asks for enough memory for the specified number of elements of the stated type



Example












int *arrayPtr;



//
get for a 4 byte storage


arrayPtr = new int[6];

/
/address return
ed

by
new function is copied





//
into memory location pointed by arrayPtr



Failures of
new



When new execute
s




There is a

r
equest of

memory from heap (free dynamic
memory part)



Operating system a
llocates that

block to executing program



It is p
ossible to use up available heap memory



If
there is
not enough memory for request
, what happens?



new throws an exception …
bad_alloc



Solution: U
se
try

and
catch

mechanism to take appropriate action,


Example:































//
--

Demonstration #1 of new failure
--

Uncaught bad_alloc
exception


#
include <iostream>

#include <new> // new, bad_alloc

using namespace std;


int main()

{


const int NUM_ARRAYS = 10;


cout << "How large should the arrays of doubles be? ";


int capacity;


cin >> capacity;



double * arrayPtr[NUM_ARRAYS];


int i;


for (i = 0; i < NUM_ARRAYS; i++)


{


arrayPtr[i] = new double [capacity];


cout << "Allocated " << capacity



<< " doubles for i = " << i << endl;


}



// If a failure happened we are not aware, since program will
not


//
crush, if it cannot allocate heap memory.



cout << "All " << NUM_ARRAYS << " arrays of "


<< capacity << " doubles were allocated successfully." <<
endl;

}


Example:






//
--

Demonstration #2 of new failure
--

Use try
-
catch
mechanixm

//
--

to handle bad_alloc except
ion.


#include <iostream>

#include <new>

using namespace std;


int main()

{


const int NUM_ARRAYS = 10;


cout << "How large should the arrays of doubles be? ";


int capacity;


cin >> capacity;



double * arrayPtr[NUM_ARRAYS];


int i;



try



{


for (i = 0; i < NUM_ARRAYS; i++)


{



arrayPtr[i] = new double [capacity];



cout << "Allocated " << capacity



<< " doubles for i = " << i << endl;


}


}


catch

(bad_alloc ex)


{


cout << "
\
nException: " << ex.what()



<< "
--

for i = " << i << endl;


exit(1);


}


cout << "All " << NUM_ARRAYS << " arrays of "


<< capacity << " doubles were allocated
successfully." << endl;

}




Pointer Arithmetic




Possible to alter pointer contents



The pointer is a
variable




It is not a pointer constant like an array name



Example


Given:








Then
, after


arrayPtr
++;








Poi
nter to an array can do + and


an integer

operations such as



p = p + i;
and



p = p
-
i;




where
p
is a pointer to an array and
i
is an integer.




For example (draw the diagrams for understanding!),



int a[20]



int * p
;


p
= a;
// we
can do



++p;

// p points to a[1]


p+=2;



p = & a[10]; // p points to a[10]



p = p


5;

// now, p points to a[5]




Assignment
: What happens if
we

do
++a; a += 2
?

Write a program and find out!


Example:


























The
delete
Operation Again



Counterpart to the
new
operation



Requests memory be returned to the heap,

can then be reused by later
allocations


Syntax



delete pointerVariable;



delete [] arrayPointerVariable;




When done

using dynamic variables or arrays, do not forget to delete them.
Otherwise, you may run out of dynamic memory.



Memory Leaks




The problem in the following codes?

int a[100], i, *p, sum = 0;


for (i= 0; I < 100; i++) a[i] = I;


for (p = a; p <= &a[99]; p++)


{ sum += *p; }

cout << sum << e
ndl;
//

**********************************1

sum=0;


for (i = 0; i < 100; i++)

{ sum += *(a + i); }

cout << sum << endl;
//

**********************************2


sum =0

p = a;

for (i = 0; i < 100; i++)

{ sum += p[i]; }

cout << sum << endl;
//

***************
*******************3


sum=0

p = a;

for (i = 0; i < 100;

i++)

{ sum += *(p + i); }

cout << sum << endl;
//

**********************************4


//What is the value of
sum

at 1, 2, 3, and 4?




int * intPtr = new int [100000];



……



intPtr = new int[100];




Should add
delete
[]
intPt
r;

before the
second
new









Originally allocated memory now cannot be accessed, nor is it available for
reallocation




Array names are addresses, so are pointers



the name of array store the address of the

first element in that array


Example:


int a[
20];

//
a is equivalent to &a[0]


int *p = a;

// same as p= &a[0]


Also:



a[i] is equivalent to *(a + i)



Therefore, &a[i] = a + i



Difference between a pointer and an array




Is the

name:

pointers can be assigned different

addresses, while an a
rray name
is an

address

that is fixed.



Example


int a[20], b[20];


int *p = a; // same as p= &a[0]


p = b; //change the value to b, legal.


a = b; //is illegal, a is fixed value,


//can’t be reassigned






Other uses of pointers




int main( int argc,
char * argv[]);



int main (int argc, char **argv);



argc: counts the number of elements in the command line


argv
: contains command line words.




argv[0]: executables name


argv[1]: first word after the name of the executabl
e


argv[2]: second “ “ “ “ “ “ “


argv[n]: n’th word (string) in the command line.



Example:





































#include <iostream>

#include <climits>

using namespace std;


int main(int ar
gc, char *argv[])

{




// What is printed?? Guess.


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


cout <<
*argv[i]

<< endl;




cout<< endl << endl;



// What is printed now?


for ( i = 0; i < argc; i++)


cout <<
argv[i]
<< endl;




return

0;

}

OUTPUT:

C:
\
Desktop
\
New Folder
\
Debug>
argv_ex

This is an example

a

T

i

a

e



argv_ex

This

is

an

example



Aggregate Data Types




Predefined types not always adequate to model
the problem



When objects have multiple attributes



When objects have collections of heterogeneous elements



C++ provides
structs

and
class
es



Create new types with multiple attributes


Structures



Example:



Characteristics



has a fixed size



is ordered



elem
ents may be of different size



direct access of elements by name (not index)





struct Date {



int month, day, year;



char dayOfWeek [12];


};





structs can be nested (can contain struct objects)



Access members with



name of struct object



dot
is used a
s member selector operator



name of struct member

Date today = { 3, 4, 2005, "Tuesday");

cout << today.month;

Pointers to Structures



Pointers can be bound to
any

type

Date today = { 3, 4, 2005, "Tuesday");


Date *datePtr = &today;




Use for accessing the o
riginal location


cout << (*datePtr).day;

cin >> datePtr
-
>year;














































/*==
Time.h
============================================================




This header file defines the data type Time for processing time.


B
asic operations are:


set: To set the time


display: To display the time


advance: To advance the time by a certain amount


lessThan: To determine if one time is less than another


====================================================
===================*/


#include <iostream>

using namespace std;


struct Time

{


unsigned hour,


minute;


char AMorPM; // 'A' or 'P'


unsigned milTime; // military time equivalent

};


void set(Time & t, unsigned hours, unsigned minutes
, char AMPM);

/*
-----------------------------------------------------------------------


Set the time to a specified value.



Receive: Time object t


hours, the number of hours in standard time


minutes, the number of minutes in

standard time


AMPM ('A' if AM, 'P' if PM)


Pass back: The modified Time t with data members set to the


specified values

-----------------------------------------------------------------------
*/


void display(const Time & t, os
tream & out);

/*
-------------------------------------------------------------------------


Display time t in standard and military format using output stream out.



Receive: Time t and ostream out


Output: The time t to out


Pass back: The modifie
d ostream out with a representation of t


inserted into it


------------------------------------------------------------------------
*/


void advance(Time & t, unsigned hours, unsigned minutes);

/*
-------------------------------------------
------------------------------


Increment a time by a specified value.



Receive: Time object t


hours, the number of hours to add


minutes, the number of minutes to add


Pass back: The modified Time t with data members increme
nted by the


specified values

-------------------------------------------------------------------------
*/


bool lessThan(const Time & t1, const Time & t2);

/*
-------------------------------------------------------------------------

/* Determi
nes if one time is less than another time.


*


* Receive: Times t1 and t2


* Return: True if t1 < t2, false otherwise.

-------------------------------------------------------------------------
*/

















































/*==Time.cpp


1
--

====
=============================
=
=============




Implementations of the function members of class Time.


Prototypes are in Time.h.



=============================================================*/


#include "Time.h"


/** Utility functions
--

might be added as basic operations later
**/


int toMilitary(unsigned hours, unsigned minutes, char AMPM);

void toStandard(unsigned military,


unsigned & hours, unsigned & minutes, char & AMPM);



//
---

Definition of

set()
----------------
----------------------------

void set(Time
& t, unsigned hours, unsigned minutes, char AMPM)

{


if (hours >= 1 && hours <= 12 &&


minutes >= 0 && minutes <= 59 &&


(AMPM == 'A' || AMPM == 'P'))


{


t.hour = hours;


t.minute = minutes;


t.AMorPM = AMPM;


t.milTi
me = toMilitary(hours, minutes, AMPM);


}


else


cerr << "*** Can't set time with these values ***
\
n";


// t remains unchanged

}


//
---

Definition of display()
---------------------------------------

void display(const Time & t, ostream & out
)

{


out << t.hour << ':'


<< (t.minute < 10 ? "0" : "") << t.minute


<< ' ' << t.AMorPM << ".M. ("


<< t.milTime << " mil. time)";

}


//
---

Definition of advance(
)
-------------------------
---------------

void advance(Time & t, unsign
ed hours, unsigned minutes)

{


// Advance using military time


t.milTime += 100 * hours + minutes;


unsigned milHours = t.milTime / 100,


milMins = t.milTime % 100;



// Adjust to proper format


milHours += milMins / 60;


milMins %
= 60;


milHours %= 24;


t.milTime = 100 * milHours + milMins;



// Now set standard time


toStandard(t.milTime, t.hour, t.minute, t.AMorPM);

}


Continued below
;


















































//
Time.cpp =2=


//
---

Definition of lessThan()
-----------------------
-----------
----------

bool lessThan(const Time & t1, const Time & t2)

{


return (t1.milTime < t2.milTime);

}



//
-----

DEFINITIONS OF UTILITY FUNCTIONS
-------


int toMilitary (unsigned hours, unsigned minutes, char
AMPM)

/*
-----------------------------------------
-----------
---------------------


Convert standard time to military time.



Receive: hours, minutes, AMPM


Return: The military time equivalent

------------------------------------------------------
-------------------
*/

{


if (hours == 12)


ho
urs = 0;


return hours * 100 + minutes + (AMPM == 'P' ? 1200
: 0);

}


void toStandard(unsigned military,


unsigned & hours, unsigned & minutes,
char & AMPM)

/*
----------------------------------------------------
---------------------


Con
vert military time to standard time.




Receive: military, a time in military format


Return: hours, minutes, AMPM
--

equivalent
standard time

------------------------------------------------------
-------------------
*/

{


hours = (military / 100) %
12;


if (hours == 0)


hours = 12;


minutes = military % 100;


AMPM = (military / 100) < 12 ? 'A' : 'P';

}

Review this chapter. Make sure you understand it. Then
, solve the text quizzes
3.2, 3.3, 3.4, and 3.5. Make sure you understand them.