Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 10

Chapter 6: Structures, Pointers and Recursion

6.1 Structures

Enumeration Types

 C++ allow the user to define new simple types by listing (enumerating) the
literal values that make up the domain of the type.

 Enumerated literal values must be identifiers, not numbers.


 An Enumeration Type is a user-defined data type whose domain is an
ordered set of literal values expressed as identifiers.
 An Enumerator is one of the values in the domain of an enumeration type.
 Example:

    enum Days {SUN, MON, TUE, WED, THU, FRI, SAT};
 
 

The value of SUN is 0, MON is 1, TUE is 2, etc.

    enum Month {JAN = 1, FEB, MAR, APR, MAY,


               JUN, JUL, AUG, SEP, OCT,
               NOV, DEC};

The value of JAN is 1, FEB is 2, etc.

 The enumerated values can be used instead of their numeric equivalents.

    Days today;


    today = TUE; 

 Arithmetic with enumerated values is not as might be expected. You


cannot increment or add a constant to change from one value to another.
You can however use type casting to accomplish the same thing:

Examples:

    Days today;


    today = TUE;
    today = Days(today + 1); // today++ won't work

    for (today = SUN;


         today <= SAT;
         today = Days(today + 1)
    {
        cout << today << endl;
    }

1
outputs the numbers 0, 1, 2, 3, 4, 5, 6; not the literals. 

 Comparisons with enumerated values work fine:

Examples:

    if (today == TUE)


        . . .
    if (today < FRI)
        . . . 

Enumerated values can be used with a switch statement:

    enum Days {SUN, MON, TUE, WED, THU, FRI, SAT};
    Days today;
    int  weekday;
 
    . . .
    switch (today)
    {
        case SUN:
        case SAT:
            weekday = FALSE;
            break;

        default:
            weekday = TRUE;
    }

Records

 A Record is a structured data type with a fixed number of components that


are accessed by name rather than by index. The components may be
heterogeneous (of different types).

 A Field is a component or member of a record.


 In C++ records are declared using the struct statement.

  enum GradeType {A, B, C, D, F};


  typedef char NameString[20];

  struct StudentRec
  {
    NameString firstName;
2
    NameString lastName;
    long       studentId;
    float      gpa;
    float      programAvg;
    float      examAvg;
    float      labAvg;
    int        finalExam;
    GradeType  coursegrade;
  }

  StudentRec aStudent;
  StudentRec aPupil; 

 Each member of the struct is accessed by using the member selector


operator (.).

  aStudent.courseGrade =
        aStudent.examAvg * 0.30 +
        aStudent.programAvg * 0.25 +
        aStudent.labAvg * 0.30 +
        aStudent.finalExam * 0.15; 

 Members of a struct can be initialized when the declaration is made:

  StudentRec aStudent =
  {
    "Ophelia",
    "Payne",
    12345678,
    0.725,
    54.3,
    62.0,
    25.4,
    76.0,
    D
  }; 
 The members firstName and lastName are arrays. To access their
individual components, specify the entire name of the field followed by the
index of the array member enclosed in square brackets.

  aStudent.firstName[2] = 'i'; 
 The following table compares aggregate operations for arrays and structs.

Aggregate Operation Arrays Structs


I/O Strings only No
Assignment operation = No Yes
Arithmetic No No

3
Comparison No No
Parameter passage By reference only By value or by reference
 Unlike arrays, the contents of a struct can be assigned to another variable
of the same type.

  aPupil = aStudent;

 Alternate forms of the struct statement:

  struct StudentRec
 {
    NameString firstName;
    NameString lastName;
    long       studentId;
    float      gpa;
    float      programAvg;
    float      examAvg;
    float      labAvg;
    int        finalExam;
    GradeType  coursegrade;
   } aStudent, aPupil;

Arrays of Records

 Structs can be used as the members of arrays. For example:

  const int MAX_STUDENTS = 200;


  enum GradeType {A, B, C, D, F};
  typedef char NameString[20];

  struct StudentRec
 {
    NameString firstName;
    NameString lastName;
    long       studentId;
    float      gpa;
    float      programAvg;
    float      examAvg;
    float      labAvg;
    int        finalExam;
    GradeType  coursegrade;
 }

  StudentRec gradeBook[MAX_STUDENTS];  

 To access individual members of the array, you must specify both the
array index and the field of the struct.

4
  gradeBook[2].finalExam = 96.0;

6.3 Pointers and Dynamic Memory Management

In this lecture we introduce the notion of a pointer, which gives the programmer a
greater level of control over the way the program allocates and de-allocates
memory during its execution.

Declaring Pointers

A pointer is just the memory address of a variable, so that a pointer variable is


just a variable in which we can store different memory addresses. Pointer
variables are declared using a "*", and have data types like the other variables
we have seen. For example, the declaration

int *number_ptr;

states that "number_ptr" is a pointer variable that can store addresses of


variables of data type "int".

Assignments with Pointers Using the Operators "*" and "&"

Given a particular data type, such as "int", we can write assignment statements
involving both ordinary variables and pointer variables of this data type using the
dereference operator "*" and the (complementary) address-of operator "&".
Roughly speaking, "*" means "the variable located at the address", and "&"
means "the address of the variable". We can illustrate the uses of these
operators with a simple example program:

#include <iostream>
using namespace std;

int main()
{
int *ptr_a, *ptr_b;
int num_c = 4, num_d = 7;

ptr_a = &num_c; /* LINE 10 */


ptr_b = ptr_a; /* LINE 11 */

cout << *ptr_a << " " << *ptr_b << "\n";

ptr_b = &num_d; /* LINE 15 */

cout << *ptr_a << " " << *ptr_b << "\n";

*ptr_a = *ptr_b; /* LINE 19 */

5
cout << *ptr_a << " " << *ptr_b << "\n";

cout << num_c << " " << *&*&*&num_c << "\n";

return 0;
}
Program 6.1.

The output of this program is:

44
47
77
77

Diagramatically, the state of the program after the assignments at lines 10 and
11 is:

after the assignment at line 15 this changes to:

and after the assignment at line 19 it becomes:

The "new" and "delete" operators

Dynamic variables are "created" using the reserved word "new", and "destroyed"
(thus freeing-up memory for other uses) using the reserved word "delete". Below
is a program analogous to Program 6.1, which illustrates the use of these
operations:

#include <iostream>
using namespace std;
int main()
{
int *ptr_a, *ptr_b; /* LINE 7 */

6
ptr_a = new int; /* LINE 9 */
*ptr_a = 4;
ptr_b = ptr_a; /* LINE 11 */

cout << *ptr_a << " " << *ptr_b << "\n";

ptr_b = new int; /* LINE 15 */


*ptr_b = 7; /* LINE 16 */

cout << *ptr_a << " " << *ptr_b << "\n";

delete ptr_a;
ptr_a = ptr_b; /* LINE 21 */

cout << *ptr_a << " " << *ptr_b << "\n";

delete ptr_a; /* LINE 25 */

return 0;
}
Program 6.2

The output of this program is:

44
47
77

The state of the program after the declarations in line 7 is:

after the assignments in lines 9, 10 and 11 this changes to:

after the assignments at lines 15 and 16 the state is:

and after the assignment at line 21 it becomes:

7
Finally, after the "delete" statement in lines 25, the program state returns to:

Why Would You Use Pointers?

The above programs demonstrate the use of pointers. But why bother with a
pointer when you already have a variable with access to that value? Pointers are
used, most often, for three tasks:

 Managing data on the free store.( massive section of memory in which


thousands of sequentially numbered locations lie waiting for your data)
 Accessing class member data and functions.
 Passing variables by reference to functions.

6.3 Recursion

What is Recursion?

 A Recursive Call is a function call in which the function being called is the
same as the one making the call.

 A Recursive Definition is a definition that is made in terms of a smaller


version of itself.

    xn = x * x * . . . * x        (Iterative definition - nonrecursive)

or

    xn = x * xn-1 for n > 1    (Recursive definition)

        =  x           for n = 1

        =  1           for n = 0 

 A Recursive algorithm is a solution that is expressed in terms of

a. a smaller instance of itself. 


b. One or more base cases.

 A base case is a case for which the solution is stated nonrecursively.


8
 A general case (or recursive case) is a case for which the solution is
expressed in terms of a smaller version of itself.

Recursive Functions

 In C++, a function may call itself to define a recursive function.

 Every recursive function consists of one or more base cases and a


general, recursive case.

 Example: Power Function

  // Exponentiation program
  #include <iostream.h>

  int Power( int, int);

  int main()
  {
    int number;
    int exponent;

    cin >> number >> exponent;


    cout << number << "^"
         << exponent << " = "
         << Power(number, exponent);

    return 0;
  }

  // Power recursive function


  int Power (int x, int n)
  {
    if (n <= 0)
        return 1;
    if (n == 1)
        return n;
    return x * Power(x, n-1);
  } 

 The Power function can be coded as a nonrecursive (iterative) algorithm:

  // Power iterative function


  int Power (int x, int n)
  {
    int pow = 1;
 

9
    for ( ; n > 0; n--)
        pow *= x;

    return pow;


  } 

 If there is no base case, or if the base case is never executed, an infinite


recursion occurs.

 An Infinite Recursion is when a recursive function calls itself endlessly.


 The factorial of a non-negative number is defined as the product of all the
values from 1 to the number:

                        n! = 1 * 2 * . . . * n

It can also be defined recursively as

                       n! =  1                  if n < 2


                           =  n * (n -1)!     if n >= 2  

 Example: Recursive Factorial Function

  // Factorial Function
  int Factorial ( int n )
  {
    if ( n < 2)
      return 1;
    return n * Factorial(n - 1);
  } 

 The factorial function can also be defined iteratively by a simple function.


(The exercise is left to the reader).
 Many functions are much easier to define recursively than they are
iteratively.

10

You might also like