LAB 11 -- C++ Structured Data Types

CREATE ANSWER SHEET for LAB 11
Objectives: 
Sections:
  1. C++ Data Types
  2. The C++ struct
  3. The C++ class
  4. Compiling and linking multiple files
C++ Data Types
Type statements in C++ are used to allow the compiler to: C++ has three basic data types available for the programmer: simple data types (aka scalars), structured data types (aka composites), and address types. We have previously studied the simple data types such as int, float, char, and string.  Selected structured data types will be discussed in this lab (specifically, the C++ struct and the C++ class). Address types will be reserved for more advanced C++ study.

Simple data types include the int type, the float type and the char type, for example. These types differ mainly in "how" the data is stored. For example, the char type will use 8 bits (1 byte) of memory while the float type will use 32 bits (4 bytes) of memory. Simple data types have a major restriction -- variables that are declared as a simple data type may only store one data item. For example, if the following declaration is made:

int oneNumber;

oneNumber may only store one integer value. There are many applications where it would be beneficial to have one variable that could store several different types of information. Many programs are built around a collection of different values that are all related in some way. For example, consider a collection of information related to a book. A book has a title; it has an author, a publisher's name, and a retail cost of the book. In database terminology, collections of related information are called records and the individual data items contained in the record are called fields. If we wished to work with a book record in C++, for example, we might list the different fields of the record.  Also, we would need to determine the data type for each field.  Lastly, we should determine a name for each of the fields.  The following table briefly describes information that might be included in a book record.
 

Field  Field Data Type Field Name
title of book string title
Author of book string author
Publisher string publisher
retail cost of book float cost

 


Exercise 1:
Suppose that we want to store information about a student in a record.  This will require several fields. On the answer sheet, complete the following table with your ideas regarding the types and names of fields that could be included in a student's record.

 

Field  Field Data Type Field Name
a student's name     
a student's major    
a student's tuition    
a student's gpa    

Programmers often have the need to work with records and C++ provides mechanisms for accomplishing this with the use of the struct structured data type.  Let us now consider the C++ struct.

The C++ Struct
A C++ struct provides a mechanism for programmers to create a group of related items, called members, that are not necessarily of the same types. The C++ struct allows the programmer to create a new type that can store several pieces of information.  A C++ struct may store data and functions. Therefore, we say that a struct contains two types of members, data members (data) and function members (methods). Usually, structs contain only data members and very few, if any methods. We will discuss methods more completely later in this lab.

There are some basic beginning questions that need to be addressed related to using records (structs) in C++.

1) What is the syntax for setting up a struct data type?
2) How do we access the fields (i.e., members) contained in a struct?
3) Can structs be used as field components of another struct?
1)    What is the syntax for setting up a struct data type?

The basic syntax is:

struct NameType
{

MemberList; //listing of variable names and their associated types
};

(^ A common mistake is to forget to put the required semi-colon at the end of the declaration.)


For example, suppose that we wish to set up a C++ struct to store book information as described above. The actual declaration might appear as follows:

struct BookRec 
{
       string title;
       string author;
       string publisher;
       float cost;
};

Now, we have a new C++ type; it is called a BookRec. (WARNING: Please remember that BookRec is a type, not a variable.) If we wish to use this new type, we must set up (i.e., declare) a variable using the BookRec type.  For example, the following statement creates a variable called myBook.

BookRec myBook;


Exercise 2:
On the answer sheet, show a C++ statement to set up a new type called StudentRec to store information about a student. This answer should relate to your answer to Exercise 1. Also, show C++ to declare a variable called aStudent of type StudentRec.

2)    How do we access the fields contained in a struct?
The ".", called the dot operator in C++ (but, of course, is really a period), is used to access members of a struct. Consider the variable myBook. If myBook is a struct variable and title is a member of that struct, then myBook.title would be used to access the title of the book. If we wished to read in all infomation for the myBook variable, we could use the following statements.

       cout << "Enter book title: ";
       getline(cin, myBook.title);
       cout << "Enter book author: ";
       getline(cin, myBook.author);
       cout << "Enter publisher: ";
       getline(cin,myBook.publisher);
       cout << "Enter cost of book: ";
       cin >> myBook.cost;
       cin.ignore(80,'\n');            // "skip" the trailing newline

