C++ Plus Data Structures
-
Upload
lee-becker -
Category
Documents
-
view
53 -
download
2
description
Transcript of C++ Plus Data Structures
expanded by J. Goetz
1
C++ Plus Data Structures
Nell Dale
David Teague
Chapter 2
Data Design and ImplementationSlides by Sylvia Sorkin, Community College of Baltimore County - Essex Campus
expanded by J. Goetz
2
Data
• The representation of information in a manner suitable for communication or analysis by humans or machines
• Data are the nouns of the programming world: – The objects that are manipulated– The information that is processed
expanded by J. Goetz
3
Data Abstraction
• Separation of a data type’s logical properties (domain and operations) from its implementation.– e.g. declare an int type variable and operations are
allowed: =, +, -, *,/, %
LOGICAL PROPERTIES IMPLEMENTATION
What are the possible values? How can this be done in C++?
What operations will be needed? How can data types be used?
expanded by J. Goetz
4
Data Abstraction
Whether we use
• functional decomposition producing a hierarchy of tasks or
• object-oriented design producing a hierarchy of cooperating objects,
data abstraction is essential.
expanded by J. Goetz
5
APPLICATION
0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1
REPRESENTATION
Data Encapsulation
• is the separation of the representation of data from the applications that use the data at a logical level; a programming language feature that enforces information hiding.
• The user of the data doesn’t see the implementation, but deals with its abstraction.
int y;
y = 25;
expanded by J. Goetz
6
Encapsulated C++ Data Type int
Value range: INT_MIN . . INT_MAX
Operations: + prefix - prefix + infix - infix * infix / infix % infixRelational Operators Equality Operators
TYPE int
inside
Representation ofint
as 16 bits two’s complement
+Implementation of Operations
expanded by J. Goetz
7
Abstract Data Type (ADT)
• A data type whose logical properties (domain and operations) are specified independently of any particular implementation (so you don’t worry about implementation, the lower level is hidden).
– Domain: int y;– Operations:
• create variables by declarations,
• assign values by using “=“,• reading by using arithmetic
operators• etc.
• The goal of design is to reduce complexity through abstraction and protect our data abstraction through encapsulation.
expanded by J. Goetz
8
ADT vs Data StructureADT
The logical picture of the data and the operations that manipulate them
Data Structure • 1. The concrete implementation of the data.• 2. A collection of data elements whose
organization (arrangement ) is characterized by accessing operations that are used to store and retrieve the individual data elements;
• 3. The implementation of the composite data members in an abstract date type
expanded by J. Goetz
9
Data Structure
1. The logical arrangement of data elements, combined with
2. The set of operations we need to access the elements
expanded by J. Goetz
10
Data Structures
• Data Structures can be – Decomposed into their components– Arrange that affects how each element is
accessed– The arrangement can be encapsulated
• An abstract data type (ADT) is implementation independent and a data structure is implementation dependent.
expanded by J. Goetz
11
• Application (or user) level: modeling real-life data in a specific context.
• Logical (or ADT) level: abstract view of the domain (the data values) and operations. WHAT question
• ADT Implementation level: specific representation of the structure to hold the data items, and the algorithm for operations.
• HOW question
Data from 3 different levels in modeling data in a program
expanded by J. Goetz
12
Viewing a library from 3 different levels
• Application (or user) level: Library of Congress, or Baltimore County Public Library.
• Logical (or ADT) level: What is a library?; domain is a collection of books; (What are) operations include: check book out, check book in, pay fine, reserve a book.
• Implementation level: representation of the structure to hold the “books”, and the coding for operations. – How are the books cataloged? A decimal system. How are they
organized on the shelf? 4 leves with 20 shelvs on each level. How does the librarian process a book when it is checked in? p.58 etc.
expanded by J. Goetz
13
Modeling Data Goal in Program
•1. Determine the logical picture of the data (ADT)
•2. Choose the representation and arrangement of the data
•3. Develop the operations that encapsulate this arrangement.
expanded by J. Goetz
4 Basic Kinds of ADT Operations• Constructor -- creates a new instance (object) of an
ADT. • Transformer -- changes the state of one or more of the
data values of an instance.– e.g. insert/delete an item, making an object empty , a[1] = 5
• Observer -- allows us to observe the state of one or more of the data values without changing them. – e.g. accessor/selector functions that return a copy of an item, val = a[1];
summary functions about the object as a whole - # of items in the object; Boolean functions that returns true if an object empty
• Iterator -- allows us to process all the components in a data structure sequentially.– e.g. return successive list items
14
expanded by J. Goetz
15
Composite Data Type
A composite data type is a type which
• stores a collection of individual data components under one variable name,
• and allows the individual data components to be accessed.
expanded by J. Goetz
Two Forms of Composite Data Types
Components are not organized with respect to one another.
The organization determines method used to access individual data components.
UNSTRUCTURED STRUCTURED
EXAMPLES: EXAMPLES: arraysclasses and structs, unions
16
17
C++ Built-In Data Types
Composite
array struct union class
Address
pointer reference
Simple
Integral Floating
char short int long enum
float double long double
expanded by J. Goetz
18
Records
A record is a composite data type made up of a finite collection of not necessarily homogeneous elements called members or fields. For example . . .
.year 1999
.maker ‘h’ ‘o’ ‘n’ ‘d’ ‘a’ ‘\0’ . . .
.price 18678.92
thisCar at Base Address 6000
expanded by J. Goetz
19
struct CarTypestruct CarType{
int year ; char maker[10];
float price ;
} ;
CarType thisCar; //CarType variables
CarType myCar;
expanded by J. Goetz
20
Accessing struct members
The member selection operator (period . ) is used between the record variable name and the member identifier (selector) to access individual members of a record (struct or class) type variable.
EXAMPLESmyCar.yearthisCar.maker[4]
expanded by J. Goetz
21
Valid struct operations
• Operations valid on an entire struct type variable:
1. assignment to another struct variable of same type,
2. pass as a parameter to a function
(either by value or by reference),
3. return as the value of a function.
expanded by J. Goetz
Pass-by-value
CALLINGBLOCK
FUNCTION CALLED
sends a copy of the contents of the actual parameter
SO, the actual parameter cannot be changed by the function. 22
expanded by J. Goetz
Pass-by-reference
sends the location (memory address)of the actual parameter
can change value ofactual parameter
CALLINGBLOCK FUNCTION
CALLED
23
expanded by J. Goetz
24
Implementation level using struct type Reference Parameter to change a member
void AdjustForInflation(CarType& car, float perCent)
// Increases price by the amount specified in perCent{
car.price = car.price * perCent + car.price; } ;
SAMPLE CALL
AdjustForInflation(myCar, 0.03);
expanded by J. Goetz
25
Using struct type Value Parameter to examine a member
bool LateModel(CarType car, int date)
// Returns true if the car’s model year is later than or// equal to date; returns false otherwise.{
return ( car.year >= date ) ;
} ;
SAMPLE CALL
if ( LateModel(myCar, 1995) )std::cout << myCar.price << std::endl ;
expanded by J. Goetz
26
One-Dimensional Array at the Logical Level
A one-dimensional array is a structured composite data type made up of a finite, fixed size (known at compile time) collection of ordered homogeneous (all of the same data type) elements having relative positions and to which there is direct access (any element can be accessed immediately without accessing preceding elements).
Syntax of the declaration:
DataType arrayName [ConstIntExpression];
ConstIntExpression is an integer expression composed only literal or named constants e.g. MAX).
expanded by J. Goetz
27
One-Dimensional Array
Syntax of the component selector:
array-Name[IndexExpression]Whatever the form of the expression, it must result in an integer value.
• Array operations (creation) are performed using a declaration and (storing a value, retrieving a value) using indexes.
expanded by J. Goetz
28
Implementation Level
float values[5]; //it serves as a primitive constructor operation // assume element size is 4 bytes
This ACCESSING FUNCTION gives position of values[Index]
Address(Index) = BaseAddress + Index * SizeOfElement
Base Address
values[0] values[1] values[2] values[3] values[4]
7000 7004 7008 7012 7016
Indexes
expanded by J. Goetz
29
One-Dimensional Arrays in C++
• The index must be of an integral type (char, short, int, long, or enum).
• The index range is always 0 through the array size minus 1.
Valid struct operations1. Arrays cannot be assigned,
2. and cannot be the return type of a function.
expanded by J. Goetz
30
Another Example
char name[10]; // assume element size is 1 byte
The arrangment of this array in memory
name[0] name[1] name[2] name[3] name[4] . . . . . name[9]
Offset = Index * SizeOfElement
6000 6001 6002 6003 6004 6005 6006 6007 6008 6009
Base Address
This ACCESSING FUNCTION gives position of name[Index]
Address(Index) = BaseAddress + Index * SizeOfElement
expanded by J. Goetz
31
Passing Arrays as Parameters
• In C++, arrays are always passed by reference, and & is not used (omitted) ! with the formal parameter type.
• Whenever an array is passed as a parameter, its base address is sent to the called function.
expanded by J. Goetz
32
const array parameter
Because arrays are always passed as reference parameters, you can protect the actual parameter from unintentional changes by using const in formal parameter list and function prototype.
FOR EXAMPLE . . . // prototype
float SumValues( const float values[ ],
int numOfValues );
float SumValues (const float values[ ], /* the compiler needs to know that is an array; separate parameter is passed for the # of elements */ int numOfValues )
// Pre: values[ 0] through values[numOfValues-1] // have been assigned// Post: Returns the sum of values[0] through values[numOfValues-1]{ float sum = 0;
for ( int index = 0; index < numOfValues; index++ ) {
sum += values [ index ] ; }
return sum;}
33
expanded by J. Goetz
34
Two-Dimensional Array at the Logical Level
A two-dimensional array is a structured composite data type made up of a finite, fixed size collection of homogeneous elements having relative positions and to which there is direct access.
Array operations (creation) are performed using a declaration and (storing a value, retrieving a value) using a pair of indexes (called row and column) representing the component’s position in each dimension.
expanded by J. Goetz
35
EXAMPLE -- To keep monthly high temperatures for 50 states in a two-dimensional array. const int NUM_STATES = 50 ;const int NUM_MONTHS = 12 ;int stateHighs [ NUM_STATES ] [ NUM_MONTHS ] ;
[ 0 ]
[ 1 ] [ 2 ] . . stateHighs [2] [7] . [ 48 ] [ 49 ]
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]
66 64 72 78 85 90 99 115 98 90 88 80row 2,col 7might beArizona’shigh forAugust
expanded by J. Goetz
36
Finding the average high temperature for Arizona
int total = 0 ;
int month ;
int average ;
for ( month = 0 ; month < NUM_MONTHS ; month ++ )
total = total + stateHighs [ 2 ] [ month ] ;
average = int ( total / 12.0 + 0.5 ) ;
expanded by J. Goetz
37
const int NUM_STATES = 50 ;const int NUM_MONTHS = 12 ;int stateHighs [ NUM_STATES ] [ NUM_MONTHS ] ;
• In memory, C++ stores arrays in row order. The first row is followed by the second row, etc.
12 highs for state 0 12 highs for state 1 etc. Alabama Alaska first row second row
8000 8024 8048
Base Address
Implementation level - STORAGE
. . .
rows columns
expanded by J. Goetz
38
Implementation Level ViewstateHighs[ 0 ] [ 0 ]stateHighs[ 0 ] [ 1 ]stateHighs[ 0 ] [ 2 ]stateHighs[ 0 ] [ 3 ]stateHighs[ 0 ] [ 4 ]stateHighs[ 0 ] [ 5 ]stateHighs[ 0 ] [ 6 ]stateHighs[ 0 ] [ 7 ]stateHighs[ 0 ] [ 8 ]stateHighs[ 0 ] [ 9 ]stateHighs[ 0 ] [10 ]stateHighs[ 0 ] [11 ]stateHighs[ 1 ] [ 0 ]stateHighs[ 1 ] [ 1 ]stateHighs[ 1 ] [ 2 ]stateHighs[ 1 ] [ 3 ] . . .
To locate an element such asstateHighs [ 2 ] [ 7] the compiler needs to know that there are 12 columnsin this two-dimensional array.
At what address will stateHighs [ 2 ] [ 7 ] be found?
Assume 2 bytes for type int.
Base Address 8000
expanded by J. Goetz
39
Two-Dimensional Array Parameters
• Just as with a one-dimensional array, when a two- (or higher) dimensional array is passed as a parameter, the base address of the actual array is sent to the function.
• The size of all dimensions except the first must be included in the function heading and prototype.
• The sizes of those dimensions for the formal parameter must be exactly the same as in the actual array.
expanded by J. Goetz
40
const int NUM_STATES = 50 ;const int NUM_MONTHS = 12 ;int stateHighs [ NUM_STATES ] [ NUM_MONTHS ] ;int stateAverages [ NUM_STATES ] ;
[ 0 ] ? [ 1 ] ? [ 2 ] . . . [ 48 ] [ 49 ]
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]
43 42 50 55 60 78 79 80 77 72 63 4066 64 72 78 85 90 99 115 98 90 88 80
Use the two-dimensional stateHighs array to fill a
one-dimensional stateAverages array
Alaska
Arizona
void FindAverages( /* in */ const int stateHighs [ ] [ NUM_MONTHS] , /* in/out */ int stateAverages [ ] )
// Pre: stateHighs[ 0..NUM_STATES-1] [ 0..NUM_MONTHS-1] assigned// Post: stateAverages[ 0..NUM_STATES-1 ] contains rounded average// high temperature for each state{
int state; int month; int total; for ( state = 0 ; state < NUM_STATES; state++ ) {
total = 0 ; for ( month = 0 ; month < NUM_MONTHS ; month++ )
total += stateHighs [ state ] [ month ] ;stateAverages [ state ] = int ( total / 12.0 + 0.5 ) ;
}} 41
expanded by J. Goetz
42
Finding the Average High Temperature for Arizonaenum StateType { AL, AK, AZ, AR, CA, CO, CT, DE, FL, GA, HI, ID, IL, IN, IA, KS, KY, LA, ME,
MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY };
enum MonthType { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC } ;
const int NUM_MONTHS = 12 ;const int NUM_STATES = 50 ;int stateHighs [ NUM_STATES ] [ NUM_MONTHS ] ;
int total = 0 ;MonthType month ; // WITH ENUM TYPES DEFINEDint average ;
for ( month = JAN ; month <= DEC ; month = MonthType( month + 1) ) total = total + stateHighs [ AZ] [ month ] ;average = int ( total / 12.0 + 0.5 ) ;
expanded by J. Goetz
43
Using typedef with arrayshelps eliminate the chances of size mismatches between
formal and actual parameters. FOR EXAMPLE,
typedef int StateHighsType [ NUM_STATES ] [ NUM_MONTHS ] ;
typedef int StateAveragesType [ NUM_STATES ] ;
void FindAverages( /* in */ const StateHighsType stateHighs , /* out */ StateAveragesType stateAverages )
{ . . .
}43
expanded by J. Goetz
44
Declaring Multidimensional Arrays
EXAMPLE USING TYPEDEF
const int NUM_DEPTS = 5 ; // mens, womens, childrens, electronics, linens
const int NUM_MONTHS = 12 ;
const int NUM_STORES = 3 ; // White Marsh, Owings Mills, Towson
typedef long MonthlySalesType [NUM_DEPTS] [NUM_MONTHS] [NUM_STORES];
MonthlySalesType monthlySales;
const int NUM_DEPTS = 5 ; // mens, womens, childrens, electronics, linensconst int NUM_MONTHS = 12 ; const int NUM_STORES = 3 ; // White Marsh, Owings Mills, Towson
typedef long MonthlySalesType [NUM_DEPTS] [NUM_MONTHS] [NUM_STORES] ;
MonthlySalesType monthlySales; monthlySales[3][7][0]sales for electronics in August at White Marsh
12 MONTHS columns
5 D
EP
TS
ro
ws
3 STORES
sheets
45
expanded by J. Goetz
46
C++ class data type
1. A class is an unstructured type that encapsulates a fixed number of data components (data members) with the functions (called member functions) that manipulate them.
2. The predefined operations on an instance of a class are whole assignment and component access.
expanded by J. Goetz
47
Use of C++ data type class
• Variables of a class type are called objects (or instances) of that particular class.
• Software that declares and uses objects of the class is called a client.
• Client code uses public member functions (called methods in OOP) to handle its class objects.
• Sending a message means calling a public member function.
expanded by J. Goetz
48
class DateType Specification// SPECIFICATION FILE ( datetype.h )
class DateType // declares a class data type{
public : // 4 public member functions - accessed by the client code
void Initialize ( int newMonth , int newDay , int newYear ) ; // a transformer operation
int YearIs( ) const ; // returns year – an accessor functionint MonthIs( ) const ; // returns month – an accessor int DayIs( ) const ; // returns day – an accessor
private :// 3 private data members – cannot be accessed by the client code, accessed by the class member functions
int year ; int month ; int day ;
} ; 48
expanded by J. Goetz
49
2 separate files generally used for class type
// SPECIFICATION FILE ( datetype .h ) // Specifies the data and function members. class DateType { public: . . .
private: . . . } ;
// IMPLEMENTATION FILE ( datetype.cpp ) // Implements the DateType member functions. . . .
expanded by J. Goetz
50
Implementation of DateType member functions
// IMPLEMENTATION FILE (datetype.cpp)#include “datetype.h” // also must appear in client code
void DateType :: Initialize ( int newMonth, int newDay, int newYear )// Post: year is set to newYear.// month is set to newMonth.// day is set to newDay.{
year = newYear ; month = newMonth ; day = newDay ;}
50
int DateType :: MonthIs ( ) const// Accessor function for data member month{ return month ;}
int DateType :: YearIs ( ) const// Accessor function for data member year{ return year ;}
int DateType :: DayIs ( ) const// Accessor function for data member day{ return day ;}
51
expanded by J. Goetz
52
Client Code Using DateType#include “DateType.h” // includes specification of the class#include “Bool.h”using namespace std;int main ( void ){
DateType startDate ; // declares 2 objects of DateType DateType endDate ; bool retired = false ; startDate.Initialize ( 6, 30, 1998 ) ; endDate.Initialize ( 10, 31, 2002 ) ;
cout << startDate.MonthIs( ) << “/” << startDate.DayIs( ) << “/” << startDate.YearIs( ) << endl;
while ( ! retired ) { finishSomeTask( ) ; . . . } }
52
expanded by J. Goetz
53
DateType Class Instance Diagrams
Initialize
YearIs
MonthIs
DayIs
startDate endDate
Private data:
year
month
day
2002
10
31
Initialize
YearIs
MonthIs
DayIs
1998
6
30
Private data:
year
month
day
expanded by J. Goetz
54
Familiar Class Instances and Member Functions
• The member selection operator ( . ) selects either data members or member functions.
• Header files iostream and fstream declare – the istream, ostream,and ifstream, ofstream I/O classes.
• Both cin and cout are class objects and get and ignore are member functions.
cin.get (someChar) ;cin.ignore (100, ‘\n’) ;
• These statements declare myInfile as an instance of class ifstream and invoke member function open.
ifstream myInfile ;myInfile.open ( “A:\\mydata.dat” ) ;
expanded by J. Goetz
55
Scope Resolution Operator ( :: ) • C++ programs typically use several class types.
• Different classes can have member functions with the same identifier, like Write( ).
• Member selection operator is used to determine the class whose member function Write( ) is invoked. currentDate .Write( ) ; // class DateTypenumberZ .Write( ) ; // class ComplexNumberType
• In the implementation file, the scope resolution operator is used in the heading before the member function’s name to specify its class. void DateType :: Write ( ) const{ . . .
}
expanded by J. Goetz
56
Object-Oriented Programming• Three inter-related constructs: classes,
objects, and inheritance• Objects are the basic run-time entities in an
object-oriented system.• An object is a class object or class instance
(an instance of a class type)• A class defines the structure of its objects.• Classes are organized in an “is-a” hierarchy
defined by inheritance (every object of a derived class is also an object of the base class)
expanded by J. Goetz
57
Inheritance
1. Allows programmers to create a new class that is a specialization of an existing class.
2. The new class is called a derived class of the existing class; the existing class is the base class of the new class.
3. Each descendant (child) class inherits the properties (data and operations) of its ancestors (parents) class
4. The child doesn’t have access to parents’ private variables, only via parents’ public functions
expanded by J. Goetz
58
Inheritance
• Inheritance and polymorphism combined allow the programmer to build useful hierarchies of classes that can be reused in different applications
• Mapping of problem into solution
expanded by J. Goetz
59
# include <string>class MoneyType{public: void Initialize(long, long); long DollarsAre( ) const; long CentsAre( ) const;private: long dollars; long cents;};
class ExtMoneyType:public MoneyType
{public: string CurrencyIs( ); void Initialize(long, long, const string);private: string currency;};
ExtMoneyType extMoney;
void ExtMoneyType::Initialize
(long newDollars, long newCents, string newCurrency)
{
currency = newCurrency;
MoneyType::Initialize(
newDollars, newCents);
}
String ExtMoneyType::CurrencyIs()
const
{
return currency;
}
expanded by J. Goetz
60
Exceptions• An exception is an unusual situation that occurs
when the program is running.
• Exception Management – Define the error condition
– Enclose code containing possible error (try clause).
– Alert the system if error occurs (throw statement).
– Handle error if it is thrown (catch clause).
expanded by J. Goetz
61
try, catch, and throw// Reading and summing positive values from a filetry // code that contains a possible error{infile >> value;if (value < o) throw string(“An error has occurred in function …”); // a string is thrown; // catch has a string as a parametersum = sum + value;}
// error handler :catch (string message) //syntax: catch( exceptionType variable) –
//catch (type of the exception and the catch parameter) {
std::cout << message << std::endl;return 1;
}std::cout << “Sum of value on the file: “ << sum;
expanded by J. Goetz
62
Namespace = named scope
C++ language technique for grouping together a collection of names that logically belong together.
// in header file
namespace mySpace{
// All variables and functions prototypes within this// block must be accessed using scope// resolution operator (::).
}Purpose: Avoid namespace pollution when the same
name is used many times. Names can be grouped in the different namespace definition.
expanded by J. Goetz
63
Three Ways to Access Members within a Namespace
•Qualify each reference: mySpace::name with every reference.
•Using declaration: using mySpace::name;All future individual references to name refer to mySpace::name.
•Using directive:using namespace mySpace;All members of mySpace can be referenced without qualification.ex. using namespace std; // then you have access cout and cin
expanded by J. Goetz
64
Rules for Use of Namespace std(within text)
• Qualify names in prototypes and/or function definitions.
• If name used more than once in a function block, use a using declaration.
• If more than one name is used from a namespace, use a using directive.
• More about “Access to Identifiers in a Namespace” text p.98-99 or CS121 text 3 rd ed. ch.8 p.379-380
expanded by J. Goetz
65
Information Hiding
Class implementation details are hidden from the client’s view. This is called information hiding.
Public functions of a class provide the interface between the client code and the class objects.
clientcode
specification implementation
abstraction barrier
// SPECIFICATION FILE ( strtype.h )#include <fstream>#include <iostream>const int MAX_CHARS = 200 ;enum RelationType { LESS, EQUAL, GREATER } ;enum InType { ALPHA_NUM, ALPHA, NON_WHITE, NOT_NEW } ;class StrType // declares class data type{public : // 7 public member functions
void MakeEmpty ( ) ; void GetString ( bool skip, InType charsAllowed ) ;
void GetStringFile ( bool skip, InType charsAllowed, std::ifstream& inFile ) ;
void PrintToScreen ( bool newLine ) const ; void PrintToFile ( bool newLine, std::ofstream& outFile) const ;
int LengthIs( ) const ; void CopyString( StrType& newString ) const ;
private : // 1 private data memberchar letters [MAX_CHARS + 1 ] ;
} ;66
expanded by J. Goetz
67
StrType Class Interface Diagram
StrType class
Private data:
letters
GetString
GetStringFile
CopyString
LengthIs
PrintToFile
MakeEmpty
PrintToScreen‘c’ ’a’ ’t’ ’\0’ ...
// IMPLEMENTATION FILE (strtype.cpp)
#include “strtype.h” // also appears in client code #include “<cstring>”
void StrType :: MakeEmpty ( )// Post: letters is empty string.{
letters[0] = ‘\0’ ;}
. . .
int StrType :: LengthIs ( ) const// Returns length of letters string.{
return strlen ( letters ) ;} 68