Lab 5: Practice with structs, new, arrays, pointers and sorting
Part 1
Definition of a Pointer.
Pointers are a type of variable that allow you to specify the address
of a variable.
They provide a convenient means of passing arguments to functions and for referring to
more complex datatypes such as structures.
They are also essential if you want to use dynamic data in the
free store area. (That was a free look ahead to the dynamic data topic
covered later in these notes.)
You won't always know the specific value in a pointer, but you won't care as long as
it contains the address of the variable you are after.
You need to declare and initialize pointers just as you would other variables, but there
are special operators that you need to use.
Pointer Operators.
Here is a table showing the special characters used in C++ to declare
and use pointers.
|
* |
dereference operator, indirection operator |
This is used
to declare
a variable as a pointer.
It is also used when you want
to access
the value pointed to by
the pointer variable. |
|
& |
reference operator, address-of operator |
Use before a variable to indicate that you mean the
address of
that variable.
You'll often see this in a function header where the parameter list is given. |
|
-> |
member selection operator | This is used to refer
to members of structures
|
Simple Pointer Use.
We'd better look at some examples to make this clear.
First, we'll declare two ordinary integers, and also pointers to those integers.
int alpha = 5;
int beta = 20;
int* alphaPtr = α
int* betaPtr = β
The characters Ptr in the pointer variable name have no special significance.
They are simply a memory aid for the programmer.
Let's look more closely at one of the pointer declarations.
int* alphaPtr = α
The first part int*, tells the compiler to declare a pointer for integers.
alphaPtr will be the name of that pointer.
In the last part of that statement, α specifies that the
address of the variable alpha is what should be
assigned to the pointer variable.
An aside here: It is also permissable to position the asterisk closer to the pointer
variable name,
i.e. int *alphaPtr.
However the convention seems to be moving towards
placing the asterisk closer to the datatype.
Try to visualize memory after these declarations, thinking of the pointer variable
as not having a particular value, simply links to the variables
to which they had been assigned.
Now let's look at a trivial example of how to access this data.
*alphaPtr += 5;
*betaPtr += 5;
After these statements, it is only the contents of the alpha and
beta variables that would be changed.
You might say, "What's the big deal here? I could just as easily have written this:"
alpha += 5;
beta += 5;
True, but typically pointers aren't used in such a simple manner.
We just showed this to illustrate the use of pointer syntax.
Assignment: Create a function, called swap, that takes two pointers
and swaps the values in them. You function should look like this:
void swap(int* arg1, int* arg2)
Use this small main to test this.
void swap(int*, int*);
int main()
{
int a = 5;
int b = 10;
int *aPtr;
int *bPtr;
aPtr = &a;
bPtr = &b;
*aPtr = 5;
*bPtr = 10;
swap(aPtr,bPtr);
cout << *aPtr <<endl; //Should print out 10;
cout << *bPtr <<endl; //should print out 5;
}
Hint: In your swap function, you probably need to make a temp pointer (to do the swap). Remember what a pointer always needs.
Question (You must answer this): Passing pointers is pass by value. What actually happens to a and b, and why?
Part 2
Consider the following struct
struct student
{
char name[50];
double gradePointAverage;
};
Make sure you remember the semicolon at the end of the struct definition (missing it is a
common error)
You can create and use one of these structs in your program with code like the following:
student ChrisFischer;
strcpy( ChrisFischer.name, "Chris Fischer" );
ChrisFischer.gradePointAverage = 99.9;
Note the use of the dot operator. The dot operator is what allows you to go "inside" the struct
and access the individual pieces.
You can also make a pointer this structure, like this:
student* ChrisFischerPtr;
ChrisFischerPtr = & ChrisFischer;
and access it like this:
strcpy( ( *ChrisFischerPtr ).name, "Chris Fischer" );
( *ChrisFischerPtr ).gradePointAverage = 99.9;
But the far better way of doing this is with the new operator.
student* ChrisFischerPtr = new student;
strcpy( ( *ChrisFischerPtr ).name, "Chris Fischer" );
( *ChrisFischerPtr ).gradePointAverage = 99.9;
You can also make arrays of pointers, like the following:
const int CLASS_SIZE = 5;
student* classArray[ CLASS_SIZE ];
for ( int i = 0; i < CLASS_SIZE; i ++ )
{
classArray[ i ] = new student;
( *classArray[ i ] ).gradePointAverage = 99.9; //get this from somewhere else
strcpy( ( *classArray[ i ] ).name, "Some Name" ); //get name from somewhere
}
for ( int i = 0; i < CLASS_SIZE; i ++ )
{
cout << "Student #" << i << "Name: " << ( *classArray[ i ] ).name
<<" GPA: "<< ( *classArray[ i ] ).gradePointAverage <<endl;
}
So why make an array of pointers? Why not just a normal array? Because with pointers,
swapping two positions in an array becomes as simple as moving pointers since you can make a simple
swap function to do it (HINT: YOU ALREADY HAVE.)
Assignment:
Using the above student struct, create a short program that creates an array of pointers to student objects.
Input a reasonable amount of students, say 5 or 6, using something like the above way of doing it
(taking input from the keyboard is fine.) Then, after your array is created and you've inputted all the
students, you should print out the array, sorted by highest GPA, is some neat fashion.
Grading:
Part 1 (including the question): 40%
Part 2: 60%