Note in the statement, getline(cin, myBook.title); in the example above, that myBook is a variable that refers to a data type struct BookRec and myBook.title refers to the title portion of the struct BookRec. The statement getline(cin, myBook.title); allows us to read in the title of a book object called myBook.


Exercise 3:
On the answer sheet, show C++ statement(s) to perform each of the following for the variable, aStudent, as described in Exercise 2.

a) Read in a student's name
b) Add $200.00 to the student's tuition.
c) If the student's major is "Computer Science", print out the student's gpa.

3)    Can structs be used as field components of another struct?

Yes! Suppose that we wish to store additional information in our book record related to the date of publication. In this case, we may want to set up an additional record to store date information. For example, note the following date record type:

       struct DateRec
       {
           int year;
           int month;
           int day;
       };

Now, we can add an additional field to our book record as shown below:

       struct BookRec
       {
           string title;
           string author;
           string publisher;
           float cost;
           DateRec publishDate;
       };
To gain access to the "nested" struct, we will need to use the dot operator twice (the first dot operator is used to access the publishDate field of the BookRec and the second dot operator is used to access the fields of the publishDate record.  The following statement allows us to print out the publication date for the myBook variable.

cout << myBook.publishDate.month << myBook.publishDate.year << myBook.publishDate.day << endl;


Exercise 4:
On the answer sheet, show code to change the year of myBook’s publication date to 1999. (HINT:  Use an assignment statement.)


Exercise 5:
Copy the program called cla11a.cpp to your account.  This program uses BookRec as described above. Using this as an example, modify the code to:

You are to submit the source program listing of the modified code, compilation results, and a sample run of the program. Something like the following UNIX commands will let you create what is required:
       $ script lab11ex5.log
       $ pr -n -t -e4 cla11a.cpp
       $ c++ cla11a.cpp -o cla11a
       $ cla11a
       ...the data you enter...
       $ exit
(Be sure to properly exit the script session!)



The C++ Class
C++ has an additional structured data type called the class. It is very similar to the C++ struct. The main difference being that the struct data type usually contains only a collection data members while the class data type usually contains a collection of data members and function members (aka methods) that manipulate the data contained in the class.

The C++ class provides a mechanism for programmers to create objects. A software object is a self-contained computing entity that has its own data and its own associated operations called methods. We say that the C++ class supports data encapsulation (combining data and functions on that data into a single program unit). In real life, we deal with physical objects continually. When we sit in a chair (an object) at our desk (an object), we might consult our calendar (an object) to plan our activities for the day. Think of an object that we experience and use daily, say an automobile. The automobile object has data or data features (a steering wheel, an ignition, is either straight shift or automatic, etc.) and it has certain functions or operations that it should perform. Some of the functions include: move forward, move backward, start motor, stop motor, turn lights on, etc.

Objects have a public interface and a private component. The public interface of an object is composed of the collection of functions and features that are available to the user to allow effective use of the object. For example, the public interface of the “automobile” object would include buttons on the dashboard to allow the user to control certain operations like turning on the lights and allowing the user to use a key to start the motor. Private data or functions are unavailable to the public. This would be like disabling the hood release so that the user cannot access the internal parts of an automobile (which would be a good idea in some cases). Normally, private data and functions are those data and instructions that should not be changed by the user.

Suppose that we wish to create a book object.  We have previously considered what the data might look like for this object (book title, book author, publisher, etc).  The following table indicates possible functions that we might want to include in this object.
 
Function Name
Function Purpose
PrintBook
Prints out the data contained in a book object
ChangeCost
Changes the cost of a book
IsAvailable
Determines whether the book is currently available

 A large portion of a programmer's job is to design objects and then use the C++ class mechanism to actually define the object and determine how the object is to be manipulated. To design the object, the programmer first thinks of the type of data that is needed to form the object. Secondly, the programmer determines what functions are needed to manipulate the object. The C++ class allows a programmer to create this new type.  There are many benefits for creating objects using the C++ class.  Some of these benefits include data encapsulation, data security and information hiding. Information hiding refers to the process of hiding implementation details from the users (called clients) of the created class or object.  The C++ class can be set up to “hide” implementation details from the user and can restrict the user from seeing how the data is actually stored. This promotes data security since the user cannot “see” the data contained in the object and thus, cannot manipulate the data erroneously.  The C++ class promotes "encapsulation"  - the concept of binding the data and functions on the data items into one single program unit.

How do we set up a C++ class?

When creating a class, the programmer should (usually) construct the class in two parts: a specification file and an implementation file. The specification file declares the object ( indicates the data types and functions of the class).The implementation file contains the definitions of the class methods (member functions).We will examine the specification file first.

The C++ class specification file

Suppose that we wish to design a rectangle object. We must decide 1) what data should be included in this object and 2) what functions are needed for this object. The data needed for this object should include a rectangle's dimensions: width and height of the rectangle. Some of the functions needed might include: a function to print a rectangle, a function to compute the area of the rectangle, a function to compute and print the perimeter of a rectangle, a function to draw a rectangle and a function to allow the user to set the length and width of the rectangle. Now we are ready to construct the class. The basic syntax is:


