Chapter 10 – User-defined Data Types Simple (Atomic) data types

Chapter 10 – User-defined Data Types
Simple (Atomic) data types – each value is indivisible
-- by definition, size of C++ char is always 1 byte
-- 1 byte = 8 bits
-- so how many different characters can be represented using 1 byte of storage?
-- how about 2 bytes (16 bits)
-- bool – contains only 2 values: true and false – allowable ops: (!, &&, || and relational
ops
-- char – really an integer type – internal representation is a number and external
representation is a character – values are ordered based on collating sequence
--sizeof(type) operator – yields the size (in bytes) of the specified type on your
machine – operand can be variable name or name of data type
Notice: when determining
size of a variable, do not
enclose in parenthesis!
Ex:: int age;
cout<< “Size in bytes of variable age is “
<<sizeof age << end;
cout<< “Size in bytes of type float is “
<<sizeof (float) <<endl;
-- so what are the sizes of the integral types on our machines??
-- guarantees about size of integral types:
1 = sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
1 <= sizeof (bool) <= sizeof (long)
sizeof (float) <= sizeof (double) <= sizeof (long double)
char is at least 8 bits
short is at least 16 bits
long is at least 32 bits
-- floats-- floating point constants in C++ like 94.6 without a suffix are of type
double by default -- to obtain another floating point type constant a suffix must be used
-- the suffix F or f denotes float type, as in 94.6F-- the suffix L or l denotes long
double, as in 94.6L
-- climits and cfloat – header files that contain constants whose values are the max
and min for a specific machine – ieFLT_MAX, FLT_MIN, LONG_MAX, LONG_MIN
Ex:: #include
<climits>
using namespacestd;
cout << “Maximum long is “
<<endl;
<< LONG_MAX
cout << “Minimum long is “
<<endl;
<< LONG_MIN
typedef statement – creates an additional name for an already existing data type – helps in
writing self-documenting code – obeys the same scope rules that apply to identifiers in general
Classic example: before bool became part of ISO-ANSI C++, a boolean was commonly
defined as:
typedef int
const
const
Boolean;
Boolean
Boolean
true = 1;
false = 0;
:
Boolean dataOK;
:
dataOK =
true;
enum types – user-defined type that is ordered set of literal values expressed as identifiers – an
enumerator is one value in the set
Ex::
enum MonthType {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG,
SEP, OCT, NOV, DEC};
Name of new type
List of possible values of
this new type
-- style is to capitalize the enumerator because they are essentially named constants –
enumerators must follow the rules for forming identifiers
-- this is just a type declaration – you must still declare variables of this type!
Ex::
MonthType thisMonth; // Declares 2 variables
MonthType lastMonth; // of type MonthType
-- storage of enum type variables:
Stored as 0
Stored as 1
Stored as 2
Stored as 3
enum MonthType {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP,
OCT, NOV, DEC};
Stored as 11
-- assignment – variable = enumerator – cannot assign an integer to enum type, but can assign
an enumerator to an int type (this is done so you don’t assign out-of-range value to an enum
type)
Ex::
lastMonth
thisMonth
=
=
OCT;
NOV;
// Assigns values
// to these variables
lastMonth = thisMonth;
-- increment – cannot simply add 1 because type coercion lets you add 1 on the right side, but it
then becomes an int – must use a type cast
Ex::
thisMonth = thisMonth++; // COMPILE ERROR!
thisMonth = MonthType(thisMonth + 1);
Type cast
for loop:
for (var = enumerator; var<= enumerator; var = enumtype(var + 1));
for (thisMonth = JUN; thisMonth <= DEC; thisMonth = MonthType(thisMonth + 1))
{
}
-- we need to be careful of this – why?
-- comparison – var relop enumerator– order determined by position in the type
declaration
-- enumeration type can be used in a switch statement for the switch expression and the case
labels
-- stream I/O (using the insertion << and extraction >> operators) is not defined for enumeration
types
-- an enum type can be the return type of a value-returning function
Ex1:: void WriteOutName(/*
in */ MonthType month)
// Prints out month name
// Precondition: month is assigned
// Postcondition: month name has been written out
{
switch (month)
{
case JAN : cout << “ January ”; break;
case FEB : cout << “ February ”; break;
case MAR : cout << “ March ”;
break;
case APR : cout << “ April ”;
break;
case MAY : cout << “ May ”;
break;
case JUN : cout << “ June ”;
break;
case JUL : cout << “ July ”;
break;
case AUG : cout << “ August ”;
break;
case SEP : cout << “ September ”; break;
case OCT : cout << “ October ”; break;
case NOV : cout << “ November ”; break;
case DEC : cout << “ December ”; break;
}
}
Ex2:: enum SchoolType {PRE_SCHOOL, ELEM_SCHOOL, MIDDLE_SCHOOL,
HIGH_SCHOOL, COLLEGE};
SchoolType GetSchoolData(void)
// Obtains information from keyboard to determine level
// Postcondition: Return value == personal school level
{
SchoolType schoolLevel;
int age;
int lastGrade;
cout << “Enter age : “; // Prompt for information
cin >> age;
if(age <
6)
schoolLevel = PRE_SCHOOL;
else
{
cout << “Enter last grade completed in school: “;
cin >> lastGrade;
if(lastGrade < 5)
schoolLevel = ELEM_SCHOOL;
else if(lastGrade < 8)
schoolLevel = MIDDLE_SCHOOL;
else if(lastGrade < 12)
schoolLevel = HIGH_SCHOOL;
else
schoolLevel = COLLEGE;
}
return schoolLevel;
// Return enum type value
}
A couple of in-class problems:
Write C++ statements to do the following:
a. Define an enum type bookType, with the values MATH, CSCI, ENGLISH,
HISTORY, PHYSICS, and PHILOSOPHY.
b. Declare a variable book of type bookType.
c. Assign MATH to the variable book.
d. Advance book to the next value in the list.
e. Output the value of the variable book.
Given:
enum currencyType {DOLLAR, POUND, FRANK, LIRA, MARK};
currencyType currency;
which of the following statements are valid?
a.
b.
c.
d.
currency = DOLLAR;
cin >> currency;
currency = static_cast<currencyType>(currency + 1);
for (currency = DOLLAR; currency <= MARK; currency ++)
cout<< “* “;
Structured Data Types -- type in which each value is a collection of component items
-- the entire collection has a single name
-- each component can be accessed individually
-- used to bundle together related data of various types for convenient access under the
same identifier
Ex::
enum HealthType {Poor, Fair, Good, Excellent};
struct AnimalType // Declares a struct data type
{
// does not allocate memory
long
id;
string
name;
string
genus;
struct members
string
species;
string
country;
int
age;
float
weight;
HealthType health;
};
// Declare variables of AnimalType
AnimalType thisAnimal;
AnimalType anotherAnimal
Records (structs) – components may be of different types – each component is called a field and
is given a name – c++ terms: record = struct, field = member
declaration is a type definition – variables must be declared of this type before memory
is allocated – type declaration just provides a “pattern” for what the struct should look like – ie:
struct
structTypeName
{
MemberList
};
// Does not allocate memory
-- each member given a type and member names within the struct are unique –struct
declaration ends with a ;
-- scope of a struct- if the struct type declaration precedes all functions, it will be visible
throughout the rest of the file -- if it is placed within a function, only that function can use it
-- it is common to place struct type declarations in a (.h) header file and #include that file -- it
is possible for members of different struct types to have the same identifiers -- a non-struct
variable may have the same identifier as a structure member
Accessing struct Members -- After the struct type declaration, the various members can be
used in your program only when they are preceded by a struct variable name and a dot(.) –
called the member selection operator
Ex::
thisAnimal.weight
anotherAnimal.country
-- can also declare a variable at the end of the type definition
Ex::
enum HealthType {Poor, Fair, Good, Excellent};
struct AnimalType // Declares a struct data type
{
// does not allocate memory
long
id;
string
name;
string
genus;
string
species;
string
country;
int
age;
float
weight;
HealthType health;
} thisAnimal;
Operations on struct members -- type of the member determines the allowable operations
Ex::
thisAnimal.age = 18;
thisAnimal.id
= 2037581;
cin >> thisAnimal.weight;
getline (cin, thisAnimal.species);
thisAnimal.name = “giant panda”;
thisAnimal.genus[0] = toupper(thisAnimal.genus[0]);
thisAnimal.age++;
Aggregate operation -- operation on a data structure as a whole, as opposed to an operation on
an individual component of the data structure – aggregate struct operations:
Assignment -- to another struct variable of the same type
Pass-- as an argument (by value or by reference)
Return-- as value of a function
Homework #1:
pp. 490-91 EPE 1 – 15
pp. 492 PWU 1 - 8
I/O, arithmetic, and comparisons of entire struct variables are NOT ALLOWED!
Ex::
anotherAnimal = thisAnimal;
WriteOut(thisAnimal);
ChangeWeightAndAge(thisAnimal);
thisAnimal = GetAnimalData();
void WriteOut( /*
in
*/
//
//
//
//
Assignment
Value parameter
Reference parameter
Function return value
AnimalType thisAnimal)
// Prints out values of all members of thisAnimal
// Precondition: all members of thisAnimal are assigned
// Postcondition:all members have been written out
{
cout << “ID # “ << thisAnimal.id
<< thisAnimal.name << endl;
cout << thisAnimal.genus << thisAnimal.species
<< endl;
cout << thisAnimal.country << endl;
cout << thisAnimal.age << “ years “ << endl;
cout << thisAnimal.weight << “ lbs. “ << endl;
cout << “General health : “;
WriteWord (thisAnimal.health);
}
void ChangeAge(/* inout */ AnimalType& thisAnimal)
// Adds 1 to age
// Precondition: thisAnimal.age is assigned
// Postcondition:thisAnimal.age ==
//
thisAnimal.age + 1
{
thisAnimal.age++;
}
AnimalType GetAnimalData ()
// Obtains all information about an animal from keyboard
// Postcondition:
//
Return value == AnimalType members entered at kbd
{
AnimalType thisAnimal;
char response;
do
{
// Have user enter members until they are correct
.
.
.
} while (response != ‘Y’);
return thisAnimal;
}
Hierarchical records – component of a record can be a record – member selectors built from
left to right – why would we do this? – repeated member types – information that changes vs.
information that remains static – (good example in book on page 477)
A couple of in-class problems:
Assume the following structure:
struct Rectangle
{
int length;
int width;
};
a) Write a function that accepts a Rectangle structure as its argument and displays the
structure’s content on the screen.
b) Write a function that uses a Rectangle structure reference variable as its parameter and
stores the user’s input in the structure’s members.
c) Write a function that returns a Rectangle structure. The function should store the user’s
input in the members of the structure before returning it.
d) Write a function that returns the area of the Rectangle.
e) Write a function that returns the perimeter of the Rectangle.
Union Types -- a struct that holds only one of its members at a time during program execution
Ex::
union PaySource
{
short hours;
float sales;
};
// declares a union type
Only one member at a time
PaySource empPaySource;
// declares a union variable
empPaySource.hours = 25;
// pay source in hours no longer needed, reuse memory
empPaySource.sales = 5000;
empPaysource – a union variable
hours
sales