CSC 306 Introduction to Programming with C++

More on Classes, Some on Enumerated Types and the Switch Statement

Chapter 6


Objectives

  • Create your own C++ class that can be expanded upon later.
  • Learn to use the enumerated type in C++
  • Learn to use C++ switch statements for multi-way branching.

Important Definitions

  • enumerated type, switch

C++ Class Revisited

In making a C++ class, you are essentially creating your own data type in C++. This type can contain multiple related kinds of data, and special functions can be created to manipulate the data. There are special functions such as constructors, accessors, and mutators that are designed to create, access, and manipulate the data in the class that is otherwise typically hidden from outside access. The programmer can designate member data and functions for either public or private access by using the appropriate keyword. Feel free to reread assignment 13 for review if any of the above is not very clear.

In this assignment, we will create a class of objects that represent playing cards. Playing cards have both (1) a suit (like diamond or heart) and (2) a rank (like King or Ace) these are the items we will need to know to know which playing card we possess. Furthermore, we will need to create a new playing card with using a constructor function, and we should be able to see which suit and rank a playing card using accessor functions change these values with manipulator functions. An additional useful function is one that tests two cards to see if they are in the same suit. Before we do this, it will help to introduce and learn some notions that will make our code more readable and easier to implement.

Enumerated types

C++ provides a feature called enumerated types that makes it possible to (1) include a mapping between real-world values and the internal representations of these concepts and (2) define the set of values that make up this mapping. In some ways this is like setting up a bunch of constants, but it is better because the constants are all of the same type.

For example, the declaration

enum DaysofWeek {MON, TUES, WED, THURS, FRI, SAT, SUN};
is a kind of shorthand for:

const int MON = 0;
const int TUES = 1;
const int WED = 2;
const int THURS = 3;
const int FRI = 4;
const int SAT = 5;
const int SUN = 6;
NOTE: By tradition all constants and enumerated types are given names in all capital letters.

Although members of an enum list are typically given the values 0, 1, 2, etc., one can change the values elements get by initializing them. Uninitialized members of the list have values that are one more than the previous value on the list. Consider:

enum DaysofWeek {MON = 1, TUES, WED, THURS, FRI, SAT = -1, SUN};
is a kind of shorthand for:

const int MON = 1;
const int TUES = 2;
const int WED = 3;
const int THURS = 4;
const int FRI = 5;
const int SAT = -1;  // SAT was set to -1 in the declaration
const int SUN = 0;
Using enumerated types like this can be used to make code more readable. For example, suppose we incorporated an enumerated type into our Date class, which will enable us to use the month names instead of the numbers:

enum Monthenum {JANUARY=1 , FEBRUARY=2, MARCH=3, APRIL=4, MAY=5, JUNE=6,
		JULY=7, AUGUST=8, SEPTEMBER=9, OCTOBER=10, NOVEMBER=11, DECEMBER=12};
The rest of the code for the class can now use these month names. The checkDate(...) function would look like:

void Date::checkDate( int m, int d, int y ) {
// postcondition: adjusts out-of-range dates before setting member variables
    if( m < JANUARY || DECEMBER < m) { 
    	m = JANUARY;
    	cout << "WARNING: Invalid month set to January." << endl;
    }
    myMonth = m;
    
    if( d < 1 || daysInMonth(m,y) < d ) { 
    	d = 1;
    	cout << "WARNING: Invalid day set to 1." << endl;
    }
    myDay = d;
    
    if( y < 100 ) {
    	y = y + 1900;
    }
    myYear = y;   
}
Unfortunately, these enumerated type names cannot be written directly to a stream so a statement such as
cout << JANUARY << endl;
will not work.

The switch statement

Enumerated types and the switch statement structure are often used together. A switch statement is a syntactically cleaner and more efficient alternative to a chained conditional, and it has the following format, with its corresponding chained if conditional:

SWITCHCHAINED IF
switch (symbol) {
  case <case1>:	
		Statements for <case1>;
		break;
  case <case2>:
		Statements for <case2>;
		break;
  default:
		Statements for default;
		break;
}
if( symbol == <case1> ) { 
  Statements for case1;
} 
else if (symbol == <case2>:
  Statements for <case2>;
}
else {
  Statements for default;
}
The break statements (break is a reserved word in C++) are necessary in each branch in a switch statement because otherwise the flow of execution "falls through" to the next case. Without the break statements, the symbol case1 would make the program perform the statements for case1, then those for case2 and finally those for the default. Occasionally this feature is useful, but most of the time it is a source of errors when people forget the break statements.

C++ switch statements work with integers, characters, and enumerated types, which brings us back to why these statements can be useful in the Date class. The daysInMonth(...) function can be modified to the following to return the number of days there for each month:

int daysInMonth(int month, int year) {
// postcondition: returns # of days in month in year

switch( month ) {
  case JANUARY: 
  case MARCH:
  case MAY:
  case JULY:
  case AUGUST:
  case OCTOBER:
  case DECEMBER:    
		return 31;
  case FEBRUARY:
		if( isLeap( year ) )
		  return 29
		else
		  return 28;
  case APRIL:
  case JUNE:
  case SEPTEMBER:
  case NOVEMBER:  
    return 30;
  default:
    return 0;
}
In this case break statements are unnecessary because the return statements cause the flow of execution to return to the caller instead of falling through to the next case. It is good style to include a default case in every switch statement, to handle errors or unexpected values.


Assignment Specifics

This assignment must be completed individually.

Your task in this assignment is to begin the creation of a class that will store playing card values. This class will be a part of future assignments, so make sure it works correctly. This assignment is intentionally structured to get you to use class features appropriately, so be sure to conform to the stated assignment requirements.


Notes:

When you are finished writing and testing your assignment, drop your source code file, YourLastName_306A15.cpp, into the CSC306_A15 dropbox on the Academic server.


Back to Introduction to Computer Programming with C++ Homepage