class name
{
public:
     //declare all functions and variables that are available 
     //to the user of the class
private:
     //declare all functions and variables that should not be 
     //available to the user
};

For example, the declaration of the rectangle class may appear as follows:


//FILE: cla11rectangle.h
class RectangleType
{
public:
    void PrintRectangle();          // Print rectangle dimensions
    float ReturnArea();             // Compute and return area of rectangle 
    float ReturnPerimeter();        // Compute and return perimeter of rectangle
    void SetSize(float l, float h); // Set the length and height of rectangle
private:
    float length;                   // Length of the rectangle
    float height;                   // Height of the rectangle
};

The RectangleType class has six members - four member functions (PrintRectangle, ReturnArea, ReturnPerimeter and SetSize) and two member variables (length and height). The member variables form the data that is needed to create a rectangle and the member functions allow the user to perform different operations with a rectangle. Note that in this example, clients (users) of this class have access to the member functions but do not have access to the member variables.


Exercise 6:
Design a class called CircleType and then create (using an editor) a class specification file called, cla11circle.h, that contains functions and data members similar to the functions and data members contained in the RectangleType class.
NOTE: Data members are generally, but not always, placed in the private portion of the class. What data member(s) will be needed for a circle? (Hint: radius)


The C++ Implementation File
Next, the programmer should build the implementation file. The implementation file for the rectangle object should contain the function definitions for all functions that were declared in the specification file, cla11rectangle.h.

IMPORTANT: Note the following:

  1. Functions in the implementation file have access to all the private data members of the class!
  2. The scope resolution operator  ::  is always used in the function headers of the member functions. This informs the compiler to what class the member function belongs.

Observe the following implementation file that might be used to define the functions contained in cla11rectangle.h.


//FILE: cla11rectangle.cpp 
#include "cla11rectangle.h" #include <iostream> using namespace std; //Sets the length and height of the rectangle void RectangleType::SetSize(float l, float h) { length = l; height = h; } //Prints the length and height of the rectangle void RectangleType::PrintRectangle() { cout << "RECTANGLE\n"; cout << "Rectangle Height:" << height << endl; cout << "Rectangle Length:" << length << endl; } // Computes and returns the area of the rectangle float RectangleType::ReturnArea() { return (length * height); } //Computes and returns the perimeter of the rectangle float RectangleType::ReturnPerimeter() { return (2*length + 2* height); }

Exercise 7:
Write the implementation file for the circle class and save it using the name cla11circle.cpp.   Note: The area of a circle is π*r*r where π=3.14159 and r is the radius of a circle. The perimeter (circumference) of a circle is found using the formula, 2 * π * r. Define and use a symbolic constant, PI, to hold the value of π.


Now, how do we use the rectangle class described above?   Consider the following example of a client file (a file that declares and manipulates objects of a particular class):

//FILE: cla11b.cpp

#include <iostream>
#include "cla11rectangle.h"      //#include file created by the programmer

using namespace std;

