CS245 - Comp Sci II

Chapter 6 - Pointers and References

POINTERS

A pointeris an indirect reference to an object of a specified type (address of a location where an object of a given type may be stored).

int n; // an integer
int *p; // a pointer to an integer

int *p, *q, n;
n = -16;
*p = 101;
*q = n + *p;
p = q;


Pointers and Arrays (name of an array can be used as a pointer to the first element in the array)

double a[10];
double* p = a;

a[6] == p[6] == *(p+6)


Functions and Arrays (the contents of an array can be modified by a function)

void Swap2(Card *c, int firstIndex, secondIndex) 
{ 
	Card temp = c[firstIndex]; 
	c[firstIndex] = c[secondIndex]; 
	c[secondIndex] = temp; 
}

to avoid accidentally changing the contents of an object, declare the argument as a constant:
void Display(const VeryBigObject *v);

new and delete Operators

int* p; or
p = new int; int* p = new int;

Fraction* fp = new Fraction;
Fraction* fp = new Fraction(3,7);

class Pair 
// A class representing ordered pairs of integers (x, y) 
{ 
	public: 
	Pair(); 				// construct the pair (0,0) 
	void Show(); 			// Displays the elements
	int x, y; 				// the two elements of the pair
}; 
:
Pair* p = new Pair; 
: 
cout << "the first component is " << (*p).x;
cout << "Here's the entire pair: "; 
(*p).Show();
:
cout >> "The first component is " << p->x;
cout << "Here's the entire pair: "; 
p->Show();

delete - returns the storage to the list of available storage locations

Dynamic Arrays

class Directory
{
:
Entry* entryList;
:
}
:
entryList = new Entry[5]; //allocates room for 5 Entrys


Pointers and Strings

char string1[15] = "Object Concept";
char* string2 = string1;

"zero terminated" strings \0

cout << string1;


cin >> anotherString; //reads until a "white space" is reached
get(char* string, int length, char delimiter = '\n'); //reads until length or delimiter reached
getline(char* string, int length, char delimiter = '\n'); //same as get except it extracts terminating delimiter

int strlen (const char *s)
{
	int i = 0;
	while (s[I] != '\0') 
		i++;
	return i;
}
int strlen(const char* s) 
{
	for (int i = 0; s[i]; i++);
		return i;
}

int strcmp (const char* s1, const char* s2) 
// compares strings s1 and s2 for lexicographic order, returning 0 if equal 
{ 
	int i = 0; 
	while ((s1[i] != '0') && (s1[i] == s2[i]))
		i++; 
	return (s1[i] - s2[i]); 
}

int strcmp (const char* s1, const char* s2) 
{
	while ((*s1) && (*s1 == *s2))
	{
		++;
		++;
	}
	return (*s1 - *s2);
}

QUESTION: What happens if we reverse the order of s1 and s2?


char* strcpy (char* s1, const char* s2) 
// copies s2 into s1 and returns a pointer to the new string 
{
	for (int j = 0; s2[j] != '\0'; j++) 
		s1[j] = s2[j];
	s1[j] = s2[j]; 			//copies the terminator
	return s1;
}

char* strcpy (char* s1, const char* s2)
{
	char* temp = s1;
	while (*s2)
		*s1++ = *s2++;
	*s1 = *s2;
	return temp;
}
QUESTION: Is temp necessary? Why?

Pointers as Links: A Preview

struct Node
{
int value; // the integer stored in the node
Node* link; // a pointer to the next node in the list
};


References

void ModifiedSwap(Card* p1, Card* p2) 
//p1 and p2 are pointers to cards, so the arguments must be pointers
{
	Card temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}

Reference Types (aliases) - must be defined to refer to a variable when it is declared or as a formal argument to a function

int n = 10;
int& r = n;
r = 20;

void SimpleSwap(Card& r1, Card& r2) 
//r1 and r2 are references to cards
{
	Card temp = r1; 
	r1 = r2; 
	r2 = temp; 
}

More Input and Output

