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 operatorThis 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%