int main()
{
      //declare variables
      RectangleType aRectangle, bRectangle;    //Set up two rectangle objects

      //Set length and width of rectangle
      aRectangle.SetSize(10, 5);

      //Print the dimensions of a rectangle
      aRectangle.PrintRectangle();

      //Print statistics for the aRectangle
      cout << "Rectangle Area: ";
      cout << aRectangle.ReturnArea() << endl;
      cout << "Rectangle Perimeter: ";
      cout << aRectangle.ReturnPerimeter() << endl;
      cout << endl << endl;

      //Using assignment statement with objects
      bRectangle=aRectangle;
  
      //Print statistics for bRectangle
      bRectangle.PrintRectangle();

      return 0;
}

Note that the dot operator is used to invoke member functions. This is how “messages” are passed to an object in C++. Thus,
           aRectangle.SetSize(5, 10);
sends the SetSize message to the object called aRectangle.   
(Don't get confused by this object-oriented terminology: What we would ordinarily term "invoking" or "calling" a member function is sometimes called "sending messages" in object-oriented languages. There's an esoteric reason for that related to the early object-oriented programming language Smalltalk.)

Also note the assignment statement after the cout statements. This line is valid and copies all data fields from the object, aRectangle, to the object, bRectangle.

Observe that nowhere in our main function do we try to access the data variables, length and height, that were defined in the RectangleType class. In fact, we could not do so because these data members were placed in the private section of the class. This means that only members of the class can access them. 


Compiling and Linking with Multiple Files

Exercise 8:
The above example is a very simple example of a main program that utilizes the rectangle class. All of the rectangle class files have been created for you (cla11rectangle.h, cla11rectangle.cpp, cla11b.cpp). Copy these files to your account. Both the main function and the implementation functions for the rectangle class must be compiled. Since they are in separate files, a slight variation of the c++ statement is required. To compile and link this program, type

      c++ cla11b.cpp clal1rectangle.cpp -o rectangle

Compile and run this program to verify that the program runs properly - Do not submit this run for grading.

Note: .h files are never put on the c++ command-line. These files are not compiled directly but rather their contents gets #included into other files by the C preprocessor.



Exercise 9:
You have created two additional files, cla11circle.h and cla11circle.cpp. Edit the cla11b.cpp file so that it performs the following activities. IMPORTANT: You must tell the compiler to include your cla11circle.h file; use: #include "cla11circle.h"

  1. Create a rectangle object with a width and height that is input by the user and then call all of the functions in the rectangle class.
  2. Create a circle object with a radius that is input by the user and then call all of the functions in the circle class.

Exercise 10:
You are to submit the source program listings of the three modified files (cla11b.cpp, cla11circle.h, cla11circle.cpp), compilation results, and a sample run of the program. Something like the following UNIX commands will let you create what is required:

       $ script lab11ex10.log
       $ pr -n -t -e4 cla11b.cpp
       $ pr -n -t -e4 cla11circle.h
       $ pr -n -t -e4 cla11circle.cpp
       $ c++ cla11b.cpp clal1rectangle.cpp cla11circle.cpp
       $ a.out
       ...the data you enter...
       $ exit
(Be sure to properly exit the script session!)


Exercise 11:

Submit the log file you have created in Lab 11 typing

            $ handin lab11log lab11ex5.log lab11ex10.log
Exercise 12:

From the PC you are working on, you must also submit the answer sheet (AnswerSheet11.pdf) using the following directions:

  • Save your Lab11 Final Answer Sheet (click icon on very bottom of the answer sheet window)
  • Create the file AnswerSheet11.pdf using your Browser's 'Save as PDF' feature
    (1. ctrl+p [Windows] or command+p [Mac]    2. Select 'Save as PDF')
  • Use your C-number/password to log into the Gus Homework Repository System:
    https://www.cs.mtsu.edu/cgi-bin/gus/gus.py
  • Submit your AnswerSheet11.pdf file to the Gus Homework Repository System
    1. Select the assignment from the dropdown menu: lab11ans
    2. Select the Submit radio button
    3. Click the button: Perform Action
    4. (On the subsequent screen) Click the button: Choose File to locate your AnswerSheet11.pdf
    5. Click the Upload button to upload the chosen file.

Congratulations! You have finished Lab 11.



Once you are done, you will need to log off ranger. Enter   $ exit   to exit the (sakura) terminal window. Depending on how you logged in to ranger you will need to enter $ exit one or more times to get completely logged off the system.