220 likes | 342 Views
Lecture #5 Topics. Declaring Pointer Types and Pointer Variables. Dynamic Allocation and Deallocation of Memory. Linked Lists. Implementations of class List Living in a dynamically allocated array Living in a linked list. n. n. ?. 19. Explicit Declaration of a Data Object.
E N D
Lecture #5 Topics Declaring Pointer Types and Pointer Variables Dynamic Allocation and Deallocation of Memory Linked Lists Implementations of class List Living in a dynamically allocated array Living in a linked list
n n ? 19 Explicit Declaration of a Data Object The Scope of an Identifier for a Data Object (Variable) is from the point at which it is declared to the end of the function or block within which it is declared ... { //n does not exist ...//until it is declared int n=19; ... } //after closing bracket ...//n no longer exists int n; int n; n=19; symbolic name for address in memory memory contents is an integer value Data Objects Declared Locally Within a Function or Block are said to have storage class automatic
p p p p ? 19 Implicit Declaration of a Data Object The lifetime of such a data object is from its point of creation to its point of dissolution int* p; . . delete p; int* p; p=new int; int* p; p=new int; *p=19; dereference operator symbolic name for address in memory dangling dangling memory allocated Data Objects declared through pointers are said to have storage class dynamic
Consider the following sequence of statements: p q p 18 28 19 p q q p 18 28 28 a phantom space //let p point to a //new memory space p=new int; //assign 18 to //the memory space //pointed to by p *p=18; //declare pointer //variable p int* p; //let p point to a //new memory space p=new int; //assign 19 to //the memory space //pointed to by p *p=19; //deallocate the //memory space //that p is //pointing to delete q; //let q point //to the same //place that p //is pointing to int* q=p; //assign 28 to //the memory space //pointed to by p *q=28;
What You Should Say to Yourself int* p; p=new int; *p=19; . . delete p; explicitly declare a variable p of type “pointer to int” let p point to a newly allocated memory space for an int assign 19 to the memory space that p is pointing to do whatever else you want to do with the memory space deallocate the memory space that p is pointing to You Should Consider the Following Advice When Dealing With Pointers: Repeat Phrases Like Those Given Above! and Always Draw Pictures!
A Pair of Idioms Dealing with Pointers head NULL p p p head NULL q p q q p p class node { public: int num; node* next; }; Moving a pointer, p down a linked list: node* p=head; while ( <condition> ) p=p->next; E.g., node* p=head; while (p->next!=NULL) p=p->next; Moving a pair of pointers p & q down a linked list: node* p=head; node* q; while ( <condition> ) { q=p; p=p->next; };
Sample Code void PtrTest::run() { num=18; cout<<"num="<<num<<endl; //File ptrtest.cpp #include <iostream.h> class PtrTest { public: void run(); private: int num; int* intPtr; int arrayOfInt[5]; int* arrayOfIntPtr; class node { public: int num; node* next; }; node m; node* nPtr; }; intPtr=new int; *intPtr=19; cout<<"*intPtr="<<*intPtr; cout<<endl; for (int i=0; i<5; i++) arrayOfInt[i]=3*i; cout<<"arrayOfInt[0..4]="; for (i=0; i<5; i++) cout<<arrayOfInt[i]<<" "; cout<<endl; arrayOfIntPtr=new int[5]; for (i=0; i<5; i++) arrayOfIntPtr[i]=6*i; cout<<"arrayOfIntPtr[0..4]="; for (i=0; i<5; i++) cout<<arrayOfIntPtr[i]<<" "; cout<<endl;
Sample Code (cont’d) //PtrTest::run() continued m.num=20; m.next=NULL; cout<<"m.num="<<m.num<<endl; //File ptrtest.cpp #include <iostream.h> class PtrTest { public: void run(); private: int num; int* intPtr; int arrayOfInt[5]; int* arrayOfIntPtr; class node { public: int num; node* next; }; node m; node* nPtr; }; nPtr=new node; (*nPtr).num=21; (*nPtr).next=nPtr; cout<<"(*nPtr).num=“; cout<<(*nPtr).num<<endl; //or using //shorthand notation: nPtr=new node; nPtr->num=21; nPtr->next=nPtr; cout<<"nPtr->num=“; cout<<nPtr->num<<endl; }; void main() { PtrTest p; p.run(); }
//File liststuf.cpp #include <iostream.h> #include <stdlib.h> enum boolean {FALSE,TRUE}; typedef double itemtype; class List { public: List(int size=10); ~List(); void insert(itemtype item,int pos); void remove(int pos); void retrieve(itemtype& item,int pos) const; int length() const {return len;}; boolean empty() const {return boolean(len==0);}; boolean full() const {return boolean(len==MAX);}; void display() const; private: itemtype* data; int len,MAX; enum listerror {INSERTPOSERR,OVERFLOW,REMOVEPOSERR, RETRIEVEPOSERR,NEGSIZEERR}; void err(listerror e,int errnum) const; }; A Second Version of the List Class Working Towards the Development of the List Class Living in a Dynamically Allocated Array parameter with default value destructor now needed this will be a pointer to an array a place to save maximum size new error
//constructor List::List(int size) { if (size>0) { data=new itemtype[size]; len=0; MAX=size; } else err(NEGSIZEERR,0); }; //destructor List::~List() { delete[] data; }; //these 4 functions are same as for previous version (see Module 3) void List::display() const { ... }; void List::insert(itemtype item,int pos) { ... }; void List::remove(int pos) { ... }; void List::retrieve(itemtype& item,int pos) const { ... };
//error handling void List::err(listerror e,int errnum) const { cout<<"\nERROR: "; switch (e) { case NEGSIZEERR: cerr<<"parameter must be positive\n“; break; case INSERTPOSERR: cerr<<"function insert(); position "<<errnum; cerr<<" does not exist!\n"; break; case OVERFLOW: cerr<<"function insert(); already filled "; cerr<<errnum<<" positions!\n"; break; case REMOVEPOSERR: cerr<<"function remove(); position "<<errnum; cerr<<" does not exist"; break; case RETRIEVEPOSERR: cerr<<"function retrieve(); position "<<errnum; cerr<<" does not exist"; break; default: cerr<<"Unknown!"; }; exit(1); };
double num; cout<<"\n\"retrieve(num,3);\""; L1.retrieve(num,3); cout<<"\nnum="<<num; cout<<"\n\"retrieve(num,1);\""; L1.retrieve(num,1); cout<<"\nnum="<<num; cout<<"\n\"retrieve(num,4);\""; L1.retrieve(num,4); cout<<"\nnum="<<num; cout<<"\n\"retrieve(num,2);\""; L1.retrieve(num,2); cout<<"\nnum="<<num; cout<<"\n\"remove(2);\""; L1.remove(2); L1.display(); cout<<"\n\"remove(3);\""; L1.remove(3); L1.display(); cout<<"\n\"remove(1);\""; L1.remove(1); L1.display(); cout<<"\n\"remove(1);\""; L1.remove(1); L1.display(); cout<<"\n...end!"; }; void main() { ListTest t; } class ListTest { public: ListTest(); }; ListTest::ListTest() { cout<<"A Short Test for class List"; cout<<"\nBegin..."; cout<<"\n\"create();\""; list L1; cout<<"\nIs the list empty? "; if (L1.empty()) cout<<"yes!"; L1.display(); cout<<"\n\"insert(19.19,1);\""; L1.insert(19.19,1); L1.display(); cout<<"\n\"insert(18.18,2);\""; L1.insert(18.18,2); L1.display(); cout<<"\n\"insert(20.21,1);\""; L1.insert(20.21,1); cout<<"\nIs the list empty? "; if (!L1.empty()) cout<<"no!"; L1.display(); cout<<"\n\"insert(17.17,4);\""; L1.insert(17.17,4); L1.display();
A Third Version of the List Class enum boolean {FALSE,TRUE}; typedef int itemtype; class node { friend class List; private: itemtype item; node* next; }; Working Towards the Development of the List Class Living in a Linked List friendship yet continued privacy class List { public: List(); ~List(); void insert(itemtype item,int pos); void remove(int pos); void overwrite(itemtype item,int pos); void retrieve(itemtype& item,int pos) const; int length() const; boolean empty() const; private: node* head; . . }; this is the pointer to the beginning of the list
head Inserting a Node in a Linked List 1 2 3 NULL num p head 1 2 3 NULL q num p head 1 2 4 NULL 3 q num p node* p; p=new node; p->item=num; node* q=head; /*move q to appropriate position*/ p->next=q->next; q->next=p;
Are There Any Special Cases? node* p; p=new node; p->item=num; node* q=head; /*move q to appropriate position*/ p->next=q->next; q->next=p; Check out what might be called the Boundaries (or the Boundary Conditions) Can the code be used, as is, to insert a node in an empty Linked List? Can the code be used, as is, to insert a node at the beginning of a Linked List? Can the code be used, as is, to insert a node at the end of a Linked List?
head NULL num p head 1 num NULL p node* p; p=new node; p->item=num; node* q=head; /*move q to appropriate position*/ p->next=q->next; q->next=p; Can the code be used, as is, to insert a node in an empty Linked List? NO! node* p; p=new node; p->item=num; p->next=head; head=p;
head 1 2 3 NULL num p 2 3 4 NULL head 1 num p node* p; p=new node; p->item=num; node* q=head; /*move q to appropriate position*/ p->next=q->next; q->next=p; Can the code be used, as is, to insert a node at the beginning of a Linked List? NO! node* p; p=new node; p->item=num; p->next=head; head=p; Note that inserting a node in an empty list and at the beginning of a list yield the same code
head 1 2 3 NULL num p head 1 2 3 4 num q NULL p node* p; p=new node; p->item=num; node* q=head; /*move q to appropriate position*/ p->next=q->next; q->next=p; Can the code be used, as is, to insert a node at the end of a Linked List? YES!
Removing a Node from a Linked List head 1 2 3 4 NULL q p head 1 2 3 NULL q p head 1 2 3 NULL q p a phantom node node* p=head; node* q; /*move both p,q to appropriate positions*/ q->next=p->next; delete p;
Are There Any Special Cases? node* p=head; node* q; /*move both p,q to appropriate positions*/ q->next=p->next; delete p; Check out the Boundary Conditions Can the code be used, as is, to remove a node at the beginning of a Linked List? Can the code be used, as is, to remove a node at the end of a Linked List?
head 1 2 3 4 NULL p head 1 2 3 NULL p head 1 2 3 NULL p node* p=head; node* q; /*move both p,q to appropriate positions*/ q->next=p->next; delete p; Can the code be used, as is, to remove a node at the beginning of a Linked List? NO! node* p=head; head=p->next; delete p;
head 1 2 3 4 NULL q p head 1 2 3 NULL q p head 1 2 3 NULL q p node* p=head; node* q; /*move both p,q to appropriate positions*/ q->next=p->next; delete p; Can the code be used, as is, to remove a node at the end of a Linked List? YES!