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
© Copyright 2024 Paperzz