class ostream
{
public:
//---------Overloads of << Operator
ostream& operator<<(const char* string);
ostream& operator<<(char c);
ostream& operator<<(int n);
ostream& operator<<(double v);
};

cout << j < '\n';

friend ostream& operator<<(ostream &s, Fraction f);

ostream& operator<<(ostream& s, Fraction f)
// Inserts the numerator, '/', and the denominator into the ostream s, and then
// returns a reference to s
{
s << f.numerator << '/' << f.denominator;
return s;
}

class istream
{
public:
istream& operator>>(char* string);
istream& operator>>(char& c);
istream& operator>>(int& n);

//--------Utility Routines---------
istream& get(char* string, int length, char delimiter = '\n');
istream& get(char& c); // extract a single character
int get(); // get one character and return it in an int.
istream& getline(char* string, int length, char delimiter = '\n');
:
friend istream& operator>>(istream& s, Fraction& f);


Designing the PIP: A Phone Directory

phone directory - list of entries
entry - name, address, phone #

class entry
{
friend istream& operator>>(istream& s, Entry& e);
friend ostream& operator<<ostream& s, Entry e);
public:
Entry();
char* GetName();
private:
char name[20];
char phoneNumber[20];
char address[20];
};

class Directory
{
public:
Directory();
~Directory();
void Insert();
void Lookup();
void Remove();
void Update();
void DisplayDirectory();
private:
int maxSize, currentSize;
Entry* entryList;
void Grow();
int FindName(char* aName);
};

destructor
no arguments
handles all tasks before an object is destroyed

Directory::~Directory()
{
delete entryList;
}

if

  1. entryList is a pointer to an array,
  2. the elements of the array are class objects and
  3. the class has a destructor,

then delete [] entryList;


The Main Program:

//----------------- PIP6.CPP -----------------
// Test program and general support functions
// for phone directory

#include <ctype.h> // for toupper
#include <iostream.h> // for cin, cout
#include "FONEBOOK.H" // for class Directory

void ShowMenu()
// Display the main program menu.
{
cout << "\n\t\t*** PIP 6 PHONE DIRECTORY ***";
cout << "\n\tI \tInsert a new entry into the directory";
cout << "\n\tL \tLook up an entry";
cout << "\n\tR \tRemove an entry";
cout << "\n\tU \tUpdate an entry";
cout << "\n\tD \tDisplay the entire directory";
cout << "\n\t? \tDisplay this menu";
cout << "\n\tQ \tQuit";
}

char GetAChar(char* promptString)
// Prompt the user and get a single character, discarding the Return character.
// Used in GetCommand.
{
char response; // the char to be returned
cout << promptString; // Prompt the user
cin >> response; // Get a char,
response = toupper(response); // and convert it to uppercase
cin.get(); // Discard newline char from input.
return response;
}
char Legal(char c)
// Determine if a particular character, c, corresponds to a legal menu command.
// Returns 1 if legal, 0 if not. Used in GetCommand.
{
return ((c == 'I') || (c == 'L') || (c == 'R') || (c == 'U') ||
(c == 'D') || (c == '?') || (c == 'Q'));
}

char GetCommand()
// Prompts the user for a menu command until a legal
// command character is entered. Return the command character.
// Calls GetAChar, Legal, ShowMenu.
{
char cmd = GetAChar("\n\n>"); // Get a command character.
while (!Legal(cmd)) // As long as it's not a legal command,
{ // display menu and try again.
cout << "\nIllegal command, please try again . . .";
ShowMenu();
cmd = GetAChar("\n\n>");
}
return cmd;
}

void main()
{
Directory d; // Create and initialize a new directory.
ShowMenu(); // Display the menu.
char command; // menu command entered by user
do
{
command = GetCommand(); // Retrieve a command.
switch (command)
{
case 'I': d.Insert(); break;
case 'L': d.Lookup(); break;
case 'R': d.Remove(); break;
case 'U': d.Update(); break;
case 'D': d.DisplayDirectory(); break;
case '?': ShowMenu(); break;
case 'Q': break;
}
} while (command != 'Q');
}

6.5 Exploring the PIP (files available on share drive [JARING/CS245])

Exercises